mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-05-05 20:56:13 -05:00
Chat fixes
This commit is contained in:
parent
b063b9300a
commit
d884cb3f3b
|
|
@ -4,7 +4,11 @@ import * as React from "react";
|
||||||
import { useMatches, useRevalidator } from "react-router";
|
import { useMatches, useRevalidator } from "react-router";
|
||||||
import { logger } from "~/utils/logger";
|
import { logger } from "~/utils/logger";
|
||||||
import { soundPath } from "~/utils/urls";
|
import { soundPath } from "~/utils/urls";
|
||||||
import type { RoomInfo, ServerRoomInfo } from "./chat-provider-types";
|
import type {
|
||||||
|
RoomInfo,
|
||||||
|
RoomMetadata,
|
||||||
|
ServerRoomInfo,
|
||||||
|
} from "./chat-provider-types";
|
||||||
import type { ChatMessage, ChatUser } from "./chat-types";
|
import type { ChatMessage, ChatUser } from "./chat-types";
|
||||||
import { messageTypeToSound, soundEnabled, soundVolume } from "./chat-utils";
|
import { messageTypeToSound, soundEnabled, soundVolume } from "./chat-utils";
|
||||||
import { ChatContext } from "./useChatContext";
|
import { ChatContext } from "./useChatContext";
|
||||||
|
|
@ -161,7 +165,7 @@ function ChatProviderInner({
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHAT_HISTORY response
|
// CHAT_HISTORY response (also returned by SUBSCRIBE with metadata)
|
||||||
if (parsed.event === "CHAT_HISTORY" && Array.isArray(parsed.messages)) {
|
if (parsed.event === "CHAT_HISTORY" && Array.isArray(parsed.messages)) {
|
||||||
const chatCode = parsed.chatCode as string;
|
const chatCode = parsed.chatCode as string;
|
||||||
const messages = parsed.messages as ChatMessage[];
|
const messages = parsed.messages as ChatMessage[];
|
||||||
|
|
@ -169,6 +173,30 @@ function ChatProviderInner({
|
||||||
...prev,
|
...prev,
|
||||||
[chatCode]: messages,
|
[chatCode]: messages,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
if (parsed.metadata) {
|
||||||
|
const metadata = parsed.metadata as RoomMetadata;
|
||||||
|
const newRoom: RoomInfo = {
|
||||||
|
chatCode,
|
||||||
|
header: metadata.header,
|
||||||
|
subtitle: metadata.subtitle ?? "",
|
||||||
|
url: metadata.url ?? "",
|
||||||
|
participantUserIds: metadata.participantUserIds,
|
||||||
|
expiresAt: metadata.expiresAt,
|
||||||
|
lastMessageTimestamp: messages.at(-1)?.timestamp ?? 0,
|
||||||
|
totalMessageCount: messages.length,
|
||||||
|
};
|
||||||
|
setRooms((prev) => {
|
||||||
|
const exists = prev.some((r) => r.chatCode === chatCode);
|
||||||
|
if (exists) return prev;
|
||||||
|
return [...prev, newRoom];
|
||||||
|
});
|
||||||
|
|
||||||
|
if (metadata.chatUsers) {
|
||||||
|
setChatUsersCache((prev) => ({ ...prev, ...metadata.chatUsers }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -379,6 +407,8 @@ function ChatProviderInner({
|
||||||
setSidebarOpen,
|
setSidebarOpen,
|
||||||
subscribe,
|
subscribe,
|
||||||
unsubscribe,
|
unsubscribe,
|
||||||
|
setRooms,
|
||||||
|
setMessagesByRoom,
|
||||||
});
|
});
|
||||||
|
|
||||||
const contextValue = React.useMemo(
|
const contextValue = React.useMemo(
|
||||||
|
|
@ -422,6 +452,9 @@ function ChatProviderInner({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// xxx: bug: when viewing as non-participant can't go back to list view
|
||||||
|
// xxx: bug: room should close automatically if non-participant and leaves the route
|
||||||
|
// xxx: bug: route loading state should show before room metadata loads
|
||||||
function useChatRouteSync({
|
function useChatRouteSync({
|
||||||
rooms,
|
rooms,
|
||||||
userId,
|
userId,
|
||||||
|
|
@ -429,6 +462,8 @@ function useChatRouteSync({
|
||||||
setSidebarOpen,
|
setSidebarOpen,
|
||||||
subscribe,
|
subscribe,
|
||||||
unsubscribe,
|
unsubscribe,
|
||||||
|
setRooms,
|
||||||
|
setMessagesByRoom,
|
||||||
}: {
|
}: {
|
||||||
rooms: RoomInfo[];
|
rooms: RoomInfo[];
|
||||||
userId: number;
|
userId: number;
|
||||||
|
|
@ -436,6 +471,10 @@ function useChatRouteSync({
|
||||||
setSidebarOpen: (open: boolean) => void;
|
setSidebarOpen: (open: boolean) => void;
|
||||||
subscribe: (chatCode: string) => void;
|
subscribe: (chatCode: string) => void;
|
||||||
unsubscribe: (chatCode: string) => void;
|
unsubscribe: (chatCode: string) => void;
|
||||||
|
setRooms: React.Dispatch<React.SetStateAction<RoomInfo[]>>;
|
||||||
|
setMessagesByRoom: React.Dispatch<
|
||||||
|
React.SetStateAction<Record<string, ChatMessage[]>>
|
||||||
|
>;
|
||||||
}) {
|
}) {
|
||||||
const matches = useMatches();
|
const matches = useMatches();
|
||||||
const subscribedRoomRef = React.useRef<string | null>(null);
|
const subscribedRoomRef = React.useRef<string | null>(null);
|
||||||
|
|
@ -451,38 +490,31 @@ function useChatRouteSync({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!chatCode) {
|
const previousSubscribed = subscribedRoomRef.current;
|
||||||
// Leaving a chat route: unsubscribe from staff-subscribed rooms
|
|
||||||
if (subscribedRoomRef.current) {
|
// Clean up previous non-participant subscription if chatCode changed
|
||||||
unsubscribe(subscribedRoomRef.current);
|
if (previousSubscribed && previousSubscribed !== chatCode) {
|
||||||
subscribedRoomRef.current = null;
|
unsubscribe(previousSubscribed);
|
||||||
}
|
setRooms((prev) => prev.filter((r) => r.chatCode !== previousSubscribed));
|
||||||
return;
|
setMessagesByRoom((prev) => {
|
||||||
|
const { [previousSubscribed]: _, ...rest } = prev;
|
||||||
|
return rest;
|
||||||
|
});
|
||||||
|
subscribedRoomRef.current = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!chatCode) return;
|
||||||
|
|
||||||
const room = rooms.find((r) => r.chatCode === chatCode);
|
const room = rooms.find((r) => r.chatCode === chatCode);
|
||||||
|
const isParticipant = room?.participantUserIds.includes(userId);
|
||||||
|
|
||||||
if (room) {
|
if (!isParticipant && subscribedRoomRef.current !== chatCode) {
|
||||||
const isParticipant = room.participantUserIds.includes(userId);
|
subscribe(chatCode);
|
||||||
|
subscribedRoomRef.current = chatCode;
|
||||||
if (isParticipant) {
|
|
||||||
setActiveRoom(chatCode);
|
|
||||||
setSidebarOpen(true);
|
|
||||||
} else {
|
|
||||||
// Staff/TO viewing: subscribe temporarily
|
|
||||||
subscribe(chatCode);
|
|
||||||
subscribedRoomRef.current = chatCode;
|
|
||||||
setActiveRoom(chatCode);
|
|
||||||
setSidebarOpen(true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return () => {
|
setActiveRoom(chatCode);
|
||||||
if (subscribedRoomRef.current) {
|
setSidebarOpen(true);
|
||||||
unsubscribe(subscribedRoomRef.current);
|
|
||||||
subscribedRoomRef.current = null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}, [
|
}, [
|
||||||
matches,
|
matches,
|
||||||
rooms,
|
rooms,
|
||||||
|
|
@ -491,5 +523,7 @@ function useChatRouteSync({
|
||||||
setSidebarOpen,
|
setSidebarOpen,
|
||||||
subscribe,
|
subscribe,
|
||||||
unsubscribe,
|
unsubscribe,
|
||||||
|
setRooms,
|
||||||
|
setMessagesByRoom,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,8 @@ export const loader = async ({ params }: LoaderFunctionArgs) => {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
post,
|
post,
|
||||||
|
// xxx: only chatCode if permissions
|
||||||
|
chatCode: post.chatCode,
|
||||||
anyUserPrefersNoScreen:
|
anyUserPrefersNoScreen:
|
||||||
await UserRepository.anyUserPrefersNoScreen(participantIds),
|
await UserRepository.anyUserPrefersNoScreen(participantIds),
|
||||||
tournamentMapPool: post.mapsTournament
|
tournamentMapPool: post.mapsTournament
|
||||||
|
|
|
||||||
|
|
@ -67,5 +67,7 @@ export const loader = async ({ params }: LoaderFunctionArgs) => {
|
||||||
})
|
})
|
||||||
: null,
|
: null,
|
||||||
rawReportedWeapons,
|
rawReportedWeapons,
|
||||||
|
// xxx: only chatCode if permissions
|
||||||
|
chatCode: match.chatCode,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,8 @@ export const loader = async ({ request }: LoaderFunctionArgs) => {
|
||||||
? []
|
? []
|
||||||
: groups,
|
: groups,
|
||||||
ownGroup,
|
ownGroup,
|
||||||
|
// xxx: only chatCode if permissions
|
||||||
|
chatCode: ownGroup?.chatCode,
|
||||||
likes: ownGroup
|
likes: ownGroup
|
||||||
? await SQGroupRepository.allLikesByGroupId(ownGroup.id)
|
? await SQGroupRepository.allLikesByGroupId(ownGroup.id)
|
||||||
: {
|
: {
|
||||||
|
|
|
||||||
|
|
@ -119,5 +119,7 @@ export const loader = async ({ params }: LoaderFunctionArgs) => {
|
||||||
matchIsOver,
|
matchIsOver,
|
||||||
endedEarly,
|
endedEarly,
|
||||||
noScreen,
|
noScreen,
|
||||||
|
// xxx: only chatCode if permissions
|
||||||
|
chatCode: match.chatCode,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user