mirror of
https://github.com/NanmiCoder/cc-haha
synced 2026-07-17 13:13:35 +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()
|
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) {
|
function delay(ms: number) {
|
||||||
return new Promise((resolve) => setTimeout(resolve, ms))
|
return new Promise((resolve) => setTimeout(resolve, ms))
|
||||||
}
|
}
|
||||||
@ -136,6 +150,17 @@ describe('sessionStore', () => {
|
|||||||
expect(useTabStore.getState().tabs[0]?.title).toBe('使用bash写一个shell,随便写点什么东西')
|
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 () => {
|
it('ignores stale session list responses when a newer refresh finishes first', async () => {
|
||||||
const slow = createDeferred<{
|
const slow = createDeferred<{
|
||||||
sessions: Array<{
|
sessions: Array<{
|
||||||
|
|||||||
@ -11,6 +11,8 @@ import type { SessionListItem } from '../types/session'
|
|||||||
import type { PermissionMode } from '../types/settings'
|
import type { PermissionMode } from '../types/settings'
|
||||||
import { isPlaceholderSessionTitle } from '../lib/sessionTitle'
|
import { isPlaceholderSessionTitle } from '../lib/sessionTitle'
|
||||||
|
|
||||||
|
const SESSION_LIST_LIMIT = 400
|
||||||
|
|
||||||
type CreateSessionOptions = {
|
type CreateSessionOptions = {
|
||||||
repository?: CreateSessionRepositoryOptions
|
repository?: CreateSessionRepositoryOptions
|
||||||
permissionMode?: PermissionMode
|
permissionMode?: PermissionMode
|
||||||
@ -61,22 +63,11 @@ export const useSessionStore = create<SessionStore>((set, get) => ({
|
|||||||
const requestId = ++fetchSessionsRequestId
|
const requestId = ++fetchSessionsRequestId
|
||||||
set({ isLoading: true, error: null })
|
set({ isLoading: true, error: null })
|
||||||
try {
|
try {
|
||||||
const { sessions: raw } = await sessionsApi.list({ project, limit: 100 })
|
const { sessions: raw } = await sessionsApi.list(buildSessionListParams(project))
|
||||||
if (requestId !== fetchSessionsRequestId) return
|
if (requestId !== fetchSessionsRequestId) return
|
||||||
let syncedSessions: SessionListItem[] = []
|
let syncedSessions: SessionListItem[] = []
|
||||||
set((state) => {
|
set((state) => {
|
||||||
const currentById = new Map(state.sessions.map((session) => [session.id, session]))
|
const sessions = mergeSessionList(raw, state.sessions)
|
||||||
// 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()]
|
|
||||||
syncedSessions = sessions
|
syncedSessions = sessions
|
||||||
return { sessions, isLoading: false }
|
return { sessions, isLoading: false }
|
||||||
})
|
})
|
||||||
@ -237,6 +228,36 @@ function removeIdsFromSet(selected: Set<string>, ids: string[]): Set<string> {
|
|||||||
return next
|
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(
|
function preserveLocalTitle(
|
||||||
current: SessionListItem | undefined,
|
current: SessionListItem | undefined,
|
||||||
incoming: SessionListItem,
|
incoming: SessionListItem,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user