diff --git a/src/app/components/VoiceRoomItem.svelte b/src/app/components/VoiceRoomItem.svelte
index 5676c314..30c7fe9f 100644
--- a/src/app/components/VoiceRoomItem.svelte
+++ b/src/app/components/VoiceRoomItem.svelte
@@ -5,7 +5,7 @@
import ProfileCircle from "@app/components/ProfileCircle.svelte"
import RoomImage from "@app/components/RoomImage.svelte"
import RoomName from "@app/components/RoomName.svelte"
- import {pushToast} from "@app/util/toast"
+ import {handleJoinError} from "@app/components/VoiceWidget.svelte"
import {makeRoomPath} from "@app/util/routes"
import {
deriveVoiceParticipants,
@@ -42,12 +42,7 @@
return
}
- try {
- await joinVoiceRoom(url, h)
- } catch (e) {
- console.error("Failed to join voice room", e)
- pushToast({theme: "error", message: "Failed to join voice room"})
- }
+ await joinVoiceRoom(url, h).catch(handleJoinError)
}
$effect(() => {
diff --git a/src/app/components/VoiceWidget.svelte b/src/app/components/VoiceWidget.svelte
index ae3f3eb5..239ba8f4 100644
--- a/src/app/components/VoiceWidget.svelte
+++ b/src/app/components/VoiceWidget.svelte
@@ -1,3 +1,20 @@
+
+
{#if $currentVoiceRoom}
@@ -70,7 +91,7 @@
{/if}
diff --git a/src/app/voice.ts b/src/app/voice.ts
index e8222e99..8856c2d2 100644
--- a/src/app/voice.ts
+++ b/src/app/voice.ts
@@ -17,6 +17,13 @@ export const LIVEKIT_PARTICIPANTS = 39004
export {checkRelayHasLivekit} from "$lib/livekit"
+export class VoiceJoinMembershipError extends Error {
+ constructor() {
+ super("Failed to join voice room: you must be a member.")
+ this.name = "VoiceJoinMembershipError"
+ }
+}
+
export type VoiceSession = {
url: string
h: string
@@ -95,6 +102,7 @@ const fetchLivekitToken = async (
if (!response.ok) {
const text = await response.text()
+ if (response.status === 403) throw new VoiceJoinMembershipError()
throw new Error(`Token request failed (${response.status}): ${text}`)
}
@@ -243,7 +251,6 @@ export const joinVoiceRoom = async (url: string, h: string): Promise => {
playJoinSound()
} catch (e) {
if (isActive()) voiceState.set("disconnected")
- if (e instanceof AbortError) return
throw e
} finally {
if (isActive()) joinAbortController = undefined
@@ -264,9 +271,10 @@ export const leaveVoiceRoom = async () => {
participantPubkeyMap.set(new Map())
}
-export const rejoinVoiceRoom = () => {
+export const rejoinVoiceRoom = async (): Promise => {
const target = get(currentVoiceRoom)
- if (target) joinVoiceRoom(target.url, target.h)
+ if (!target) return
+ return joinVoiceRoom(target.url, target.h)
}
export const toggleMute = async () => {