feat(ui-workspace): reorder ungrouped sessions
This commit is contained in:
@@ -24,8 +24,9 @@ const workspace = (id: string, sessionIds: string[], title = id): WorkspaceView
|
||||
workspaceId: wid(id), path: `/projects/${id}`, title,
|
||||
sessionIds: sessionIds.map(sid), createdAt: '2026-01-01T00:00:00.000Z', updatedAt: '2026-01-01T00:00:00.000Z',
|
||||
})
|
||||
const view = (expandedProjects: readonly string[] = []) => ({
|
||||
const view = (expandedProjects: readonly string[] = [], ungroupedOrder?: readonly string[]) => ({
|
||||
expandedProjects,
|
||||
...(ungroupedOrder === undefined ? {} : { ungroupedOrder }),
|
||||
})
|
||||
const noArchive: readonly SessionId[] = []
|
||||
const archived = (...ids: string[]): readonly SessionId[] => ids.map(sid)
|
||||
@@ -54,6 +55,19 @@ describe('deriveGroups', () => {
|
||||
expect(groups[1]!.sessions.map(session => session.id)).toEqual([sid('loose')])
|
||||
})
|
||||
|
||||
it('applies stored Ungrouped order and appends new loose Sessions by recency', () => {
|
||||
const sessions = list(summary('one', 3), summary('two', 2), summary('new', 4))
|
||||
const groups = deriveGroups(
|
||||
sessions,
|
||||
[],
|
||||
noArchive,
|
||||
view([UNGROUPED_KEY], ['two', 'stale', 'two']),
|
||||
)
|
||||
expect(groups[0]!.sessions.map(session => session.id)).toEqual([
|
||||
sid('two'), sid('new'), sid('one'),
|
||||
])
|
||||
})
|
||||
|
||||
it('shows only the current blank session in its Workspace count and tree', () => {
|
||||
const currentBlank = { ...summary('current-blank', 5), blank: true }
|
||||
const staleBlank = { ...summary('stale-blank', 4), blank: true }
|
||||
|
||||
@@ -9,6 +9,7 @@ import { makeTranslate } from '@deepseek-ai/dsh-client-test-runtime'
|
||||
import { zh as commonZh } from '@deepseek-ai/dsh-client-locale/src/locales/zh.ts'
|
||||
import type { WorkspaceBrowserProps } from '../src/client/contract/slots.ts'
|
||||
import { createWorkspaceViewStore } from '../src/client/stores.ts'
|
||||
import { UNGROUPED_KEY } from '../src/client/tree.ts'
|
||||
import { WorkspaceBrowser } from '../src/client/WorkspaceBrowser.tsx'
|
||||
import { zh } from '../src/client/locales.ts'
|
||||
|
||||
@@ -111,8 +112,8 @@ describe('WorkspaceBrowser', () => {
|
||||
rerender(b, { useWorkspaces: hook(workspaceState([])) })
|
||||
await waitFor(() => {
|
||||
expect(b.store.getSnapshot().workspaceExpansion).toEqual({})
|
||||
expect(b.store.getSnapshot().recentSessionOrder).toEqual({})
|
||||
expect(b.store.getSnapshot().recentSessionUpdatedAt).toEqual({})
|
||||
expect(b.store.getSnapshot().recentSessionOrder).toEqual({ [UNGROUPED_KEY]: [] })
|
||||
expect(b.store.getSnapshot().recentSessionUpdatedAt).toEqual({ [UNGROUPED_KEY]: {} })
|
||||
})
|
||||
})
|
||||
|
||||
@@ -776,6 +777,55 @@ describe('WorkspaceBrowser', () => {
|
||||
expect(insertSessionBefore).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
it('persists Ungrouped drag order in both modes without writing a Host Workspace account', async () => {
|
||||
const insertSessionBefore = vi.fn(async () => {})
|
||||
const sessions = sessionState([summary('one', 3), summary('two', 2), summary('three', 1)])
|
||||
const b = mount({
|
||||
useSessions: hook(sessions),
|
||||
useWorkspaces: hook(workspaceState([])),
|
||||
insertSessionBefore,
|
||||
})
|
||||
fireEvent.click(screen.getByText('未分组'))
|
||||
|
||||
const dragAfter = (sourceTitle: string, targetTitle: string): void => {
|
||||
const source = screen.getByText(sourceTitle).closest('[role="treeitem"]') as HTMLElement
|
||||
const target = screen.getByText(targetTitle).closest('[role="treeitem"]') as HTMLElement
|
||||
target.getBoundingClientRect = () => ({
|
||||
top: 150, bottom: 184, left: 0, right: 200, width: 200, height: 34, x: 0, y: 150, toJSON: () => ({}),
|
||||
})
|
||||
fireEvent.dragStart(source, { dataTransfer: dragData() })
|
||||
fireDrag(target, 'drop', 180)
|
||||
}
|
||||
|
||||
dragAfter('one', 'three')
|
||||
expect(b.store.getSnapshot().recentSessionOrder[UNGROUPED_KEY]).toEqual(['two', 'three', 'one'])
|
||||
dragAfter('two', 'one')
|
||||
expect(b.store.getSnapshot().recentSessionOrder[UNGROUPED_KEY]).toEqual(['three', 'one', 'two'])
|
||||
expect(insertSessionBefore).not.toHaveBeenCalled()
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: '视图选项' }))
|
||||
fireEvent.click(screen.getByRole('menuitem', { name: '最近更新' }))
|
||||
await waitFor(() => {
|
||||
expect(b.store.getSnapshot().recentSessionOrder[UNGROUPED_KEY]).toEqual(['one', 'two', 'three'])
|
||||
})
|
||||
dragAfter('one', 'three')
|
||||
expect(b.store.getSnapshot().recentSessionOrder[UNGROUPED_KEY]).toEqual(['two', 'three', 'one'])
|
||||
expect(insertSessionBefore).not.toHaveBeenCalled()
|
||||
|
||||
b.view.unmount()
|
||||
const restored = mount({
|
||||
useSessions: hook(sessions),
|
||||
useWorkspaces: hook(workspaceState([])),
|
||||
insertSessionBefore,
|
||||
})
|
||||
expect(restored.store.getSnapshot().recentSessionOrder[UNGROUPED_KEY]).toEqual(['two', 'three', 'one'])
|
||||
expect(screen.getAllByRole('treeitem').slice(1).map(row => row.textContent)).toEqual([
|
||||
expect.stringContaining('two'),
|
||||
expect.stringContaining('three'),
|
||||
expect.stringContaining('one'),
|
||||
])
|
||||
})
|
||||
|
||||
it('still sends the reorder when the dragged row left the group mid-drag', () => {
|
||||
const insertSessionBefore = vi.fn(async () => {})
|
||||
const sessions = sessionState([summary('one', 2), summary('two', 1)])
|
||||
|
||||
Reference in New Issue
Block a user