about summary refs log tree commit diff
path: root/app/javascript/mastodon/reducers/conversations.js
diff options
context:
space:
mode:
authorEugen Rochko <eugen@zeonfederated.com>2018-10-07 23:44:58 +0200
committerGitHub <noreply@github.com>2018-10-07 23:44:58 +0200
commit774ac473736cbf348827cf6d861e7fbbb72d7623 (patch)
treec8ce87b43cd8fa58f7124a8a6baf93a71cb274e8 /app/javascript/mastodon/reducers/conversations.js
parent25744d43b0c9ae58227e1e46ac9e2b33a7944925 (diff)
Add conversations API (#8832)
* Add conversations API

* Add web UI for conversations

* Add test for conversations API

* Add tests for ConversationAccount

* Improve web UI

* Rename ConversationAccount to AccountConversation

* Remove conversations on block and mute

* Change last_status_id to be a denormalization of status_ids

* Add optimistic locking
Diffstat (limited to 'app/javascript/mastodon/reducers/conversations.js')
-rw-r--r--app/javascript/mastodon/reducers/conversations.js79
1 files changed, 79 insertions, 0 deletions
diff --git a/app/javascript/mastodon/reducers/conversations.js b/app/javascript/mastodon/reducers/conversations.js
new file mode 100644
index 000000000..f339abf56
--- /dev/null
+++ b/app/javascript/mastodon/reducers/conversations.js
@@ -0,0 +1,79 @@
+import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
+import {
+  CONVERSATIONS_FETCH_REQUEST,
+  CONVERSATIONS_FETCH_SUCCESS,
+  CONVERSATIONS_FETCH_FAIL,
+  CONVERSATIONS_UPDATE,
+} from '../actions/conversations';
+import compareId from '../compare_id';
+
+const initialState = ImmutableMap({
+  items: ImmutableList(),
+  isLoading: false,
+  hasMore: true,
+});
+
+const conversationToMap = item => ImmutableMap({
+  id: item.id,
+  accounts: ImmutableList(item.accounts.map(a => a.id)),
+  last_status: item.last_status.id,
+});
+
+const updateConversation = (state, item) => state.update('items', list => {
+  const index   = list.findIndex(x => x.get('id') === item.id);
+  const newItem = conversationToMap(item);
+
+  if (index === -1) {
+    return list.unshift(newItem);
+  } else {
+    return list.set(index, newItem);
+  }
+});
+
+const expandNormalizedConversations = (state, conversations, next) => {
+  let items = ImmutableList(conversations.map(conversationToMap));
+
+  return state.withMutations(mutable => {
+    if (!items.isEmpty()) {
+      mutable.update('items', list => {
+        list = list.map(oldItem => {
+          const newItemIndex = items.findIndex(x => x.get('id') === oldItem.get('id'));
+
+          if (newItemIndex === -1) {
+            return oldItem;
+          }
+
+          const newItem = items.get(newItemIndex);
+          items = items.delete(newItemIndex);
+
+          return newItem;
+        });
+
+        list = list.concat(items);
+
+        return list.sortBy(x => x.get('last_status'), (a, b) => compareId(a, b) * -1);
+      });
+    }
+
+    if (!next) {
+      mutable.set('hasMore', false);
+    }
+
+    mutable.set('isLoading', false);
+  });
+};
+
+export default function conversations(state = initialState, action) {
+  switch (action.type) {
+  case CONVERSATIONS_FETCH_REQUEST:
+    return state.set('isLoading', true);
+  case CONVERSATIONS_FETCH_FAIL:
+    return state.set('isLoading', false);
+  case CONVERSATIONS_FETCH_SUCCESS:
+    return expandNormalizedConversations(state, action.conversations, action.next);
+  case CONVERSATIONS_UPDATE:
+    return updateConversation(state, action.conversation);
+  default:
+    return state;
+  }
+};