Skip to content

Commit 38ca1df

Browse files
authored
chore(voip): dead-code and hygiene sweep (#7174)
1 parent a10bf80 commit 38ca1df

8 files changed

Lines changed: 92 additions & 372 deletions

File tree

MERGE_NOTES.md

Lines changed: 0 additions & 244 deletions
This file was deleted.

__mocks__/react-native-callkeep.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ export default {
44
displayIncomingCall: jest.fn(),
55
endCall: jest.fn(),
66
setCurrentCallActive: jest.fn(),
7+
setAvailable: jest.fn(),
78
addEventListener: jest.fn((event, callback) => ({
89
remove: jest.fn()
910
}))

app/lib/services/voip/mockCall.ts

Lines changed: 0 additions & 93 deletions
This file was deleted.
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { parseStringToIceServers } from './parseStringToIceServers';
2+
3+
describe('parseStringToIceServers', () => {
4+
it('returns empty array for empty input', () => {
5+
expect(parseStringToIceServers('')).toEqual([]);
6+
});
7+
8+
it('returns empty array for whitespace-only input', () => {
9+
expect(parseStringToIceServers(' ')).toEqual([]);
10+
});
11+
12+
it('parses STUN-only server', () => {
13+
expect(parseStringToIceServers('stun:stun.example.com:3478')).toEqual([{ urls: 'stun:stun.example.com:3478' }]);
14+
});
15+
16+
it('parses TURN server with username and credential', () => {
17+
const input = 'user:secret@turn:turn.example.com:3478?transport=udp';
18+
expect(parseStringToIceServers(input)).toEqual([
19+
{
20+
urls: 'turn:turn.example.com:3478?transport=udp',
21+
username: 'user',
22+
credential: 'secret'
23+
}
24+
]);
25+
});
26+
27+
it('decodes URI-encoded username and credential', () => {
28+
const user = encodeURIComponent('user:with:colons');
29+
const cred = encodeURIComponent('p@ss/word');
30+
const input = `${user}:${cred}@turns:turn.example.com:5349`;
31+
expect(parseStringToIceServers(input)).toEqual([
32+
{
33+
urls: 'turns:turn.example.com:5349',
34+
username: 'user:with:colons',
35+
credential: 'p@ss/word'
36+
}
37+
]);
38+
});
39+
40+
it('parses comma-separated list', () => {
41+
const a = 'stun:stun1.example.com';
42+
const b = 'u:p@turn:turn.example.com';
43+
expect(parseStringToIceServers(`${a},${b}`)).toEqual([
44+
{ urls: a },
45+
{ urls: 'turn:turn.example.com', username: 'u', credential: 'p' }
46+
]);
47+
});
48+
49+
it('tolerates malformed tokens without throwing', () => {
50+
expect(parseStringToIceServers('@@@')).toEqual([{ urls: '' }]);
51+
});
52+
});

app/lib/services/voip/parseStringToIceServers.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { IceServer } from '../../../definitions/Voip';
22

3-
export const parseStringToIceServer = (server: string): IceServer => {
3+
function parseStringToIceServer(server: string): IceServer {
44
const credentials = server.trim().split('@');
55
const urls = credentials.pop() as string;
66
const [username, credential] = credentials.length === 1 ? credentials[0].split(':') : [];
@@ -13,7 +13,7 @@ export const parseStringToIceServer = (server: string): IceServer => {
1313
credential: decodeURIComponent(credential)
1414
})
1515
};
16-
};
16+
}
1717

