(fix): chat issues when sending messages
This commit is contained in:
parent
b4662bc1a4
commit
4a0f9e3b58
2 changed files with 76 additions and 33 deletions
|
|
@ -266,7 +266,11 @@ export default function Provider(props: { children: ReactNode }) {
|
|||
return updated ? next : prev;
|
||||
});
|
||||
|
||||
const queryKey = ["chat-messages", String(userIdValue)] as const;
|
||||
const queryKey = [
|
||||
"chat-messages",
|
||||
String(userIdValue),
|
||||
currentSharedSecret.length > 0,
|
||||
] as const;
|
||||
queryClient.setQueryData<InfiniteData<RawMessages>>(
|
||||
queryKey,
|
||||
(current) => {
|
||||
|
|
@ -301,7 +305,7 @@ export default function Provider(props: { children: ReactNode }) {
|
|||
},
|
||||
);
|
||||
});
|
||||
}, [subscribePush, userIdValue]);
|
||||
}, [currentSharedSecret, subscribePush, userIdValue]);
|
||||
|
||||
return (
|
||||
<QueryClientProvider client={queryClient}>
|
||||
|
|
|
|||
|
|
@ -12,8 +12,16 @@ import {
|
|||
PAGE_SIZE,
|
||||
FALLBACK_MESSAGE_HEIGHT,
|
||||
MESSAGES_PER_VIRTUAL_ROW,
|
||||
type LiveMessage,
|
||||
type RawMessage,
|
||||
} from "./values";
|
||||
|
||||
type MessageChunk = {
|
||||
key: string;
|
||||
messages: Array<RawMessage | LiveMessage>;
|
||||
startIndex: number;
|
||||
};
|
||||
|
||||
function getEstimatedMessageHeight(message: { height?: number }) {
|
||||
return typeof message.height === "number" && Number.isFinite(message.height)
|
||||
? Math.max(1, Math.ceil(message.height))
|
||||
|
|
@ -39,6 +47,34 @@ function shouldFetchPreviousPage({
|
|||
].every(Boolean);
|
||||
}
|
||||
|
||||
function getMessageRenderKey(message: RawMessage | LiveMessage) {
|
||||
return "localId" in message ? message.localId : String(message.send_time);
|
||||
}
|
||||
|
||||
function buildMessageChunks(
|
||||
messages: Array<RawMessage | LiveMessage>,
|
||||
keyPrefix: string,
|
||||
startOffset = 0,
|
||||
) {
|
||||
const chunks: MessageChunk[] = [];
|
||||
|
||||
for (let end = messages.length; end > 0; end -= MESSAGES_PER_VIRTUAL_ROW) {
|
||||
const start = Math.max(0, end - MESSAGES_PER_VIRTUAL_ROW);
|
||||
const chunkMessages = messages.slice(start, end);
|
||||
const firstMessage = chunkMessages[0];
|
||||
|
||||
if (firstMessage) {
|
||||
chunks.push({
|
||||
key: `${keyPrefix}-${getMessageRenderKey(firstMessage)}`,
|
||||
messages: chunkMessages,
|
||||
startIndex: startOffset + start,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return chunks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the chat screen with virtualized history and live message updates.
|
||||
* @returns Chat screen JSX.
|
||||
|
|
@ -148,49 +184,52 @@ export default function Screen() {
|
|||
|
||||
const historicalMessages = React.useMemo(() => {
|
||||
const pages = messagesQuery.data?.pages ?? [];
|
||||
return [...pages].reverse().flat();
|
||||
const seenSendTimes = new Set<number>();
|
||||
const dedupedMessages: RawMessage[] = [];
|
||||
|
||||
for (const message of [...pages].reverse().flat()) {
|
||||
if (seenSendTimes.has(message.send_time)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
seenSendTimes.add(message.send_time);
|
||||
dedupedMessages.push(message);
|
||||
}
|
||||
|
||||
return dedupedMessages;
|
||||
}, [messagesQuery.data]);
|
||||
|
||||
const liveMessagesSnapshot = liveMessages();
|
||||
|
||||
const messages = React.useMemo(() => {
|
||||
if (historicalMessages.length === 0) {
|
||||
return liveMessagesSnapshot;
|
||||
}
|
||||
|
||||
const liveWithoutDuplicates = React.useMemo(() => {
|
||||
const historicalSendTimes = new Set(
|
||||
historicalMessages.map((message) => message.send_time),
|
||||
);
|
||||
const liveWithoutDuplicates = liveMessagesSnapshot.filter(
|
||||
|
||||
return liveMessagesSnapshot.filter(
|
||||
(message) => !historicalSendTimes.has(message.send_time),
|
||||
);
|
||||
|
||||
return [...historicalMessages, ...liveWithoutDuplicates];
|
||||
}, [historicalMessages, liveMessagesSnapshot]);
|
||||
|
||||
const messages = React.useMemo(() => {
|
||||
return [...historicalMessages, ...liveWithoutDuplicates];
|
||||
}, [historicalMessages, liveWithoutDuplicates]);
|
||||
|
||||
const historicalMessageChunks = React.useMemo(() => {
|
||||
return buildMessageChunks(historicalMessages, "history");
|
||||
}, [historicalMessages]);
|
||||
|
||||
const liveMessageChunks = React.useMemo(() => {
|
||||
return buildMessageChunks(
|
||||
liveWithoutDuplicates,
|
||||
"live",
|
||||
historicalMessages.length,
|
||||
);
|
||||
}, [historicalMessages.length, liveWithoutDuplicates]);
|
||||
|
||||
const messageChunks = React.useMemo(() => {
|
||||
const chunks: Array<{
|
||||
key: number;
|
||||
messages: typeof messages;
|
||||
startIndex: number;
|
||||
}> = [];
|
||||
|
||||
for (let end = messages.length; end > 0; end -= MESSAGES_PER_VIRTUAL_ROW) {
|
||||
const start = Math.max(0, end - MESSAGES_PER_VIRTUAL_ROW);
|
||||
const chunkMessages = messages.slice(start, end);
|
||||
const firstMessage = chunkMessages[0];
|
||||
|
||||
if (firstMessage) {
|
||||
chunks.push({
|
||||
key: firstMessage.send_time,
|
||||
messages: chunkMessages,
|
||||
startIndex: start,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return chunks;
|
||||
}, [messages]);
|
||||
return [...liveMessageChunks, ...historicalMessageChunks];
|
||||
}, [historicalMessageChunks, liveMessageChunks]);
|
||||
|
||||
const shouldShowConversationStart =
|
||||
!!messagesQuery.data && !messagesQuery.hasNextPage;
|
||||
|
|
@ -530,7 +569,7 @@ export default function Screen() {
|
|||
|
||||
return (
|
||||
<Message
|
||||
key={message.send_time}
|
||||
key={getMessageRenderKey(message)}
|
||||
grouped={isGrouped}
|
||||
message={message}
|
||||
user={
|
||||
|
|
|
|||
Loading…
Reference in a new issue