Derive connection state for current call from RTC peer (#8878)
Co-authored-by: Mattermost Build <build@mattermost.com>
This commit is contained in:
parent
47241539d4
commit
5030525c3e
8 changed files with 67 additions and 7 deletions
|
|
@ -28,6 +28,7 @@ import {
|
|||
userJoinedCall,
|
||||
getCurrentCall,
|
||||
} from '@calls/state';
|
||||
import * as StateActions from '@calls/state/actions';
|
||||
import {
|
||||
type Call,
|
||||
type CallsState,
|
||||
|
|
@ -86,7 +87,7 @@ jest.mock('@calls/connection/connection', () => ({
|
|||
disconnect: jest.fn((err?: Error) => onClose(err)),
|
||||
mute: jest.fn(),
|
||||
unmute: jest.fn(),
|
||||
waitForPeerConnection: jest.fn(() => Promise.resolve()),
|
||||
waitForPeerConnection: jest.fn(() => Promise.resolve('session-id')),
|
||||
initializeVoiceTrack: jest.fn(),
|
||||
sendReaction: jest.fn(),
|
||||
})),
|
||||
|
|
@ -258,6 +259,7 @@ describe('Actions.Calls', () => {
|
|||
return [useCallsState('server1'), useCurrentCall()];
|
||||
});
|
||||
addFakeCall('server1', 'channel-id');
|
||||
const setCurrentCallConnectedMock = jest.spyOn(StateActions, 'setCurrentCallConnected');
|
||||
|
||||
let response: { data?: string };
|
||||
await act(async () => {
|
||||
|
|
@ -266,6 +268,8 @@ describe('Actions.Calls', () => {
|
|||
messages: {},
|
||||
}));
|
||||
|
||||
expect(setCurrentCallConnectedMock).toHaveBeenCalledWith('channel-id', 'session-id');
|
||||
|
||||
// manually call newCurrentConnection because newConnection is mocked
|
||||
newCurrentCall('server1', 'channel-id', 'myUserId');
|
||||
});
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import {
|
|||
getCurrentCall,
|
||||
myselfLeftCall,
|
||||
newCurrentCall,
|
||||
setCurrentCallConnected,
|
||||
setCallForChannel,
|
||||
setCalls,
|
||||
setChannelEnabled,
|
||||
|
|
@ -249,7 +250,9 @@ export const joinCall = async (
|
|||
}
|
||||
|
||||
try {
|
||||
await connection.waitForPeerConnection();
|
||||
const sessionId = await connection.waitForPeerConnection();
|
||||
|
||||
setCurrentCallConnected(channelId, sessionId);
|
||||
|
||||
// Follow the thread.
|
||||
const database = DatabaseManager.serverDatabases[serverUrl]?.database;
|
||||
|
|
|
|||
|
|
@ -585,6 +585,7 @@ describe('newConnection', () => {
|
|||
}
|
||||
},
|
||||
send: jest.fn(),
|
||||
sessionID: 'sessionID',
|
||||
}));
|
||||
|
||||
connection = await newConnection(
|
||||
|
|
@ -600,7 +601,7 @@ describe('newConnection', () => {
|
|||
|
||||
res = connection.waitForPeerConnection();
|
||||
jest.runAllTimers();
|
||||
await expect(res).resolves.not.toThrow();
|
||||
await expect(res).resolves.toBe('sessionID');
|
||||
jest.useRealTimers();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -458,7 +458,7 @@ export async function newConnection(
|
|||
});
|
||||
|
||||
const waitForPeerConnection = () => {
|
||||
const waitForReadyImpl = (callback: () => void, fail: (reason: string) => void, timeout: number) => {
|
||||
const waitForReadyImpl = (callback: (sessionId: string) => void, fail: (reason: string) => void, timeout: number) => {
|
||||
if (timeout <= 0) {
|
||||
fail('timed out waiting for peer connection');
|
||||
return;
|
||||
|
|
@ -466,14 +466,14 @@ export async function newConnection(
|
|||
setTimeout(() => {
|
||||
if (peer?.connected) {
|
||||
rtcMonitor?.start();
|
||||
callback();
|
||||
callback(ws.sessionID);
|
||||
} else {
|
||||
waitForReadyImpl(callback, fail, timeout - 200);
|
||||
}
|
||||
}, 200);
|
||||
};
|
||||
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
return new Promise<string>((resolve, reject) => {
|
||||
waitForReadyImpl(resolve, reject, peerConnectTimeout);
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -180,4 +180,8 @@ export class WebSocketClient extends EventEmitter {
|
|||
}
|
||||
return this.ws.readyState;
|
||||
}
|
||||
|
||||
get sessionID() {
|
||||
return this.originalConnID;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import {
|
|||
useCallsConfig,
|
||||
useCallsState,
|
||||
useChannelsWithCalls,
|
||||
setCurrentCallConnected,
|
||||
useCurrentCall,
|
||||
useGlobalCallsState,
|
||||
useIncomingCalls,
|
||||
|
|
@ -1628,6 +1629,39 @@ describe('useCallsState', () => {
|
|||
assert.deepEqual(result.current[1], {'channel-2': true});
|
||||
});
|
||||
|
||||
it('setCurrentCallConnected', () => {
|
||||
const initialCurrentCallState: CurrentCall = {
|
||||
...DefaultCurrentCall,
|
||||
serverUrl: 'server1',
|
||||
myUserId: 'myUserId',
|
||||
connected: false,
|
||||
mySessionId: '',
|
||||
...call1,
|
||||
};
|
||||
|
||||
// setup
|
||||
const {result} = renderHook(() => useCurrentCall());
|
||||
act(() => {
|
||||
setCurrentCall(initialCurrentCallState);
|
||||
});
|
||||
assert.deepEqual(result.current, initialCurrentCallState);
|
||||
|
||||
// test
|
||||
act(() => setCurrentCallConnected('channel-1', 'session-test-id'));
|
||||
assert.deepEqual(result.current, {
|
||||
...initialCurrentCallState,
|
||||
connected: true,
|
||||
mySessionId: 'session-test-id',
|
||||
});
|
||||
|
||||
// test with wrong channel ID (should not change state)
|
||||
act(() => {
|
||||
setCurrentCall(initialCurrentCallState);
|
||||
setCurrentCallConnected('wrong-channel', 'session-test-id');
|
||||
});
|
||||
assert.deepEqual(result.current, initialCurrentCallState);
|
||||
});
|
||||
|
||||
it('captions', () => {
|
||||
const initialCallsState = {
|
||||
...DefaultCallsState,
|
||||
|
|
|
|||
|
|
@ -451,6 +451,20 @@ export const newCurrentCall = (serverUrl: string, channelId: string, myUserId: s
|
|||
});
|
||||
};
|
||||
|
||||
export const setCurrentCallConnected = (channelId: string, sessionId: string) => {
|
||||
const currentCall = getCurrentCall();
|
||||
if (!currentCall || currentCall.channelId !== channelId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const nextCurrentCall: CurrentCall = {
|
||||
...currentCall,
|
||||
connected: true,
|
||||
mySessionId: sessionId,
|
||||
};
|
||||
setCurrentCall(nextCurrentCall);
|
||||
};
|
||||
|
||||
export const myselfLeftCall = () => {
|
||||
setCurrentCall(null);
|
||||
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@ export type CallsConnection = {
|
|||
disconnect: (err?: Error) => void;
|
||||
mute: () => void;
|
||||
unmute: () => void;
|
||||
waitForPeerConnection: () => Promise<void>;
|
||||
waitForPeerConnection: () => Promise<string>;
|
||||
raiseHand: () => void;
|
||||
unraiseHand: () => void;
|
||||
initializeVoiceTrack: () => void;
|
||||
|
|
|
|||
Loading…
Reference in a new issue