You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

125 lines
3.5 KiB

  1. import React from 'react';
  2. import PropTypes from 'prop-types';
  3. import ImmutablePropTypes from 'react-immutable-proptypes';
  4. import ImmutablePureComponent from 'react-immutable-pure-component';
  5. import StatusContent from 'flavours/glitch/components/status_content';
  6. import Avatar from 'flavours/glitch/components/avatar';
  7. import RelativeTimestamp from 'flavours/glitch/components/relative_timestamp';
  8. import DisplayName from 'flavours/glitch/components/display_name';
  9. import classNames from 'classnames';
  10. import Icon from 'flavours/glitch/components/icon';
  11. import Link from 'flavours/glitch/components/link';
  12. import Toggle from 'react-toggle';
  13. export default class ActionsModal extends ImmutablePureComponent {
  14. static propTypes = {
  15. status: ImmutablePropTypes.map,
  16. actions: PropTypes.arrayOf(PropTypes.shape({
  17. active: PropTypes.bool,
  18. href: PropTypes.string,
  19. icon: PropTypes.string,
  20. meta: PropTypes.node,
  21. name: PropTypes.string,
  22. on: PropTypes.bool,
  23. onClick: PropTypes.func,
  24. onPassiveClick: PropTypes.func,
  25. text: PropTypes.node,
  26. })),
  27. };
  28. renderAction = (action, i) => {
  29. if (action === null) {
  30. return <li key={`sep-${i}`} className='dropdown-menu__separator' />;
  31. }
  32. const {
  33. active,
  34. href,
  35. icon,
  36. meta,
  37. name,
  38. on,
  39. onClick,
  40. onPassiveClick,
  41. text,
  42. } = action;
  43. return (
  44. <li key={name || i}>
  45. <Link
  46. className={classNames('link', { active })}
  47. href={href}
  48. onClick={on !== null && typeof on !== 'undefined' && onPassiveClick || onClick}
  49. role={onClick ? 'button' : null}
  50. >
  51. {function () {
  52. // We render a `<Toggle>` if we were provided an `on`
  53. // property, and otherwise show an `<Icon>` if available.
  54. switch (true) {
  55. case on !== null && typeof on !== 'undefined':
  56. return (
  57. <Toggle
  58. checked={on}
  59. onChange={onPassiveClick || onClick}
  60. />
  61. );
  62. case !!icon:
  63. return (
  64. <Icon
  65. className='icon'
  66. fullwidth
  67. icon={icon}
  68. />
  69. );
  70. default:
  71. return null;
  72. }
  73. }()}
  74. {meta ? (
  75. <div>
  76. <strong>{text}</strong>
  77. {meta}
  78. </div>
  79. ) : <div>{text}</div>}
  80. </Link>
  81. </li>
  82. );
  83. }
  84. render () {
  85. const status = this.props.status && (
  86. <div className='status light'>
  87. <div className='boost-modal__status-header'>
  88. <div className='boost-modal__status-time'>
  89. <a href={this.props.status.get('url')} className='status__relative-time' target='_blank' rel='noopener'>
  90. <RelativeTimestamp timestamp={this.props.status.get('created_at')} />
  91. </a>
  92. </div>
  93. <a href={this.props.status.getIn(['account', 'url'])} className='status__display-name'>
  94. <div className='status__avatar'>
  95. <Avatar account={this.props.status.get('account')} size={48} />
  96. </div>
  97. <DisplayName account={this.props.status.get('account')} />
  98. </a>
  99. </div>
  100. <StatusContent status={this.props.status} />
  101. </div>
  102. );
  103. return (
  104. <div className='modal-root__modal actions-modal'>
  105. {status}
  106. <ul>
  107. {this.props.actions.map(this.renderAction)}
  108. </ul>
  109. </div>
  110. );
  111. }
  112. }