From 26b3fbf87f94132409c4471923e47dafdcb6e54e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Espino=20Garc=C3=ADa?= Date: Sat, 9 Apr 2022 05:10:08 +0200 Subject: [PATCH] Fix add DM screen and some other database related issues (#6144) * Fix add DM screen and some other database related issues * Minor style fixes * Handle create DM/GM websocket by using the teammate ids * Address feedback --- app/actions/local/category.ts | 4 +- app/actions/local/channel.ts | 44 ++--- app/actions/local/draft.ts | 16 +- app/actions/local/post.ts | 8 +- app/actions/local/team.ts | 4 +- app/actions/local/thread.ts | 16 +- app/actions/local/user.ts | 8 +- app/actions/remote/channel.ts | 163 +++++++----------- app/actions/remote/command.ts | 16 +- app/actions/remote/entry/app.ts | 8 +- app/actions/remote/entry/common.ts | 6 +- app/actions/remote/entry/login.ts | 4 +- app/actions/remote/entry/notification.ts | 4 +- app/actions/remote/post.ts | 28 +-- app/actions/remote/reactions.ts | 4 +- app/actions/remote/retry.ts | 8 +- app/actions/remote/team.ts | 21 ++- app/actions/remote/user.ts | 20 +-- app/actions/websocket/channel.ts | 43 ++++- app/actions/websocket/index.ts | 1 + app/constants/websocket.ts | 1 + .../operator/base_data_operator/index.ts | 8 +- .../server_data_operator/handlers/channel.ts | 2 +- .../server_data_operator/handlers/index.ts | 4 +- app/queries/servers/channel.ts | 6 +- app/queries/servers/entry.ts | 4 +- app/queries/servers/preference.ts | 4 +- app/queries/servers/system.ts | 17 +- app/queries/servers/team.ts | 12 +- app/queries/servers/user.ts | 9 +- .../create_direct_message.tsx | 20 +-- app/store/ephemeral_store.ts | 2 + 32 files changed, 262 insertions(+), 253 deletions(-) diff --git a/app/actions/local/category.ts b/app/actions/local/category.ts index 3fcc1ac348..9cc204abb8 100644 --- a/app/actions/local/category.ts +++ b/app/actions/local/category.ts @@ -30,7 +30,7 @@ export const deleteCategory = async (serverUrl: string, categoryId: string) => { } }; -export const storeCategories = async (serverUrl: string, categories: CategoryWithChannels[], prune = false, prepareRecordsOnly = false) => { +export async function storeCategories(serverUrl: string, categories: CategoryWithChannels[], prune = false, prepareRecordsOnly = false) { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { @@ -83,7 +83,7 @@ export const storeCategories = async (serverUrl: string, categories: CategoryWit } return {models: flattenedModels}; -}; +} export const toggleCollapseCategory = async (serverUrl: string, categoryId: string) => { const database = DatabaseManager.serverDatabases[serverUrl].database; diff --git a/app/actions/local/channel.ts b/app/actions/local/channel.ts index 3bbb3bf125..3626f5f485 100644 --- a/app/actions/local/channel.ts +++ b/app/actions/local/channel.ts @@ -25,7 +25,7 @@ import {displayGroupMessageName, displayUsername, getUserIdFromChannelName} from import type ChannelModel from '@typings/database/models/servers/channel'; import type UserModel from '@typings/database/models/servers/user'; -export const switchToChannel = async (serverUrl: string, channelId: string, teamId?: string, prepareRecordsOnly = false) => { +export async function switchToChannel(serverUrl: string, channelId: string, teamId?: string, prepareRecordsOnly = false) { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { return {error: `${serverUrl} database not found`}; @@ -113,9 +113,9 @@ export const switchToChannel = async (serverUrl: string, channelId: string, team } return {models}; -}; +} -export const removeCurrentUserFromChannel = async (serverUrl: string, channelId: string, prepareRecordsOnly = false) => { +export async function removeCurrentUserFromChannel(serverUrl: string, channelId: string, prepareRecordsOnly = false) { const serverDatabase = DatabaseManager.serverDatabases[serverUrl]; if (!serverDatabase) { return {error: `${serverUrl} database not found`}; @@ -146,9 +146,9 @@ export const removeCurrentUserFromChannel = async (serverUrl: string, channelId: } } return {models}; -}; +} -export const setChannelDeleteAt = async (serverUrl: string, channelId: string, deleteAt: number) => { +export async function setChannelDeleteAt(serverUrl: string, channelId: string, deleteAt: number) { const serverDatabase = DatabaseManager.serverDatabases[serverUrl]; if (!serverDatabase) { return; @@ -171,18 +171,18 @@ export const setChannelDeleteAt = async (serverUrl: string, channelId: string, d // eslint-disable-next-line no-console console.log('FAILED TO BATCH CHANGES FOR CHANNEL DELETE AT'); } -}; +} -export const selectAllMyChannelIds = async (serverUrl: string) => { +export async function selectAllMyChannelIds(serverUrl: string) { const database = DatabaseManager.serverDatabases[serverUrl]?.database; if (!database) { return []; } return queryAllMyChannel(database).fetchIds(); -}; +} -export const markChannelAsViewed = async (serverUrl: string, channelId: string, prepareRecordsOnly = false) => { +export async function markChannelAsViewed(serverUrl: string, channelId: string, prepareRecordsOnly = false) { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { return {error: `${serverUrl} database not found`}; @@ -210,9 +210,9 @@ export const markChannelAsViewed = async (serverUrl: string, channelId: string, } catch (error) { return {error}; } -}; +} -export const markChannelAsUnread = async (serverUrl: string, channelId: string, messageCount: number, mentionsCount: number, lastViewed: number, prepareRecordsOnly = false) => { +export async function markChannelAsUnread(serverUrl: string, channelId: string, messageCount: number, mentionsCount: number, lastViewed: number, prepareRecordsOnly = false) { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { return {error: `${serverUrl} database not found`}; @@ -241,9 +241,9 @@ export const markChannelAsUnread = async (serverUrl: string, channelId: string, } catch (error) { return {error}; } -}; +} -export const resetMessageCount = async (serverUrl: string, channelId: string) => { +export async function resetMessageCount(serverUrl: string, channelId: string) { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { return {error: `${serverUrl} database not found`}; @@ -264,9 +264,9 @@ export const resetMessageCount = async (serverUrl: string, channelId: string) => } catch (error) { return {error}; } -}; +} -export const storeMyChannelsForTeam = async (serverUrl: string, teamId: string, channels: Channel[], memberships: ChannelMembership[], prepareRecordsOnly = false) => { +export async function storeMyChannelsForTeam(serverUrl: string, teamId: string, channels: Channel[], memberships: ChannelMembership[], prepareRecordsOnly = false) { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { return {error: `${serverUrl} database not found`}; @@ -297,9 +297,9 @@ export const storeMyChannelsForTeam = async (serverUrl: string, teamId: string, } return {models: flattenedModels}; -}; +} -export const updateMyChannelFromWebsocket = async (serverUrl: string, channelMember: ChannelMembership, prepareRecordsOnly = false) => { +export async function updateMyChannelFromWebsocket(serverUrl: string, channelMember: ChannelMembership, prepareRecordsOnly = false) { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { return {error: `${serverUrl} database not found`}; @@ -315,9 +315,9 @@ export const updateMyChannelFromWebsocket = async (serverUrl: string, channelMem } } return {model: member}; -}; +} -export const updateChannelInfoFromChannel = async (serverUrl: string, channel: Channel, prepareRecordsOnly = false) => { +export async function updateChannelInfoFromChannel(serverUrl: string, channel: Channel, prepareRecordsOnly = false) { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { return {error: `${serverUrl} database not found`}; @@ -333,9 +333,9 @@ export const updateChannelInfoFromChannel = async (serverUrl: string, channel: C operator.batchRecords(newInfo); } return {model: newInfo}; -}; +} -export const updateLastPostAt = async (serverUrl: string, channelId: string, lastPostAt: number, prepareRecordsOnly = false) => { +export async function updateLastPostAt(serverUrl: string, channelId: string, lastPostAt: number, prepareRecordsOnly = false) { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { return {error: `${serverUrl} database not found`}; @@ -361,7 +361,7 @@ export const updateLastPostAt = async (serverUrl: string, channelId: string, las } return {member: undefined}; -}; +} export async function updateChannelsDisplayName(serverUrl: string, channels: ChannelModel[], users: UserProfile[], prepareRecordsOnly = false) { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; diff --git a/app/actions/local/draft.ts b/app/actions/local/draft.ts index b02d33f046..b21a026d2b 100644 --- a/app/actions/local/draft.ts +++ b/app/actions/local/draft.ts @@ -4,7 +4,7 @@ import DatabaseManager from '@database/manager'; import {getDraft} from '@queries/servers/drafts'; -export const updateDraftFile = async (serverUrl: string, channelId: string, rootId: string, file: FileInfo, prepareRecordsOnly = false) => { +export async function updateDraftFile(serverUrl: string, channelId: string, rootId: string, file: FileInfo, prepareRecordsOnly = false) { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { return {error: `${serverUrl} database not found`}; @@ -36,9 +36,9 @@ export const updateDraftFile = async (serverUrl: string, channelId: string, root } catch (error) { return {error}; } -}; +} -export const removeDraftFile = async (serverUrl: string, channelId: string, rootId: string, clientId: string, prepareRecordsOnly = false) => { +export async function removeDraftFile(serverUrl: string, channelId: string, rootId: string, clientId: string, prepareRecordsOnly = false) { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { return {error: `${serverUrl} database not found`}; @@ -71,9 +71,9 @@ export const removeDraftFile = async (serverUrl: string, channelId: string, root } catch (error) { return {error}; } -}; +} -export const updateDraftMessage = async (serverUrl: string, channelId: string, rootId: string, message: string, prepareRecordsOnly = false) => { +export async function updateDraftMessage(serverUrl: string, channelId: string, rootId: string, message: string, prepareRecordsOnly = false) { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { return {error: `${serverUrl} database not found`}; @@ -115,9 +115,9 @@ export const updateDraftMessage = async (serverUrl: string, channelId: string, r } catch (error) { return {error}; } -}; +} -export const addFilesToDraft = async (serverUrl: string, channelId: string, rootId: string, files: FileInfo[], prepareRecordsOnly = false) => { +export async function addFilesToDraft(serverUrl: string, channelId: string, rootId: string, files: FileInfo[], prepareRecordsOnly = false) { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { return {error: `${serverUrl} database not found`}; @@ -148,7 +148,7 @@ export const addFilesToDraft = async (serverUrl: string, channelId: string, root } catch (error) { return {error}; } -}; +} export const removeDraft = async (serverUrl: string, channelId: string, rootId = '') => { const database = DatabaseManager.serverDatabases[serverUrl]?.database; diff --git a/app/actions/local/post.ts b/app/actions/local/post.ts index 827c82f0d6..644c922566 100644 --- a/app/actions/local/post.ts +++ b/app/actions/local/post.ts @@ -99,7 +99,7 @@ export const sendEphemeralPost = async (serverUrl: string, message: string, chan return {post}; }; -export const removePost = async (serverUrl: string, post: PostModel | Post) => { +export async function removePost(serverUrl: string, post: PostModel | Post) { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { return {error: `${serverUrl} database not found`}; @@ -130,9 +130,9 @@ export const removePost = async (serverUrl: string, post: PostModel | Post) => { } return {post}; -}; +} -export const markPostAsDeleted = async (serverUrl: string, post: Post, prepareRecordsOnly = false) => { +export async function markPostAsDeleted(serverUrl: string, post: Post, prepareRecordsOnly = false) { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { return {error: `${serverUrl} database not found`}; @@ -154,4 +154,4 @@ export const markPostAsDeleted = async (serverUrl: string, post: Post, prepareRe operator.batchRecords([dbPost]); } return {model}; -}; +} diff --git a/app/actions/local/team.ts b/app/actions/local/team.ts index 7e711e4f06..2c04c9583f 100644 --- a/app/actions/local/team.ts +++ b/app/actions/local/team.ts @@ -6,7 +6,7 @@ import {prepareDeleteTeam, getMyTeamById, removeTeamFromTeamHistory} from '@quer import type TeamModel from '@typings/database/models/servers/team'; -export const removeUserFromTeam = async (serverUrl: string, teamId: string) => { +export async function removeUserFromTeam(serverUrl: string, teamId: string) { const serverDatabase = DatabaseManager.serverDatabases[serverUrl]; if (!serverDatabase) { return; @@ -31,4 +31,4 @@ export const removeUserFromTeam = async (serverUrl: string, teamId: string) => { } } } -}; +} diff --git a/app/actions/local/thread.ts b/app/actions/local/thread.ts index d75d4d15d0..5df8990548 100644 --- a/app/actions/local/thread.ts +++ b/app/actions/local/thread.ts @@ -96,7 +96,7 @@ export const switchToThread = async (serverUrl: string, rootId: string) => { // When new post arrives: // 1. If a reply, then update the reply_count, add user as the participant // 2. Else add the post as a thread -export const createThreadFromNewPost = async (serverUrl: string, post: Post, prepareRecordsOnly = false) => { +export async function createThreadFromNewPost(serverUrl: string, post: Post, prepareRecordsOnly = false) { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { return {error: `${serverUrl} database not found`}; @@ -133,10 +133,10 @@ export const createThreadFromNewPost = async (serverUrl: string, post: Post, pre } return {models}; -}; +} // On receiving threads, Along with the "threads" & "thread participants", extract and save "posts" & "users" -export const processReceivedThreads = async (serverUrl: string, threads: Thread[], teamId: string, prepareRecordsOnly = false, loadedInGlobalThreads = false) => { +export async function processReceivedThreads(serverUrl: string, threads: Thread[], teamId: string, prepareRecordsOnly = false, loadedInGlobalThreads = false) { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { return {error: `${serverUrl} database not found`}; @@ -177,9 +177,9 @@ export const processReceivedThreads = async (serverUrl: string, threads: Thread[ await operator.batchRecords(models); } return {models}; -}; +} -export const markTeamThreadsAsRead = async (serverUrl: string, teamId: string, prepareRecordsOnly = false) => { +export async function markTeamThreadsAsRead(serverUrl: string, teamId: string, prepareRecordsOnly = false) { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { return {error: `${serverUrl} database not found`}; @@ -199,9 +199,9 @@ export const markTeamThreadsAsRead = async (serverUrl: string, teamId: string, p } catch (error) { return {error}; } -}; +} -export const updateThread = async (serverUrl: string, threadId: string, updatedThread: Partial, prepareRecordsOnly = false) => { +export async function updateThread(serverUrl: string, threadId: string, updatedThread: Partial, prepareRecordsOnly = false) { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { return {error: `${serverUrl} database not found`}; @@ -228,4 +228,4 @@ export const updateThread = async (serverUrl: string, threadId: string, updatedT } catch (error) { return {error}; } -}; +} diff --git a/app/actions/local/user.ts b/app/actions/local/user.ts index 8746f72706..331cac00e6 100644 --- a/app/actions/local/user.ts +++ b/app/actions/local/user.ts @@ -12,7 +12,7 @@ import {addRecentReaction} from './reactions'; import type Model from '@nozbe/watermelondb/Model'; import type UserModel from '@typings/database/models/servers/user'; -export const setCurrentUserStatusOffline = async (serverUrl: string) => { +export async function setCurrentUserStatusOffline(serverUrl: string) { const serverDatabase = DatabaseManager.serverDatabases[serverUrl]; if (!serverDatabase) { return {error: `No database present for ${serverUrl}`}; @@ -35,9 +35,9 @@ export const setCurrentUserStatusOffline = async (serverUrl: string) => { } return null; -}; +} -export const updateLocalCustomStatus = async (serverUrl: string, user: UserModel, customStatus?: UserCustomStatus) => { +export async function updateLocalCustomStatus(serverUrl: string, user: UserModel, customStatus?: UserCustomStatus) { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { return {error: `${serverUrl} database not found`}; @@ -72,7 +72,7 @@ export const updateLocalCustomStatus = async (serverUrl: string, user: UserModel } return {}; -}; +} export const updateRecentCustomStatuses = async (serverUrl: string, customStatus: UserCustomStatus, prepareRecordsOnly = false, remove = false) => { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; diff --git a/app/actions/remote/channel.ts b/app/actions/remote/channel.ts index aeef35e441..5966ca80cd 100644 --- a/app/actions/remote/channel.ts +++ b/app/actions/remote/channel.ts @@ -7,6 +7,7 @@ import {IntlShape} from 'react-intl'; import {storeCategories} from '@actions/local/category'; import {addChannelToDefaultCategory, storeMyChannelsForTeam, switchToChannel} from '@actions/local/channel'; +import EphemeralStore from '@app/store/ephemeral_store'; import {General, Preferences} from '@constants'; import DatabaseManager from '@database/manager'; import {privateChannelJoinPrompt} from '@helpers/api/channel'; @@ -40,7 +41,7 @@ export type MyChannelsRequest = { error?: unknown; } -export const addMembersToChannel = async (serverUrl: string, channelId: string, userIds: string[], postRootId = '', fetchOnly = false) => { +export async function addMembersToChannel(serverUrl: string, channelId: string, userIds: string[], postRootId = '', fetchOnly = false) { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { return {error: `${serverUrl} database not found`}; @@ -77,9 +78,9 @@ export const addMembersToChannel = async (serverUrl: string, channelId: string, forceLogoutIfNecessary(serverUrl, error as ClientErrorProps); return {error}; } -}; +} -export const fetchChannelByName = async (serverUrl: string, teamId: string, channelName: string, fetchOnly = false) => { +export async function fetchChannelByName(serverUrl: string, teamId: string, channelName: string, fetchOnly = false) { let client: Client; try { client = NetworkManager.getClient(serverUrl); @@ -102,9 +103,9 @@ export const fetchChannelByName = async (serverUrl: string, teamId: string, chan forceLogoutIfNecessary(serverUrl, error as ClientErrorProps); return {error}; } -}; +} -export const createChannel = async (serverUrl: string, displayName: string, purpose: string, header: string, type: ChannelType) => { +export async function createChannel(serverUrl: string, displayName: string, purpose: string, header: string, type: ChannelType) { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { return {error: `${serverUrl} database not found`}; @@ -131,6 +132,7 @@ export const createChannel = async (serverUrl: string, displayName: string, purp type, } as Channel; + EphemeralStore.creatingChannel = true; const channelData = await client.createChannel(channel); const member = await client.getChannelMember(channelData.id, currentUserId); @@ -149,13 +151,15 @@ export const createChannel = async (serverUrl: string, displayName: string, purp await operator.batchRecords(models); } fetchChannelStats(serverUrl, channelData.id, false); + EphemeralStore.creatingChannel = false; return {channel: channelData}; } catch (error) { + EphemeralStore.creatingChannel = false; return {error}; } -}; +} -export const patchChannel = async (serverUrl: string, channelPatch: Partial & {id: string}) => { +export async function patchChannel(serverUrl: string, channelPatch: Partial & {id: string}) { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { return {error: `${serverUrl} database not found`}; @@ -194,9 +198,9 @@ export const patchChannel = async (serverUrl: string, channelPatch: Partial { +export async function fetchChannelCreator(serverUrl: string, channelId: string, fetchOnly = false) { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { return {error: `${serverUrl} database not found`}; @@ -241,9 +245,9 @@ export const fetchChannelCreator = async (serverUrl: string, channelId: string, forceLogoutIfNecessary(serverUrl, error as ClientErrorProps); return {error}; } -}; +} -export const fetchChannelStats = async (serverUrl: string, channelId: string, fetchOnly = false) => { +export async function fetchChannelStats(serverUrl: string, channelId: string, fetchOnly = false) { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { return {error: `${serverUrl} database not found`}; @@ -276,9 +280,9 @@ export const fetchChannelStats = async (serverUrl: string, channelId: string, fe forceLogoutIfNecessary(serverUrl, error as ClientErrorProps); return {error}; } -}; +} -export const fetchMyChannelsForTeam = async (serverUrl: string, teamId: string, includeDeleted = true, since = 0, fetchOnly = false, excludeDirect = false): Promise => { +export async function fetchMyChannelsForTeam(serverUrl: string, teamId: string, includeDeleted = true, since = 0, fetchOnly = false, excludeDirect = false): Promise { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { return {error: `${serverUrl} database not found`}; @@ -327,9 +331,9 @@ export const fetchMyChannelsForTeam = async (serverUrl: string, teamId: string, forceLogoutIfNecessary(serverUrl, error as ClientErrorProps); return {error}; } -}; +} -export const fetchMyChannel = async (serverUrl: string, teamId: string, channelId: string, fetchOnly = false): Promise => { +export async function fetchMyChannel(serverUrl: string, teamId: string, channelId: string, fetchOnly = false): Promise { const database = DatabaseManager.serverDatabases[serverUrl]?.database; if (!database) { return {error: `${serverUrl} database not found`}; @@ -360,9 +364,9 @@ export const fetchMyChannel = async (serverUrl: string, teamId: string, channelI forceLogoutIfNecessary(serverUrl, error as ClientErrorProps); return {error}; } -}; +} -export const fetchMissingSidebarInfo = async (serverUrl: string, directChannels: Channel[], locale?: string, teammateDisplayNameSetting?: string, currentUserId?: string, fetchOnly = false) => { +export async function fetchMissingSidebarInfo(serverUrl: string, directChannels: Channel[], locale?: string, teammateDisplayNameSetting?: string, currentUserId?: string, fetchOnly = false) { const channelIds = directChannels.sort((a, b) => b.last_post_at - a.last_post_at).map((dc) => dc.id); const result = await fetchProfilesPerChannels(serverUrl, channelIds, currentUserId, false); if (result.error) { @@ -416,9 +420,9 @@ export const fetchMissingSidebarInfo = async (serverUrl: string, directChannels: } return {directChannels, users}; -}; +} -export const joinChannel = async (serverUrl: string, userId: string, teamId: string, channelId?: string, channelName?: string, fetchOnly = false) => { +export async function joinChannel(serverUrl: string, userId: string, teamId: string, channelId?: string, channelName?: string, fetchOnly = false) { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { return {error: `${serverUrl} database not found`}; @@ -477,9 +481,9 @@ export const joinChannel = async (serverUrl: string, userId: string, teamId: str } return {channel, member}; -}; +} -export const markChannelAsRead = async (serverUrl: string, channelId: string) => { +export async function markChannelAsRead(serverUrl: string, channelId: string) { try { const client = NetworkManager.getClient(serverUrl); await client.viewMyChannel(channelId); @@ -488,9 +492,9 @@ export const markChannelAsRead = async (serverUrl: string, channelId: string) => } catch (error) { return {error}; } -}; +} -export const switchToChannelByName = async (serverUrl: string, channelName: string, teamName: string, errorHandler: (intl: IntlShape) => void, intl: IntlShape) => { +export async function switchToChannelByName(serverUrl: string, channelName: string, teamName: string, errorHandler: (intl: IntlShape) => void, intl: IntlShape) { const database = DatabaseManager.serverDatabases[serverUrl]?.database; if (!database) { return {error: `${serverUrl} database not found`}; @@ -642,9 +646,9 @@ export const switchToChannelByName = async (serverUrl: string, channelName: stri errorHandler(intl); return {error}; } -}; +} -export const createDirectChannel = async (serverUrl: string, userId: string, displayName = '') => { +export async function createDirectChannel(serverUrl: string, userId: string, displayName = '') { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { return {error: `${serverUrl} database not found`}; @@ -663,6 +667,7 @@ export const createDirectChannel = async (serverUrl: string, userId: string, dis if (!currentUser) { return {error: 'Cannot get the current user'}; } + EphemeralStore.creatingDMorGMTeammates = [userId]; const created = await client.createDirectChannel([userId, currentUser.id]); const profiles: UserProfile[] = []; @@ -712,14 +717,17 @@ export const createDirectChannel = async (serverUrl: string, userId: string, dis } await operator.batchRecords(models); + EphemeralStore.creatingDMorGMTeammates = []; fetchRolesIfNeeded(serverUrl, member.roles.split(' ')); return {data: created}; } catch (error) { + EphemeralStore.creatingDMorGMTeammates = []; forceLogoutIfNecessary(serverUrl, error as ClientErrorProps); return {error}; } -}; -export const fetchChannels = async (serverUrl: string, teamId: string, page = 0, perPage: number = General.CHANNELS_CHUNK_SIZE) => { +} + +export async function fetchChannels(serverUrl: string, teamId: string, page = 0, perPage: number = General.CHANNELS_CHUNK_SIZE) { let client: Client; try { client = NetworkManager.getClient(serverUrl); @@ -735,9 +743,9 @@ export const fetchChannels = async (serverUrl: string, teamId: string, page = 0, forceLogoutIfNecessary(serverUrl, error as ClientErrorProps); return {error}; } -}; +} -export const makeDirectChannel = async (serverUrl: string, userId: string, displayName = '', shouldSwitchToChannel = true) => { +export async function makeDirectChannel(serverUrl: string, userId: string, displayName = '', shouldSwitchToChannel = true) { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { return {error: `${serverUrl} database not found`}; @@ -763,8 +771,8 @@ export const makeDirectChannel = async (serverUrl: string, userId: string, displ } catch (error) { return {error}; } -}; -export const fetchArchivedChannels = async (serverUrl: string, teamId: string, page = 0, perPage: number = General.CHANNELS_CHUNK_SIZE) => { +} +export async function fetchArchivedChannels(serverUrl: string, teamId: string, page = 0, perPage: number = General.CHANNELS_CHUNK_SIZE) { let client: Client; try { client = NetworkManager.getClient(serverUrl); @@ -780,9 +788,9 @@ export const fetchArchivedChannels = async (serverUrl: string, teamId: string, p forceLogoutIfNecessary(serverUrl, error as ClientErrorProps); return {error}; } -}; +} -export const createGroupChannel = async (serverUrl: string, userIds: string[]) => { +export async function createGroupChannel(serverUrl: string, userIds: string[]) { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { return {error: `${serverUrl} database not found`}; @@ -799,11 +807,13 @@ export const createGroupChannel = async (serverUrl: string, userIds: string[]) = if (!currentUser) { return {error: 'Cannot get the current user'}; } + EphemeralStore.creatingDMorGMTeammates = userIds; const created = await client.createGroupChannel(userIds); // Check the channel previous existency: if the channel already have // posts is because it existed before. if (created.total_msg_count > 0) { + EphemeralStore.creatingChannel = false; return {data: created}; } @@ -844,14 +854,16 @@ export const createGroupChannel = async (serverUrl: string, userIds: string[]) = operator.batchRecords(models); } } + EphemeralStore.creatingDMorGMTeammates = []; fetchRolesIfNeeded(serverUrl, member.roles.split(' ')); return {data: created}; } catch (error) { + EphemeralStore.creatingDMorGMTeammates = []; forceLogoutIfNecessary(serverUrl, error as ClientErrorProps); return {error}; } -}; -export const fetchSharedChannels = async (serverUrl: string, teamId: string, page = 0, perPage: number = General.CHANNELS_CHUNK_SIZE) => { +} +export async function fetchSharedChannels(serverUrl: string, teamId: string, page = 0, perPage: number = General.CHANNELS_CHUNK_SIZE) { let client: Client; try { client = NetworkManager.getClient(serverUrl); @@ -866,9 +878,9 @@ export const fetchSharedChannels = async (serverUrl: string, teamId: string, pag forceLogoutIfNecessary(serverUrl, error as ClientErrorProps); return {error}; } -}; +} -export const makeGroupChannel = async (serverUrl: string, userIds: string[], shouldSwitchToChannel = true) => { +export async function makeGroupChannel(serverUrl: string, userIds: string[], shouldSwitchToChannel = true) { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { return {error: `${serverUrl} database not found`}; @@ -887,7 +899,7 @@ export const makeGroupChannel = async (serverUrl: string, userIds: string[], sho } catch (error) { return {error}; } -}; +} export async function getChannelMemberCountsByGroup(serverUrl: string, channelId: string, includeTimezones: boolean) { let client: Client; try { @@ -920,66 +932,7 @@ export async function getChannelTimezones(serverUrl: string, channelId: string) } } -export async function getOrCreateDirectChannel(serverUrl: string, otherUserId: string, shouldSwitchToChannel = true) { - const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; - if (!operator) { - return {error: `${serverUrl} database not found`}; - } - - let client: Client; - try { - client = NetworkManager.getClient(serverUrl); - } catch (error) { - return {error}; - } - - const currentUserId = await getCurrentUserId(operator.database); - const channelName = getDirectChannelName(currentUserId, otherUserId); - - const channel = await getChannelByName(operator.database, channelName); - let result; - if (channel) { - result = {channel}; - } else { - try { - const newChannel = await client.createDirectChannel([currentUserId, otherUserId]); - result = {channel: newChannel}; - - const member = await client.getMyChannelMember(newChannel.id); - - const modelPromises: Array> = [...await prepareMyChannelsForTeam(operator, '', [newChannel], [member])]; - if (modelPromises.length) { - const channelModels = await Promise.all(modelPromises); - const models: Model[] = channelModels.flat(); - const categoryModels = await addChannelToDefaultCategory(serverUrl, newChannel, true); - if (categoryModels.models?.length) { - models.push(...categoryModels.models); - } - if (models.length) { - operator.batchRecords(models); - } - if (models.length > 0) { - try { - await operator.batchRecords(models); - } catch { - // eslint-disable-next-line no-console - console.log('FAILED TO BATCH CHANNELS'); - } - } - } - } catch (error) { - return {error}; - } - } - - if (shouldSwitchToChannel) { - switchToChannelById(serverUrl, result.channel.id); - } - - return result; -} - -export const switchToChannelById = async (serverUrl: string, channelId: string, teamId?: string) => { +export async function switchToChannelById(serverUrl: string, channelId: string, teamId?: string) { const database = DatabaseManager.serverDatabases[serverUrl]?.database; if (!database) { return {error: `${serverUrl} database not found`}; @@ -991,9 +944,9 @@ export const switchToChannelById = async (serverUrl: string, channelId: string, fetchChannelStats(serverUrl, channelId); return {}; -}; +} -export const switchToPenultimateChannel = async (serverUrl: string) => { +export async function switchToPenultimateChannel(serverUrl: string) { const database = DatabaseManager.serverDatabases[serverUrl]?.database; if (!database) { return {error: `${serverUrl} database not found`}; @@ -1006,9 +959,9 @@ export const switchToPenultimateChannel = async (serverUrl: string) => { } catch (error) { return {error}; } -}; +} -export const searchChannels = async (serverUrl: string, term: string) => { +export async function searchChannels(serverUrl: string, term: string) { const database = DatabaseManager.serverDatabases[serverUrl]?.database; if (!database) { return {error: `${serverUrl} database not found`}; @@ -1028,9 +981,9 @@ export const searchChannels = async (serverUrl: string, term: string) => { } catch (error) { return {error}; } -}; +} -export const fetchChannelById = async (serverUrl: string, id: string) => { +export async function fetchChannelById(serverUrl: string, id: string) { let client: Client; try { client = NetworkManager.getClient(serverUrl); @@ -1044,4 +997,4 @@ export const fetchChannelById = async (serverUrl: string, id: string) => { } catch (error) { return {error}; } -}; +} diff --git a/app/actions/remote/command.ts b/app/actions/remote/command.ts index f7dc1abfb7..5019d5ee5e 100644 --- a/app/actions/remote/command.ts +++ b/app/actions/remote/command.ts @@ -12,12 +12,13 @@ import DatabaseManager from '@database/manager'; import NetworkManager from '@init/network_manager'; import {getChannelById} from '@queries/servers/channel'; import {getConfig, getCurrentTeamId} from '@queries/servers/system'; -import {queryUsersByUsername} from '@queries/servers/user'; +import {getTeammateNameDisplay, queryUsersByUsername} from '@queries/servers/user'; import {showModal} from '@screens/navigation'; import * as DraftUtils from '@utils/draft'; import {matchDeepLink, tryOpenURL} from '@utils/url'; +import {displayUsername} from '@utils/user'; -import {getOrCreateDirectChannel, switchToChannelById, switchToChannelByName} from './channel'; +import {makeDirectChannel, switchToChannelById, switchToChannelByName} from './channel'; import type {DeepLinkChannel, DeepLinkPermalink, DeepLinkDM, DeepLinkGM, DeepLinkPlugin} from '@typings/launch'; @@ -128,8 +129,9 @@ export const handleGotoLocation = async (serverUrl: string, intl: IntlShape, loc if (!operator) { return {error: `${serverUrl} database not found`}; } + const {database} = operator; - const config = await getConfig(operator.database); + const config = await getConfig(database); const match = matchDeepLink(location, serverUrl, config?.SiteURL); if (match) { @@ -151,20 +153,18 @@ export const handleGotoLocation = async (serverUrl: string, intl: IntlShape, loc return {data: false}; } - let serverDatabase = operator.database; if (data.serverUrl !== serverUrl) { - serverDatabase = DatabaseManager.serverDatabases[serverUrl]?.database; - if (!serverDatabase) { + if (!database) { return {error: `${serverUrl} database not found`}; } } - const user = (await queryUsersByUsername(serverDatabase, [data.userName]).fetch())[0]; + const user = (await queryUsersByUsername(database, [data.userName]).fetch())[0]; if (!user) { DraftUtils.errorUnkownUser(intl); return {data: false}; } - getOrCreateDirectChannel(data.serverUrl, user.id); + makeDirectChannel(data.serverUrl, user.id, displayUsername(user, intl.locale, await getTeammateNameDisplay(database)), true); break; } case DeepLinkTypes.GROUPCHANNEL: { diff --git a/app/actions/remote/entry/app.ts b/app/actions/remote/entry/app.ts index 9c2265dfd2..7b41c35bc6 100644 --- a/app/actions/remote/entry/app.ts +++ b/app/actions/remote/entry/app.ts @@ -14,7 +14,7 @@ import {isTablet} from '@utils/helpers'; import {AppEntryData, AppEntryError, deferredAppEntryActions, fetchAppEntryData, syncOtherServers, teamsToRemove} from './common'; -export const appEntry = async (serverUrl: string, since = 0) => { +export async function appEntry(serverUrl: string, since = 0) { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { return {error: `${serverUrl} database not found`}; @@ -86,9 +86,9 @@ export const appEntry = async (serverUrl: string, since = 0) => { const error = teamData.error || chData?.error || prefData.error || meData.error; return {error, userId: meData?.user?.id}; -}; +} -export const upgradeEntry = async (serverUrl: string) => { +export async function upgradeEntry(serverUrl: string) { const dt = Date.now(); const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { @@ -115,4 +115,4 @@ export const upgradeEntry = async (serverUrl: string) => { } catch (e) { return {error: e, time: Date.now() - dt}; } -}; +} diff --git a/app/actions/remote/entry/common.ts b/app/actions/remote/entry/common.ts index 1278a5c785..4ff33d6d0d 100644 --- a/app/actions/remote/entry/common.ts +++ b/app/actions/remote/entry/common.ts @@ -180,10 +180,10 @@ export const fetchAlternateTeamData = async ( return {initialTeamId, removeTeamIds}; }; -export const deferredAppEntryActions = async ( +export async function deferredAppEntryActions( serverUrl: string, since: number, currentUserId: string, currentUserLocale: string, preferences: PreferenceType[] | undefined, config: ClientConfig, license: ClientLicense, teamData: MyTeamsRequest, chData: MyChannelsRequest | undefined, - initialTeamId?: string, initialChannelId?: string) => { + initialTeamId?: string, initialChannelId?: string) { // defer fetching posts for initial channel if (initialChannelId) { fetchPostsForChannel(serverUrl, initialChannelId); @@ -211,7 +211,7 @@ export const deferredAppEntryActions = async ( fetchAllTeams(serverUrl); updateAllUsersSince(serverUrl, since); -}; +} export const syncOtherServers = async (serverUrl: string) => { const database = DatabaseManager.appDatabase?.database; diff --git a/app/actions/remote/entry/login.ts b/app/actions/remote/entry/login.ts index eff90c422c..ece0c63bdd 100644 --- a/app/actions/remote/entry/login.ts +++ b/app/actions/remote/entry/login.ts @@ -29,7 +29,7 @@ type AfterLoginArgs = { deviceToken?: string; } -export const loginEntry = async ({serverUrl, user, deviceToken}: AfterLoginArgs) => { +export async function loginEntry({serverUrl, user, deviceToken}: AfterLoginArgs) { const dt = Date.now(); const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { @@ -186,4 +186,4 @@ export const loginEntry = async ({serverUrl, user, deviceToken}: AfterLoginArgs) return {error}; } -}; +} diff --git a/app/actions/remote/entry/notification.ts b/app/actions/remote/entry/notification.ts index 8081f39a18..c6fa676e0a 100644 --- a/app/actions/remote/entry/notification.ts +++ b/app/actions/remote/entry/notification.ts @@ -17,7 +17,7 @@ import {emitNotificationError} from '@utils/notification'; import {AppEntryData, AppEntryError, deferredAppEntryActions, fetchAppEntryData, syncOtherServers, teamsToRemove} from './common'; -export const pushNotificationEntry = async (serverUrl: string, notification: NotificationWithData) => { +export async function pushNotificationEntry(serverUrl: string, notification: NotificationWithData) { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { return {error: `${serverUrl} database not found`}; @@ -137,4 +137,4 @@ export const pushNotificationEntry = async (serverUrl: string, notification: Not syncOtherServers(serverUrl); const error = teamData.error || chData?.error || prefData.error || meData.error; return {error, userId: meData?.user?.id}; -}; +} diff --git a/app/actions/remote/post.ts b/app/actions/remote/post.ts index e901d1c92d..4d5fef4225 100644 --- a/app/actions/remote/post.ts +++ b/app/actions/remote/post.ts @@ -52,7 +52,7 @@ type AuthorsRequest = { error?: unknown; } -export const createPost = async (serverUrl: string, post: Partial, files: FileInfo[] = []): Promise<{data?: boolean; error?: any}> => { +export async function createPost(serverUrl: string, post: Partial, files: FileInfo[] = []): Promise<{data?: boolean; error?: any}> { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { return {error: `${serverUrl} database not found`}; @@ -176,7 +176,7 @@ export const createPost = async (serverUrl: string, post: Partial, files: } return {data: true}; -}; +} export const fetchPostsForCurrentChannel = async (serverUrl: string) => { const database = DatabaseManager.serverDatabases[serverUrl]?.database; @@ -188,7 +188,7 @@ export const fetchPostsForCurrentChannel = async (serverUrl: string) => { return fetchPostsForChannel(serverUrl, currentChannelId); }; -export const fetchPostsForChannel = async (serverUrl: string, channelId: string, fetchOnly = false) => { +export async function fetchPostsForChannel(serverUrl: string, channelId: string, fetchOnly = false) { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { return {error: `${serverUrl} database not found`}; @@ -261,7 +261,7 @@ export const fetchPostsForChannel = async (serverUrl: string, channelId: string, } return {posts: data.posts, order: data.order, authors, actionType, previousPostId: data.previousPostId}; -}; +} export const fetchPostsForUnreadChannels = async (serverUrl: string, channels: Channel[], memberships: ChannelMembership[], excludeChannelId?: string) => { const database = DatabaseManager.serverDatabases[serverUrl]?.database; @@ -283,7 +283,7 @@ export const fetchPostsForUnreadChannels = async (serverUrl: string, channels: C return {error: undefined}; }; -export const fetchPosts = async (serverUrl: string, channelId: string, page = 0, perPage = General.POST_CHUNK_SIZE, fetchOnly = false): Promise => { +export async function fetchPosts(serverUrl: string, channelId: string, page = 0, perPage = General.POST_CHUNK_SIZE, fetchOnly = false): Promise { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { return {error: `${serverUrl} database not found`}; @@ -318,9 +318,9 @@ export const fetchPosts = async (serverUrl: string, channelId: string, page = 0, forceLogoutIfNecessary(serverUrl, error as ClientErrorProps); return {error}; } -}; +} -export const fetchPostsBefore = async (serverUrl: string, channelId: string, postId: string, perPage = General.POST_CHUNK_SIZE, fetchOnly = false) => { +export async function fetchPostsBefore(serverUrl: string, channelId: string, postId: string, perPage = General.POST_CHUNK_SIZE, fetchOnly = false) { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { return {error: `${serverUrl} database not found`}; @@ -385,9 +385,9 @@ export const fetchPostsBefore = async (serverUrl: string, channelId: string, pos } return {error}; } -}; +} -export const fetchPostsSince = async (serverUrl: string, channelId: string, since: number, fetchOnly = false): Promise => { +export async function fetchPostsSince(serverUrl: string, channelId: string, since: number, fetchOnly = false): Promise { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { return {error: `${serverUrl} database not found`}; @@ -423,7 +423,7 @@ export const fetchPostsSince = async (serverUrl: string, channelId: string, sinc forceLogoutIfNecessary(serverUrl, error as ClientErrorProps); return {error}; } -}; +} export const fetchPostAuthors = async (serverUrl: string, posts: Post[], fetchOnly = false): Promise => { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; @@ -496,7 +496,7 @@ export const fetchPostAuthors = async (serverUrl: string, posts: Post[], fetchOn } }; -export const fetchPostThread = async (serverUrl: string, postId: string, fetchOnly = false): Promise => { +export async function fetchPostThread(serverUrl: string, postId: string, fetchOnly = false): Promise { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { return {error: `${serverUrl} database not found`}; @@ -532,7 +532,7 @@ export const fetchPostThread = async (serverUrl: string, postId: string, fetchOn forceLogoutIfNecessary(serverUrl, error as ClientErrorProps); return {error}; } -}; +} export async function fetchPostsAround(serverUrl: string, channelId: string, postId: string, perPage = General.POST_AROUND_CHUNK_SIZE) { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; @@ -699,7 +699,7 @@ export async function fetchMissingChannelsFromPosts(serverUrl: string, posts: Po } } -export const fetchPostById = async (serverUrl: string, postId: string, fetchOnly = false) => { +export async function fetchPostById(serverUrl: string, postId: string, fetchOnly = false) { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { return {error: `${serverUrl} database not found`}; @@ -749,7 +749,7 @@ export const fetchPostById = async (serverUrl: string, postId: string, fetchOnly forceLogoutIfNecessary(serverUrl, error as ClientErrorProps); return {error}; } -}; +} export const togglePinPost = async (serverUrl: string, postId: string) => { const database = DatabaseManager.serverDatabases[serverUrl]?.database; diff --git a/app/actions/remote/reactions.ts b/app/actions/remote/reactions.ts index b7819dce03..1d95b88863 100644 --- a/app/actions/remote/reactions.ts +++ b/app/actions/remote/reactions.ts @@ -16,7 +16,7 @@ import {forceLogoutIfNecessary} from './session'; import type {Client} from '@client/rest'; import type PostModel from '@typings/database/models/servers/post'; -export const addReaction = async (serverUrl: string, postId: string, emojiName: string) => { +export async function addReaction(serverUrl: string, postId: string, emojiName: string) { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { return {error: `${serverUrl} database not found`}; @@ -68,7 +68,7 @@ export const addReaction = async (serverUrl: string, postId: string, emojiName: forceLogoutIfNecessary(serverUrl, error as ClientErrorProps); return {error}; } -}; +} export const removeReaction = async (serverUrl: string, postId: string, emojiName: string) => { const database = DatabaseManager.serverDatabases[serverUrl]?.database; diff --git a/app/actions/remote/retry.ts b/app/actions/remote/retry.ts index 115dbf5cdd..df04b6f418 100644 --- a/app/actions/remote/retry.ts +++ b/app/actions/remote/retry.ts @@ -23,7 +23,7 @@ import {fetchMyTeams, MyTeamsRequest} from './team'; import type {Model} from '@nozbe/watermelondb'; -export const retryInitialTeamAndChannel = async (serverUrl: string) => { +export async function retryInitialTeamAndChannel(serverUrl: string) { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { return {error: `${serverUrl} database not found`}; @@ -130,9 +130,9 @@ export const retryInitialTeamAndChannel = async (serverUrl: string) => { } catch (error) { return {error: true}; } -}; +} -export const retryInitialChannel = async (serverUrl: string, teamId: string) => { +export async function retryInitialChannel(serverUrl: string, teamId: string) { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { return {error: `${serverUrl} database not found`}; @@ -209,4 +209,4 @@ export const retryInitialChannel = async (serverUrl: string, teamId: string) => } catch (error) { return {error: true}; } -}; +} diff --git a/app/actions/remote/team.ts b/app/actions/remote/team.ts index 8d464ed795..ecbfb6e364 100644 --- a/app/actions/remote/team.ts +++ b/app/actions/remote/team.ts @@ -27,7 +27,7 @@ export type MyTeamsRequest = { error?: unknown; } -export const addUserToTeam = async (serverUrl: string, teamId: string, userId: string, fetchOnly = false) => { +export async function addUserToTeam(serverUrl: string, teamId: string, userId: string, fetchOnly = false) { let client; try { client = NetworkManager.getClient(serverUrl); @@ -72,9 +72,9 @@ export const addUserToTeam = async (serverUrl: string, teamId: string, userId: s forceLogoutIfNecessary(serverUrl, error as ClientError); return {error}; } -}; +} -export const fetchMyTeams = async (serverUrl: string, fetchOnly = false): Promise => { +export async function fetchMyTeams(serverUrl: string, fetchOnly = false): Promise { let client; try { client = NetworkManager.getClient(serverUrl); @@ -122,9 +122,9 @@ export const fetchMyTeams = async (serverUrl: string, fetchOnly = false): Promis forceLogoutIfNecessary(serverUrl, error as ClientError); return {error}; } -}; +} -export const fetchMyTeam = async (serverUrl: string, teamId: string, fetchOnly = false): Promise => { +export async function fetchMyTeam(serverUrl: string, teamId: string, fetchOnly = false): Promise { let client; try { client = NetworkManager.getClient(serverUrl); @@ -156,7 +156,7 @@ export const fetchMyTeam = async (serverUrl: string, teamId: string, fetchOnly = forceLogoutIfNecessary(serverUrl, error as ClientError); return {error}; } -}; +} export const fetchAllTeams = async (serverUrl: string, fetchOnly = false): Promise => { let client; @@ -168,7 +168,6 @@ export const fetchAllTeams = async (serverUrl: string, fetchOnly = false): Promi try { const teams = await client.getTeams(); - if (!fetchOnly) { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (operator) { @@ -203,7 +202,7 @@ export const fetchTeamsChannelsAndUnreadPosts = async (serverUrl: string, since: return {error: undefined}; }; -export const fetchTeamByName = async (serverUrl: string, teamName: string, fetchOnly = false) => { +export async function fetchTeamByName(serverUrl: string, teamName: string, fetchOnly = false) { let client; try { client = NetworkManager.getClient(serverUrl); @@ -227,7 +226,7 @@ export const fetchTeamByName = async (serverUrl: string, teamName: string, fetch forceLogoutIfNecessary(serverUrl, error as ClientError); return {error}; } -}; +} export const removeUserFromTeam = async (serverUrl: string, teamId: string, userId: string, fetchOnly = false) => { let client; @@ -252,7 +251,7 @@ export const removeUserFromTeam = async (serverUrl: string, teamId: string, user } }; -export const handleTeamChange = async (serverUrl: string, teamId: string) => { +export async function handleTeamChange(serverUrl: string, teamId: string) { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { return; @@ -299,4 +298,4 @@ export const handleTeamChange = async (serverUrl: string, teamId: string) => { if (channels?.length && memberships?.length) { fetchPostsForUnreadChannels(serverUrl, channels, memberships, channelId); } -}; +} diff --git a/app/actions/remote/user.ts b/app/actions/remote/user.ts index 27a39f5169..2f44542a9e 100644 --- a/app/actions/remote/user.ts +++ b/app/actions/remote/user.ts @@ -71,7 +71,7 @@ export const fetchMe = async (serverUrl: string, fetchOnly = false): Promise => { +export async function fetchProfilesInChannel(serverUrl: string, channelId: string, excludeUserId?: string, fetchOnly = false): Promise { let client: Client; try { client = NetworkManager.getClient(serverUrl); @@ -108,9 +108,9 @@ export const fetchProfilesInChannel = async (serverUrl: string, channelId: strin forceLogoutIfNecessary(serverUrl, error as ClientError); return {channelId, error}; } -}; +} -export const fetchProfilesPerChannels = async (serverUrl: string, channelIds: string[], excludeUserId?: string, fetchOnly = false): Promise => { +export async function fetchProfilesPerChannels(serverUrl: string, channelIds: string[], excludeUserId?: string, fetchOnly = false): Promise { try { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { @@ -164,7 +164,7 @@ export const fetchProfilesPerChannels = async (serverUrl: string, channelIds: st } catch (error) { return {error}; } -}; +} export const updateMe = async (serverUrl: string, user: Partial) => { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; @@ -209,7 +209,7 @@ export const fetchStatusInBatch = (serverUrl: string, id: string) => { return debouncedFetchStatusesByIds.apply(null, [serverUrl]); }; -export const fetchStatusByIds = async (serverUrl: string, userIds: string[], fetchOnly = false) => { +export async function fetchStatusByIds(serverUrl: string, userIds: string[], fetchOnly = false) { let client: Client; try { client = NetworkManager.getClient(serverUrl); @@ -246,7 +246,7 @@ export const fetchStatusByIds = async (serverUrl: string, userIds: string[], fet forceLogoutIfNecessary(serverUrl, error as ClientError); return {error}; } -}; +} export const fetchUsersByIds = async (serverUrl: string, userIds: string[], fetchOnly = false) => { let client: Client; @@ -472,7 +472,7 @@ export const fetchMissingProfilesByUsernames = async (serverUrl: string, usernam } }; -export const updateAllUsersSince = async (serverUrl: string, since: number, fetchOnly = false) => { +export async function updateAllUsersSince(serverUrl: string, since: number, fetchOnly = false) { if (!since) { return {users: []}; } @@ -512,9 +512,9 @@ export const updateAllUsersSince = async (serverUrl: string, since: number, fetc } return {users: userUpdates}; -}; +} -export const updateUsersNoLongerVisible = async (serverUrl: string, prepareRecordsOnly = false): Promise<{error?: unknown; models?: Model[]}> => { +export async function updateUsersNoLongerVisible(serverUrl: string, prepareRecordsOnly = false): Promise<{error?: unknown; models?: Model[]}> { let client: Client; try { client = NetworkManager.getClient(serverUrl); @@ -549,7 +549,7 @@ export const updateUsersNoLongerVisible = async (serverUrl: string, prepareRecor } return {models}; -}; +} export const setStatus = async (serverUrl: string, status: UserStatus) => { let client: Client; diff --git a/app/actions/websocket/channel.ts b/app/actions/websocket/channel.ts index ef981f05a8..f7814bb1e2 100644 --- a/app/actions/websocket/channel.ts +++ b/app/actions/websocket/channel.ts @@ -17,13 +17,14 @@ import {fetchMissingSidebarInfo, fetchMyChannel, fetchChannelStats, fetchChannel import {fetchPostsForChannel} from '@actions/remote/post'; import {fetchRolesIfNeeded} from '@actions/remote/role'; import {fetchUsersByIds, updateUsersNoLongerVisible} from '@actions/remote/user'; +import EphemeralStore from '@app/store/ephemeral_store'; 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, getCurrentChannelId} from '@queries/servers/system'; import {getNthLastChannelFromTeam} from '@queries/servers/team'; -import {getCurrentUser, getUserById} from '@queries/servers/user'; +import {getCurrentUser, getTeammateNameDisplay, getUserById} from '@queries/servers/user'; import {dismissAllModals, popToRoot} from '@screens/navigation'; import {isTablet} from '@utils/helpers'; @@ -33,10 +34,19 @@ export async function handleChannelCreatedEvent(serverUrl: string, msg: any) { if (!operator) { return; } + const {database} = operator; const {team_id: teamId, channel_id: channelId} = msg.data; + if (EphemeralStore.creatingChannel) { + return; // We probably don't need to handle this WS because we provoked it + } try { + const channel = await getChannelById(database, channelId); + if (channel) { + return; // We already have this channel + } + const models: Model[] = []; const {channels, memberships} = await fetchMyChannel(serverUrl, teamId, channelId, true); if (channels && memberships) { @@ -154,7 +164,7 @@ export async function handleChannelMemberUpdatedEvent(serverUrl: string, msg: an } } -export async function handleDirectAddedEvent(serverUrl: string, msg: any) { +export async function handleDirectAddedEvent(serverUrl: string, msg: WebSocketMessage) { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { return; @@ -162,8 +172,31 @@ export async function handleDirectAddedEvent(serverUrl: string, msg: any) { const {database} = operator; + if (EphemeralStore.creatingDMorGMTeammates.length) { + let userList: string[] | undefined; + if ('teammate_ids' in msg.data) { // GM + try { + userList = JSON.parse(msg.data.teammate_ids); + } catch { + // Do nothing + } + } else if (msg.data.teammate_id) { // DM + userList = [msg.data.teammate_id]; + } + if (userList?.length === EphemeralStore.creatingDMorGMTeammates.length) { + const usersSet = new Set(userList); + if (EphemeralStore.creatingDMorGMTeammates.every((v) => usersSet.has(v))) { + return; // We are adding this channel + } + } + } + try { const {channel_id: channelId} = msg.broadcast; + const channel = await getChannelById(database, channelId); + if (channel) { + return; // We already have this channel + } const {channels, memberships} = await fetchMyChannel(serverUrl, '', channelId, true); if (!channels || !memberships) { return; @@ -173,7 +206,9 @@ export async function handleDirectAddedEvent(serverUrl: string, msg: any) { return; } - const {directChannels, users} = await fetchMissingSidebarInfo(serverUrl, channels, user.locale, '', user.id, true); + const teammateDisplayNameSetting = await getTeammateNameDisplay(database); + + const {directChannels, users} = await fetchMissingSidebarInfo(serverUrl, channels, user.locale, teammateDisplayNameSetting, user.id, true); if (!directChannels?.[0]) { return; } @@ -183,7 +218,7 @@ export async function handleDirectAddedEvent(serverUrl: string, msg: any) { if (channelModels.models?.length) { models.push(...channelModels.models); } - const categoryModels = await addChannelToDefaultCategory(serverUrl, channels[0], false); + const categoryModels = await addChannelToDefaultCategory(serverUrl, channels[0], true); if (categoryModels.models?.length) { models.push(...categoryModels.models); } diff --git a/app/actions/websocket/index.ts b/app/actions/websocket/index.ts index c5caad3383..3c3b7d9d28 100644 --- a/app/actions/websocket/index.ts +++ b/app/actions/websocket/index.ts @@ -298,6 +298,7 @@ export async function handleEvent(serverUrl: string, msg: WebSocketMessage) { break; case WebsocketEvents.DIRECT_ADDED: + case WebsocketEvents.GROUP_ADDED: handleDirectAddedEvent(serverUrl, msg); break; diff --git a/app/constants/websocket.ts b/app/constants/websocket.ts index 46dd09887a..339c83f0a8 100644 --- a/app/constants/websocket.ts +++ b/app/constants/websocket.ts @@ -18,6 +18,7 @@ const WebsocketEvents = { CHANNEL_MEMBER_UPDATED: 'channel_member_updated', CHANNEL_SCHEME_UPDATED: 'channel_scheme_updated', DIRECT_ADDED: 'direct_added', + GROUP_ADDED: 'group_added', // Added to a group channel ADDED_TO_TEAM: 'added_to_team', LEAVE_TEAM: 'leave_team', UPDATE_TEAM: 'update_team', diff --git a/app/database/operator/base_data_operator/index.ts b/app/database/operator/base_data_operator/index.ts index 99f237cc22..fd22b6f577 100644 --- a/app/database/operator/base_data_operator/index.ts +++ b/app/database/operator/base_data_operator/index.ts @@ -187,7 +187,7 @@ export default class BaseDataOperator { * @throws {DataOperatorException} * @returns {Promise} */ - batchRecords = async (models: Model[]): Promise => { + async batchRecords(models: Model[]): Promise { try { if (models.length > 0) { await this.database.write(async (writer: WriterInterface) => { @@ -198,7 +198,7 @@ export default class BaseDataOperator { // eslint-disable-next-line no-console console.warn('batchRecords error ', e as Error); } - }; + } /** * handleRecords : Utility that processes some records' data against values already present in the database so as to avoid duplicity. @@ -211,7 +211,7 @@ export default class BaseDataOperator { * @param {string} handleRecordsArgs.tableName * @returns {Promise} */ - handleRecords = async ({buildKeyRecordBy, fieldName, transformer, createOrUpdateRawValues, deleteRawValues = [], tableName, prepareRecordsOnly = true}: HandleRecordsArgs): Promise => { + async handleRecords({buildKeyRecordBy, fieldName, transformer, createOrUpdateRawValues, deleteRawValues = [], tableName, prepareRecordsOnly = true}: HandleRecordsArgs): Promise { if (!createOrUpdateRawValues.length) { // eslint-disable-next-line no-console console.warn( @@ -242,5 +242,5 @@ export default class BaseDataOperator { } return models; - }; + } } diff --git a/app/database/operator/server_data_operator/handlers/channel.ts b/app/database/operator/server_data_operator/handlers/channel.ts index 72b0cafe3a..75152653dc 100644 --- a/app/database/operator/server_data_operator/handlers/channel.ts +++ b/app/database/operator/server_data_operator/handlers/channel.ts @@ -203,8 +203,8 @@ const ChannelHandler = (superclass: any) => class extends superclass { } const memberships: ChannelMember[] = channelMemberships.map((m) => ({ - id: `${m.channel_id}-${m.user_id}`, ...m, + id: `${m.channel_id}-${m.user_id}`, })); const createOrUpdateRawValues = getUniqueRawsBy({raws: memberships, key: 'id'}); diff --git a/app/database/operator/server_data_operator/handlers/index.ts b/app/database/operator/server_data_operator/handlers/index.ts index 348072513b..c9e670b85f 100644 --- a/app/database/operator/server_data_operator/handlers/index.ts +++ b/app/database/operator/server_data_operator/handlers/index.ts @@ -82,7 +82,7 @@ export default class ServerDataOperatorBase extends BaseDataOperator { * @param {(TransformerArgs) => Promise} execute.recordOperator * @returns {Promise} */ - execute = async ({createRaws, transformer, tableName, updateRaws}: OperationArgs): Promise => { + async execute({createRaws, transformer, tableName, updateRaws}: OperationArgs): Promise { const models = await this.prepareRecords({ tableName, createRaws, @@ -95,5 +95,5 @@ export default class ServerDataOperatorBase extends BaseDataOperator { } return models; - }; + } } diff --git a/app/queries/servers/channel.ts b/app/queries/servers/channel.ts index 3292790baf..320c93cb49 100644 --- a/app/queries/servers/channel.ts +++ b/app/queries/servers/channel.ts @@ -113,7 +113,7 @@ export const prepareMyChannelsForTeam = async (operator: ServerDataOperator, tea try { const channelRecords = operator.handleChannel({channels, prepareRecordsOnly: true}); const channelInfoRecords = operator.handleChannelInfo({channelInfos, prepareRecordsOnly: true}); - const membershipRecords = operator.handleChannelMembership({channelMemberships: memberships, prepareRecordsOnly: true}); + const membershipRecords = operator.handleChannelMembership({channelMemberships: channelMembers, prepareRecordsOnly: true}); const myChannelRecords = operator.handleMyChannel({channels, myChannels: memberships, prepareRecordsOnly: true}); const myChannelSettingsRecords = operator.handleMyChannelSettings({settings: memberships, prepareRecordsOnly: true}); @@ -284,7 +284,7 @@ export const observeCurrentChannel = (database: Database) => { )); }; -export const deleteChannelMembership = async (operator: ServerDataOperator, userId: string, channelId: string, prepareRecordsOnly = false) => { +export async function deleteChannelMembership(operator: ServerDataOperator, userId: string, channelId: string, prepareRecordsOnly = false) { try { const channelMembership = await operator.database.get(CHANNEL_MEMBERSHIP).query(Q.where('user_id', Q.eq(userId)), Q.where('channel_id', Q.eq(channelId))).fetch(); const models: Model[] = []; @@ -298,7 +298,7 @@ export const deleteChannelMembership = async (operator: ServerDataOperator, user } catch (error) { return {error}; } -}; +} export const addChannelMembership = async (operator: ServerDataOperator, userId: string, channelId: string) => { try { diff --git a/app/queries/servers/entry.ts b/app/queries/servers/entry.ts index 0daeed9dab..6f7d603e56 100644 --- a/app/queries/servers/entry.ts +++ b/app/queries/servers/entry.ts @@ -28,7 +28,7 @@ type PrepareModelsArgs = { meData?: MyUserRequest; } -export const prepareModels = async ({operator, initialTeamId, removeTeams, removeChannels, teamData, chData, prefData, meData}: PrepareModelsArgs): Promise>> => { +export async function prepareModels({operator, initialTeamId, removeTeams, removeChannels, teamData, chData, prefData, meData}: PrepareModelsArgs): Promise>> { const modelPromises: Array> = []; if (removeTeams?.length) { @@ -65,4 +65,4 @@ export const prepareModels = async ({operator, initialTeamId, removeTeams, remov } return modelPromises; -}; +} diff --git a/app/queries/servers/preference.ts b/app/queries/servers/preference.ts index 7d19c80d61..4aafe7b620 100644 --- a/app/queries/servers/preference.ts +++ b/app/queries/servers/preference.ts @@ -47,7 +47,7 @@ export const getThemeForCurrentTeam = async (database: Database) => { return undefined; }; -export const deletePreferences = async (database: ServerDatabase, preferences: PreferenceType[]): Promise => { +export async function deletePreferences(database: ServerDatabase, preferences: PreferenceType[]): Promise { try { const preparedModels: Model[] = []; for await (const pref of preferences) { @@ -63,4 +63,4 @@ export const deletePreferences = async (database: ServerDatabase, preferences: P } catch (error) { return false; } -}; +} diff --git a/app/queries/servers/system.ts b/app/queries/servers/system.ts index 4441a95384..3a7dd3eeaa 100644 --- a/app/queries/servers/system.ts +++ b/app/queries/servers/system.ts @@ -155,6 +155,15 @@ export const observeLicense = (database: Database) => { ); }; +export const getLicense = async (serverDatabase: Database) => { + try { + const license = await serverDatabase.get(SYSTEM).find(SYSTEM_IDENTIFIERS.LICENSE); + return (license?.value) as ClientLicense | undefined; + } catch { + return undefined; + } +}; + export const getRecentCustomStatuses = async (database: Database) => { try { const recent = await database.get(SYSTEM).find(SYSTEM_IDENTIFIERS.RECENT_CUSTOM_STATUS); @@ -311,7 +320,7 @@ export async function prepareCommonSystemValues( } } -export const setCurrentChannelId = async (operator: ServerDataOperator, channelId: string) => { +export async function setCurrentChannelId(operator: ServerDataOperator, channelId: string) { try { const models = await prepareCommonSystemValues(operator, {currentChannelId: channelId}); if (models) { @@ -322,9 +331,9 @@ export const setCurrentChannelId = async (operator: ServerDataOperator, channelI } catch (error) { return {error}; } -}; +} -export const setCurrentTeamAndChannelId = async (operator: ServerDataOperator, teamId?: string, channelId?: string) => { +export async function setCurrentTeamAndChannelId(operator: ServerDataOperator, teamId?: string, channelId?: string) { try { const models = await prepareCommonSystemValues(operator, { currentChannelId: channelId, @@ -338,5 +347,5 @@ export const setCurrentTeamAndChannelId = async (operator: ServerDataOperator, t } catch (error) { return {error}; } -}; +} diff --git a/app/queries/servers/team.ts b/app/queries/servers/team.ts index 96303f5b8b..e38eafda86 100644 --- a/app/queries/servers/team.ts +++ b/app/queries/servers/team.ts @@ -143,7 +143,7 @@ export const getLastTeam = async (database: Database) => { return getDefaultTeamId(database); }; -export const syncTeamTable = async (operator: ServerDataOperator, teams: Team[]) => { +export async function syncTeamTable(operator: ServerDataOperator, teams: Team[]) { try { const deletedTeams = teams.filter((t) => t.delete_at > 0).map((t) => t.id); const deletedSet = new Set(deletedTeams); @@ -159,12 +159,14 @@ export const syncTeamTable = async (operator: ServerDataOperator, teams: Team[]) } models.push(...await operator.handleTeam({teams: availableTeams, prepareRecordsOnly: true})); - await operator.batchRecords(models); + if (models.length) { + await operator.batchRecords(models); + } return {}; } catch (error) { return {error}; } -}; +} export const getDefaultTeamId = async (database: Database) => { const user = await getCurrentUser(database); @@ -202,7 +204,7 @@ export function prepareMyTeams(operator: ServerDataOperator, teams: Team[], memb } } -export const deleteMyTeams = async (operator: ServerDataOperator, myTeams: MyTeamModel[]) => { +export async function deleteMyTeams(operator: ServerDataOperator, myTeams: MyTeamModel[]) { try { const preparedModels: Model[] = []; for (const myTeam of myTeams) { @@ -216,7 +218,7 @@ export const deleteMyTeams = async (operator: ServerDataOperator, myTeams: MyTea } catch (error) { return {error}; } -}; +} export const prepareDeleteTeam = async (team: TeamModel): Promise => { try { diff --git a/app/queries/servers/user.ts b/app/queries/servers/user.ts index 39d63d861f..219d590978 100644 --- a/app/queries/servers/user.ts +++ b/app/queries/servers/user.ts @@ -10,7 +10,7 @@ import {MM_TABLES} from '@constants/database'; import {getTeammateNameDisplaySetting} from '@helpers/api/preference'; import {queryPreferencesByCategoryAndName} from './preference'; -import {observeConfig, observeCurrentUserId, observeLicense, getCurrentUserId} from './system'; +import {observeConfig, observeCurrentUserId, observeLicense, getCurrentUserId, getConfig, getLicense} from './system'; import type ServerDataOperator from '@database/operator/server_data_operator'; import type UserModel from '@typings/database/models/servers/user'; @@ -73,6 +73,13 @@ export const observeTeammateNameDisplay = (database: Database) => { ); }; +export async function getTeammateNameDisplay(database: Database) { + const config = await getConfig(database); + const license = await getLicense(database); + const preferences = await queryPreferencesByCategoryAndName(database, Preferences.CATEGORY_DISPLAY_SETTINGS).fetch(); + return getTeammateNameDisplaySetting(preferences, config, license); +} + export const queryUsersLike = (database: Database, likeUsername: string) => { return database.get(USER).query( Q.where('username', Q.like( diff --git a/app/screens/create_direct_message/create_direct_message.tsx b/app/screens/create_direct_message/create_direct_message.tsx index 832f8643fd..e0d87a2004 100644 --- a/app/screens/create_direct_message/create_direct_message.tsx +++ b/app/screens/create_direct_message/create_direct_message.tsx @@ -1,7 +1,7 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react'; +import React, {useCallback, useEffect, useMemo, useReducer, useRef, useState} from 'react'; import {useIntl} from 'react-intl'; import {Keyboard, Platform, View} from 'react-native'; import {Navigation} from 'react-native-navigation'; @@ -77,6 +77,13 @@ const getStyleFromTheme = makeStyleSheetFromTheme((theme) => { }; }); +function reduceProfiles(state: UserProfile[], action: {type: 'add'; values?: UserProfile[]}) { + if (action.type === 'add' && action.values?.length) { + return [...state, ...action.values]; + } + return state; +} + export default function CreateDirectMessage({ componentId, currentTeamId, @@ -95,7 +102,7 @@ export default function CreateDirectMessage({ const page = useRef(-1); const mounted = useRef(false); - const [profiles, setProfiles] = useState([]); + const [profiles, dispatchProfiles] = useReducer(reduceProfiles, []); const [searchResults, setSearchResults] = useState([]); const [loading, setLoading] = useState(false); const [term, setTerm] = useState(''); @@ -105,11 +112,6 @@ export default function CreateDirectMessage({ const isSearch = Boolean(term); - const addToProfiles = useRef((newProfiles: UserProfile[]) => setProfiles([...profiles, ...newProfiles])); - useEffect(() => { - addToProfiles.current = (newProfiles: UserProfile[]) => setProfiles([...profiles, ...newProfiles]); - }, [profiles]); - const loadedProfiles = ({users}: {users?: UserProfile[]}) => { if (mounted.current) { if (users && !users.length) { @@ -118,9 +120,7 @@ export default function CreateDirectMessage({ page.current += 1; setLoading(false); - if (users && users.length) { - addToProfiles.current(users); - } + dispatchProfiles({type: 'add', values: users}); } }; diff --git a/app/store/ephemeral_store.ts b/app/store/ephemeral_store.ts index c27de71d68..1201589095 100644 --- a/app/store/ephemeral_store.ts +++ b/app/store/ephemeral_store.ts @@ -7,6 +7,8 @@ class EphemeralStore { navigationModalStack: string[] = []; theme: Theme | undefined; visibleTab = 'Home'; + creatingChannel = false; + creatingDMorGMTeammates: string[] = []; addNavigationComponentId = (componentId: string) => { this.addToNavigationComponentIdStack(componentId);