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.

208 lines
6.8 KiB

7 years ago
7 years ago
  1. import api, { getLinks } from '../api';
  2. import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
  3. export const TIMELINE_UPDATE = 'TIMELINE_UPDATE';
  4. export const TIMELINE_DELETE = 'TIMELINE_DELETE';
  5. export const TIMELINE_REFRESH_REQUEST = 'TIMELINE_REFRESH_REQUEST';
  6. export const TIMELINE_REFRESH_SUCCESS = 'TIMELINE_REFRESH_SUCCESS';
  7. export const TIMELINE_REFRESH_FAIL = 'TIMELINE_REFRESH_FAIL';
  8. export const TIMELINE_EXPAND_REQUEST = 'TIMELINE_EXPAND_REQUEST';
  9. export const TIMELINE_EXPAND_SUCCESS = 'TIMELINE_EXPAND_SUCCESS';
  10. export const TIMELINE_EXPAND_FAIL = 'TIMELINE_EXPAND_FAIL';
  11. export const TIMELINE_SCROLL_TOP = 'TIMELINE_SCROLL_TOP';
  12. export const TIMELINE_CONNECT = 'TIMELINE_CONNECT';
  13. export const TIMELINE_DISCONNECT = 'TIMELINE_DISCONNECT';
  14. export const TIMELINE_CONTEXT_UPDATE = 'CONTEXT_UPDATE';
  15. export function refreshTimelineSuccess(timeline, statuses, skipLoading, next) {
  16. return {
  17. type: TIMELINE_REFRESH_SUCCESS,
  18. timeline,
  19. statuses,
  20. skipLoading,
  21. next,
  22. };
  23. };
  24. export function updateTimeline(timeline, status) {
  25. return (dispatch, getState) => {
  26. const references = status.reblog ? getState().get('statuses').filter((item, itemId) => (itemId === status.reblog.id || item.get('reblog') === status.reblog.id)).map((_, itemId) => itemId) : [];
  27. const parents = [];
  28. if (status.in_reply_to_id) {
  29. let parent = getState().getIn(['statuses', status.in_reply_to_id]);
  30. while (parent && parent.get('in_reply_to_id')) {
  31. parents.push(parent.get('id'));
  32. parent = getState().getIn(['statuses', parent.get('in_reply_to_id')]);
  33. }
  34. }
  35. dispatch({
  36. type: TIMELINE_UPDATE,
  37. timeline,
  38. status,
  39. references,
  40. });
  41. if (parents.length > 0) {
  42. dispatch({
  43. type: TIMELINE_CONTEXT_UPDATE,
  44. status,
  45. references: parents,
  46. });
  47. }
  48. };
  49. };
  50. export function deleteFromTimelines(id) {
  51. return (dispatch, getState) => {
  52. const accountId = getState().getIn(['statuses', id, 'account']);
  53. const references = getState().get('statuses').filter(status => status.get('reblog') === id).map(status => [status.get('id'), status.get('account')]);
  54. const reblogOf = getState().getIn(['statuses', id, 'reblog'], null);
  55. dispatch({
  56. type: TIMELINE_DELETE,
  57. id,
  58. accountId,
  59. references,
  60. reblogOf,
  61. });
  62. };
  63. };
  64. export function refreshTimelineRequest(timeline, skipLoading) {
  65. return {
  66. type: TIMELINE_REFRESH_REQUEST,
  67. timeline,
  68. skipLoading,
  69. };
  70. };
  71. export function refreshTimeline(timelineId, path, params = {}) {
  72. return function (dispatch, getState) {
  73. const timeline = getState().getIn(['timelines', timelineId], ImmutableMap());
  74. if (timeline.get('isLoading') || timeline.get('online')) {
  75. return;
  76. }
  77. const ids = timeline.get('items', ImmutableList());
  78. const newestId = ids.size > 0 ? ids.first() : null;
  79. let skipLoading = timeline.get('loaded');
  80. if (newestId !== null) {
  81. params.since_id = newestId;
  82. }
  83. dispatch(refreshTimelineRequest(timelineId, skipLoading));
  84. api(getState).get(path, { params }).then(response => {
  85. const next = getLinks(response).refs.find(link => link.rel === 'next');
  86. dispatch(refreshTimelineSuccess(timelineId, response.data, skipLoading, next ? next.uri : null));
  87. }).catch(error => {
  88. dispatch(refreshTimelineFail(timelineId, error, skipLoading));
  89. });
  90. };
  91. };
  92. export const refreshHomeTimeline = () => refreshTimeline('home', '/api/v1/timelines/home');
  93. export const refreshPublicTimeline = () => refreshTimeline('public', '/api/v1/timelines/public');
  94. export const refreshCommunityTimeline = () => refreshTimeline('community', '/api/v1/timelines/public', { local: true });
  95. export const refreshAccountTimeline = accountId => refreshTimeline(`account:${accountId}`, `/api/v1/accounts/${accountId}/statuses`);
  96. export const refreshAccountMediaTimeline = accountId => refreshTimeline(`account:${accountId}:media`, `/api/v1/accounts/${accountId}/statuses`, { only_media: true });
  97. export const refreshHashtagTimeline = hashtag => refreshTimeline(`hashtag:${hashtag}`, `/api/v1/timelines/tag/${hashtag}`);
  98. export const refreshListTimeline = id => refreshTimeline(`list:${id}`, `/api/v1/timelines/list/${id}`);
  99. export function refreshTimelineFail(timeline, error, skipLoading) {
  100. return {
  101. type: TIMELINE_REFRESH_FAIL,
  102. timeline,
  103. error,
  104. skipLoading,
  105. skipAlert: error.response && error.response.status === 404,
  106. };
  107. };
  108. export function expandTimeline(timelineId, path, params = {}) {
  109. return (dispatch, getState) => {
  110. const timeline = getState().getIn(['timelines', timelineId], ImmutableMap());
  111. const ids = timeline.get('items', ImmutableList());
  112. if (timeline.get('isLoading') || ids.size === 0) {
  113. return;
  114. }
  115. params.max_id = ids.last();
  116. params.limit = 10;
  117. dispatch(expandTimelineRequest(timelineId));
  118. api(getState).get(path, { params }).then(response => {
  119. const next = getLinks(response).refs.find(link => link.rel === 'next');
  120. dispatch(expandTimelineSuccess(timelineId, response.data, next ? next.uri : null));
  121. }).catch(error => {
  122. dispatch(expandTimelineFail(timelineId, error));
  123. });
  124. };
  125. };
  126. export const expandHomeTimeline = () => expandTimeline('home', '/api/v1/timelines/home');
  127. export const expandPublicTimeline = () => expandTimeline('public', '/api/v1/timelines/public');
  128. export const expandCommunityTimeline = () => expandTimeline('community', '/api/v1/timelines/public', { local: true });
  129. export const expandAccountTimeline = accountId => expandTimeline(`account:${accountId}`, `/api/v1/accounts/${accountId}/statuses`);
  130. export const expandAccountMediaTimeline = accountId => expandTimeline(`account:${accountId}:media`, `/api/v1/accounts/${accountId}/statuses`, { only_media: true });
  131. export const expandHashtagTimeline = hashtag => expandTimeline(`hashtag:${hashtag}`, `/api/v1/timelines/tag/${hashtag}`);
  132. export const expandListTimeline = id => expandTimeline(`list:${id}`, `/api/v1/timelines/list/${id}`);
  133. export function expandTimelineRequest(timeline) {
  134. return {
  135. type: TIMELINE_EXPAND_REQUEST,
  136. timeline,
  137. };
  138. };
  139. export function expandTimelineSuccess(timeline, statuses, next) {
  140. return {
  141. type: TIMELINE_EXPAND_SUCCESS,
  142. timeline,
  143. statuses,
  144. next,
  145. };
  146. };
  147. export function expandTimelineFail(timeline, error) {
  148. return {
  149. type: TIMELINE_EXPAND_FAIL,
  150. timeline,
  151. error,
  152. };
  153. };
  154. export function scrollTopTimeline(timeline, top) {
  155. return {
  156. type: TIMELINE_SCROLL_TOP,
  157. timeline,
  158. top,
  159. };
  160. };
  161. export function connectTimeline(timeline) {
  162. return {
  163. type: TIMELINE_CONNECT,
  164. timeline,
  165. };
  166. };
  167. export function disconnectTimeline(timeline) {
  168. return {
  169. type: TIMELINE_DISCONNECT,
  170. timeline,
  171. };
  172. };