Fix channel links when it implies joining a channel (#6686)
This commit is contained in:
parent
b086776c33
commit
4f4f96ff24
7 changed files with 74 additions and 159 deletions
|
|
@ -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<Promise<Model[]>> = [];
|
||||
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};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ type ChannelMentionProps = {
|
|||
channelName: string;
|
||||
channels: ChannelModel[];
|
||||
currentTeamId: string;
|
||||
currentUserId: string;
|
||||
linkStyle: StyleProp<TextStyle>;
|
||||
team: TeamModel;
|
||||
textStyle: StyleProp<TextStyle>;
|
||||
|
|
@ -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'),
|
||||
|
|
|
|||
|
|
@ -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<string, {id?: string; display_name: string;
|
|||
|
||||
const enhance = withObservables([], ({database}: WithDatabaseArgs) => {
|
||||
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,
|
||||
};
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@ const enhanced = withObservables([], ({database}: WithDatabaseArgs) => {
|
|||
|
||||
return {
|
||||
canCreateChannels,
|
||||
currentUserId,
|
||||
currentTeamId,
|
||||
joinedChannels,
|
||||
sharedChannelsEnabled,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in a new issue