Files
mattermost-mobile/app/actions/websocket/channel.ts
Daniel Espino García 7c642b1e80 [Gekidou] Extract common observers to queries (#5984)
* Extract common observers to queries

* Separate also queries and more agressive refactoring

* Use query to avoid throws from findAndObserve

* Fix minor error

* Address feedback

* Address feedback

* Address feedback

* Fix model types

* Address feedback
2022-03-23 09:19:29 -03:00

194 lines
7.7 KiB
TypeScript

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {Model} from '@nozbe/watermelondb';
import {DeviceEventEmitter} from 'react-native';
import {removeCurrentUserFromChannel, setChannelDeleteAt, switchToChannel} from '@actions/local/channel';
import {fetchMyChannel} from '@actions/remote/channel';
import {fetchPostsForChannel} from '@actions/remote/post';
import {fetchUsersByIds, updateUsersNoLongerVisible} from '@actions/remote/user';
import Events from '@constants/events';
import DatabaseManager from '@database/manager';
import {queryActiveServer} from '@queries/app/servers';
import {deleteChannelMembership, getChannelById, prepareMyChannelsForTeam, getCurrentChannel} from '@queries/servers/channel';
import {prepareCommonSystemValues, getConfig, setCurrentChannelId} from '@queries/servers/system';
import {getNthLastChannelFromTeam} from '@queries/servers/team';
import {getCurrentUser, getUserById} from '@queries/servers/user';
import {dismissAllModals, popToRoot} from '@screens/navigation';
import {isTablet} from '@utils/helpers';
export async function handleUserAddedToChannelEvent(serverUrl: string, msg: any) {
const database = DatabaseManager.serverDatabases[serverUrl];
if (!database) {
return;
}
const currentUser = await getCurrentUser(database.database);
const {team_id: teamId, user_id: userId} = msg.data;
const {channel_id: channelId} = msg.broadcast;
const models: Model[] = [];
try {
const addedUser = getUserById(database.database, userId);
if (!addedUser) {
// TODO Potential improvement https://mattermost.atlassian.net/browse/MM-40581
const {users} = await fetchUsersByIds(serverUrl, [userId], true);
if (users) {
models.push(...await database.operator.handleUsers({users, prepareRecordsOnly: true}));
}
}
if (userId === currentUser?.id) {
const {channels, memberships} = await fetchMyChannel(serverUrl, teamId, channelId, true);
if (channels && memberships) {
const prepare = await prepareMyChannelsForTeam(database.operator, teamId, channels, memberships);
if (prepare) {
const prepareModels = await Promise.all(prepare);
const flattenedModels = prepareModels.flat();
if (flattenedModels?.length > 0) {
models.push(...flattenedModels);
}
}
}
const {posts, order, authors, actionType, previousPostId} = await fetchPostsForChannel(serverUrl, channelId, true);
if (posts?.length && order && actionType) {
models.push(...await database.operator.handlePosts({
actionType,
order,
posts,
previousPostId,
prepareRecordsOnly: true,
}));
}
if (authors?.length) {
models.push(...await database.operator.handleUsers({users: authors, prepareRecordsOnly: true}));
}
} else {
const channel = await getChannelById(database.database, channelId);
if (channel) {
models.push(...await database.operator.handleChannelMembership({
channelMemberships: [{channel_id: channelId, user_id: userId}],
prepareRecordsOnly: true,
}));
}
}
} catch {
// Do nothing
}
database.operator.batchRecords(models);
}
export async function handleUserRemovedFromChannelEvent(serverUrl: string, msg: any) {
const database = DatabaseManager.serverDatabases[serverUrl];
if (!database) {
return;
}
const channel = await getCurrentChannel(database.database);
const user = await getCurrentUser(database.database);
if (!user) {
return;
}
// Depending on who was removed, the ids may come from one place dataset or the other.
const userId = msg.data.user_id || msg.broadcast.user_id;
const channelId = msg.data.channel_id || msg.broadcast.channel_id;
const models: Model[] = [];
if (user.isGuest) {
const {models: updateVisibleModels} = await updateUsersNoLongerVisible(serverUrl, true);
if (updateVisibleModels) {
models.push(...updateVisibleModels);
}
}
if (user.id === userId) {
const {models: removeUserModels} = await removeCurrentUserFromChannel(serverUrl, channelId, true);
if (removeUserModels) {
models.push(...removeUserModels);
}
if (channel && channel.id === channelId) {
const currentServer = await queryActiveServer(DatabaseManager.appDatabase!.database);
if (currentServer?.url === serverUrl) {
DeviceEventEmitter.emit(Events.LEAVE_CHANNEL);
await dismissAllModals();
await popToRoot();
if (await isTablet()) {
const channelToJumpTo = await getNthLastChannelFromTeam(database.database, channel?.teamId);
if (channelToJumpTo) {
const {models: switchChannelModels} = await switchToChannel(serverUrl, channelToJumpTo, '', true);
if (switchChannelModels) {
models.push(...switchChannelModels);
}
} // TODO else jump to "join a channel" screen https://mattermost.atlassian.net/browse/MM-41051
} else {
const currentChannelModels = await prepareCommonSystemValues(database.operator, {currentChannelId: ''});
if (currentChannelModels?.length) {
models.push(...currentChannelModels);
}
}
}
}
} else {
const {models: deleteMemberModels} = await deleteChannelMembership(database.operator, userId, channelId, true);
if (deleteMemberModels) {
models.push(...deleteMemberModels);
}
}
database.operator.batchRecords(models);
}
export async function handleChannelDeletedEvent(serverUrl: string, msg: WebSocketMessage) {
const database = DatabaseManager.serverDatabases[serverUrl];
if (!database) {
return;
}
const currentChannel = await getCurrentChannel(database.database);
const user = await getCurrentUser(database.database);
if (!user) {
return;
}
const {channel_id: channelId, delete_at: deleteAt} = msg.data;
const config = await getConfig(database.database);
await setChannelDeleteAt(serverUrl, channelId, deleteAt);
if (user.isGuest) {
updateUsersNoLongerVisible(serverUrl);
}
if (config?.ExperimentalViewArchivedChannels !== 'true') {
removeCurrentUserFromChannel(serverUrl, channelId);
if (currentChannel && currentChannel.id === channelId) {
const currentServer = await queryActiveServer(DatabaseManager.appDatabase!.database);
if (currentServer?.url === serverUrl) {
DeviceEventEmitter.emit(Events.CHANNEL_DELETED);
await dismissAllModals();
await popToRoot();
if (await isTablet()) {
const channelToJumpTo = await getNthLastChannelFromTeam(database.database, currentChannel?.teamId);
if (channelToJumpTo) {
switchToChannel(serverUrl, channelToJumpTo);
} // TODO else jump to "join a channel" screen
} else {
setCurrentChannelId(database.operator, '');
}
}
}
}
}