1818
export const parseStringToIceServers = (string: string): IceServer[] => {
1919
if (!string) {

app/lib/services/voip/useCallStore.test.ts

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ jest.mock('react-native-callkeep', () => ({
2121
setAvailable: jest.fn()
2222
}));
2323

24-
function createMockCall(callId: string) {
24+
function createMockCall(callId: string, options?: { initialState?: string }) {
25+
const initialState = options?.initialState ?? 'active';
2526
const listeners: Record<string, Set<(...args: unknown[]) => void>> = {};
2627
const emitter = {
2728
on: (ev: string, fn: (...args: unknown[]) => void) => {
@@ -55,7 +56,7 @@ function createMockCall(callId: string) {
5556
];
5657
const call = {
5758
callId,
58-
state: 'active',
59+
state: initialState,
5960
hidden: false,
6061
localParticipant,
6162
remoteParticipants,
@@ -98,13 +99,6 @@ describe('useCallStore controlsVisible', () => {
9899
expect(useCallStore.getState().controlsVisible).toBe(true);
99100
});
100101

101-
it('showControls sets true when hidden', () => {
102-
useCallStore.getState().toggleControlsVisible();
103-
expect(useCallStore.getState().controlsVisible).toBe(false);
104-
useCallStore.getState().showControls();
105-
expect(useCallStore.getState().controlsVisible).toBe(true);
106-
});
107-
108102
it('auto-shows controls on stateChange event', () => {
109103
const { call, emit } = createMockCall('c1');
110104
useCallStore.getState().setCall(call);
@@ -160,6 +154,39 @@ describe('useCallStore roomId', () => {
160154
useCallStore.getState().reset();
161155
expect(useCallStore.getState().roomId).toBeNull();
162156
});
157+
158+
it('setRoomId persists across setCall until reset', () => {
159+
useCallStore.getState().setRoomId('room-persist-1');
160+
const { call } = createMockCall('persist-call');
161+
useCallStore.getState().setCall(call);
162+
expect(useCallStore.getState().roomId).toBe('room-persist-1');
163+
});
164+
});
165+
166+
describe('useCallStore callStartTime', () => {
167+
beforeEach(() => {
168+
useCallStore.getState().resetNativeCallId();
169+
useCallStore.getState().reset();
170+
});
171+
172+
afterEach(() => {
173+
jest.useRealTimers();
174+
});
175+
176+
it('sets callStartTime when transitioning ringing to active', () => {
177+
jest.useFakeTimers();
178+
const fixed = new Date('2020-01-01T00:00:00.000Z');
179+
jest.setSystemTime(fixed);
180+
const { call, emit } = createMockCall('ring-to-active', { initialState: 'ringing' });
181+
useCallStore.getState().setCall(call);
182+
expect(useCallStore.getState().callStartTime).toBeNull();
183+
184+
(call as { state: string }).state = 'active';
185+
emit('stateChange');
186+
187+
expect(useCallStore.getState().callStartTime).toBe(fixed.getTime());
188+
expect(useCallStore.getState().callState).toBe('active');
189+
});
163190
});
164191

165192
describe('useCallStore native accepted + stale timer', () => {

app/lib/services/voip/useCallStore.ts

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ let staleNativeTimer: ReturnType<typeof setTimeout> | null = null;
1414
/** Call id this timer is for; only `nativeAcceptedCallId` is cleared when it fires, not `callId`. */
1515
let staleNativeScheduledId: string | null = null;
1616

17-
export function cleanupCallListeners(): void {
17+
function cleanupCallListeners(): void {
1818
callListenersCleanup?.();
1919
callListenersCleanup = null;
2020
}
@@ -89,7 +89,6 @@ interface CallStoreActions {
8989
toggleHold: () => void;
9090
toggleSpeaker: () => void;
9191
toggleControlsVisible: () => void;
92-
showControls: () => void;
9392
toggleFocus: () => void;
9493
endCall: () => void;
9594
/** Clears UI/call fields but keeps nativeAcceptedCallId. Restarts the 15s timer (media init calls reset and clears the old timer first). */
@@ -220,10 +219,6 @@ export const useCallStore = create<CallStore>((set, get) => ({
220219
set({ controlsVisible: !get().controlsVisible });
221220
},
222221

223-
showControls: () => {
224-
set({ controlsVisible: true });
225-
},
226-
227222
toggleMute: () => {
228223
const { call, isMuted } = get();
229224
if (!call) return;
@@ -310,11 +305,6 @@ export const useCallStore = create<CallStore>((set, get) => ({
310305
}
311306
}));
312307

313-
export const useCallState = () => {
314-
const callState = useCallStore(state => state.callState);
315-
return callState === 'none' || callState === 'ringing' || callState === 'accepted';
316-
};
317-
318308
export const useCallContact = () => useCallStore(state => state.contact);
319309
export const useDialpadValue = () => useCallStore(state => state.dialpadValue);
320310
export const useControlsVisible = () => {

app/views/RoomsListView/components/ListHeader.tsx

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import { E2E_BANNER_TYPE } from '../../../lib/constants/keys';
77
import { themes } from '../../../lib/constants/colors';
88
import { useAppSelector } from '../../../lib/hooks/useAppSelector';
99
import { events, logEvent } from '../../../lib/methods/helpers/log';
10-
import { launchMockCallView } from '../../../lib/services/voip/mockCall';
1110
import { useTheme } from '../../../theme';
1211
import { RoomsSearchContext } from '../contexts/RoomsSearchProvider';
1312

@@ -40,18 +39,6 @@ const ListHeader = () => {
4039

4140
return (
4241
<>
43-
{__DEV__ ? (
44-
<>
45-
<List.Item
46-
title={'Mock Call (dev)'}
47-
left={() => <List.Icon name='phone' />}
48-
onPress={() => launchMockCallView()}
49-
testID='listheader-mock-call'
50-
translateTitle={false}
51-
/>
52-
<List.Separator />
53-
</>
54-
) : null}
5542
{encryptionBanner ? (
5643
<>
5744
<List.Item

0 commit comments

Comments
 (0)