Napis o mikrofonie idzie za uprawnieniem, nie za zgloszeniem
Deploy PROD / deploy (push) Successful in 24s
Deploy PROD / deploy (push) Successful in 24s
Interfejs sali mial DWA niezalezne zrodla prawdy o tym, czy uczestnik moze mowic: napis "Masz glos, mikrofon jest wlaczony" bral sie ze stanu ZGLOSZENIA (`speak.granted`), a faktyczny mikrofon z uprawnienia w TOKENIE (`canPublishAudio`). Te dwie rzeczy nie sa tym samym. Prawo do audio daje takze rola ACTIVE_PARTICIPANT, ktora uczestnik dostaje przy wlaczonym trybie "wideo dla wszystkich". Odebranie glosu nie zmienia wtedy uprawnien, ale zmienia stan zgloszenia: napis znikal, a mikrofon zostawal otwarty. Po kilku cyklach nadania i odebrania obraz w panelu rozjezdzal sie z tym, co uczestnik faktycznie moze. Zgloszone z produkcji. Pasek akcji dostaje teraz `canPublishAudio` wprost z tokenu i to ono rozstrzyga o napisie. Gdy glos jest juz przyznany, a token jeszcze nie dotarl, pasek mowi "trwa wlaczanie mikrofonu" zamiast klamac w ktorakolwiek strone. Przycisk "Oddaj glos" zostaje przy zgloszeniu, bo dotyczy wlasnie jego. SLAD DO DIAGNOZY Rozjazd miedzy interfejsem a serwerem jest trudny do zbadania po fakcie: uczestnik zglasza "mikrofon nie dziala", a log serwera pokazuje poprawnie wydany token. Konsola sali wypisuje teraz po kazdej zmianie stan tokenu obok stanu zgloszenia i obu trybow, wiec przy nastepnym zgloszeniu widac, ktora strona jest nieaktualna. To nie jest debugowanie do usuniecia: nigdzie indziej nie widac obu tych rzeczy naraz. Hipoteza o wygasajacym tokenie sprawdzona i ODRZUCONA: TTL to szesc godzin, czyli dluzej niz najdluzszy webinar. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -32,6 +32,19 @@ export function MeetingActionBar({
|
||||
isSpeaker,
|
||||
/** Tryb otwartego mikrofonu: kazdy mowi bez proszenia o glos. */
|
||||
openMic,
|
||||
/**
|
||||
* Faktyczne uprawnienie do mikrofonu, prosto z tokenu wydanego przez backend.
|
||||
*
|
||||
* JEDYNE ZRODLO PRAWDY O TYM, CZY UCZESTNIK MOZE MOWIC
|
||||
* ---------------------------------------------------------------------
|
||||
* Wczesniej pasek skladal te odpowiedz sam, ze stanu zgloszenia
|
||||
* (`speak.granted`) i trybu otwartego mikrofonu. Rozjezdzalo sie to
|
||||
* z rzeczywistoscia, bo prawo do audio daje takze rola ACTIVE_PARTICIPANT
|
||||
* przy wlaczonym "wideo dla wszystkich": odebranie glosu nie zmienialo wtedy
|
||||
* uprawnien, ale napis "Masz glos" znikal. Uczestnik widzial zamkniety
|
||||
* mikrofon przy dzialajacym i odwrotnie.
|
||||
*/
|
||||
canPublishAudio,
|
||||
/**
|
||||
* Temat wybrany klikiem w baner.
|
||||
*
|
||||
@@ -46,6 +59,7 @@ export function MeetingActionBar({
|
||||
speak: ReturnType<typeof useSpeakRequest>
|
||||
isSpeaker: boolean
|
||||
openMic: boolean
|
||||
canPublishAudio: boolean
|
||||
offerTopicFromBanner?: string | null
|
||||
onOfferHandled?: () => void
|
||||
}) {
|
||||
@@ -96,7 +110,7 @@ export function MeetingActionBar({
|
||||
Możesz mówić bez zgłaszania się
|
||||
</span>
|
||||
) : (
|
||||
<SpeakButton speak={speak} />
|
||||
<SpeakButton speak={speak} canPublishAudio={canPublishAudio} />
|
||||
))}
|
||||
|
||||
{/*
|
||||
@@ -193,13 +207,24 @@ export function MeetingActionBar({
|
||||
* oczekiwania, czyli dokladnie ten, w ktorym uczestnik zastanawia sie,
|
||||
* czy zgloszenie w ogole doszlo.
|
||||
*/
|
||||
function SpeakButton({ speak }: { speak: ReturnType<typeof useSpeakRequest> }) {
|
||||
function SpeakButton({
|
||||
speak,
|
||||
canPublishAudio,
|
||||
}: {
|
||||
speak: ReturnType<typeof useSpeakRequest>
|
||||
canPublishAudio: boolean
|
||||
}) {
|
||||
/*
|
||||
* Napis o mikrofonie idzie za UPRAWNIENIEM, a nie za stanem zgloszenia:
|
||||
* mowi o tym, co uczestnik faktycznie moze, a nie o tym, o co prosil.
|
||||
* Przycisk "Oddaj glos" zostaje przy zgloszeniu, bo dotyczy wlasnie jego.
|
||||
*/
|
||||
if (speak.granted) {
|
||||
return (
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<span className="inline-flex items-center gap-1.5 rounded-md bg-ok-50 px-3 py-1.5 text-sm font-semibold text-ok-600">
|
||||
<Icon name="check-circle" size={16} />
|
||||
Masz głos, mikrofon jest włączony
|
||||
{canPublishAudio ? 'Masz głos, mikrofon jest włączony' : 'Masz głos, trwa włączanie mikrofonu...'}
|
||||
</span>
|
||||
<button
|
||||
type="button"
|
||||
|
||||
@@ -240,6 +240,27 @@ function MeetingRoom({
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [speak.granted, openMic, openVideo])
|
||||
|
||||
/*
|
||||
* Slad w konsoli po kazdej zmianie uprawnien.
|
||||
*
|
||||
* Rozjazd miedzy tym, co pokazuje interfejs, a tym, co faktycznie pozwala
|
||||
* serwer, jest trudny do zdiagnozowania po fakcie: uczestnik zglasza
|
||||
* "mikrofon nie dziala", a log serwera pokazuje poprawnie wydany token.
|
||||
* Ta linia pozwala porownac obie strony bez zgadywania - wystarczy otworzyc
|
||||
* konsole na sali. Nie jest to debugowanie do usuniecia: to jedyne miejsce,
|
||||
* w ktorym widac stan tokenu razem ze stanem zgloszenia.
|
||||
*/
|
||||
useEffect(() => {
|
||||
console.info('[sala] uprawnienia', {
|
||||
audio: join.canPublishAudio,
|
||||
video: join.canPublishVideo,
|
||||
rola: join.role,
|
||||
zgloszenieGlosu: speak.granted,
|
||||
otwartyMikrofon: openMic,
|
||||
wideoDlaWszystkich: openVideo,
|
||||
})
|
||||
}, [join.canPublishAudio, join.canPublishVideo, join.role, speak.granted, openMic, openVideo])
|
||||
|
||||
const src = useMemo(() => {
|
||||
if (!join.embedded) return null
|
||||
const url = new URL(join.url)
|
||||
@@ -337,6 +358,7 @@ function MeetingRoom({
|
||||
speak={speak}
|
||||
isSpeaker={isSpeaker}
|
||||
openMic={openMic}
|
||||
canPublishAudio={join.canPublishAudio}
|
||||
offerTopicFromBanner={offerTopicFromBanner}
|
||||
onOfferHandled={() => setOfferTopicFromBanner(null)}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user