闭社主体 forked from https://github.com/tootsuite/mastodon
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.

280 lines
6.8 KiB

8 years ago
8 years ago
7 years ago
7 years ago
8 years ago
  1. import api from '../api';
  2. import { updateTimeline } from './timelines';
  3. export const COMPOSE_CHANGE = 'COMPOSE_CHANGE';
  4. export const COMPOSE_SUBMIT_REQUEST = 'COMPOSE_SUBMIT_REQUEST';
  5. export const COMPOSE_SUBMIT_SUCCESS = 'COMPOSE_SUBMIT_SUCCESS';
  6. export const COMPOSE_SUBMIT_FAIL = 'COMPOSE_SUBMIT_FAIL';
  7. export const COMPOSE_REPLY = 'COMPOSE_REPLY';
  8. export const COMPOSE_REPLY_CANCEL = 'COMPOSE_REPLY_CANCEL';
  9. export const COMPOSE_MENTION = 'COMPOSE_MENTION';
  10. export const COMPOSE_UPLOAD_REQUEST = 'COMPOSE_UPLOAD_REQUEST';
  11. export const COMPOSE_UPLOAD_SUCCESS = 'COMPOSE_UPLOAD_SUCCESS';
  12. export const COMPOSE_UPLOAD_FAIL = 'COMPOSE_UPLOAD_FAIL';
  13. export const COMPOSE_UPLOAD_PROGRESS = 'COMPOSE_UPLOAD_PROGRESS';
  14. export const COMPOSE_UPLOAD_UNDO = 'COMPOSE_UPLOAD_UNDO';
  15. export const COMPOSE_SUGGESTIONS_CLEAR = 'COMPOSE_SUGGESTIONS_CLEAR';
  16. export const COMPOSE_SUGGESTIONS_READY = 'COMPOSE_SUGGESTIONS_READY';
  17. export const COMPOSE_SUGGESTION_SELECT = 'COMPOSE_SUGGESTION_SELECT';
  18. export const COMPOSE_MOUNT = 'COMPOSE_MOUNT';
  19. export const COMPOSE_UNMOUNT = 'COMPOSE_UNMOUNT';
  20. export const COMPOSE_SENSITIVITY_CHANGE = 'COMPOSE_SENSITIVITY_CHANGE';
  21. export const COMPOSE_SPOILERNESS_CHANGE = 'COMPOSE_SPOILERNESS_CHANGE';
  22. export const COMPOSE_SPOILER_TEXT_CHANGE = 'COMPOSE_SPOILER_TEXT_CHANGE';
  23. export const COMPOSE_VISIBILITY_CHANGE = 'COMPOSE_VISIBILITY_CHANGE';
  24. export const COMPOSE_LISTABILITY_CHANGE = 'COMPOSE_LISTABILITY_CHANGE';
  25. export const COMPOSE_EMOJI_INSERT = 'COMPOSE_EMOJI_INSERT';
  26. export function changeCompose(text) {
  27. return {
  28. type: COMPOSE_CHANGE,
  29. text: text,
  30. };
  31. };
  32. export function replyCompose(status, router) {
  33. return (dispatch, getState) => {
  34. dispatch({
  35. type: COMPOSE_REPLY,
  36. status: status,
  37. });
  38. if (!getState().getIn(['compose', 'mounted'])) {
  39. router.push('/statuses/new');
  40. }
  41. };
  42. };
  43. export function cancelReplyCompose() {
  44. return {
  45. type: COMPOSE_REPLY_CANCEL,
  46. };
  47. };
  48. export function mentionCompose(account, router) {
  49. return (dispatch, getState) => {
  50. dispatch({
  51. type: COMPOSE_MENTION,
  52. account: account,
  53. });
  54. if (!getState().getIn(['compose', 'mounted'])) {
  55. router.push('/statuses/new');
  56. }
  57. };
  58. };
  59. export function submitCompose() {
  60. return function (dispatch, getState) {
  61. const status = getState().getIn(['compose', 'text'], '');
  62. if (!status || !status.length) {
  63. return;
  64. }
  65. dispatch(submitComposeRequest());
  66. api(getState).post('/api/v1/statuses', {
  67. status,
  68. in_reply_to_id: getState().getIn(['compose', 'in_reply_to'], null),
  69. media_ids: getState().getIn(['compose', 'media_attachments']).map(item => item.get('id')),
  70. sensitive: getState().getIn(['compose', 'sensitive']),
  71. spoiler_text: getState().getIn(['compose', 'spoiler_text'], ''),
  72. visibility: getState().getIn(['compose', 'privacy']),
  73. }, {
  74. headers: {
  75. 'Idempotency-Key': getState().getIn(['compose', 'idempotencyKey']),
  76. },
  77. }).then(function (response) {
  78. dispatch(submitComposeSuccess({ ...response.data }));
  79. // To make the app more responsive, immediately get the status into the columns
  80. dispatch(updateTimeline('home', { ...response.data }));
  81. if (response.data.in_reply_to_id === null && response.data.visibility === 'public') {
  82. if (getState().getIn(['timelines', 'community', 'loaded'])) {
  83. dispatch(updateTimeline('community', { ...response.data }));
  84. }
  85. if (getState().getIn(['timelines', 'public', 'loaded'])) {
  86. dispatch(updateTimeline('public', { ...response.data }));
  87. }
  88. }
  89. }).catch(function (error) {
  90. dispatch(submitComposeFail(error));
  91. });
  92. };
  93. };
  94. export function submitComposeRequest() {
  95. return {
  96. type: COMPOSE_SUBMIT_REQUEST,
  97. };
  98. };
  99. export function submitComposeSuccess(status) {
  100. return {
  101. type: COMPOSE_SUBMIT_SUCCESS,
  102. status: status,
  103. };
  104. };
  105. export function submitComposeFail(error) {
  106. return {
  107. type: COMPOSE_SUBMIT_FAIL,
  108. error: error,
  109. };
  110. };
  111. export function uploadCompose(files) {
  112. return function (dispatch, getState) {
  113. if (getState().getIn(['compose', 'media_attachments']).size > 3) {
  114. return;
  115. }
  116. dispatch(uploadComposeRequest());
  117. let data = new FormData();
  118. data.append('file', files[0]);
  119. api(getState).post('/api/v1/media', data, {
  120. onUploadProgress: function (e) {
  121. dispatch(uploadComposeProgress(e.loaded, e.total));
  122. },
  123. }).then(function (response) {
  124. dispatch(uploadComposeSuccess(response.data));
  125. }).catch(function (error) {
  126. dispatch(uploadComposeFail(error));
  127. });
  128. };
  129. };
  130. export function uploadComposeRequest() {
  131. return {
  132. type: COMPOSE_UPLOAD_REQUEST,
  133. skipLoading: true,
  134. };
  135. };
  136. export function uploadComposeProgress(loaded, total) {
  137. return {
  138. type: COMPOSE_UPLOAD_PROGRESS,
  139. loaded: loaded,
  140. total: total,
  141. };
  142. };
  143. export function uploadComposeSuccess(media) {
  144. return {
  145. type: COMPOSE_UPLOAD_SUCCESS,
  146. media: media,
  147. skipLoading: true,
  148. };
  149. };
  150. export function uploadComposeFail(error) {
  151. return {
  152. type: COMPOSE_UPLOAD_FAIL,
  153. error: error,
  154. skipLoading: true,
  155. };
  156. };
  157. export function undoUploadCompose(media_id) {
  158. return {
  159. type: COMPOSE_UPLOAD_UNDO,
  160. media_id: media_id,
  161. };
  162. };
  163. export function clearComposeSuggestions() {
  164. return {
  165. type: COMPOSE_SUGGESTIONS_CLEAR,
  166. };
  167. };
  168. export function fetchComposeSuggestions(token) {
  169. return (dispatch, getState) => {
  170. api(getState).get('/api/v1/accounts/search', {
  171. params: {
  172. q: token,
  173. resolve: false,
  174. limit: 4,
  175. },
  176. }).then(response => {
  177. dispatch(readyComposeSuggestions(token, response.data));
  178. });
  179. };
  180. };
  181. export function readyComposeSuggestions(token, accounts) {
  182. return {
  183. type: COMPOSE_SUGGESTIONS_READY,
  184. token,
  185. accounts,
  186. };
  187. };
  188. export function selectComposeSuggestion(position, token, accountId) {
  189. return (dispatch, getState) => {
  190. const completion = getState().getIn(['accounts', accountId, 'acct']);
  191. dispatch({
  192. type: COMPOSE_SUGGESTION_SELECT,
  193. position,
  194. token,
  195. completion,
  196. });
  197. };
  198. };
  199. export function mountCompose() {
  200. return {
  201. type: COMPOSE_MOUNT,
  202. };
  203. };
  204. export function unmountCompose() {
  205. return {
  206. type: COMPOSE_UNMOUNT,
  207. };
  208. };
  209. export function changeComposeSensitivity() {
  210. return {
  211. type: COMPOSE_SENSITIVITY_CHANGE,
  212. };
  213. };
  214. export function changeComposeSpoilerness() {
  215. return {
  216. type: COMPOSE_SPOILERNESS_CHANGE,
  217. };
  218. };
  219. export function changeComposeSpoilerText(text) {
  220. return {
  221. type: COMPOSE_SPOILER_TEXT_CHANGE,
  222. text,
  223. };
  224. };
  225. export function changeComposeVisibility(value) {
  226. return {
  227. type: COMPOSE_VISIBILITY_CHANGE,
  228. value,
  229. };
  230. };
  231. export function insertEmojiCompose(position, emoji) {
  232. return {
  233. type: COMPOSE_EMOJI_INSERT,
  234. position,
  235. emoji,
  236. };
  237. };