diff --git a/app/actions/remote/channel.ts b/app/actions/remote/channel.ts index 0835b22cb..3d2f91d40 100644 --- a/app/actions/remote/channel.ts +++ b/app/actions/remote/channel.ts @@ -17,10 +17,10 @@ import NetworkManager from '@managers/network_manager'; import {prepareMyChannelsForTeam, getChannelById, getChannelByName, getMyChannel, getChannelInfo, queryMyChannelSettingsByIds, getMembersCountByChannelsId} from '@queries/servers/channel'; import {queryPreferencesByCategoryAndName} from '@queries/servers/preference'; import {getCommonSystemValues, getConfig, getCurrentTeamId, getCurrentUserId, getLicense, setCurrentChannelId} from '@queries/servers/system'; -import {prepareMyTeams, getNthLastChannelFromTeam, getMyTeamById, getTeamById, getTeamByName, queryMyTeams} from '@queries/servers/team'; +import {getNthLastChannelFromTeam, getMyTeamById, getTeamByName, queryMyTeams} from '@queries/servers/team'; import {getCurrentUser} from '@queries/servers/user'; import EphemeralStore from '@store/ephemeral_store'; -import {generateChannelNameFromDisplayName, getDirectChannelName, isArchived, isDMorGM} from '@utils/channel'; +import {generateChannelNameFromDisplayName, getDirectChannelName, isDMorGM} from '@utils/channel'; import {isTablet} from '@utils/helpers'; import {logError, logInfo} from '@utils/log'; import {showMuteChannelSnackbar} from '@utils/snack_bar'; @@ -32,14 +32,11 @@ import {fetchPostsForChannel} from './post'; import {setDirectChannelVisible} from './preference'; import {fetchRolesIfNeeded} from './role'; import {forceLogoutIfNecessary} from './session'; -import {addUserToTeam, fetchTeamByName, removeUserFromTeam} from './team'; +import {addCurrentUserToTeam, fetchTeamByName, removeCurrentUserFromTeam} from './team'; import {fetchProfilesInGroupChannels, fetchProfilesPerChannels, fetchUsersByIds, updateUsersNoLongerVisible} from './user'; import type {Client} from '@client/rest'; import type ChannelModel from '@typings/database/models/servers/channel'; -import type MyChannelModel from '@typings/database/models/servers/my_channel'; -import type MyTeamModel from '@typings/database/models/servers/my_team'; -import type TeamModel from '@typings/database/models/servers/team'; export type MyChannelsRequest = { categories?: CategoryWithChannels[]; @@ -531,11 +528,12 @@ export async function fetchDirectChannelsInfo(serverUrl: string, directChannels: return fetchMissingDirectChannelsInfo(serverUrl, channels, currentUser?.locale, teammateDisplayNameSetting, currentUser?.id); } -export async function joinChannel(serverUrl: string, userId: string, teamId: string, channelId?: string, channelName?: string, fetchOnly = false) { +export async function joinChannel(serverUrl: string, teamId: string, channelId?: string, channelName?: string, fetchOnly = false) { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { return {error: `${serverUrl} database not found`}; } + const database = operator.database; let client: Client; try { @@ -544,6 +542,8 @@ export async function joinChannel(serverUrl: string, userId: string, teamId: str return {error}; } + const userId = await getCurrentUserId(database); + let member: ChannelMembership | undefined; let channel: Channel | undefined; try { @@ -614,8 +614,7 @@ export async function joinChannelIfNeeded(serverUrl: string, channelId: string) return {error: undefined}; } - const userId = await getCurrentUserId(database); - return joinChannel(serverUrl, userId, '', channelId); + return joinChannel(serverUrl, '', channelId); } catch (error) { return {error}; } @@ -634,167 +633,77 @@ export async function markChannelAsRead(serverUrl: string, channelId: string) { export async function switchToChannelByName(serverUrl: string, channelName: string, teamName: string, errorHandler: (intl: IntlShape) => void, intl: IntlShape) { let database; - let operator; try { const result = DatabaseManager.getServerDatabaseAndOperator(serverUrl); database = result.database; - operator = result.operator; } catch (e) { return {error: `${serverUrl} database not found`}; } + const onError = (joinedTeam: boolean, teamId?: string) => { + errorHandler(intl); + if (joinedTeam && teamId) { + removeCurrentUserFromTeam(serverUrl, teamId, false); + } + }; + + let joinedTeam = false; + let teamId = ''; try { - let myChannel: MyChannelModel | ChannelMembership | undefined; - let team: TeamModel | Team | undefined; - let myTeam: MyTeamModel | TeamMembership | undefined; - let name = teamName; - const roles: string [] = []; - const system = await getCommonSystemValues(database); - const currentTeam = await getTeamById(database, system.currentTeamId); - - if (name === PERMALINK_GENERIC_TEAM_NAME_REDIRECT) { - name = currentTeam!.name; + if (teamName === PERMALINK_GENERIC_TEAM_NAME_REDIRECT) { + teamId = await getCurrentTeamId(database); } else { - team = await getTeamByName(database, teamName); - } + const team = await getTeamByName(database, teamName); + const isTeamMember = team ? await getMyTeamById(database, team.id) : false; + teamId = team?.id || ''; - if (!team) { - const fetchTeam = await fetchTeamByName(serverUrl, name, true); - if (fetchTeam.error) { - errorHandler(intl); - return {error: fetchTeam.error}; + if (!isTeamMember) { + const fetchRequest = await fetchTeamByName(serverUrl, teamName); + if (!fetchRequest.team) { + onError(joinedTeam); + return {error: fetchRequest.error || 'no team received'}; + } + const {error} = await addCurrentUserToTeam(serverUrl, fetchRequest.team.id); + if (error) { + onError(joinedTeam); + return {error}; + } + teamId = fetchRequest.team.id; + joinedTeam = true; } - - team = fetchTeam.team!; } - let joinedNewTeam = false; - myTeam = await getMyTeamById(database, team.id); - if (!myTeam) { - const added = await addUserToTeam(serverUrl, team.id, system.currentUserId, true); - if (added.error) { - errorHandler(intl); - return {error: added.error}; + const channel = await getChannelByName(database, teamId, channelName); + const isChannelMember = channel ? await getMyChannel(database, channel.id) : false; + let channelId = channel?.id || ''; + if (!isChannelMember) { + const fetchRequest = await fetchChannelByName(serverUrl, teamId, channelName, true); + if (!fetchRequest.channel) { + onError(joinedTeam, teamId); + return {error: fetchRequest.error || 'cannot fetch channel'}; } - myTeam = added.member!; - roles.push(...myTeam.roles.split(' ')); - joinedNewTeam = true; - } - - if (!myTeam) { - errorHandler(intl); - return {error: 'Could not fetch team member'}; - } - - let channel: Channel | ChannelModel | undefined = await getChannelByName(database, team.id, channelName); - if (!channel) { - const chReq = await fetchChannelByName(serverUrl, team.id, channelName, true); - if (chReq.error) { - errorHandler(intl); - return {error: chReq.error}; - } - channel = chReq.channel; - } - - if (!channel) { - errorHandler(intl); - return {error: 'Could not fetch channel'}; - } - - if (isArchived(channel) && system.config.ExperimentalViewArchivedChannels !== 'true') { - errorHandler(intl); - return {error: 'Channel is archived'}; - } - - myChannel = await getMyChannel(database, channel.id); - - if (!myChannel) { - const channelTeamId = 'team_id' in channel ? channel.team_id : channel.teamId; - const req = await fetchMyChannel(serverUrl, channelTeamId || team.id, channel.id, true); - myChannel = req.memberships?.[0]; - } - - if (!myChannel) { - if (channel.type === General.PRIVATE_CHANNEL) { - const displayName = 'display_name' in channel ? channel.display_name : channel.displayName; - const {join} = await privateChannelJoinPrompt(displayName, intl); + if (fetchRequest.channel.type === General.PRIVATE_CHANNEL) { + const {join} = await privateChannelJoinPrompt(fetchRequest.channel.display_name, intl); if (!join) { - if (joinedNewTeam) { - await removeUserFromTeam(serverUrl, team.id, system.currentUserId, true); - } - errorHandler(intl); + onError(joinedTeam, teamId); return {error: 'Refused to join Private channel'}; } - logInfo('joining channel', displayName, channel.id); - const result = await joinChannel(serverUrl, system.currentUserId, team.id, channel.id, undefined, true); - if (result.error || !result.channel) { - if (joinedNewTeam) { - await removeUserFromTeam(serverUrl, team.id, system.currentUserId, true); - } - - errorHandler(intl); - return {error: result.error}; - } - - myChannel = result.member!; - roles.push(...myChannel.roles.split(' ')); } + + logInfo('joining channel', fetchRequest.channel.display_name, fetchRequest.channel.id); + const joinRequest = await joinChannel(serverUrl, teamId, undefined, channelName, false); + if (!joinRequest.channel) { + onError(joinedTeam, teamId); + return {error: joinRequest.error || 'no channel returned from join'}; + } + + channelId = fetchRequest.channel.id; } - if (!myChannel) { - errorHandler(intl); - return {error: 'could not fetch channel member'}; - } - - const modelPromises: Array> = []; - if (!(team instanceof Model)) { - modelPromises.push(...prepareMyTeams(operator, [team], [(myTeam as TeamMembership)])); - } else if (!(myTeam instanceof Model)) { - const mt: MyTeam[] = [{ - id: myTeam.team_id, - roles: myTeam.roles, - }]; - modelPromises.push( - operator.handleMyTeam({myTeams: mt, prepareRecordsOnly: true}), - operator.handleTeamMemberships({teamMemberships: [myTeam], prepareRecordsOnly: true}), - ); - } - - // We are checking both, so this may become an issue - if (!(myChannel instanceof Model) && !(channel instanceof Model)) { - modelPromises.push(...await prepareMyChannelsForTeam(operator, team.id, [channel], [myChannel])); - } - - let teamId; - if (team.id !== system.currentTeamId) { - teamId = team.id; - } - - let channelId; - if (channel.id !== system.currentChannelId) { - channelId = channel.id; - } - - if (modelPromises.length) { - const models = await Promise.all(modelPromises); - await operator.batchRecords(models.flat()); - } - - if (teamId) { - fetchMyChannelsForTeam(serverUrl, teamId, true, 0, false, true); - } - - if (teamId || channelId) { - await switchToChannelById(serverUrl, channel.id, team.id); - } - - if (roles.length) { - fetchRolesIfNeeded(serverUrl, roles); - } - + switchToChannelById(serverUrl, channelId, teamId); return {error: undefined}; } catch (error) { - errorHandler(intl); + onError(joinedTeam, teamId); return {error}; } } diff --git a/app/actions/remote/team.ts b/app/actions/remote/team.ts index 534f1be13..83624fb3f 100644 --- a/app/actions/remote/team.ts +++ b/app/actions/remote/team.ts @@ -55,6 +55,7 @@ export async function addUserToTeam(serverUrl: string, teamId: string, userId: s try { EphemeralStore.startAddingToTeam(teamId); + const team = await client.getTeam(teamId); const member = await client.addToTeam(teamId, userId); if (!fetchOnly) { @@ -68,6 +69,7 @@ export async function addUserToTeam(serverUrl: string, teamId: string, userId: s }]; const models: Model[] = (await Promise.all([ + operator.handleTeam({teams: [team], prepareRecordsOnly: true}), operator.handleMyTeam({myTeams, prepareRecordsOnly: true}), operator.handleTeamMemberships({teamMemberships: [member], prepareRecordsOnly: true}), ...await prepareMyChannelsForTeam(operator, teamId, channels || [], channelMembers || []), @@ -248,6 +250,16 @@ export async function fetchTeamByName(serverUrl: string, teamName: string, fetch } } +export const removeCurrentUserFromTeam = async (serverUrl: string, teamId: string, fetchOnly = false) => { + try { + const {database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl); + const userId = await getCurrentUserId(database); + return removeUserFromTeam(serverUrl, teamId, userId, fetchOnly); + } catch (error) { + return {error}; + } +}; + export const removeUserFromTeam = async (serverUrl: string, teamId: string, userId: string, fetchOnly = false) => { let client; try { diff --git a/app/components/markdown/channel_mention/channel_mention.tsx b/app/components/markdown/channel_mention/channel_mention.tsx index 05d5c6220..a4e7ab115 100644 --- a/app/components/markdown/channel_mention/channel_mention.tsx +++ b/app/components/markdown/channel_mention/channel_mention.tsx @@ -21,7 +21,6 @@ type ChannelMentionProps = { channelName: string; channels: ChannelModel[]; currentTeamId: string; - currentUserId: string; linkStyle: StyleProp; team: TeamModel; textStyle: StyleProp; @@ -57,7 +56,7 @@ function getChannelFromChannelName(name: string, channels: ChannelModel[], chann } const ChannelMention = ({ - channelMentions, channelName, channels, currentTeamId, currentUserId, + channelMentions, channelName, channels, currentTeamId, linkStyle, team, textStyle, }: ChannelMentionProps) => { const intl = useIntl(); @@ -68,7 +67,7 @@ const ChannelMention = ({ let c = channel; if (!c?.id && c?.display_name) { - const result = await joinChannel(serverUrl, currentUserId, currentTeamId, undefined, channelName); + const result = await joinChannel(serverUrl, currentTeamId, undefined, channelName); if (result.error || !result.channel) { const joinFailedMessage = { id: t('mobile.join_channel.error'), diff --git a/app/components/markdown/channel_mention/index.ts b/app/components/markdown/channel_mention/index.ts index 9a7a55cc3..274c66de2 100644 --- a/app/components/markdown/channel_mention/index.ts +++ b/app/components/markdown/channel_mention/index.ts @@ -6,7 +6,7 @@ import withObservables from '@nozbe/with-observables'; import {switchMap} from 'rxjs/operators'; import {queryAllChannelsForTeam} from '@queries/servers/channel'; -import {observeCurrentTeamId, observeCurrentUserId} from '@queries/servers/system'; +import {observeCurrentTeamId} from '@queries/servers/system'; import {observeTeam} from '@queries/servers/team'; import ChannelMention from './channel_mention'; @@ -17,7 +17,6 @@ export type ChannelMentions = Record { const currentTeamId = observeCurrentTeamId(database); - const currentUserId = observeCurrentUserId(database); const channels = currentTeamId.pipe( switchMap((id) => queryAllChannelsForTeam(database, id).observeWithColumns(['display_name'])), ); @@ -28,7 +27,6 @@ const enhance = withObservables([], ({database}: WithDatabaseArgs) => { return { channels, currentTeamId, - currentUserId, team, }; }); diff --git a/app/screens/browse_channels/browse_channels.tsx b/app/screens/browse_channels/browse_channels.tsx index 0ba53dfa7..f70e4a007 100644 --- a/app/screens/browse_channels/browse_channels.tsx +++ b/app/screens/browse_channels/browse_channels.tsx @@ -77,7 +77,6 @@ type Props = { closeButton: ImageResource; // Properties not changing during the lifetime of the screen) - currentUserId: string; currentTeamId: string; // Calculated Props @@ -102,7 +101,6 @@ export default function BrowseChannels(props: Props) { canCreateChannels, sharedChannelsEnabled, closeButton, - currentUserId, currentTeamId, canShowArchivedChannels, typeOfChannels, @@ -137,7 +135,7 @@ export default function BrowseChannels(props: Props) { setHeaderButtons(false); setAdding(true); - const result = await joinChannel(serverUrl, currentUserId, currentTeamId, channel.id, '', false); + const result = await joinChannel(serverUrl, currentTeamId, channel.id, '', false); if (result.error) { alertErrorWithFallback( diff --git a/app/screens/browse_channels/index.ts b/app/screens/browse_channels/index.ts index a7c0f2eff..4d85c3628 100644 --- a/app/screens/browse_channels/index.ts +++ b/app/screens/browse_channels/index.ts @@ -43,7 +43,6 @@ const enhanced = withObservables([], ({database}: WithDatabaseArgs) => { return { canCreateChannels, - currentUserId, currentTeamId, joinedChannels, sharedChannelsEnabled, diff --git a/app/screens/permalink/permalink.tsx b/app/screens/permalink/permalink.tsx index 2ed80ce3b..160c8f4d8 100644 --- a/app/screens/permalink/permalink.tsx +++ b/app/screens/permalink/permalink.tsx @@ -279,7 +279,7 @@ function Permalink({ setLoading(true); setError(undefined); if (error?.teamId && error.channelId) { - const {error: joinError} = await joinChannel(serverUrl, currentUserId, error.teamId, error.channelId); + const {error: joinError} = await joinChannel(serverUrl, error.teamId, error.channelId); if (joinError) { Alert.alert('Error joining the channel', 'There was an error trying to join the channel'); setLoading(false);