ultisuite-client/components/meet/meet-join-client.tsx
R3D347HR4Y ad1370ea7e
Some checks are pending
E2E / Playwright e2e (push) Waiting to run
feat: enhance configuration and add new demo layouts
- Introduced turbopack alias for canvas in next.config.mjs.
- Updated package.json scripts for development and branding tasks.
- Added new dependencies for Tiptap extensions.
- Implemented new demo layouts for agenda, contacts, drive, and mail applications.
- Enhanced globals.css for improved theming and splash screen animations.
- Added OAuth callback handling for drive mounts.
- Updated layout components to integrate new demo shells and improve structure.
2026-06-12 19:10:24 +02:00

109 lines
3.2 KiB
TypeScript

"use client"
import { useEffect, useState } from "react"
import { useRouter, useSearchParams } from "next/navigation"
import { Loader2 } from "lucide-react"
import { MeetHeader } from "@/components/meet/meet-header"
import { MeetRoomFrame } from "@/components/meet/meet-room-frame"
import { Button } from "@/components/ui/button"
import { useMeetConfig, useMeetRoomToken } from "@/lib/api/hooks/use-meet-queries"
import { meetRoomPath, parseMeetUrl } from "@/lib/meet/meet-url"
export function MeetJoinClient() {
const router = useRouter()
const searchParams = useSearchParams()
const rawUrl = searchParams.get("u") ?? ""
const parsed = parseMeetUrl(rawUrl)
const { data: config, isLoading: configLoading } = useMeetConfig()
const roomToken = useMeetRoomToken()
const [embedUrl, setEmbedUrl] = useState<string | null>(null)
const [error, setError] = useState<string | null>(null)
useEffect(() => {
if (!parsed) {
setError("Lien de réunion invalide")
return
}
if (parsed.jwt) {
setEmbedUrl(parsed.embedUrl)
return
}
if (!config?.enabled) return
let cancelled = false
void roomToken
.mutateAsync(parsed.room)
.then((token) => {
if (!cancelled) setEmbedUrl(token.meet_url)
})
.catch(() => {
if (!cancelled) setError("Impossible de rejoindre la réunion")
})
return () => {
cancelled = true
}
// eslint-disable-next-line react-hooks/exhaustive-deps -- join once when URL/config ready
}, [rawUrl, config?.enabled])
if (!rawUrl) {
return (
<div className="flex h-dvh flex-col">
<MeetHeader title="Rejoindre" />
<div className="flex flex-1 items-center justify-center px-6 text-sm text-muted-foreground">
Lien de réunion manquant.
</div>
</div>
)
}
if (configLoading || (!embedUrl && !error && parsed && !parsed.jwt)) {
return (
<div className="flex h-dvh flex-col">
<MeetHeader title="Connexion…" />
<div className="flex flex-1 items-center justify-center text-sm text-muted-foreground">
<Loader2 className="mr-2 size-4 animate-spin" aria-hidden />
Préparation de la salle
</div>
</div>
)
}
if (error || !config?.enabled) {
return (
<div className="flex h-dvh flex-col">
<MeetHeader />
<div className="flex flex-1 flex-col items-center justify-center gap-3 px-6 text-center">
<p className="text-sm text-muted-foreground">
{error ?? "UltiMeet n'est pas activé sur cette instance."}
</p>
<Button variant="outline" className="rounded-full" onClick={() => router.push("/meet")}>
Retour au lobby
</Button>
</div>
</div>
)
}
if (!embedUrl || !parsed) return null
return (
<div className="flex h-dvh flex-col">
<MeetHeader
title={parsed.room}
trailing={
<Button
variant="outline"
size="sm"
className="hidden rounded-full sm:inline-flex"
onClick={() => router.push(meetRoomPath(parsed.room))}
>
Ouvrir en plein écran
</Button>
}
/>
<MeetRoomFrame meetUrl={embedUrl} />
</div>
)
}