Skip to content

Commit

Permalink
Merge pull request #105 from cloudflare/block-joining-room-on-session…
Browse files Browse the repository at this point in the history
…-creation

Block joining room on session creation
  • Loading branch information
third774 authored Sep 9, 2024
2 parents 53fc12e + 7f8c07e commit 4629ad5
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 20 deletions.
33 changes: 33 additions & 0 deletions app/components/Spinner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { forwardRef, type ComponentProps, type ElementRef } from 'react'
import { cn } from '~/utils/style'

export const Spinner = forwardRef<ElementRef<'svg'>, ComponentProps<'svg'>>(
({ className, ...rest }, ref) => {
return (
<svg
className={cn('animate-spin -ml-1 mr-3 h-5 w-5 text-white', className)}
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
{...rest}
ref={ref}
>
<circle
className="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
strokeWidth="4"
></circle>
<path
className="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
></path>
</svg>
)
}
)

Spinner.displayName = 'Spinner'
47 changes: 32 additions & 15 deletions app/routes/_room.$roomName._index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ import { MicButton } from '~/components/MicButton'

import { SelfView } from '~/components/SelfView'
import { SettingsButton } from '~/components/SettingsDialog'
import { Spinner } from '~/components/Spinner'
import { Tooltip } from '~/components/Tooltip'
import { useSubscribedState } from '~/hooks/rxjsHooks'
import { useRoomContext } from '~/hooks/useRoomContext'
import { errorMessageMap } from '~/hooks/useUserMedia'
import getUsername from '~/utils/getUsername.server'
Expand All @@ -27,8 +29,10 @@ export const loader = async ({ request }: LoaderFunctionArgs) => {
export default function Lobby() {
const { roomName } = useParams()
const navigate = useNavigate()
const { setJoined, userMedia, room } = useRoomContext()
const { setJoined, userMedia, room, peer } = useRoomContext()
const { videoStreamTrack, audioStreamTrack, audioEnabled } = userMedia
const session = useSubscribedState(peer.session$)
const sessionError = useSubscribedState(peer.sessionError$)

const joinedUsers = new Set(
room.otherUsers.filter((u) => u.tracks.audio).map((u) => u.name)
Expand All @@ -55,21 +59,33 @@ export default function Lobby() {
className="aspect-[4/3] w-full"
videoTrack={videoStreamTrack}
/>
{audioStreamTrack && (
<div className="absolute left-3 top-3">
{audioEnabled ? (
<AudioIndicator audioTrack={audioStreamTrack} />
) : (
<Tooltip content="Mic is turned off">
<div className="text-white indication-shadow">
<Icon type="micOff" />
<VisuallyHidden>Mic is turned off</VisuallyHidden>
</div>
</Tooltip>
)}
</div>
)}

<div className="absolute left-3 top-3">
{!sessionError && !session?.sessionId ? (
<Spinner className="text-zinc-100" />
) : (
audioStreamTrack && (
<>
{audioEnabled ? (
<AudioIndicator audioTrack={audioStreamTrack} />
) : (
<Tooltip content="Mic is turned off">
<div className="text-white indication-shadow">
<Icon type="micOff" />
<VisuallyHidden>Mic is turned off</VisuallyHidden>
</div>
</Tooltip>
)}
</>
)
)}
</div>
</div>
{sessionError && (
<div className="p-3 rounded-md text-sm text-zinc-800 bg-red-200 dark:text-zinc-200 dark:bg-red-700">
{sessionError}
</div>
)}
{(userMedia.audioUnavailableReason ||
userMedia.videoUnavailableReason) && (
<div className="p-3 rounded-md text-sm text-zinc-800 bg-zinc-200 dark:text-zinc-200 dark:bg-zinc-700">
Expand Down Expand Up @@ -123,6 +139,7 @@ export default function Lobby() {
// the room without the JS having loaded
navigate('room')
}}
disabled={!session?.sessionId}
>
Join
</Button>
Expand Down
22 changes: 17 additions & 5 deletions app/utils/rxjs/RxjsPeer.client.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import {
Observable,
catchError,
combineLatest,
distinctUntilChanged,
filter,
from,
fromEvent,
map,
Expand Down Expand Up @@ -50,6 +52,7 @@ export class RxjsPeer {
peerConnection: RTCPeerConnection
sessionId: string
}>
sessionError$: Observable<string>
peerConnectionState$: Observable<RTCPeerConnectionState>
config: PeerConfig

Expand Down Expand Up @@ -137,6 +140,13 @@ export class RxjsPeer {
})
)

this.sessionError$ = this.session$.pipe(
catchError((err) =>
of(err instanceof Error ? err.message : 'Caught non-error')
),
filter((value) => typeof value === 'string')
)

this.peerConnectionState$ = this.peerConnection$.pipe(
switchMap((peerConnection) =>
fromEvent(
Expand Down Expand Up @@ -171,12 +181,14 @@ export class RxjsPeer {
async createSession(peerConnection: RTCPeerConnection) {
console.debug('🆕 creating new session')
const { apiBase } = this.config
const { sessionId } = await this.fetchWithRecordedHistory(
const response = await this.fetchWithRecordedHistory(
`${apiBase}/sessions/new?SESSION`,
{
method: 'POST',
}
).then((res) => res.json() as any)
{ method: 'POST' }
)
if (response.status > 400) {
throw new Error('Error creating Calls session')
}
const { sessionId } = (await response.json()) as any
return { peerConnection, sessionId }
}

Expand Down

0 comments on commit 4629ad5

Please sign in to comment.