fix: stabilize older message loading
This commit is contained in:
@@ -16,7 +16,7 @@ import { hasPendingUserSendAnimation, consumePendingUserSendAnimation } from '@/
|
|||||||
import { streamPerfCount, streamPerfMeasure } from '@/stores/utils/streamDebug';
|
import { streamPerfCount, streamPerfMeasure } from '@/stores/utils/streamDebug';
|
||||||
import type { StreamPhase } from './message/types';
|
import type { StreamPhase } from './message/types';
|
||||||
|
|
||||||
const MESSAGE_LIST_VIRTUALIZE_THRESHOLD = 15;
|
const MESSAGE_LIST_VIRTUALIZE_THRESHOLD = Number.POSITIVE_INFINITY;
|
||||||
const MESSAGE_LIST_OVERSCAN = 6;
|
const MESSAGE_LIST_OVERSCAN = 6;
|
||||||
|
|
||||||
const estimateHistoryEntryHeight = (entry: RenderEntry | undefined): number => {
|
const estimateHistoryEntryHeight = (entry: RenderEntry | undefined): number => {
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import type { SessionStatus } from "@opencode-ai/sdk/v2/client"
|
|||||||
import type { PermissionRequest } from "@/types/permission"
|
import type { PermissionRequest } from "@/types/permission"
|
||||||
import type { QuestionRequest } from "@/types/question"
|
import type { QuestionRequest } from "@/types/question"
|
||||||
import * as sessionActions from "./session-actions"
|
import * as sessionActions from "./session-actions"
|
||||||
|
import { mergeMessages } from "./optimistic"
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Context
|
// Context
|
||||||
@@ -162,32 +163,6 @@ function haveEquivalentPartSnapshots(left: Part[] | undefined, right: Part[]): b
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
function haveEquivalentMessageSnapshots(left: Message[] | undefined, right: Message[]): boolean {
|
|
||||||
if (!left) {
|
|
||||||
return right.length === 0
|
|
||||||
}
|
|
||||||
|
|
||||||
if (left.length !== right.length) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let index = 0; index < left.length; index += 1) {
|
|
||||||
const leftMessage = left[index]
|
|
||||||
const rightMessage = right[index]
|
|
||||||
if (!leftMessage || !rightMessage) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if (leftMessage.id !== rightMessage.id) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if (syncSnapshotSignature(leftMessage) !== syncSnapshotSignature(rightMessage)) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
function haveEquivalentSyncSnapshots(left: unknown, right: unknown): boolean {
|
function haveEquivalentSyncSnapshots(left: unknown, right: unknown): boolean {
|
||||||
return syncSnapshotSignature(left) === syncSnapshotSignature(right)
|
return syncSnapshotSignature(left) === syncSnapshotSignature(right)
|
||||||
}
|
}
|
||||||
@@ -813,14 +788,15 @@ async function resyncDirectoryAfterReconnect(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const messagesChanged = !haveEquivalentMessageSnapshots(state.message[sessionId], nextMessages)
|
const mergedMessages = mergeMessages(state.message[sessionId] ?? [], nextMessages)
|
||||||
|
const messagesChanged = mergedMessages !== (state.message[sessionId] ?? [])
|
||||||
if (!sessionChanged && !messagesChanged && !partsChanged) {
|
if (!sessionChanged && !messagesChanged && !partsChanged) {
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...(sessionChanged ? { session: sessions, sessionTotal } : {}),
|
...(sessionChanged ? { session: sessions, sessionTotal } : {}),
|
||||||
...(messagesChanged ? { message: { ...state.message, [sessionId]: nextMessages } } : {}),
|
...(messagesChanged ? { message: { ...state.message, [sessionId]: mergedMessages } } : {}),
|
||||||
...(partsChanged ? { part: nextPartState } : {}),
|
...(partsChanged ? { part: nextPartState } : {}),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -2001,10 +1977,14 @@ export function useEnsureSessionMessages(sessionID: string, directory?: string)
|
|||||||
.sort((a: Part, b: Part) => cmp(a.id, b.id))
|
.sort((a: Part, b: Part) => cmp(a.id, b.id))
|
||||||
}
|
}
|
||||||
|
|
||||||
store.setState((state: DirectoryStore) => ({
|
store.setState((state: DirectoryStore) => {
|
||||||
message: { ...state.message, [sessionID]: nextMessages },
|
const currentMessages = state.message[sessionID] ?? []
|
||||||
part: { ...state.part, ...nextPartState },
|
const mergedMessages = mergeMessages(currentMessages, nextMessages)
|
||||||
}))
|
return {
|
||||||
|
message: mergedMessages !== currentMessages ? { ...state.message, [sessionID]: mergedMessages } : state.message,
|
||||||
|
part: { ...state.part, ...nextPartState },
|
||||||
|
}
|
||||||
|
})
|
||||||
} catch {
|
} catch {
|
||||||
// Transient failure — next navigation or reconnect will retry
|
// Transient failure — next navigation or reconnect will retry
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
@@ -222,10 +222,10 @@ export function useSync() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const current = store.getState()
|
const current = store.getState()
|
||||||
const cached = options?.mode === "prepend" ? (current.message[sessionID] ?? []) : []
|
const cached = current.message[sessionID] ?? []
|
||||||
const messages = options?.mode === "prepend"
|
const messages = options?.mode === "prepend"
|
||||||
? mergeMessages(cached, merged.session)
|
? mergeMessages(cached, merged.session)
|
||||||
: merged.session
|
: (cached.length > 0 ? mergeMessages(cached, merged.session) : merged.session)
|
||||||
|
|
||||||
// Build part updates — preserve existing references on prepend to avoid flicker
|
// Build part updates — preserve existing references on prepend to avoid flicker
|
||||||
const isPrepend = options?.mode === "prepend"
|
const isPrepend = options?.mode === "prepend"
|
||||||
|
|||||||
Reference in New Issue
Block a user