Merge pull request #385 from TaurusWood/fix/free-window-restored-id-collision

fix(state): seed restored free-window ids
This commit is contained in:
Atlas Zeng
2026-09-02 23:10:46 +08:00
committed by GitHub
2 changed files with 53 additions and 2 deletions
+2 -2
View File
@@ -155,7 +155,7 @@ export function mintTabId(): string {
/**
* The largest numeric suffix across a raw persisted state's counter ids
* (`pane:N` / `tab:N` / `split:N`). The uid counter is module-global and
* (`pane:N` / `tab:N` / `split:N` / `float:N`). The uid counter is module-global and
* resets on every reload, so a split minted AFTER a reload would collide
* with the persisted ids (a fresh "pane:1" beside the persisted "pane:1");
* mapLeaf would then visit BOTH leaves and every open would land in both
@@ -166,7 +166,7 @@ function maxCounterId(parsed: unknown): number {
let max = 0
const consider = (id: unknown): void => {
if (typeof id !== 'string') return
const match = /^(?:pane|tab|split):(\d+)$/.exec(id)
const match = /^(?:pane|tab|split|float):(\d+)$/.exec(id)
if (match !== null) max = Math.max(max, Number(match[1]))
}
const walk = (node: unknown): void => {
+51
View File
@@ -0,0 +1,51 @@
// @vitest-environment jsdom
import { beforeEach, describe, expect, it } from 'vitest'
import { createSidebarStore, floatTab } from '../src/client/state.ts'
beforeEach(() => {
localStorage.clear()
})
describe('restored free-window ids', () => {
it('seeds the shared uid counter past persisted float ids before minting another window', () => {
localStorage.setItem('dsh-sidebar:v1:s1', JSON.stringify({
panelOpen: true,
width: 400,
activePane: 'pane:1',
nextTerminal: 1,
nextBrowser: 1,
expanded: [],
splits: {
kind: 'leaf',
id: 'pane:1',
active: 'tab:2',
tabs: [{ id: 'tab:2', type: 'browser', title: 'Docked' }],
},
bottomOpen: false,
bottomHeight: 220,
bottomOpenedOnce: false,
bottomSplits: {
kind: 'leaf',
id: 'pane:3',
active: null,
tabs: [],
},
floats: [{
id: 'float:5',
tab: { id: 'tab:4', type: 'browser', title: 'Existing float' },
x: 0,
y: 0,
w: 390,
h: 500,
}],
}))
const store = createSidebarStore()
store.setSession('s1')
store.reduce(state => floatTab(state, 'tab:2', 400, 300))
const ids = store.getSnapshot().state!.floats.map(float => float.id)
expect(ids).toEqual(['float:5', 'float:6'])
expect(new Set(ids).size).toBe(ids.length)
})
})