mattermost-redux
Version:
Common code (API client, Redux stores, logic, utility functions) for building a Mattermost client
169 lines (168 loc) • 6.54 kB
JavaScript
;
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
Object.defineProperty(exports, "__esModule", { value: true });
exports.threadsReducer = void 0;
const action_types_1 = require("mattermost-redux/action_types");
const counts_1 = require("./counts");
const threadsInTeam_1 = require("./threadsInTeam");
const threadsReducer = (state = {}, action, extra) => {
switch (action.type) {
case action_types_1.ThreadTypes.RECEIVED_UNREAD_THREADS:
case action_types_1.ThreadTypes.RECEIVED_THREADS: {
const { threads } = action.data;
return {
...state,
...threads.reduce((results, thread) => {
results[thread.id] = thread;
return results;
}, {}),
};
}
case action_types_1.PostTypes.POST_DELETED:
case action_types_1.PostTypes.POST_REMOVED: {
const post = action.data;
if (post.root_id || !state[post.id]) {
return state;
}
const nextState = { ...state };
Reflect.deleteProperty(nextState, post.id);
return nextState;
}
case action_types_1.ThreadTypes.RECEIVED_THREAD: {
const { thread } = action.data;
return {
...state,
[thread.id]: thread,
};
}
case action_types_1.ThreadTypes.READ_CHANGED_THREAD: {
const { id, newUnreadMentions, newUnreadReplies, lastViewedAt, } = action.data;
return {
...state,
[id]: {
...(state[id] || {}),
last_viewed_at: lastViewedAt,
unread_mentions: newUnreadMentions,
unread_replies: newUnreadReplies,
is_following: true,
},
};
}
case action_types_1.ThreadTypes.FOLLOW_CHANGED_THREAD: {
const { id, following } = action.data;
if (!state[id]) {
return state;
}
return {
...state,
[id]: {
...state[id],
is_following: following,
},
};
}
case action_types_1.PostTypes.RECEIVED_NEW_POST: {
const post = action.data;
const thread = state[post.root_id];
if (post.root_id && thread) {
const participants = thread.participants || [];
const nextThread = { ...thread };
if (!participants.find((user) => user.id === post.user_id)) {
nextThread.participants = [...participants, { id: post.user_id }];
}
if (post.reply_count) {
nextThread.reply_count = post.reply_count;
}
return {
...state,
[post.root_id]: nextThread,
};
}
return state;
}
case action_types_1.ThreadTypes.ALL_TEAM_THREADS_READ: {
return Object.entries(state).reduce((newState, [id, thread]) => {
newState[id] = {
...thread,
unread_mentions: 0,
unread_replies: 0,
};
return newState;
}, {});
}
case action_types_1.UserTypes.LOGOUT_SUCCESS:
return {};
case action_types_1.ChannelTypes.RECEIVED_CHANNEL_DELETED:
case action_types_1.ChannelTypes.LEAVE_CHANNEL: {
if (!extra.threadsToDelete || extra.threadsToDelete.length === 0) {
return state;
}
let threadDeleted = false;
// Remove entries for any thread in the channel
const nextState = { ...state };
for (const thread of extra.threadsToDelete) {
Reflect.deleteProperty(nextState, thread.id);
threadDeleted = true;
}
if (!threadDeleted) {
// Nothing was actually removed
return state;
}
return nextState;
}
}
return state;
};
exports.threadsReducer = threadsReducer;
function getThreadsOfChannel(threads, channelId) {
const channelThreads = [];
for (const rootId of Object.keys(threads)) {
if (threads[rootId] &&
threads[rootId].post &&
threads[rootId].post.channel_id === channelId) {
channelThreads.push(threads[rootId]);
}
}
return channelThreads;
}
const initialState = {
threads: {},
threadsInTeam: {},
unreadThreadsInTeam: {},
counts: {},
countsIncludingDirect: {},
};
// custom combineReducers function
// enables passing data between reducers
function reducer(state = initialState, action) {
const extra = {
threads: state.threads,
};
// acting as a 'middleware'
if (action.type === action_types_1.ChannelTypes.LEAVE_CHANNEL) {
extra.threadsToDelete = getThreadsOfChannel(state.threads, action.data.id);
}
const nextState = {
// Object mapping thread ids to thread objects
threads: (0, exports.threadsReducer)(state.threads, action, extra),
// Object mapping teams ids to thread ids
threadsInTeam: (0, threadsInTeam_1.threadsInTeamReducer)(state.threadsInTeam, action, extra),
// Object mapping teams ids to unread thread ids
unreadThreadsInTeam: (0, threadsInTeam_1.unreadThreadsInTeamReducer)(state.unreadThreadsInTeam, action, extra),
// Object mapping teams ids to unread counts without DM/GM
counts: (0, counts_1.countsReducer)(state.counts, action, extra),
// Object mapping teams ids to unread counts including direct channels
countsIncludingDirect: (0, counts_1.countsIncludingDirectReducer)(state.countsIncludingDirect, action, extra),
};
if (state.threads === nextState.threads &&
state.threadsInTeam === nextState.threadsInTeam &&
state.unreadThreadsInTeam === nextState.unreadThreadsInTeam &&
state.counts === nextState.counts &&
state.countsIncludingDirect === nextState.countsIncludingDirect) {
// None of the children have changed so don't even let the parent object change
return state;
}
return nextState;
}
exports.default = reducer;