fix: request call permissions and simplify CTA
This commit is contained in:
+1
-4
@@ -1,5 +1,4 @@
|
|||||||
import { Button } from "@/components/Button";
|
import { Button } from "@/components/Button";
|
||||||
import { OrganicBlob } from "@/components/OrganicBlob";
|
|
||||||
import { Container } from "@/components/Section";
|
import { Container } from "@/components/Section";
|
||||||
|
|
||||||
type CTAProps = {
|
type CTAProps = {
|
||||||
@@ -20,9 +19,7 @@ export function CTA({
|
|||||||
secondaryLabel = "Kontakt aufnehmen",
|
secondaryLabel = "Kontakt aufnehmen",
|
||||||
}: CTAProps) {
|
}: CTAProps) {
|
||||||
return (
|
return (
|
||||||
<section className="relative overflow-hidden bg-anouma-plum py-20 text-anouma-cream-light sm:py-24">
|
<section className="border-y border-anouma-cream-light/15 bg-anouma-mauve-dark py-16 text-anouma-cream-light sm:py-20">
|
||||||
<OrganicBlob tone="mauve" className="-left-20 -top-20 h-80 w-80 opacity-30" />
|
|
||||||
<OrganicBlob tone="rose" className="-bottom-24 -right-16 h-72 w-72 opacity-20" />
|
|
||||||
<Container className="relative text-center">
|
<Container className="relative text-center">
|
||||||
<h2 className="mx-auto max-w-2xl text-balance font-serif text-4xl font-medium leading-tight sm:text-5xl">
|
<h2 className="mx-auto max-w-2xl text-balance font-serif text-4xl font-medium leading-tight sm:text-5xl">
|
||||||
{title}
|
{title}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { useCallback, useEffect, useRef, useState } from "react";
|
||||||
import { createLocalTracks, Track, type LocalTrack } from "livekit-client";
|
import { createLocalTracks, Track, type LocalTrack } from "livekit-client";
|
||||||
|
|
||||||
export function PreJoinScreen({ onContinue }: { onContinue: (tracks: LocalTrack[]) => void }) {
|
export function PreJoinScreen({ onContinue }: { onContinue: (tracks: LocalTrack[]) => void }) {
|
||||||
@@ -9,8 +9,10 @@ export function PreJoinScreen({ onContinue }: { onContinue: (tracks: LocalTrack[
|
|||||||
const [micOn, setMicOn] = useState(true);
|
const [micOn, setMicOn] = useState(true);
|
||||||
const [cameraOn, setCameraOn] = useState(true);
|
const [cameraOn, setCameraOn] = useState(true);
|
||||||
const [speakerTested, setSpeakerTested] = useState(false);
|
const [speakerTested, setSpeakerTested] = useState(false);
|
||||||
|
const [requestingDevices, setRequestingDevices] = useState(false);
|
||||||
const videoRef = useRef<HTMLVideoElement>(null);
|
const videoRef = useRef<HTMLVideoElement>(null);
|
||||||
const handedOffRef = useRef(false);
|
const handedOffRef = useRef(false);
|
||||||
|
const initialDeviceRequestRef = useRef(false);
|
||||||
|
|
||||||
const videoTrack = tracks.find((track) => track.kind === Track.Kind.Video);
|
const videoTrack = tracks.find((track) => track.kind === Track.Kind.Video);
|
||||||
const audioTrack = tracks.find((track) => track.kind === Track.Kind.Audio);
|
const audioTrack = tracks.find((track) => track.kind === Track.Kind.Audio);
|
||||||
@@ -30,9 +32,11 @@ export function PreJoinScreen({ onContinue }: { onContinue: (tracks: LocalTrack[
|
|||||||
};
|
};
|
||||||
}, [tracks]);
|
}, [tracks]);
|
||||||
|
|
||||||
async function requestDevices() {
|
const requestDevices = useCallback(async () => {
|
||||||
|
if (requestingDevices) return;
|
||||||
tracks.forEach((track) => track.stop());
|
tracks.forEach((track) => track.stop());
|
||||||
setError(null);
|
setError(null);
|
||||||
|
setRequestingDevices(true);
|
||||||
try {
|
try {
|
||||||
const nextTracks = await createLocalTracks({ audio: true, video: true });
|
const nextTracks = await createLocalTracks({ audio: true, video: true });
|
||||||
setTracks(nextTracks);
|
setTracks(nextTracks);
|
||||||
@@ -40,8 +44,16 @@ export function PreJoinScreen({ onContinue }: { onContinue: (tracks: LocalTrack[
|
|||||||
setCameraOn(true);
|
setCameraOn(true);
|
||||||
} catch {
|
} catch {
|
||||||
setError("Kamera oder Mikrofon konnten nicht freigegeben werden. Du kannst trotzdem ohne sie beitreten.");
|
setError("Kamera oder Mikrofon konnten nicht freigegeben werden. Du kannst trotzdem ohne sie beitreten.");
|
||||||
|
} finally {
|
||||||
|
setRequestingDevices(false);
|
||||||
}
|
}
|
||||||
}
|
}, [requestingDevices, tracks]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (initialDeviceRequestRef.current) return;
|
||||||
|
initialDeviceRequestRef.current = true;
|
||||||
|
void requestDevices();
|
||||||
|
}, [requestDevices]);
|
||||||
|
|
||||||
async function toggleMic() {
|
async function toggleMic() {
|
||||||
if (!audioTrack) return;
|
if (!audioTrack) return;
|
||||||
@@ -104,9 +116,10 @@ export function PreJoinScreen({ onContinue }: { onContinue: (tracks: LocalTrack[
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={requestDevices}
|
onClick={requestDevices}
|
||||||
className="rounded-full bg-white px-5 py-3 text-sm font-medium text-neutral-900 hover:bg-white/85"
|
disabled={requestingDevices}
|
||||||
|
className="rounded-full bg-white px-5 py-3 text-sm font-medium text-neutral-900 hover:bg-white/85 disabled:cursor-wait disabled:opacity-75"
|
||||||
>
|
>
|
||||||
{tracks.length > 0 ? "Geräte erneut prüfen" : "Kamera & Mikrofon aktivieren"}
|
{requestingDevices ? "Berechtigung wird angefragt …" : tracks.length > 0 ? "Geräte erneut prüfen" : "Kamera & Mikrofon aktivieren"}
|
||||||
</button>
|
</button>
|
||||||
<div className="grid grid-cols-2 gap-3">
|
<div className="grid grid-cols-2 gap-3">
|
||||||
<button type="button" onClick={() => void toggleMic()} disabled={!audioTrack} className="rounded-2xl bg-white/10 px-4 py-3 text-xs hover:bg-white/15 disabled:opacity-40">
|
<button type="button" onClick={() => void toggleMic()} disabled={!audioTrack} className="rounded-2xl bg-white/10 px-4 py-3 text-xs hover:bg-white/15 disabled:opacity-40">
|
||||||
|
|||||||
Reference in New Issue
Block a user