Add TO/Stream labels back to tournament chats

This commit is contained in:
Kalle
2026-03-23 21:04:49 +02:00
parent 6d5301ff45
commit 0aa31c0683
4 changed files with 65 additions and 1 deletions

View File

@@ -156,6 +156,17 @@ function ChatView({ onClose }: { onClose?: () => void }) {
const roomExpired = Boolean(room?.expiresAt && room.expiresAt < Date.now());
const messages = chatContext.messagesForRoom(activeRoom);
const participantIds = new Set(room?.participantUserIds ?? []);
const usersWithLabels = { ...chatContext.chatUsers };
for (const [userIdStr, label] of Object.entries(chatContext.chatLabels)) {
const userId = Number(userIdStr);
if (participantIds.has(userId)) continue;
const existing = usersWithLabels[userId];
if (existing) {
usersWithLabels[userId] = { ...existing, title: label };
}
}
const chatAdapter = {
messages,
send: (contents: string) => chatContext.send(activeRoom, contents),
@@ -229,7 +240,7 @@ function ChatView({ onClose }: { onClose?: () => void }) {
</div>
<div className={styles.chatContainer}>
<Chat
users={chatContext.chatUsers}
users={usersWithLabels}
rooms={[
{
label: room?.header ?? "Chat",

View File

@@ -136,6 +136,10 @@ function ChatProviderInner({
const [unreadCounts, setUnreadCounts] = React.useState<
Record<string, number>
>({});
const [chatLabels, setChatLabels] = React.useState<Record<number, string>>(
{},
);
const clearChatLabels = React.useCallback(() => setChatLabels({}), []);
const ws = React.useRef<WebSocket>(undefined);
@@ -508,6 +512,9 @@ function ChatProviderInner({
setChatOpen,
activeRoom,
setActiveRoom,
chatLabels,
setChatLabels,
clearChatLabels,
}),
[
isLoading,
@@ -525,6 +532,8 @@ function ChatProviderInner({
chatOpen,
activeRoom,
setChatOpen,
chatLabels,
clearChatLabels,
],
);

View File

@@ -52,4 +52,7 @@ export interface ChatContextValue {
setChatOpen: (open: boolean) => void;
activeRoom: string | null;
setActiveRoom: (chatCode: string | null) => void;
chatLabels: Record<number, string>;
setChatLabels: (labels: Record<number, string>) => void;
clearChatLabels: () => void;
}

View File

@@ -12,6 +12,7 @@ import { Placeholder } from "~/components/Placeholder";
import { SubNav, SubNavLink } from "~/components/SubNav";
import { DANGEROUS_CAN_ACCESS_DEV_CONTROLS } from "~/features/admin/core/dev-controls";
import { useUser } from "~/features/auth/core/user";
import { useChatContext } from "~/features/chat/useChatContext";
import { Tournament } from "~/features/tournament-bracket/core/Tournament";
import { useIsMounted } from "~/hooks/useIsMounted";
import type { SendouRouteHandle } from "~/utils/remix.server";
@@ -111,6 +112,8 @@ export function TournamentLayout() {
);
const [bracketExpanded, setBracketExpanded] = React.useState(true);
useTournamentChatLabels(tournament);
// this is nice to debug with tournament in browser console
if (process.env.NODE_ENV === "development") {
// biome-ignore lint/correctness/useHookAtTopLevel: process.env.NODE_ENV is a constant
@@ -240,3 +243,41 @@ export function useTournamentFriendCodes() {
export function useTournamentPreparedMaps() {
return useOutletContext<TournamentContext>().preparedMaps;
}
function useTournamentChatLabels(tournament: Tournament) {
const chatContext = useChatContext();
const setChatLabels = chatContext?.setChatLabels;
const clearChatLabels = chatContext?.clearChatLabels;
React.useEffect(() => {
if (!setChatLabels || !clearChatLabels) return;
const labels: Record<number, string> = {};
labels[tournament.ctx.author.id] = "TO";
for (const staff of tournament.ctx.staff) {
if (staff.role === "ORGANIZER") {
labels[staff.id] = "TO";
} else if (staff.role === "STREAMER") {
labels[staff.id] = "Stream";
}
}
if (tournament.ctx.organization) {
for (const member of tournament.ctx.organization.members) {
if (["ADMIN", "ORGANIZER"].includes(member.role)) {
labels[member.userId] = "TO";
} else if (member.role === "STREAMER") {
labels[member.userId] = "Stream";
}
}
}
setChatLabels(labels);
return () => {
clearChatLabels();
};
}, [setChatLabels, clearChatLabels, tournament]);
}