feature/23-voice-room/poc #93
@@ -15,6 +15,7 @@
|
||||
import ModalBody from "@lib/components/ModalBody.svelte"
|
||||
import {pushToast} from "@app/util/toast"
|
||||
import {uploadFile} from "@app/core/commands"
|
||||
import {checkRelayHasLivekit} from "@app/voice"
|
||||
|
||||
type RoomMode = "text" | "voice" | "both"
|
||||
|
||||
@@ -46,10 +47,29 @@
|
||||
|
||||
const values = $state(initialValues)
|
||||
let roomMode = $state<RoomMode>(getRoomModeFromEvent(initialValues.event))
|
||||
let relayHasLivekit = $state<boolean | undefined>(undefined)
|
||||
|
||||
$effect(() => {
|
||||
const u = url
|
||||
let cancelled = false
|
||||
checkRelayHasLivekit(u).then(has => {
|
||||
if (!cancelled) relayHasLivekit = has
|
||||
})
|
||||
return () => {
|
||||
cancelled = true
|
||||
}
|
||||
})
|
||||
|
hodlbod marked this conversation as resolved
Outdated
|
||||
|
||||
const submit = async () => {
|
||||
const room = $state.snapshot(values)
|
||||
|
||||
if ((roomMode === "voice" || roomMode === "both") && !relayHasLivekit) {
|
||||
return pushToast({
|
||||
theme: "error",
|
||||
message: "This relay does not support voice rooms.",
|
||||
})
|
||||
}
|
||||
|
hodlbod marked this conversation as resolved
Outdated
hodlbod
commented
This should never run if we make the form change below. This should never run if we make the form change below.
|
||||
|
||||
if (imageFile) {
|
||||
const {error, result} = await uploadFile(imageFile, {
|
||||
maxWidth: 256,
|
||||
@@ -211,8 +231,12 @@
|
||||
{#snippet input()}
|
||||
<select class="select select-bordered w-full" bind:value={roomMode} aria-label="Room type">
|
||||
<option value="text">Text only</option>
|
||||
<option value="both">Text and voice</option>
|
||||
<option value="voice">Voice only</option>
|
||||
<option value="both" disabled={relayHasLivekit === false}>
|
||||
Text and voice{relayHasLivekit === false ? " (not setup)" : ""}
|
||||
</option>
|
||||
<option value="voice" disabled={relayHasLivekit === false}>
|
||||
Voice only{relayHasLivekit === false ? " (not setup)" : ""}
|
||||
</option>
|
||||
</select>
|
||||
{/snippet}
|
||||
</FieldInline>
|
||||
|
||||
+26
-5
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Voice rooms via LiveKit. Note: Voice does not work on localhost in Firefox
|
||||
* (ICE candidate gathering fails). Use Chrome or test from deployed HTTPS.
|
||||
*/
|
||||
import {DisconnectReason, Room, RoomEvent, Track} from "livekit-client"
|
||||
import {getToken} from "nostr-tools/nip98"
|
||||
import {derived, get, writable} from "svelte/store"
|
||||
@@ -9,6 +13,27 @@ import {pushToast} from "@app/util/toast"
|
||||
|
||||
export const ROOM_PRESENCE = 10312
|
||||
|
||||
const livekitEndpoint = (url: string, groupId: string) => {
|
||||
const httpUrl = url
|
||||
.replace(/^wss:\/\//, "https://")
|
||||
.replace(/^ws:\/\//, "http://")
|
||||
.replace(/\/$/, "")
|
||||
return `${httpUrl}/.well-known/nip29/livekit/${groupId}`
|
||||
}
|
||||
|
||||
export const checkRelayHasLivekit = async (url: string): Promise<boolean> => {
|
||||
const endpoint = livekitEndpoint(url, "nop")
|
||||
|
||||
try {
|
||||
// Currently we are hitting the API with no auth because zooid returns a 401 livekit
|
||||
// is configured and 404 if it is not. But we need a standardized solution in the NIP.
|
||||
const response = await fetch(endpoint)
|
||||
return response.status === 401
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
const PRESENCE_INTERVAL_MS = 60_000
|
||||
const PRESENCE_EXPIRY_S = 300
|
||||
|
||||
@@ -26,11 +51,7 @@ const fetchLivekitToken = async (
|
||||
groupId: string,
|
||||
signal?: AbortSignal,
|
||||
): Promise<{server_url: string; participant_token: string}> => {
|
||||
const httpUrl = url
|
||||
.replace(/^wss:\/\//, "https://")
|
||||
.replace(/^ws:\/\//, "http://")
|
||||
.replace(/\/$/, "")
|
||||
const endpoint = `${httpUrl}/.well-known/nip29/livekit/${groupId}`
|
||||
const endpoint = livekitEndpoint(url, groupId)
|
||||
|
||||
const $signer = signer.get()
|
||||
if (!$signer) throw new Error("No signer available")
|
||||
|
||||
Reference in New Issue
Block a user
Better would be to add a util to app/state called
deriveHasLiveKit(url)that can cache the request. This complex effect behavior is something I've noticed a lot recently, but we can assume url will not change here.