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.
 
 
 
 

117 line
3.5 KiB

  1. import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
  2. import {
  3. CONVERSATIONS_MOUNT,
  4. CONVERSATIONS_UNMOUNT,
  5. CONVERSATIONS_FETCH_REQUEST,
  6. CONVERSATIONS_FETCH_SUCCESS,
  7. CONVERSATIONS_FETCH_FAIL,
  8. CONVERSATIONS_UPDATE,
  9. CONVERSATIONS_READ,
  10. CONVERSATIONS_DELETE_SUCCESS,
  11. } from '../actions/conversations';
  12. import { ACCOUNT_BLOCK_SUCCESS, ACCOUNT_MUTE_SUCCESS } from 'mastodon/actions/accounts';
  13. import { DOMAIN_BLOCK_SUCCESS } from 'mastodon/actions/domain_blocks';
  14. import compareId from '../compare_id';
  15. const initialState = ImmutableMap({
  16. items: ImmutableList(),
  17. isLoading: false,
  18. hasMore: true,
  19. mounted: false,
  20. });
  21. const conversationToMap = item => ImmutableMap({
  22. id: item.id,
  23. unread: item.unread,
  24. accounts: ImmutableList(item.accounts.map(a => a.id)),
  25. last_status: item.last_status ? item.last_status.id : null,
  26. });
  27. const updateConversation = (state, item) => state.update('items', list => {
  28. const index = list.findIndex(x => x.get('id') === item.id);
  29. const newItem = conversationToMap(item);
  30. if (index === -1) {
  31. return list.unshift(newItem);
  32. } else {
  33. return list.set(index, newItem);
  34. }
  35. });
  36. const expandNormalizedConversations = (state, conversations, next, isLoadingRecent) => {
  37. let items = ImmutableList(conversations.map(conversationToMap));
  38. return state.withMutations(mutable => {
  39. if (!items.isEmpty()) {
  40. mutable.update('items', list => {
  41. list = list.map(oldItem => {
  42. const newItemIndex = items.findIndex(x => x.get('id') === oldItem.get('id'));
  43. if (newItemIndex === -1) {
  44. return oldItem;
  45. }
  46. const newItem = items.get(newItemIndex);
  47. items = items.delete(newItemIndex);
  48. return newItem;
  49. });
  50. list = list.concat(items);
  51. return list.sortBy(x => x.get('last_status'), (a, b) => {
  52. if(a === null || b === null) {
  53. return -1;
  54. }
  55. return compareId(a, b) * -1;
  56. });
  57. });
  58. }
  59. if (!next && !isLoadingRecent) {
  60. mutable.set('hasMore', false);
  61. }
  62. mutable.set('isLoading', false);
  63. });
  64. };
  65. const filterConversations = (state, accountIds) => {
  66. return state.update('items', list => list.filterNot(item => item.get('accounts').some(accountId => accountIds.includes(accountId))));
  67. };
  68. export default function conversations(state = initialState, action) {
  69. switch (action.type) {
  70. case CONVERSATIONS_FETCH_REQUEST:
  71. return state.set('isLoading', true);
  72. case CONVERSATIONS_FETCH_FAIL:
  73. return state.set('isLoading', false);
  74. case CONVERSATIONS_FETCH_SUCCESS:
  75. return expandNormalizedConversations(state, action.conversations, action.next, action.isLoadingRecent);
  76. case CONVERSATIONS_UPDATE:
  77. return updateConversation(state, action.conversation);
  78. case CONVERSATIONS_MOUNT:
  79. return state.update('mounted', count => count + 1);
  80. case CONVERSATIONS_UNMOUNT:
  81. return state.update('mounted', count => count - 1);
  82. case CONVERSATIONS_READ:
  83. return state.update('items', list => list.map(item => {
  84. if (item.get('id') === action.id) {
  85. return item.set('unread', false);
  86. }
  87. return item;
  88. }));
  89. case ACCOUNT_BLOCK_SUCCESS:
  90. case ACCOUNT_MUTE_SUCCESS:
  91. return filterConversations(state, [action.relationship.id]);
  92. case DOMAIN_BLOCK_SUCCESS:
  93. return filterConversations(state, action.accounts);
  94. case CONVERSATIONS_DELETE_SUCCESS:
  95. return state.update('items', list => list.filterNot(item => item.get('id') === action.id));
  96. default:
  97. return state;
  98. }
  99. };