From a4674915c19068f1f5a782c8f0c5eeea412d7039 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Espino=20Garc=C3=ADa?= Date: Thu, 19 May 2022 09:06:31 +0200 Subject: [PATCH] Better handle go to location (#6262) * Better handle go to location * Improve server check --- app/actions/local/channel.ts | 23 ++++++++----------- app/actions/remote/channel.ts | 11 ++++++--- app/actions/remote/command.ts | 20 +++++++++++----- app/actions/websocket/channel.ts | 1 - .../slash_suggestion/slash_suggestion.tsx | 4 ++-- .../post_draft/send_handler/send_handler.tsx | 2 +- app/database/manager/__mocks__/index.ts | 6 +++++ app/database/manager/index.ts | 13 +++++++++++ app/screens/apps_form/apps_form_component.tsx | 4 ++-- types/api/channels.d.ts | 1 - 10 files changed, 56 insertions(+), 29 deletions(-) diff --git a/app/actions/local/channel.ts b/app/actions/local/channel.ts index 34405c5ca..26e0c9e6b 100644 --- a/app/actions/local/channel.ts +++ b/app/actions/local/channel.ts @@ -37,7 +37,7 @@ export async function switchToChannel(serverUrl: string, channelId: string, team } const {database} = operator; - const models: Model[] = []; + let models: Model[] = []; try { const dt = Date.now(); const isTabletDevice = await isTablet(); @@ -61,9 +61,9 @@ export async function switchToChannel(serverUrl: string, channelId: string, team await setCurrentChannelId(operator, ''); } + const modelPromises: Array> = []; if (system.currentTeamId !== toTeamId) { - const history = await addTeamToTeamHistory(operator, toTeamId, true); - models.push(...history); + modelPromises.push(addTeamToTeamHistory(operator, toTeamId, true)); } const commonValues: PrepareCommonSystemValuesArgs = { @@ -75,16 +75,13 @@ export async function switchToChannel(serverUrl: string, channelId: string, team commonValues.currentTeamId = system.currentTeamId === toTeamId ? undefined : toTeamId; } - const common = await prepareCommonSystemValues(operator, commonValues); - if (common) { - models.push(...common); - } + modelPromises.push(prepareCommonSystemValues(operator, commonValues)); if (system.currentChannelId !== channelId || system.currentTeamId !== toTeamId) { - const history = await addChannelToTeamHistory(operator, toTeamId, channelId, true); - models.push(...history); + modelPromises.push(addChannelToTeamHistory(operator, toTeamId, channelId, true)); } + models = (await Promise.all(modelPromises)).flat(); const {member: viewedAt} = await markChannelAsViewed(serverUrl, channelId, true); if (viewedAt) { models.push(viewedAt); @@ -145,10 +142,10 @@ export async function removeCurrentUserFromChannel(serverUrl: string, channelId: if (teamId) { teamId = await getCurrentTeamId(database); } - const system = await removeChannelFromTeamHistory(operator, teamId, channel.id, true); - if (system) { - models.push(...system); - } + + // We update the history ASAP to avoid clashes with channel switch. + await removeChannelFromTeamHistory(operator, teamId, channel.id, false); + if (models.length && !prepareRecordsOnly) { try { await operator.batchRecords(models); diff --git a/app/actions/remote/channel.ts b/app/actions/remote/channel.ts index b125df807..1389c15d1 100644 --- a/app/actions/remote/channel.ts +++ b/app/actions/remote/channel.ts @@ -577,7 +577,7 @@ export async function switchToChannelByName(serverUrl: string, channelName: stri } let isArchived = false; - const chReq = await fetchChannelByName(serverUrl, team.id, channelName); + const chReq = await fetchChannelByName(serverUrl, team.id, channelName, true); if (chReq.error) { errorHandler(intl); return {error: chReq.error}; @@ -596,6 +596,11 @@ export async function switchToChannelByName(serverUrl: string, channelName: stri myChannel = await getMyChannel(database, channel.id); + if (!myChannel) { + const req = await fetchMyChannel(serverUrl, channel.team_id || team.id, channel.id, true); + myChannel = req.memberships?.[0]; + } + if (!myChannel) { if (channel.type === General.PRIVATE_CHANNEL) { const displayName = channel.display_name; @@ -666,8 +671,8 @@ export async function switchToChannelByName(serverUrl: string, channelName: stri fetchMyChannelsForTeam(serverUrl, teamId, true, 0, false, true); } - if (teamId && channelId) { - await switchToChannelById(serverUrl, channelId, teamId); + if (teamId || channelId) { + await switchToChannelById(serverUrl, channel.id, team.id); } if (roles.length) { diff --git a/app/actions/remote/command.ts b/app/actions/remote/command.ts index 757125f99..9fb07280b 100644 --- a/app/actions/remote/command.ts +++ b/app/actions/remote/command.ts @@ -61,7 +61,11 @@ export const executeCommand = async (serverUrl: string, intl: IntlShape, message } const cmd = msg.substring(0, cmdLength).toLowerCase(); - msg = cmd + msg.substring(cmdLength); + if (cmd === '/code') { + msg = cmd + ' ' + msg.substring(cmdLength, msg.length).trimEnd(); + } else { + msg = cmd + ' ' + msg.substring(cmdLength, msg.length).trim(); + } let data; try { @@ -129,17 +133,21 @@ export const handleGotoLocation = async (serverUrl: string, intl: IntlShape, loc const config = await getConfig(database); const match = matchDeepLink(location, serverUrl, config?.SiteURL); + let linkServerUrl: string | undefined; + if (match?.data?.serverUrl) { + linkServerUrl = DatabaseManager.searchUrl(match.data.serverUrl); + } - if (match) { + if (match && linkServerUrl) { switch (match.type) { case DeepLinkTypes.CHANNEL: { const data = match.data as DeepLinkChannel; - switchToChannelByName(data.serverUrl, data.channelName, data.teamName, DraftUtils.errorBadChannel, intl); + switchToChannelByName(linkServerUrl, data.channelName, data.teamName, DraftUtils.errorBadChannel, intl); break; } case DeepLinkTypes.PERMALINK: { const data = match.data as DeepLinkPermalink; - showPermalink(serverUrl, data.teamName, data.postId, intl); + showPermalink(linkServerUrl, data.teamName, data.postId, intl); break; } case DeepLinkTypes.DMCHANNEL: { @@ -160,7 +168,7 @@ export const handleGotoLocation = async (serverUrl: string, intl: IntlShape, loc return {data: false}; } - makeDirectChannel(data.serverUrl, user.id, displayUsername(user, intl.locale, await getTeammateNameDisplay(database)), true); + makeDirectChannel(linkServerUrl, user.id, displayUsername(user, intl.locale, await getTeammateNameDisplay(database)), true); break; } case DeepLinkTypes.GROUPCHANNEL: { @@ -170,7 +178,7 @@ export const handleGotoLocation = async (serverUrl: string, intl: IntlShape, loc return {data: false}; } - switchToChannelById(data.serverUrl, data.channelId); + switchToChannelById(linkServerUrl, data.channelId); break; } case DeepLinkTypes.PLUGIN: { diff --git a/app/actions/websocket/channel.ts b/app/actions/websocket/channel.ts index 319c4b589..ac06763af 100644 --- a/app/actions/websocket/channel.ts +++ b/app/actions/websocket/channel.ts @@ -383,7 +383,6 @@ export async function handleUserRemovedFromChannelEvent(serverUrl: string, msg: } } - await fetchChannelStats(serverUrl, channelId, false); operator.batchRecords(models); } diff --git a/app/components/autocomplete/slash_suggestion/slash_suggestion.tsx b/app/components/autocomplete/slash_suggestion/slash_suggestion.tsx index d6d466984..2d86e1f43 100644 --- a/app/components/autocomplete/slash_suggestion/slash_suggestion.tsx +++ b/app/components/autocomplete/slash_suggestion/slash_suggestion.tsx @@ -20,8 +20,8 @@ import {AppCommandParser} from './app_command_parser/app_command_parser'; import SlashSuggestionItem from './slash_suggestion_item'; // TODO: Remove when all below commands have been implemented -const COMMANDS_TO_IMPLEMENT_LATER = ['collapse', 'expand', 'join', 'open', 'leave', 'logout', 'msg', 'grpmsg']; -const NON_MOBILE_COMMANDS = ['rename', 'invite_people', 'shortcuts', 'search', 'help', 'settings', 'remove']; +const COMMANDS_TO_IMPLEMENT_LATER = ['collapse', 'expand', 'logout']; +const NON_MOBILE_COMMANDS = ['shortcuts', 'search', 'settings']; const COMMANDS_TO_HIDE_ON_MOBILE = new Set([...COMMANDS_TO_IMPLEMENT_LATER, ...NON_MOBILE_COMMANDS]); diff --git a/app/components/post_draft/send_handler/send_handler.tsx b/app/components/post_draft/send_handler/send_handler.tsx index 2214ffa9c..3cda650c6 100644 --- a/app/components/post_draft/send_handler/send_handler.tsx +++ b/app/components/post_draft/send_handler/send_handler.tsx @@ -160,7 +160,7 @@ export default function SendHandler({ // showAppForm(data.form, data.call, theme); // } - if (data?.goto_location) { + if (data?.goto_location && !value.startsWith('/leave')) { handleGotoLocation(serverUrl, intl, data.goto_location); } }, [userIsOutOfOffice, currentUserId, intl, value, serverUrl, channelId, rootId]); diff --git a/app/database/manager/__mocks__/index.ts b/app/database/manager/__mocks__/index.ts index 2567ee575..07030b1b3 100644 --- a/app/database/manager/__mocks__/index.ts +++ b/app/database/manager/__mocks__/index.ts @@ -25,6 +25,7 @@ import {queryActiveServer, queryServer, queryServerByIdentifier} from '@queries/ import {DatabaseType} from '@typings/database/enums'; import {deleteIOSDatabase} from '@utils/mattermost_managed'; import {hashCode} from '@utils/security'; +import {removeProtocol} from '@utils/url'; import type {AppDatabase, CreateServerDatabaseArgs, Models, RegisterServerDatabaseArgs, ServerDatabase, ServerDatabases} from '@typings/database/database'; @@ -357,6 +358,11 @@ class DatabaseManager { private getDatabaseFilePath = (dbName: string): string => { return Platform.OS === 'ios' ? `${this.databaseDirectory}/${dbName}.db` : `${this.databaseDirectory}${dbName}.db`; }; + + public searchUrl = (toFind: string): string | undefined => { + const toFindWithoutProtocol = removeProtocol(toFind); + return Object.keys(this.serverDatabases).find((k) => removeProtocol(k) === toFindWithoutProtocol); + }; } export default new DatabaseManager(); diff --git a/app/database/manager/index.ts b/app/database/manager/index.ts index b770ec6e0..c5b8f14fd 100644 --- a/app/database/manager/index.ts +++ b/app/database/manager/index.ts @@ -27,6 +27,7 @@ import {DatabaseType} from '@typings/database/enums'; import {emptyFunction} from '@utils/general'; import {deleteIOSDatabase, getIOSAppGroupDetails} from '@utils/mattermost_managed'; import {hashCode} from '@utils/security'; +import {removeProtocol} from '@utils/url'; import type {AppDatabase, CreateServerDatabaseArgs, RegisterServerDatabaseArgs, Models, ServerDatabase, ServerDatabases} from '@typings/database/database'; @@ -461,6 +462,18 @@ class DatabaseManager { private getDatabaseFilePath = (dbName: string): string => { return Platform.OS === 'ios' ? `${this.databaseDirectory}/${dbName}.db` : `${this.databaseDirectory}/${dbName}.db`; }; + + /** + * searchUrl returns the serverUrl that matches the passed string among the servers currently loaded. + * Returns undefined if none found. + * + * @param {string} toFind + * @returns {string|undefined} + */ + public searchUrl = (toFind: string): string | undefined => { + const toFindWithoutProtocol = removeProtocol(toFind); + return Object.keys(this.serverDatabases).find((k) => removeProtocol(k) === toFindWithoutProtocol); + }; } if (!__DEV__) { diff --git a/app/screens/apps_form/apps_form_component.tsx b/app/screens/apps_form/apps_form_component.tsx index ac8d8c6d7..64fa53c39 100644 --- a/app/screens/apps_form/apps_form_component.tsx +++ b/app/screens/apps_form/apps_form_component.tsx @@ -312,10 +312,10 @@ function AppsFormComponent({ const callResponse = res.data!; switch (callResponse.type) { case AppCallResponseTypes.OK: - await close(); + close(); return; case AppCallResponseTypes.NAVIGATE: - await close(); + close(); handleGotoLocation(serverUrl, intl, callResponse.navigate_to_url!); return; case AppCallResponseTypes.FORM: diff --git a/types/api/channels.d.ts b/types/api/channels.d.ts index 0cd1e4f1e..e935ea356 100644 --- a/types/api/channels.d.ts +++ b/types/api/channels.d.ts @@ -5,7 +5,6 @@ type ChannelStats = { channel_id: string; guest_count: number; member_count: number; - guest_count: number; pinnedpost_count: number; };