mirror of
https://github.com/block/buzz.git
synced 2026-11-13 04:41:12 +00:00
fix(desktop): project sends into open thread cache
Co-authored-by: npub1mprnacetjua2xx3p5eddmhxyk6wv929ymm5py8kd2xfxurxahspqqlgyta <d8473ee32b973aa31a21a65adddcc4b69cc2a8a4dee8121ecd51926e0cddbc02@sprout-oss.stage.blox.sqprod.co> Signed-off-by: npub1mprnacetjua2xx3p5eddmhxyk6wv929ymm5py8kd2xfxurxahspqqlgyta <d8473ee32b973aa31a21a65adddcc4b69cc2a8a4dee8121ecd51926e0cddbc02@sprout-oss.stage.blox.sqprod.co>
This commit is contained in:
parent
738d456367
commit
d7b6d5de07
@@ -74,6 +74,8 @@ type MessageQueryContext = {
|
||||
previousWindow: ChannelWindowStore | undefined;
|
||||
channelId: string;
|
||||
queryKey: ReturnType<typeof channelMessagesKey>;
|
||||
threadQueryKey?: ReturnType<typeof threadRepliesKey>;
|
||||
previousThreadReplies?: RelayEvent[];
|
||||
};
|
||||
|
||||
const CHANNEL_TIMELINE_KINDS = new Set<number>(CHANNEL_TIMELINE_CONTENT_KINDS);
|
||||
@@ -565,6 +567,17 @@ export function useSendMessageMutation(
|
||||
mediaTags ?? [],
|
||||
);
|
||||
|
||||
const threadRootId = getThreadReference(optimisticMessage.tags).rootId;
|
||||
const threadQueryKey = threadRootId
|
||||
? threadRepliesKey(effectiveChannel.id, threadRootId)
|
||||
: undefined;
|
||||
if (threadQueryKey) {
|
||||
await queryClient.cancelQueries({ queryKey: threadQueryKey });
|
||||
}
|
||||
const previousThreadReplies = threadQueryKey
|
||||
? (queryClient.getQueryData<RelayEvent[]>(threadQueryKey) ?? [])
|
||||
: undefined;
|
||||
|
||||
const nextWindow = mergeLiveChannelWindowEvent(
|
||||
previousWindow ?? emptyChannelWindowStore(),
|
||||
optimisticMessage,
|
||||
@@ -572,12 +585,21 @@ export function useSendMessageMutation(
|
||||
queryClient.setQueryData(windowKey, nextWindow);
|
||||
projectChannelWindowMessages(queryClient, effectiveChannel.id);
|
||||
|
||||
if (threadQueryKey) {
|
||||
queryClient.setQueryData<RelayEvent[]>(
|
||||
threadQueryKey,
|
||||
mergeMessages(previousThreadReplies ?? [], optimisticMessage),
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
optimisticId: optimisticMessage.id,
|
||||
previousMessages,
|
||||
previousWindow,
|
||||
channelId: effectiveChannel.id,
|
||||
queryKey,
|
||||
threadQueryKey,
|
||||
previousThreadReplies,
|
||||
};
|
||||
},
|
||||
onError: (error, _variables, context) => {
|
||||
@@ -594,6 +616,12 @@ export function useSendMessageMutation(
|
||||
channelWindowKey(context.channelId),
|
||||
context.previousWindow,
|
||||
);
|
||||
if (context.threadQueryKey) {
|
||||
queryClient.setQueryData(
|
||||
context.threadQueryKey,
|
||||
context.previousThreadReplies,
|
||||
);
|
||||
}
|
||||
},
|
||||
onSuccess: (message, _variables, context) => {
|
||||
// An accepted send proves the write-block is lifted; clear any recorded
|
||||
@@ -619,6 +647,16 @@ export function useSendMessageMutation(
|
||||
});
|
||||
queryClient.setQueryData(windowKey, next);
|
||||
projectChannelWindowMessages(queryClient, context.channelId);
|
||||
if (context.threadQueryKey) {
|
||||
queryClient.setQueryData<RelayEvent[]>(
|
||||
context.threadQueryKey,
|
||||
(current = []) =>
|
||||
mergeMessages(current, {
|
||||
...message,
|
||||
localKey: context.optimisticId,
|
||||
}),
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -164,6 +164,8 @@ type E2eConfig = {
|
||||
applyCommunityDelayMs?: number;
|
||||
openDmDelayMs?: number;
|
||||
sendMessageDelayMs?: number;
|
||||
/** Persist sends without echoing them to live subscriptions. */
|
||||
suppressLiveMessageEcho?: boolean;
|
||||
/** Reject successive kind-9 sends with these messages, then resume. */
|
||||
sendMessageErrors?: string[];
|
||||
/** Reject successive managed-agent starts, then resume. */
|
||||
@@ -7660,7 +7662,9 @@ async function handleSendChannelMessage(
|
||||
...extraTags,
|
||||
]);
|
||||
recordMockMessage(args.channelId, event);
|
||||
emitMockLiveEvent(args.channelId, event);
|
||||
if (!config?.mock?.suppressLiveMessageEcho) {
|
||||
emitMockLiveEvent(args.channelId, event);
|
||||
}
|
||||
|
||||
return {
|
||||
event_id: event.id,
|
||||
@@ -7723,7 +7727,9 @@ async function handleSendChannelMessage(
|
||||
};
|
||||
|
||||
recordMockMessage(args.channelId, event);
|
||||
emitMockLiveEvent(args.channelId, event);
|
||||
if (!config?.mock?.suppressLiveMessageEcho) {
|
||||
emitMockLiveEvent(args.channelId, event);
|
||||
}
|
||||
|
||||
return {
|
||||
event_id: event.id,
|
||||
|
||||
@@ -1158,6 +1158,35 @@ test("thread refetch preserves a live reply and reaction received in flight", as
|
||||
await expect(replyRow.getByLabel("Toggle 👍 reaction")).toBeVisible();
|
||||
});
|
||||
|
||||
test("thread reply appears without a live subscription echo", async ({
|
||||
page,
|
||||
}) => {
|
||||
await installMockBridge(page, { suppressLiveMessageEcho: true });
|
||||
await page.goto("/");
|
||||
await page.getByTestId("channel-general").click();
|
||||
await expect(page.getByTestId("chat-title")).toHaveText("general");
|
||||
|
||||
const seed = `Thread no-echo seed ${Date.now()}`;
|
||||
await page.getByTestId("message-input").fill(seed);
|
||||
await page.getByTestId("send-message").click();
|
||||
await expect(page.getByTestId("message-timeline")).toContainText(seed);
|
||||
|
||||
const rootMessage = page
|
||||
.getByTestId("message-timeline")
|
||||
.getByTestId("message-row")
|
||||
.last();
|
||||
await rootMessage.hover();
|
||||
await rootMessage.getByRole("button", { name: "Reply" }).click();
|
||||
|
||||
const threadPanel = page.getByTestId("message-thread-panel");
|
||||
const reply = `Thread reply without echo ${Date.now()}`;
|
||||
await threadPanel.getByTestId("message-input").fill(reply);
|
||||
await threadPanel.getByTestId("send-message").click();
|
||||
|
||||
await expect(threadPanel).toContainText(reply);
|
||||
await expect(threadPanel.getByTestId("message-input")).toBeEnabled();
|
||||
});
|
||||
|
||||
test("thread composer keeps focus after sending a thread reply", async ({
|
||||
page,
|
||||
}) => {
|
||||
|
||||
@@ -184,6 +184,8 @@ type MockBridgeOptions = {
|
||||
applyCommunityDelayMs?: number;
|
||||
openDmDelayMs?: number;
|
||||
sendMessageDelayMs?: number;
|
||||
/** Persist sends without echoing them to live subscriptions. */
|
||||
suppressLiveMessageEcho?: boolean;
|
||||
/** Reject successive kind-9 sends with these messages, then resume. */
|
||||
sendMessageErrors?: string[];
|
||||
/** Reject successive managed-agent starts, then resume. */
|
||||
|
||||
Reference in New Issue
Block a user