Skip to content

Commit adfeec0

Browse files
committed
fix: render message route anchor before context loads
1 parent 812479d commit adfeec0

9 files changed

Lines changed: 1300 additions & 115 deletions

packages/web/src/entities/message/message-workspace.model.test.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import type {
1111
import {
1212
selectWorkspaceMessagesForConversation,
1313
selectWorkspaceMessageStatusForConversation,
14+
selectWorkspaceMessageWindowStateForConversation,
1415
useWorkspaceMessageStore,
1516
} from "./message.model";
1617

@@ -413,6 +414,33 @@ describe("workspace message store", () => {
413414
expect(state.hasMoreByConversationId[TOPIC_CONVERSATION_ID]).toBe(true);
414415
});
415416

417+
it("tracks whether a direct message window is staged or complete", () => {
418+
const store = useWorkspaceMessageStore.getState();
419+
store.setConversationMessageWindowState(TOPIC_CONVERSATION_ID, "staged");
420+
expect(
421+
selectWorkspaceMessageWindowStateForConversation(
422+
useWorkspaceMessageStore.getState(),
423+
TOPIC_CONVERSATION_ID,
424+
),
425+
).toBe("staged");
426+
427+
store.setConversationMessageWindowState(TOPIC_CONVERSATION_ID, "complete");
428+
expect(
429+
selectWorkspaceMessageWindowStateForConversation(
430+
useWorkspaceMessageStore.getState(),
431+
TOPIC_CONVERSATION_ID,
432+
),
433+
).toBe("complete");
434+
435+
store.clear();
436+
expect(
437+
selectWorkspaceMessageWindowStateForConversation(
438+
useWorkspaceMessageStore.getState(),
439+
TOPIC_CONVERSATION_ID,
440+
),
441+
).toBeNull();
442+
});
443+
416444
it("clears before and after window markers with the existing store reset", () => {
417445
useWorkspaceMessageStore.getState().setConversationWindowMarkers(TOPIC_CONVERSATION_ID, {
418446
beforePageMarker: "before-1",

packages/web/src/entities/message/message.model.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,15 @@ import {
2121
removeWorkspaceMessageId,
2222
} from "./message-workspace-order.lib";
2323
import type {
24+
WorkspaceConversationMessageWindowState,
2425
WorkspaceConversationMessagesStatus,
2526
WorkspaceMessageStoreData,
2627
WorkspaceMessageStoreState,
2728
WorkspaceOptimisticMessageReadChange,
2829
} from "./message.model.types";
2930

3031
export type {
32+
WorkspaceConversationMessageWindowState,
3133
WorkspaceConversationMessagesStatus,
3234
WorkspaceConversationPagination,
3335
WorkspaceConversationWindowMarkers,
@@ -42,6 +44,9 @@ export type {
4244

4345
const EMPTY_MESSAGES_BY_ID: Record<MessengerUuid, MessengerMessage> = {};
4446
const EMPTY_MESSAGE_IDS_BY_CONVERSATION_ID: Record<MessengerConversationId, MessengerUuid[]> = {};
47+
const EMPTY_MESSAGE_WINDOW_STATE_BY_CONVERSATION_ID: Partial<
48+
Record<MessengerConversationId, WorkspaceConversationMessageWindowState>
49+
> = {};
4550
const EMPTY_MESSAGES_LOADING_BY_CONVERSATION_ID: Record<MessengerConversationId, boolean> = {};
4651
const EMPTY_MESSAGES_ERROR_BY_CONVERSATION_ID: Record<MessengerConversationId, string | null> = {};
4752
const EMPTY_NEXT_PAGE_MARKER_BY_CONVERSATION_ID: Record<MessengerConversationId, string | null> =
@@ -160,6 +165,7 @@ function createEmptyWorkspaceMessageData(): WorkspaceMessageStoreData {
160165
return {
161166
messagesById: EMPTY_MESSAGES_BY_ID,
162167
messageIdsByConversationId: EMPTY_MESSAGE_IDS_BY_CONVERSATION_ID,
168+
messageWindowStateByConversationId: EMPTY_MESSAGE_WINDOW_STATE_BY_CONVERSATION_ID,
163169
messagesLoadingByConversationId: EMPTY_MESSAGES_LOADING_BY_CONVERSATION_ID,
164170
messagesErrorByConversationId: EMPTY_MESSAGES_ERROR_BY_CONVERSATION_ID,
165171
nextPageMarkerByConversationId: EMPTY_NEXT_PAGE_MARKER_BY_CONVERSATION_ID,
@@ -799,13 +805,28 @@ export const useWorkspaceMessageStore = create<WorkspaceMessageStoreState>((set)
799805
}));
800806
},
801807

808+
setConversationMessageWindowState(conversationId, windowState) {
809+
if (isRemovedStreamConversation(conversationId)) return;
810+
logStoreAction("workspaceMessage", "setConversationMessageWindowState", {
811+
conversationId,
812+
windowState,
813+
});
814+
set((state) => ({
815+
messageWindowStateByConversationId: {
816+
...state.messageWindowStateByConversationId,
817+
[conversationId]: windowState,
818+
},
819+
}));
820+
},
821+
802822
removeMessagesForStream(streamUuid) {
803823
logStoreAction("workspaceMessage", "removeMessagesForStream", { streamUuid });
804824
removedStreamUuids.add(streamUuid);
805825
set((state) => {
806826
const removedConversationIds = new Set(
807827
[
808828
...Object.keys(state.messageIdsByConversationId),
829+
...Object.keys(state.messageWindowStateByConversationId),
809830
...Object.keys(state.messagesLoadingByConversationId),
810831
...Object.keys(state.messagesErrorByConversationId),
811832
...Object.keys(state.nextPageMarkerByConversationId),
@@ -828,6 +849,10 @@ export const useWorkspaceMessageStore = create<WorkspaceMessageStoreState>((set)
828849
state.messageIdsByConversationId,
829850
removedConversationIds,
830851
),
852+
messageWindowStateByConversationId: omitConversationRecords(
853+
state.messageWindowStateByConversationId,
854+
removedConversationIds,
855+
),
831856
messagesLoadingByConversationId: omitConversationRecords(
832857
state.messagesLoadingByConversationId,
833858
removedConversationIds,
@@ -903,6 +928,13 @@ export function selectWorkspaceMessagesForConversation(
903928
return messages;
904929
}
905930

931+
export function selectWorkspaceMessageWindowStateForConversation(
932+
state: WorkspaceMessageStoreState,
933+
conversationId: MessengerConversationId,
934+
): WorkspaceConversationMessageWindowState | null {
935+
return state.messageWindowStateByConversationId[conversationId] ?? null;
936+
}
937+
906938
interface ConversationStatusCacheEntry {
907939
loading: boolean;
908940
error: string | null;

packages/web/src/entities/message/message.model.types.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ import type {
1111
export interface WorkspaceMessageStoreData {
1212
messagesById: Record<MessengerUuid, MessengerMessage>;
1313
messageIdsByConversationId: Record<MessengerConversationId, MessengerUuid[]>;
14+
messageWindowStateByConversationId: Partial<
15+
Record<MessengerConversationId, WorkspaceConversationMessageWindowState>
16+
>;
1417
messagesLoadingByConversationId: Record<MessengerConversationId, boolean>;
1518
messagesErrorByConversationId: Record<MessengerConversationId, string | null>;
1619
nextPageMarkerByConversationId: Record<MessengerConversationId, string | null>;
@@ -53,6 +56,8 @@ export interface WorkspaceConversationWindowMarkers {
5356
afterPageMarker: string | null;
5457
}
5558

59+
export type WorkspaceConversationMessageWindowState = "staged" | "complete";
60+
5661
export interface WorkspaceConversationMessagesStatus {
5762
loading: boolean;
5863
error: string | null;
@@ -136,6 +141,10 @@ export interface WorkspaceMessageStoreState extends WorkspaceMessageStoreData {
136141
conversationId: MessengerConversationId,
137142
markers: WorkspaceConversationWindowMarkers,
138143
) => void;
144+
setConversationMessageWindowState: (
145+
conversationId: MessengerConversationId,
146+
state: WorkspaceConversationMessageWindowState,
147+
) => void;
139148
removeMessagesForStream: (streamUuid: MessengerUuid) => void;
140149
restoreMessagesForStream: (streamUuid: MessengerUuid) => void;
141150
clear: () => void;

0 commit comments

Comments
 (0)