mirror of
https://github.com/NanmiCoder/cc-haha
synced 2026-07-16 13:03:31 +08:00
fix(desktop): include more sidebar sessions (#759)
Increase the desktop session list fetch window so noisy observer sessions are less likely to hide real user sessions from the sidebar. Tested: cd desktop && bun run test -- src/stores/sessionStore.test.ts src/components/layout/Sidebar.test.tsx Tested: bun run check:desktop Confidence: high Scope-risk: narrow
This commit is contained in:
parent
90a50eca1c
commit
88d04a6267
@ -21,6 +21,20 @@ import { useTabStore } from './tabStore'
|
||||
|
||||
const initialState = useSessionStore.getState()
|
||||
|
||||
function makeSession(id: string, modifiedAt: string, title = id) {
|
||||
return {
|
||||
id,
|
||||
title,
|
||||
createdAt: modifiedAt,
|
||||
modifiedAt,
|
||||
messageCount: 1,
|
||||
projectPath: '/workspace/project',
|
||||
projectRoot: '/workspace/project',
|
||||
workDir: '/workspace/project',
|
||||
workDirExists: true,
|
||||
}
|
||||
}
|
||||
|
||||
function delay(ms: number) {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms))
|
||||
}
|
||||
@ -136,6 +150,17 @@ describe('sessionStore', () => {
|
||||
expect(useTabStore.getState().tabs[0]?.title).toBe('使用bash写一个shell,随便写点什么东西')
|
||||
})
|
||||
|
||||
it('requests a large default session page for noisy history directories', async () => {
|
||||
listMock.mockResolvedValue({
|
||||
sessions: [makeSession('session-newest', '2026-05-07T00:00:03.000Z')],
|
||||
total: 474,
|
||||
})
|
||||
|
||||
await useSessionStore.getState().fetchSessions()
|
||||
|
||||
expect(listMock).toHaveBeenCalledWith({ limit: 400 })
|
||||
})
|
||||
|
||||
it('ignores stale session list responses when a newer refresh finishes first', async () => {
|
||||
const slow = createDeferred<{
|
||||
sessions: Array<{
|
||||
|
||||
@ -11,6 +11,8 @@ import type { SessionListItem } from '../types/session'
|
||||
import type { PermissionMode } from '../types/settings'
|
||||
import { isPlaceholderSessionTitle } from '../lib/sessionTitle'
|
||||
|
||||
const SESSION_LIST_LIMIT = 400
|
||||
|
||||
type CreateSessionOptions = {
|
||||
repository?: CreateSessionRepositoryOptions
|
||||
permissionMode?: PermissionMode
|
||||
@ -61,22 +63,11 @@ export const useSessionStore = create<SessionStore>((set, get) => ({
|
||||
const requestId = ++fetchSessionsRequestId
|
||||
set({ isLoading: true, error: null })
|
||||
try {
|
||||
const { sessions: raw } = await sessionsApi.list({ project, limit: 100 })
|
||||
const { sessions: raw } = await sessionsApi.list(buildSessionListParams(project))
|
||||
if (requestId !== fetchSessionsRequestId) return
|
||||
let syncedSessions: SessionListItem[] = []
|
||||
set((state) => {
|
||||
const currentById = new Map(state.sessions.map((session) => [session.id, session]))
|
||||
// Deduplicate by session ID - keep the most recently modified entry.
|
||||
const byId = new Map<string, SessionListItem>()
|
||||
for (const s of raw) {
|
||||
const current = currentById.get(s.id)
|
||||
const candidate = preserveLocalTitle(current, s)
|
||||
const existing = byId.get(s.id)
|
||||
if (!existing || new Date(candidate.modifiedAt) > new Date(existing.modifiedAt)) {
|
||||
byId.set(s.id, candidate)
|
||||
}
|
||||
}
|
||||
const sessions = [...byId.values()]
|
||||
const sessions = mergeSessionList(raw, state.sessions)
|
||||
syncedSessions = sessions
|
||||
return { sessions, isLoading: false }
|
||||
})
|
||||
@ -237,6 +228,36 @@ function removeIdsFromSet(selected: Set<string>, ids: string[]): Set<string> {
|
||||
return next
|
||||
}
|
||||
|
||||
function buildSessionListParams(project: string | undefined) {
|
||||
return project
|
||||
? { project, limit: SESSION_LIST_LIMIT }
|
||||
: { limit: SESSION_LIST_LIMIT }
|
||||
}
|
||||
|
||||
function mergeSessionList(
|
||||
incoming: SessionListItem[],
|
||||
currentForTitle: SessionListItem[],
|
||||
): SessionListItem[] {
|
||||
const currentById = new Map(currentForTitle.map((session) => [session.id, session]))
|
||||
const byId = new Map<string, SessionListItem>()
|
||||
|
||||
for (const item of incoming) {
|
||||
const current = currentById.get(item.id)
|
||||
const candidate = preserveLocalTitle(current, item)
|
||||
const existing = byId.get(candidate.id)
|
||||
if (!existing || sessionModifiedTime(candidate) > sessionModifiedTime(existing)) {
|
||||
byId.set(candidate.id, candidate)
|
||||
}
|
||||
}
|
||||
|
||||
return [...byId.values()].sort((a, b) => sessionModifiedTime(b) - sessionModifiedTime(a))
|
||||
}
|
||||
|
||||
function sessionModifiedTime(session: SessionListItem): number {
|
||||
const timestamp = new Date(session.modifiedAt).getTime()
|
||||
return Number.isFinite(timestamp) ? timestamp : 0
|
||||
}
|
||||
|
||||
function preserveLocalTitle(
|
||||
current: SessionListItem | undefined,
|
||||
incoming: SessionListItem,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user