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.

251 lines
6.1 KiB

  1. /*
  2. `<StatusContainer>`
  3. ===================
  4. Original file by @gargron@mastodon.social et al as part of
  5. tootsuite/mastodon. Documentation by @kibi@glitch.social. The code
  6. detecting reblogs has been moved here from <Status>.
  7. */
  8. /* * * * */
  9. /*
  10. Imports:
  11. --------
  12. */
  13. // Package imports //
  14. import React from 'react';
  15. import { connect } from 'react-redux';
  16. import {
  17. defineMessages,
  18. injectIntl,
  19. FormattedMessage,
  20. } from 'react-intl';
  21. // Mastodon imports //
  22. import { makeGetStatus } from '../../../mastodon/selectors';
  23. import {
  24. replyCompose,
  25. mentionCompose,
  26. } from '../../../mastodon/actions/compose';
  27. import {
  28. reblog,
  29. favourite,
  30. unreblog,
  31. unfavourite,
  32. } from '../../../mastodon/actions/interactions';
  33. import {
  34. blockAccount,
  35. muteAccount,
  36. } from '../../../mastodon/actions/accounts';
  37. import {
  38. muteStatus,
  39. unmuteStatus,
  40. deleteStatus,
  41. } from '../../../mastodon/actions/statuses';
  42. import { initReport } from '../../../mastodon/actions/reports';
  43. import { openModal } from '../../../mastodon/actions/modal';
  44. // Our imports //
  45. import Status from '.';
  46. /* * * * */
  47. /*
  48. Inital setup:
  49. -------------
  50. The `messages` constant is used to define any messages that we will
  51. need in our component. In our case, these are the various confirmation
  52. messages used with statuses.
  53. */
  54. const messages = defineMessages({
  55. deleteConfirm : {
  56. id : 'confirmations.delete.confirm',
  57. defaultMessage : 'Delete',
  58. },
  59. deleteMessage : {
  60. id : 'confirmations.delete.message',
  61. defaultMessage : 'Are you sure you want to delete this status?',
  62. },
  63. blockConfirm : {
  64. id : 'confirmations.block.confirm',
  65. defaultMessage : 'Block',
  66. },
  67. muteConfirm : {
  68. id : 'confirmations.mute.confirm',
  69. defaultMessage : 'Mute',
  70. },
  71. });
  72. /* * * * */
  73. /*
  74. State mapping:
  75. --------------
  76. The `mapStateToProps()` function maps various state properties to the
  77. props of our component. We wrap this in a `makeMapStateToProps()`
  78. function to give us closure and preserve `getStatus()` across function
  79. calls.
  80. */
  81. const makeMapStateToProps = () => {
  82. const getStatus = makeGetStatus();
  83. const mapStateToProps = (state, ownProps) => {
  84. let status = getStatus(state, ownProps.id);
  85. let reblogStatus = status.get('reblog', null);
  86. let account = undefined;
  87. let prepend = undefined;
  88. /*
  89. Here we process reblogs. If our status is a reblog, then we create a
  90. `prependMessage` to pass along to our `<Status>` along with the
  91. reblogger's `account`, and set `coreStatus` (the one we will actually
  92. render) to the status which has been reblogged.
  93. */
  94. if (reblogStatus !== null && typeof reblogStatus === 'object') {
  95. account = status.get('account');
  96. status = reblogStatus;
  97. prepend = 'reblogged_by';
  98. }
  99. /*
  100. Here are the props we pass to `<Status>`.
  101. */
  102. return {
  103. status : status,
  104. account : account || ownProps.account,
  105. me : state.getIn(['meta', 'me']),
  106. settings : state.get('local_settings'),
  107. prepend : prepend || ownProps.prepend,
  108. reblogModal : state.getIn(['meta', 'boost_modal']),
  109. deleteModal : state.getIn(['meta', 'delete_modal']),
  110. autoPlayGif : state.getIn(['meta', 'auto_play_gif']),
  111. };
  112. };
  113. return mapStateToProps;
  114. };
  115. /* * * * */
  116. /*
  117. Dispatch mapping:
  118. -----------------
  119. The `mapDispatchToProps()` function maps dispatches to our store to the
  120. various props of our component. We need to provide dispatches for all
  121. of the things you can do with a status: reply, reblog, favourite, et
  122. cetera.
  123. For a few of these dispatches, we open up confirmation modals; the rest
  124. just immediately execute their corresponding actions.
  125. */
  126. const mapDispatchToProps = (dispatch, { intl }) => ({
  127. onReply (status, router) {
  128. dispatch(replyCompose(status, router));
  129. },
  130. onModalReblog (status) {
  131. dispatch(reblog(status));
  132. },
  133. onReblog (status, e) {
  134. if (status.get('reblogged')) {
  135. dispatch(unreblog(status));
  136. } else {
  137. if (e.shiftKey || !this.reblogModal) {
  138. this.onModalReblog(status);
  139. } else {
  140. dispatch(openModal('BOOST', { status, onReblog: this.onModalReblog }));
  141. }
  142. }
  143. },
  144. onFavourite (status) {
  145. if (status.get('favourited')) {
  146. dispatch(unfavourite(status));
  147. } else {
  148. dispatch(favourite(status));
  149. }
  150. },
  151. onDelete (status) {
  152. if (!this.deleteModal) {
  153. dispatch(deleteStatus(status.get('id')));
  154. } else {
  155. dispatch(openModal('CONFIRM', {
  156. message: intl.formatMessage(messages.deleteMessage),
  157. confirm: intl.formatMessage(messages.deleteConfirm),
  158. onConfirm: () => dispatch(deleteStatus(status.get('id'))),
  159. }));
  160. }
  161. },
  162. onMention (account, router) {
  163. dispatch(mentionCompose(account, router));
  164. },
  165. onOpenMedia (media, index) {
  166. dispatch(openModal('MEDIA', { media, index }));
  167. },
  168. onOpenVideo (media, time) {
  169. dispatch(openModal('VIDEO', { media, time }));
  170. },
  171. onBlock (account) {
  172. dispatch(openModal('CONFIRM', {
  173. message: <FormattedMessage id='confirmations.block.message' defaultMessage='Are you sure you want to block {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />,
  174. confirm: intl.formatMessage(messages.blockConfirm),
  175. onConfirm: () => dispatch(blockAccount(account.get('id'))),
  176. }));
  177. },
  178. onReport (status) {
  179. dispatch(initReport(status.get('account'), status));
  180. },
  181. onMute (account) {
  182. dispatch(openModal('CONFIRM', {
  183. message: <FormattedMessage id='confirmations.mute.message' defaultMessage='Are you sure you want to mute {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />,
  184. confirm: intl.formatMessage(messages.muteConfirm),
  185. onConfirm: () => dispatch(muteAccount(account.get('id'))),
  186. }));
  187. },
  188. onMuteConversation (status) {
  189. if (status.get('muted')) {
  190. dispatch(unmuteStatus(status.get('id')));
  191. } else {
  192. dispatch(muteStatus(status.get('id')));
  193. }
  194. },
  195. });
  196. export default injectIntl(
  197. connect(makeMapStateToProps, mapDispatchToProps)(Status)
  198. );