Moderacja uczestnika dziala takze przy wiadomosciach na zywo
Wyciszenie i blokada byly zbudowane w polowie: backend mial endpointy
`/participants/{id}/mute` i `/ban`, migracja V28 jest, a uczestnik z
wyciszeniem faktycznie nie mogl pisac. Brakowalo jednego ogniwa.
Zdarzenie na temacie moderacji nioslo widok PUBLICZNY, bez identyfikatora
zapisu autora, a panel uzupelnial brakujace pola wartosciami domyslnymi
(`authorRegistrationId: null`). Warunek pokazujacy przyciski sprawdza wlasnie
to pole, wiec:
- wiadomosci wczytane przy wejsciu mialy przyciski,
- wiadomosci przychodzace NA ZYWO mialy tylko kosz.
Komentarz w kodzie zakladal, ze dane uzupelni "najblizsze odswiezenie listy po
akcji mute/ban". Zalozenie bylo bledne: zeby wykonac te akcje, trzeba miec
przycisk. Bez odswiezenia nie ma przycisku, bez przycisku nie ma odswiezenia,
wiec pomagalo dopiero przeladowanie strony. Zgloszone z produkcji.
Temat moderacji niesie teraz PELNY widok moderatora, razem z identyfikatorem
zapisu i stanem wyciszenia autora. Jest to bezpieczne, bo temat subskrybuje
wylacznie panel prowadzacego, uwierzytelniony tokenem administratora.
**Strumien publiczny zostaje bez zmian.** `InteractionView` nadal nie niesie
identyfikatora zapisu ani adresu e-mail: czat widza wszyscy obecni, wiec nic,
co pozwala wskazac konkretna osobe poza spotkaniem, nie moze stamtad wyjsc.
Dlatego doszedl osobny `InteractionService.moderatorView`, a nie pole
dopisane do widoku publicznego.
Mapowanie jest w transakcji: autor to relacja leniwa, a rozglaszanie dzieje sie
juz poza nia.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -7,7 +7,7 @@ import type { Webinar } from '../../api/types'
|
||||
import { Icon } from '../../components/Icon'
|
||||
import { useToasts } from '../../components/Toasts'
|
||||
import { Badge, Button, ErrorState, Input, Spinner, Textarea } from '../../components/ui'
|
||||
import type { InteractionView, ModeratorInteractionView } from '../../lib/useInteractions'
|
||||
import type { ModeratorInteractionView } from '../../lib/useInteractions'
|
||||
import { SpeakQueue, type SpeakRequestView } from './SpeakQueue'
|
||||
import { panelPath } from '../../lib/routes'
|
||||
|
||||
@@ -217,7 +217,7 @@ export function HostConsolePage() {
|
||||
void webinar.refetch()
|
||||
|
||||
stomp.subscribe(`/topic/webinars/${id}/moderation`, (message: IMessage) => {
|
||||
const event = JSON.parse(message.body) as { kind: string; payload: InteractionView }
|
||||
const event = JSON.parse(message.body) as { kind: string; payload: ModeratorInteractionView }
|
||||
apply(event)
|
||||
})
|
||||
|
||||
@@ -233,17 +233,20 @@ export function HostConsolePage() {
|
||||
onWebSocketClose: () => setConnected(false),
|
||||
})
|
||||
|
||||
function apply(event: { kind: string; payload: InteractionView }) {
|
||||
// zdarzenie WS niesie publiczny widok bez danych moderacji autora.
|
||||
// Uzupelniamy je do widoku moderatora wartosciami domyslnymi: przyciski
|
||||
// moderacji uzyja pelnych danych po najblizszym odswiezeniu listy (robimy
|
||||
// je po kazdej akcji mute/ban), a nowa wiadomosc i tak jest widoczna od razu.
|
||||
const item: ModeratorInteractionView = {
|
||||
...event.payload,
|
||||
authorRegistrationId: null,
|
||||
authorChatMuted: false,
|
||||
authorRoomBanned: false,
|
||||
}
|
||||
function apply(event: { kind: string; payload: ModeratorInteractionView }) {
|
||||
/*
|
||||
* Zdarzenie z tematu moderacji niesie PELNY widok, razem z
|
||||
* identyfikatorem zapisu autora i jego stanem wyciszenia.
|
||||
*
|
||||
* Wczesniej szedl tu widok publiczny, a brakujace pola uzupelniano
|
||||
* wartosciami domyslnymi (`authorRegistrationId: null`). Skutek: przy
|
||||
* wiadomosciach przychodzacych NA ZYWO panel nie pokazywal przyciskow
|
||||
* wyciszenia ani blokady, bo warunek sprawdza wlasnie to pole. Pojawialy
|
||||
* sie dopiero po odswiezeniu strony. Zalozenie, ze uzupelni je
|
||||
* "najblizsze odswiezenie po akcji mute/ban", bylo bledne: zeby wykonac
|
||||
* te akcje, trzeba miec przycisk.
|
||||
*/
|
||||
const item: ModeratorInteractionView = event.payload
|
||||
|
||||
// zapytanie ofertowe ma wlasny licznik i wlasna kolumne, zeby nie ginelo
|
||||
// w kolejce pytan: to jedyne zgloszenie, ktore jest kontaktem handlowym
|
||||
|
||||
Reference in New Issue
Block a user