Skip to content

Commit

Permalink
feat: anon and guest login for Pronto
Browse files Browse the repository at this point in the history
  • Loading branch information
oliverlaz committed Dec 20, 2023
1 parent 318892f commit 8b0ea77
Show file tree
Hide file tree
Showing 9 changed files with 172 additions and 125 deletions.
111 changes: 71 additions & 40 deletions sample-apps/react/react-dogfood/components/Lobby.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
VideoPreview,
} from '@stream-io/video-react-sdk';
import clsx from 'clsx';
import Link from 'next/link';
import { isAndroid, isIOS, isSafari } from 'mobile-device-detect';

import { DisabledVideoPreview } from './DisabledVideoPreview';
Expand All @@ -21,14 +22,22 @@ import { ToggleCameraButton } from './ToggleCameraButton';
import { useEdges } from '../hooks/useEdges';
import { DefaultAppHeader } from './DefaultAppHeader';
import { useLayoutSwitcher } from '../hooks';
import { useIsDemoEnvironment } from '../context/AppEnvironmentContext';
import {
useIsDemoEnvironment,
useIsProntoEnvironment,
} from '../context/AppEnvironmentContext';

export type UserMode = 'regular' | 'guest' | 'anon';

type LobbyProps = {
export type LobbyProps = {
onJoin: () => void;
callId?: string;
enablePreview?: boolean;
mode?: UserMode;
};
export const Lobby = ({ onJoin, callId, enablePreview = true }: LobbyProps) => {

const basePath = process.env.NEXT_PUBLIC_BASE_PATH || '';

export const Lobby = ({ onJoin, callId, mode = 'regular' }: LobbyProps) => {
const { data: session, status } = useSession();
const { useMicrophoneState, useCameraState } = useCallStateHooks();
const { hasBrowserPermission: hasMicPermission } = useMicrophoneState();
Expand Down Expand Up @@ -56,6 +65,7 @@ export const Lobby = ({ onJoin, callId, enablePreview = true }: LobbyProps) => {
};
}, [onJoin]);

const isProntoEnvironment = useIsProntoEnvironment();
const isDemoEnvironment = useIsDemoEnvironment();
const [shouldRenderMobileAppBanner, setShouldRenderMobileAppBanner] =
useState(isDemoEnvironment && (isAndroid || (isIOS && !isSafari)));
Expand All @@ -72,43 +82,45 @@ export const Lobby = ({ onJoin, callId, enablePreview = true }: LobbyProps) => {
<LatencyMap sourceData={edges} />
<div className="rd__lobby-container">
<div className="rd__lobby-content">
<h1 className="rd__lobby-heading">
Set up your call before joining!
</h1>
<div
className={clsx(
'rd__lobby-camera',
isCameraMute && 'rd__lobby-camera--off',
)}
>
<div className="rd__lobby-video-preview">
<VideoPreview
DisabledVideoPreview={
hasBrowserMediaPermission
? DisabledVideoPreview
: AllowBrowserPermissions
}
/>
<div className="rd__lobby-media-toggle">
<ToggleAudioPreviewButton />

<ToggleVideoPreviewButton />
</div>
</div>
<div className="rd__lobby-controls">
<div className="rd__lobby-media">
<ToggleMicButton />
<ToggleCameraButton />
</div>

<ToggleSettingsTabModal
selectedLayout={layout}
onMenuItemClick={setLayout}
inMeeting={false}
/>
</div>
</div>
{mode !== 'anon' && (
<>
<h1 className="rd__lobby-heading">
Set up your call before joining!
</h1>
<div
className={clsx(
'rd__lobby-camera',
isCameraMute && 'rd__lobby-camera--off',
)}
>
<div className="rd__lobby-video-preview">
<VideoPreview
DisabledVideoPreview={
hasBrowserMediaPermission
? DisabledVideoPreview
: AllowBrowserPermissions
}
/>
<div className="rd__lobby-media-toggle">
<ToggleAudioPreviewButton />
<ToggleVideoPreviewButton />
</div>
</div>
<div className="rd__lobby-controls">
<div className="rd__lobby-media">
<ToggleMicButton />
<ToggleCameraButton />
</div>

<ToggleSettingsTabModal
selectedLayout={layout}
onMenuItemClick={setLayout}
inMeeting={false}
/>
</div>
</div>
</>
)}
<button
className="rd__button rd__button--primary rd__button--large rd__lobby-join"
data-testid="join-call-button"
Expand All @@ -117,6 +129,25 @@ export const Lobby = ({ onJoin, callId, enablePreview = true }: LobbyProps) => {
<Icon className="rd__button__icon" icon="login" />
{t('Join')}
</button>

{isProntoEnvironment && (
<div className="rd__lobby__user-modes">
{mode === 'regular' && (
<Link
href={`${basePath}/guest/?callId=${callId}`}
className="rd__link rd__link--faux-button"
children="Continue as Guest or Anonymous"
/>
)}
{(mode === 'guest' || mode === 'anon') && (
<Link
href={`${basePath}/join/${callId}`}
className="rd__link rd__link--faux-button"
children="Continue with Regular User"
/>
)}
</div>
)}
</div>
{shouldRenderMobileAppBanner && (
<MobileAppBanner
Expand Down
12 changes: 4 additions & 8 deletions sample-apps/react/react-dogfood/components/MeetingUI.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
usePersistedDevicePreferences,
} from '@stream-io/video-react-sdk';

import { Lobby } from './Lobby';
import { Lobby, UserMode } from './Lobby';
import { StreamChat } from 'stream-chat';
import { useKeyboardShortcuts, useWakeLock } from '../hooks';
import { ActiveCall } from './ActiveCall';
Expand All @@ -27,9 +27,9 @@ const contents = {

type MeetingUIProps = {
chatClient?: StreamChat | null;
enablePreview?: boolean;
mode?: UserMode;
};
export const MeetingUI = ({ chatClient, enablePreview }: MeetingUIProps) => {
export const MeetingUI = ({ chatClient, mode }: MeetingUIProps) => {
const [show, setShow] = useState<
'lobby' | 'error-join' | 'error-leave' | 'loading' | 'active-call'
>('lobby');
Expand Down Expand Up @@ -134,11 +134,7 @@ export const MeetingUI = ({ chatClient, enablePreview }: MeetingUIProps) => {
);
} else if (show === 'lobby') {
ComponentToRender = (
<Lobby
onJoin={onJoin}
callId={activeCall?.id}
enablePreview={enablePreview}
/>
<Lobby onJoin={onJoin} callId={activeCall?.id} mode={mode} />
);
} else if (show === 'loading') {
ComponentToRender = <LoadingScreen />;
Expand Down
114 changes: 48 additions & 66 deletions sample-apps/react/react-dogfood/pages/guest/index.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import { Box, Button, Input, Stack, Typography } from '@mui/material';
import { useSearchParams } from 'next/navigation';
import { useRouter } from 'next/router';
import Link from 'next/link';
import { useEffect, useState } from 'react';
import { meetingId } from '../../lib/meetingId';
import { DefaultAppHeader } from '../../components/DefaultAppHeader';

export default function Guest() {
const params = useSearchParams();
const router = useRouter();

const callIdFromQuery = params.get('callId');
const nameFromQuery = params.get('name') || 'Guest';
Expand All @@ -27,70 +25,54 @@ export default function Guest() {
return (
<>
<DefaultAppHeader />
<Stack
direction="row"
justifyContent="center"
alignItems="center"
spacing={2}
flexGrow={1}
>
<Stack spacing={2} alignItems="center" flexGrow={1}>
<Box padding={2}>
<Typography variant="h2" textAlign="center">
Stream Meetings
</Typography>
<Typography variant="h5" textAlign="center">
Guest Mode
</Typography>
</Box>
<Stack direction="row" gap="10px">
<Input
classes={{
input: `rd__input rd__input--underlined rd__join-call-input`,
}}
placeholder="Meeting ID"
value={callId}
onChange={(e) => {
setCallId(e.target.value);
}}
<div className="rd__guest-page rd__home">
<div className="rd__guest-page__content">
<div className="rd__guest-page__header">
<img
className="rd__home-image"
src={`${process.env.NEXT_PUBLIC_BASE_PATH || ''}/home.png`}
alt="Home"
/>
<Input
classes={{
input: `rd__input rd__input--underlined rd__join-call-input`,
}}
placeholder="Your name"
value={name}
onChange={(e) => {
setName(e.target.value);
}}
/>
</Stack>
<Stack gap="10px">
<Button
disabled={!callId || !name}
data-testid="join-call-as-guest-button"
variant="contained"
onClick={() => {
router.push(
`/guest/join/${callId}?mode=guest&guest_user_id=${name}`,
);
}}
>
Join as Guest
</Button>
<Button
disabled={!callId || !name}
data-testid="join-call-as-anon-button"
variant="outlined"
onClick={() => {
router.push(`/guest/join/${callId}?mode=anon`);
}}
>
Continue Anonymously
</Button>
</Stack>
</Stack>
</Stack>
<h1 className="rd__home-heading">
Stream
<span>[Video Calling]</span>
</h1>
<p className="rd__home-description">
Start a new call or join an existing one by providing its Call ID
</p>
<div className="rd__guest-page__config">
<input
type="text"
className="rd__input rd__input--underlined rd__join-call-input"
placeholder="Meeting ID"
value={callId}
onChange={(e) => setCallId(e.target.value)}
/>
<input
type="text"
className="rd__input rd__input--underlined rd__join-call-input"
placeholder="Your name"
value={name}
onChange={(e) => setName(e.target.value)}
/>
</div>
<div className="rd__guest-page__buttons">
<Link
className="rd__link rd__link--faux-button rd__link--primary"
data-testid="join-call-as-guest-button"
href={`/guest/join/${callId}?mode=guest&guest_user_id=${name}`}
children="Join as Guest"
/>
<Link
className="rd__link rd__link--faux-button"
data-testid="join-call-as-anon-button"
href={`/guest/join/${callId}?mode=anon`}
children="Join Anonimously"
/>
</div>
</div>
</div>
</div>
</>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
import Head from 'next/head';
import { useRouter } from 'next/router';
import { MeetingUI } from '../../../components';
import { type UserMode } from '../../../components/Lobby';
import { createToken } from '../../../helpers/jwt';
import { useEffect, useState } from 'react';
import { useGleap } from '../../../hooks/useGleap';
Expand All @@ -33,15 +34,15 @@ export default function GuestCallRoom(props: GuestCallRoomProps) {
const router = useRouter();
const callId = router.query['guestCallId'] as string;
const callType = (router.query['type'] as string) || 'default';
const mode = (router.query['mode'] as 'anon' | 'guest') || 'anon';
const mode = (router.query['mode'] as UserMode) || 'anon';
const guestUserId = (router.query['guest_user_id'] as string) || 'Guest';

const [client, setClient] = useState<StreamVideoClient>();
useEffect(() => {
const userToConnect: User =
mode === 'anon'
? { type: 'anonymous' }
: { id: guestUserId, type: 'guest' };
: { id: guestUserId, name: guestUserId, type: 'guest' };
const tokenToUse = mode === 'anon' ? token : undefined;
const _client = new StreamVideoClient({
apiKey,
Expand Down Expand Up @@ -102,7 +103,7 @@ export default function GuestCallRoom(props: GuestCallRoomProps) {
</Head>
<StreamVideo client={client}>
<StreamCall call={call}>
<MeetingUI enablePreview={mode !== 'anon'} />
<MeetingUI mode={mode} />
</StreamCall>
</StreamVideo>
</>
Expand Down
4 changes: 1 addition & 3 deletions sample-apps/react/react-dogfood/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,7 @@ const HomeContent = () => {
{isDemoEnvironment && t('Demo')}
</h1>
<p className="rd__home-description">
{t(
'Start a new call or join an existing one by providing its Call ID',
)}
Start a new call or join an existing one by providing its Call ID
</p>
<div className="rd__home-join">
<input
Expand Down
31 changes: 31 additions & 0 deletions sample-apps/react/react-dogfood/style/guest.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
.rd__guest-page {
display: flex;

.rd__guest-page__content {
display: flex;
flex-grow: 1;
justify-content: center;
align-items: center;
gap: 10px;
}

.rd__guest-page__header {
display: flex;
flex-grow: 1;
flex-direction: column;
align-items: center;
gap: 10px;
}

.rd__guest-page__config {
display: flex;
flex-direction: row;
gap: 10px;
}

.rd__guest-page__buttons {
display: flex;
flex-direction: column;
width: 100%;
}
}
Loading

0 comments on commit 8b0ea77

Please sign in to comment.