The code powering m.abunchtell.com https://m.abunchtell.com
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.
 
 
 
 

214 line
7.0 KiB

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