Skip to content

Commit 165a9c3

Browse files
authored
fix: allow anonymous StreamVideoClientOptions to accept token fields (#2142)
- allow `StreamVideoClientOptions` for anonymous users to accept `token` and `tokenProvider` - fix React Native sample app compile errors caused by guest/anonymous union arguments at `getOrCreateInstance` ### 📝 Implementation notes - split guest and anonymous option variants in `packages/client/src/types.ts` - keep guest behavior unchanged (`token`/`tokenProvider` are disallowed) - add anonymous variant with optional `token` and `tokenProvider` - keep authenticated user variant strict (at least one of `token` or `tokenProvider`) - update dogfood `GuestMeetingScreen` and expo sample `VideoWrapper` to narrow user type before calling `getOrCreateInstance` 🎫 Ticket: #2138
1 parent 12749ae commit 165a9c3

File tree

3 files changed

+43
-30
lines changed

3 files changed

+43
-30
lines changed

packages/client/src/types.ts

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -350,14 +350,21 @@ type StreamVideoClientOptionsWithoutUser = StreamVideoClientBaseOptions & {
350350
tokenProvider?: never;
351351
};
352352

353-
type GuestOrAnonymousUser = Extract<User, { type: 'guest' | 'anonymous' }>;
354-
type AuthenticatedUser = Exclude<User, GuestOrAnonymousUser>;
353+
type GuestUser = Extract<User, { type: 'guest' }>;
354+
type AnonymousUser = Extract<User, { type: 'anonymous' }>;
355+
type AuthenticatedUser = Exclude<User, GuestUser | AnonymousUser>;
355356

356-
type StreamVideoClientOptionsWithGuestOrAnonymousUser =
357+
type StreamVideoClientOptionsWithGuestUser = StreamVideoClientBaseOptions & {
358+
user: GuestUser;
359+
token?: never;
360+
tokenProvider?: never;
361+
};
362+
363+
type StreamVideoClientOptionsWithAnonymousUser =
357364
StreamVideoClientBaseOptions & {
358-
user: GuestOrAnonymousUser;
359-
token?: never;
360-
tokenProvider?: never;
365+
user: AnonymousUser;
366+
token?: string;
367+
tokenProvider?: TokenProvider;
361368
};
362369

363370
type StreamVideoClientOptionsWithAuthenticatedUser =
@@ -370,7 +377,8 @@ type StreamVideoClientOptionsWithAuthenticatedUser =
370377

371378
export type StreamVideoClientOptions =
372379
| StreamVideoClientOptionsWithoutUser
373-
| StreamVideoClientOptionsWithGuestOrAnonymousUser
380+
| StreamVideoClientOptionsWithGuestUser
381+
| StreamVideoClientOptionsWithAnonymousUser
374382
| StreamVideoClientOptionsWithAuthenticatedUser;
375383

376384
export type CallRecordingType = CallRecordingStartedEventRecordingTypeEnum;

sample-apps/react-native/dogfood/src/screens/Meeting/GuestMeetingScreen.tsx

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import {
55
StreamCall,
66
StreamVideo,
77
StreamVideoClient,
8-
User,
98
} from '@stream-io/video-react-native-sdk';
109
import { MeetingStackParamList } from '../../../types';
1110
import { MeetingUI } from '../../components/MeetingUI';
@@ -29,34 +28,33 @@ export const GuestMeetingScreen = (props: Props) => {
2928
} = props.route;
3029
const callType = 'default';
3130

32-
const userToConnect: User = useMemo(
33-
() =>
34-
mode === 'guest'
35-
? {
36-
id: guestUserId,
37-
type: 'guest',
38-
}
39-
: {
40-
type: 'anonymous',
41-
},
42-
[mode, guestUserId],
43-
);
44-
4531
useEffect(() => {
4632
let _videoClient: StreamVideoClient | undefined;
4733
const run = async () => {
48-
const { apiKey } = await createToken(
34+
const { apiKey, token } = await createToken(
4935
{
50-
user_id: userToConnect.id ?? '!anon',
36+
user_id: mode === 'guest' ? guestUserId : '!anon',
5137
call_cids: mode === 'anonymous' ? `${callType}:${callId}` : undefined,
5238
},
5339
appEnvironment,
5440
);
55-
_videoClient = StreamVideoClient.getOrCreateInstance({
56-
apiKey,
57-
user: userToConnect,
58-
options: { logLevel: 'warn', rejectCallWhenBusy: true },
59-
});
41+
42+
const options = { logLevel: 'warn', rejectCallWhenBusy: true } as const;
43+
if (mode === 'guest') {
44+
_videoClient = StreamVideoClient.getOrCreateInstance({
45+
apiKey,
46+
user: { id: guestUserId, type: 'guest' },
47+
options,
48+
});
49+
} else {
50+
_videoClient = StreamVideoClient.getOrCreateInstance({
51+
apiKey,
52+
user: { type: 'anonymous' },
53+
token,
54+
options,
55+
});
56+
}
57+
6058
setVideoClient(_videoClient);
6159
};
6260

@@ -66,7 +64,7 @@ export const GuestMeetingScreen = (props: Props) => {
6664
_videoClient?.disconnectUser();
6765
setVideoClient(undefined);
6866
};
69-
}, [userToConnect, mode, callId, appEnvironment]);
67+
}, [mode, guestUserId, callId, appEnvironment]);
7068

7169
const call = useMemo<Call | undefined>(() => {
7270
if (!videoClient) {

sample-apps/react-native/expo-video-sample/components/VideoWrapper.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,19 @@ export const VideoWrapper = ({ children }: PropsWithChildren<{}>) => {
2323
};
2424
const { apiKey, token } = await fetchAuthDetails();
2525

26-
if (user.type === 'guest' || user.type === 'anonymous') {
26+
if (user.type === 'guest') {
2727
_videoClient = StreamVideoClient.getOrCreateInstance({
2828
apiKey,
2929
user,
3030
options: { logLevel: 'warn' },
3131
});
32+
} else if (user.type === 'anonymous') {
33+
_videoClient = StreamVideoClient.getOrCreateInstance({
34+
apiKey,
35+
user,
36+
token,
37+
options: { logLevel: 'warn' },
38+
});
3239
} else {
3340
const tokenProvider = () =>
3441
fetchAuthDetails().then((auth) => auth.token);

0 commit comments

Comments
 (0)