The code powering m.abunchtell.com https://m.abunchtell.com
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 
 

255 linhas
8.4 KiB

  1. import {
  2. TIMELINE_REFRESH_SUCCESS,
  3. TIMELINE_UPDATE,
  4. TIMELINE_DELETE,
  5. TIMELINE_EXPAND_SUCCESS
  6. } from '../actions/timelines';
  7. import {
  8. REBLOG_SUCCESS,
  9. UNREBLOG_SUCCESS,
  10. FAVOURITE_SUCCESS,
  11. UNFAVOURITE_SUCCESS
  12. } from '../actions/interactions';
  13. import {
  14. ACCOUNT_SET_SELF,
  15. ACCOUNT_FETCH_SUCCESS,
  16. ACCOUNT_FOLLOW_SUCCESS,
  17. ACCOUNT_UNFOLLOW_SUCCESS,
  18. ACCOUNT_BLOCK_SUCCESS,
  19. ACCOUNT_UNBLOCK_SUCCESS,
  20. ACCOUNT_TIMELINE_FETCH_SUCCESS,
  21. ACCOUNT_TIMELINE_EXPAND_SUCCESS
  22. } from '../actions/accounts';
  23. import {
  24. STATUS_FETCH_SUCCESS,
  25. STATUS_DELETE_SUCCESS
  26. } from '../actions/statuses';
  27. import { FOLLOW_SUBMIT_SUCCESS } from '../actions/follow';
  28. import { SUGGESTIONS_FETCH_SUCCESS } from '../actions/suggestions';
  29. import Immutable from 'immutable';
  30. const initialState = Immutable.Map({
  31. home: Immutable.List([]),
  32. mentions: Immutable.List([]),
  33. public: Immutable.List([]),
  34. statuses: Immutable.Map(),
  35. accounts: Immutable.Map(),
  36. accounts_timelines: Immutable.Map(),
  37. me: null,
  38. ancestors: Immutable.Map(),
  39. descendants: Immutable.Map(),
  40. relationships: Immutable.Map(),
  41. suggestions: Immutable.List([])
  42. });
  43. function normalizeStatus(state, status) {
  44. // Separate account
  45. let account = status.get('account');
  46. status = status.set('account', account.get('id'));
  47. // Separate reblog, repeat for reblog
  48. let reblog = status.get('reblog', null);
  49. if (reblog !== null) {
  50. status = status.set('reblog', reblog.get('id'));
  51. state = normalizeStatus(state, reblog);
  52. }
  53. // Replies
  54. if (status.get('in_reply_to_id')) {
  55. state = state.updateIn(['descendants', status.get('in_reply_to_id')], set => {
  56. if (!Immutable.OrderedSet.isOrderedSet(set)) {
  57. return Immutable.OrderedSet([status.get('id')]);
  58. } else {
  59. return set.add(status.get('id'));
  60. }
  61. });
  62. }
  63. return state.withMutations(map => {
  64. if (status.get('in_reply_to_id')) {
  65. map.updateIn(['descendants', status.get('in_reply_to_id')], Immutable.OrderedSet(), set => set.add(status.get('id')));
  66. map.updateIn(['ancestors', status.get('id')], Immutable.OrderedSet(), set => set.add(status.get('in_reply_to_id')));
  67. }
  68. map.setIn(['accounts', account.get('id')], account);
  69. map.setIn(['statuses', status.get('id')], status);
  70. });
  71. };
  72. function normalizeTimeline(state, timeline, statuses) {
  73. let ids = Immutable.List([]);
  74. statuses.forEach((status, i) => {
  75. state = normalizeStatus(state, status);
  76. ids = ids.set(i, status.get('id'));
  77. });
  78. return state.update(timeline, list => list.unshift(...ids));
  79. };
  80. function appendNormalizedTimeline(state, timeline, statuses) {
  81. let moreIds = Immutable.List([]);
  82. statuses.forEach((status, i) => {
  83. state = normalizeStatus(state, status);
  84. moreIds = moreIds.set(i, status.get('id'));
  85. });
  86. return state.update(timeline, list => list.push(...moreIds));
  87. };
  88. function normalizeAccountTimeline(state, accountId, statuses) {
  89. let ids = Immutable.List([]);
  90. statuses.forEach((status, i) => {
  91. state = normalizeStatus(state, status);
  92. ids = ids.set(i, status.get('id'));
  93. });
  94. return state.updateIn(['accounts_timelines', accountId], Immutable.List([]), list => list.unshift(...ids));
  95. };
  96. function appendNormalizedAccountTimeline(state, accountId, statuses) {
  97. let moreIds = Immutable.List([]);
  98. statuses.forEach((status, i) => {
  99. state = normalizeStatus(state, status);
  100. moreIds = moreIds.set(i, status.get('id'));
  101. });
  102. return state.updateIn(['accounts_timelines', accountId], Immutable.List([]), list => list.push(...moreIds));
  103. };
  104. function updateTimeline(state, timeline, status) {
  105. state = normalizeStatus(state, status);
  106. state = state.update(timeline, list => {
  107. const reblogOfId = status.getIn(['reblog', 'id'], null);
  108. if (reblogOfId !== null) {
  109. const otherReblogs = state.get('statuses').filter(item => item.get('reblog') === reblogOfId).map((_, itemId) => itemId);
  110. list = list.filterNot(itemId => (itemId === reblogOfId || otherReblogs.includes(itemId)));
  111. }
  112. return list.unshift(status.get('id'));
  113. });
  114. //state = state.updateIn(['accounts_timelines', status.getIn(['account', 'id'])], Immutable.List([]), list => (list.includes(status.get('id')) ? list : list.unshift(status.get('id'))));
  115. return state;
  116. };
  117. function deleteStatus(state, id) {
  118. const status = state.getIn(['statuses', id]);
  119. if (!status) {
  120. return state;
  121. }
  122. // Remove references from timelines
  123. ['home', 'mentions'].forEach(function (timeline) {
  124. state = state.update(timeline, list => list.filterNot(item => item === id));
  125. });
  126. // Remove references from account timelines
  127. state = state.updateIn(['accounts_timelines', status.get('account')], Immutable.List([]), list => list.filterNot(item => item === id));
  128. // Remove reblogs of deleted status
  129. const references = state.get('statuses').filter(item => item.get('reblog') === id);
  130. references.forEach(referencingId => {
  131. state = deleteStatus(state, referencingId);
  132. });
  133. // Remove normalized status
  134. return state.deleteIn(['statuses', id]);
  135. };
  136. function normalizeAccount(state, account, relationship) {
  137. if (relationship) {
  138. state = normalizeRelationship(state, relationship);
  139. }
  140. return state.setIn(['accounts', account.get('id')], account);
  141. };
  142. function normalizeRelationship(state, relationship) {
  143. if (state.get('suggestions').includes(relationship.get('id')) && (relationship.get('following') || relationship.get('blocking'))) {
  144. state = state.update('suggestions', list => list.filterNot(id => id === relationship.get('id')));
  145. }
  146. return state.setIn(['relationships', relationship.get('id')], relationship);
  147. };
  148. function setSelf(state, account) {
  149. state = normalizeAccount(state, account);
  150. return state.set('me', account.get('id'));
  151. };
  152. function normalizeContext(state, status, ancestors, descendants) {
  153. state = normalizeStatus(state, status);
  154. let ancestorsIds = ancestors.map(ancestor => {
  155. state = normalizeStatus(state, ancestor);
  156. return ancestor.get('id');
  157. }).toOrderedSet();
  158. let descendantsIds = descendants.map(descendant => {
  159. state = normalizeStatus(state, descendant);
  160. return descendant.get('id');
  161. }).toOrderedSet();
  162. return state.withMutations(map => {
  163. map.setIn(['ancestors', status.get('id')], ancestorsIds);
  164. map.setIn(['descendants', status.get('id')], descendantsIds);
  165. });
  166. };
  167. function normalizeSuggestions(state, accounts) {
  168. accounts.forEach(account => {
  169. state = state.setIn(['accounts', account.get('id')], account);
  170. });
  171. return state.set('suggestions', accounts.map(account => account.get('id')));
  172. };
  173. export default function timelines(state = initialState, action) {
  174. switch(action.type) {
  175. case TIMELINE_REFRESH_SUCCESS:
  176. return normalizeTimeline(state, action.timeline, Immutable.fromJS(action.statuses));
  177. case TIMELINE_EXPAND_SUCCESS:
  178. return appendNormalizedTimeline(state, action.timeline, Immutable.fromJS(action.statuses));
  179. case TIMELINE_UPDATE:
  180. return updateTimeline(state, action.timeline, Immutable.fromJS(action.status));
  181. case TIMELINE_DELETE:
  182. case STATUS_DELETE_SUCCESS:
  183. return deleteStatus(state, action.id);
  184. case REBLOG_SUCCESS:
  185. case FAVOURITE_SUCCESS:
  186. case UNREBLOG_SUCCESS:
  187. case UNFAVOURITE_SUCCESS:
  188. return normalizeStatus(state, Immutable.fromJS(action.response));
  189. case ACCOUNT_SET_SELF:
  190. return setSelf(state, Immutable.fromJS(action.account));
  191. case ACCOUNT_FETCH_SUCCESS:
  192. case FOLLOW_SUBMIT_SUCCESS:
  193. return normalizeAccount(state, Immutable.fromJS(action.account), Immutable.fromJS(action.relationship));
  194. case ACCOUNT_FOLLOW_SUCCESS:
  195. case ACCOUNT_UNFOLLOW_SUCCESS:
  196. case ACCOUNT_UNBLOCK_SUCCESS:
  197. case ACCOUNT_BLOCK_SUCCESS:
  198. return normalizeRelationship(state, Immutable.fromJS(action.relationship));
  199. case STATUS_FETCH_SUCCESS:
  200. return normalizeContext(state, Immutable.fromJS(action.status), Immutable.fromJS(action.context.ancestors), Immutable.fromJS(action.context.descendants));
  201. case ACCOUNT_TIMELINE_FETCH_SUCCESS:
  202. return normalizeAccountTimeline(state, action.id, Immutable.fromJS(action.statuses));
  203. case ACCOUNT_TIMELINE_EXPAND_SUCCESS:
  204. return appendNormalizedAccountTimeline(state, action.id, Immutable.fromJS(action.statuses));
  205. case SUGGESTIONS_FETCH_SUCCESS:
  206. return normalizeSuggestions(state, Immutable.fromJS(action.suggestions));
  207. default:
  208. return state;
  209. }
  210. };