fix reconnect state; correct new channel state (#6574)

This commit is contained in:
Christopher Poile
2022-08-12 16:02:04 -04:00
committed by GitHub
parent da4b7184df
commit 6e3b2c2bd9
5 changed files with 114 additions and 29 deletions

View File

@@ -15,6 +15,7 @@ import {fetchMissingDirectChannelsInfo, fetchMyChannel, fetchChannelStats, fetch
import {fetchPostsForChannel} from '@actions/remote/post';
import {fetchRolesIfNeeded} from '@actions/remote/role';
import {fetchUsersByIds, updateUsersNoLongerVisible} from '@actions/remote/user';
import {loadCallForChannel} from '@calls/actions/calls';
import {Events, Screens} from '@constants';
import DatabaseManager from '@database/manager';
import {queryActiveServer} from '@queries/app/servers';
@@ -293,6 +294,8 @@ export async function handleUserAddedToChannelEvent(serverUrl: string, msg: any)
models.push(...prepared);
}
}
loadCallForChannel(serverUrl, channelId);
} else {
const addedUser = getUserById(database, userId);
if (!addedUser) {

View File

@@ -11,7 +11,8 @@ import {fetchStatusByIds} from '@actions/remote/user';
import {loadConfigAndCalls} from '@calls/actions/calls';
import {
handleCallChannelDisabled,
handleCallChannelEnabled, handleCallEnded,
handleCallChannelEnabled,
handleCallEnded,
handleCallScreenOff,
handleCallScreenOn,
handleCallStarted,
@@ -175,10 +176,6 @@ async function doReconnectRest(serverUrl: string, operator: ServerDataOperator,
const {locale: currentUserLocale} = (await getCurrentUser(database))!;
await deferredAppEntryActions(serverUrl, lastDisconnectedAt, currentUserId, currentUserLocale, prefData.preferences, config, license, teamData, chData, initialTeamId, switchedToChannel ? initialChannelId : undefined);
if (isSupportedServerCalls(config?.Version)) {
loadConfigAndCalls(serverUrl, currentUserId);
}
// https://mattermost.atlassian.net/browse/MM-41520
}
@@ -207,6 +204,11 @@ async function doReconnect(serverUrl: string) {
} else {
await doReconnectRest(serverUrl, operator, system.currentTeamId, system.currentUserId, config, license, lastDisconnectedAt);
}
// Calls is not set up for GraphQL yet
if (isSupportedServerCalls(config?.Version)) {
loadConfigAndCalls(serverUrl, system.currentUserId);
}
}
export async function handleEvent(serverUrl: string, msg: WebSocketMessage) {

View File

@@ -6,7 +6,8 @@ import InCallManager from 'react-native-incall-manager';
import {forceLogoutIfNecessary} from '@actions/remote/session';
import {fetchUsersByIds} from '@actions/remote/user';
import {
getCallsConfig, getCallsState,
getCallsConfig,
getCallsState,
myselfLeftCall,
setCalls,
setChannelEnabled,
@@ -14,6 +15,7 @@ import {
setPluginEnabled,
setScreenShareURL,
setSpeakerPhone,
setCallForChannel,
} from '@calls/state';
import {General, Preferences} from '@constants';
import Calls from '@constants/calls';
@@ -33,6 +35,7 @@ import type {
Call,
CallParticipant,
CallsConnection,
ServerCallState,
ServerChannelState,
} from '@calls/types/calls';
import type {Client} from '@client/rest';
@@ -94,24 +97,7 @@ export const loadCalls = async (serverUrl: string, userId: string) => {
for (const channel of resp) {
if (channel.call) {
const call = channel.call;
callsResults[channel.channel_id] = {
participants: channel.call.users.reduce((accum, cur, curIdx) => {
// Add the id to the set of UserModels we want to ensure are loaded.
ids.add(cur);
// Create the CallParticipant
const muted = call.states && call.states[curIdx] ? !call.states[curIdx].unmuted : true;
const raisedHand = call.states && call.states[curIdx] ? call.states[curIdx].raised_hand : 0;
accum[cur] = {id: cur, muted, raisedHand};
return accum;
}, {} as Dictionary<CallParticipant>),
channelId: channel.channel_id,
startTime: call.start_at,
screenOn: call.screen_sharing_id,
threadId: call.thread_id,
ownerId: call.owner_id,
};
callsResults[channel.channel_id] = createCallAndAddToIds(channel.channel_id, channel.call, ids);
}
enabledChannels[channel.channel_id] = channel.enabled;
}
@@ -126,6 +112,58 @@ export const loadCalls = async (serverUrl: string, userId: string) => {
return {data: {calls: callsResults, enabled: enabledChannels}};
};
export const loadCallForChannel = async (serverUrl: string, channelId: string) => {
let client: Client;
try {
client = NetworkManager.getClient(serverUrl);
} catch (error) {
return {error};
}
let resp: ServerChannelState;
try {
resp = await client.getCallForChannel(channelId);
} catch (error) {
await forceLogoutIfNecessary(serverUrl, error as ClientError);
return {error};
}
let call: Call | undefined;
const ids = new Set<string>();
if (resp.call) {
call = createCallAndAddToIds(channelId, resp.call, ids);
}
// Batch load user models async because we'll need them later
if (ids.size > 0) {
fetchUsersByIds(serverUrl, Array.from(ids));
}
setCallForChannel(serverUrl, channelId, resp.enabled, call);
return {data: {call, enabled: resp.enabled}};
};
const createCallAndAddToIds = (channelId: string, call: ServerCallState, ids: Set<string>) => {
return {
participants: call.users.reduce((accum, cur, curIdx) => {
// Add the id to the set of UserModels we want to ensure are loaded.
ids.add(cur);
// Create the CallParticipant
const muted = call.states && call.states[curIdx] ? !call.states[curIdx].unmuted : true;
const raisedHand = call.states && call.states[curIdx] ? call.states[curIdx].raised_hand : 0;
accum[cur] = {id: cur, muted, raisedHand};
return accum;
}, {} as Dictionary<CallParticipant>),
channelId,
startTime: call.start_at,
screenOn: call.screen_sharing_id,
threadId: call.thread_id,
ownerId: call.owner_id,
} as Call;
};
export const loadConfigAndCalls = async (serverUrl: string, userId: string) => {
const res = await checkIsCallsPluginEnabled(serverUrl);
if (res.data) {

View File

@@ -6,6 +6,7 @@ import type {ServerChannelState, ServerCallsConfig, ApiResp, ICEServersConfigs}
export interface ClientCallsMix {
getEnabled: () => Promise<Boolean>;
getCalls: () => Promise<ServerChannelState[]>;
getCallForChannel: (channelId: string) => Promise<ServerChannelState>;
getCallsConfig: () => Promise<ServerCallsConfig>;
enableChannelCalls: (channelId: string, enable: boolean) => Promise<ServerChannelState>;
endCall: (channelId: string) => Promise<ApiResp>;
@@ -32,6 +33,13 @@ const ClientCalls = (superclass: any) => class extends superclass {
);
};
getCallForChannel = async (channelId: string) => {
return this.doFetch(
`${this.getCallsRoute()}/${channelId}`,
{method: 'get'},
);
};
getCallsConfig = async () => {
return this.doFetch(
`${this.getCallsRoute()}/config`,

View File

@@ -24,6 +24,40 @@ export const setCalls = (serverUrl: string, myUserId: string, calls: Dictionary<
setCallsState(serverUrl, {serverUrl, myUserId, calls, enabled});
};
export const setCallForChannel = (serverUrl: string, channelId: string, enabled: boolean, call?: Call) => {
const callsState = getCallsState(serverUrl);
const nextEnabled = {...callsState.enabled, [channelId]: enabled};
const nextCalls = {...callsState.calls};
if (call) {
nextCalls[channelId] = call;
// In case we got a complete update on the currentCall
const currentCall = getCurrentCall();
if (currentCall?.channelId === channelId) {
setCurrentCall({
...currentCall,
...call,
});
}
} else {
delete nextCalls[channelId];
}
setCallsState(serverUrl, {...callsState, calls: nextCalls, enabled: nextEnabled});
const channelsWithCalls = getChannelsWithCalls(serverUrl);
if (call && !channelsWithCalls[channelId]) {
const nextChannelsWithCalls = {...channelsWithCalls};
nextChannelsWithCalls[channelId] = true;
setChannelsWithCalls(serverUrl, nextChannelsWithCalls);
} else if (!call && channelsWithCalls[channelId]) {
const nextChannelsWithCalls = {...channelsWithCalls};
delete nextChannelsWithCalls[channelId];
setChannelsWithCalls(serverUrl, nextChannelsWithCalls);
}
};
export const userJoinedCall = (serverUrl: string, channelId: string, userId: string) => {
const callsState = getCallsState(serverUrl);
if (!callsState.calls[channelId]) {
@@ -46,11 +80,11 @@ export const userJoinedCall = (serverUrl: string, channelId: string, userId: str
// Did the user join the current call? If so, update that too.
const currentCall = getCurrentCall();
if (currentCall && currentCall.channelId === channelId) {
const nextCall2 = {
const nextCurrentCall = {
...currentCall,
participants: {...currentCall.participants, [userId]: nextCall.participants[userId]},
};
setCurrentCall(nextCall2);
setCurrentCall(nextCurrentCall);
}
// Was it me that joined the call?
@@ -97,12 +131,12 @@ export const userLeftCall = (serverUrl: string, channelId: string, userId: strin
return;
}
const nextCall2 = {
const nextCurrentCall = {
...currentCall,
participants: {...currentCall.participants},
};
delete nextCall2.participants[userId];
setCurrentCall(nextCall2);
delete nextCurrentCall.participants[userId];
setCurrentCall(nextCurrentCall);
};
export const myselfLeftCall = () => {