|
|
@@ -25,11 +25,11 @@ type TerminalCacheEntry = {
|
|
|
dispose: VoidFunction
|
|
|
}
|
|
|
|
|
|
-function createTerminalSession(sdk: ReturnType<typeof useSDK>, dir: string, id: string | undefined) {
|
|
|
- const legacy = `${dir}/terminal${id ? "/" + id : ""}.v1`
|
|
|
+function createTerminalSession(sdk: ReturnType<typeof useSDK>, dir: string, session?: string) {
|
|
|
+ const legacy = session ? [`${dir}/terminal/${session}.v1`, `${dir}/terminal.v1`] : [`${dir}/terminal.v1`]
|
|
|
|
|
|
const [store, setStore, _, ready] = persisted(
|
|
|
- Persist.scoped(dir, id, "terminal", [legacy]),
|
|
|
+ Persist.workspace(dir, "terminal", legacy),
|
|
|
createStore<{
|
|
|
active?: string
|
|
|
all: LocalPTY[]
|
|
|
@@ -43,17 +43,28 @@ function createTerminalSession(sdk: ReturnType<typeof useSDK>, dir: string, id:
|
|
|
all: createMemo(() => Object.values(store.all)),
|
|
|
active: createMemo(() => store.active),
|
|
|
new() {
|
|
|
+ const parse = (title: string) => {
|
|
|
+ const match = title.match(/^Terminal (\d+)$/)
|
|
|
+ if (!match) return
|
|
|
+ const value = Number(match[1])
|
|
|
+ if (!Number.isFinite(value) || value <= 0) return
|
|
|
+ return value
|
|
|
+ }
|
|
|
+
|
|
|
const existingTitleNumbers = new Set(
|
|
|
- store.all.map((pty) => {
|
|
|
- const match = pty.titleNumber
|
|
|
- return match
|
|
|
+ store.all.flatMap((pty) => {
|
|
|
+ const direct = Number.isFinite(pty.titleNumber) && pty.titleNumber > 0 ? pty.titleNumber : undefined
|
|
|
+ if (direct !== undefined) return [direct]
|
|
|
+ const parsed = parse(pty.title)
|
|
|
+ if (parsed === undefined) return []
|
|
|
+ return [parsed]
|
|
|
}),
|
|
|
)
|
|
|
|
|
|
- let nextNumber = 1
|
|
|
- while (existingTitleNumbers.has(nextNumber)) {
|
|
|
- nextNumber++
|
|
|
- }
|
|
|
+ const nextNumber =
|
|
|
+ Array.from({ length: existingTitleNumbers.size + 1 }, (_, index) => index + 1).find(
|
|
|
+ (number) => !existingTitleNumbers.has(number),
|
|
|
+ ) ?? 1
|
|
|
|
|
|
sdk.client.pty
|
|
|
.create({ title: `Terminal ${nextNumber}` })
|
|
|
@@ -166,8 +177,8 @@ export const { use: useTerminal, provider: TerminalProvider } = createSimpleCont
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- const load = (dir: string, id: string | undefined) => {
|
|
|
- const key = `${dir}:${id ?? WORKSPACE_KEY}`
|
|
|
+ const load = (dir: string, session?: string) => {
|
|
|
+ const key = `${dir}:${WORKSPACE_KEY}`
|
|
|
const existing = cache.get(key)
|
|
|
if (existing) {
|
|
|
cache.delete(key)
|
|
|
@@ -176,7 +187,7 @@ export const { use: useTerminal, provider: TerminalProvider } = createSimpleCont
|
|
|
}
|
|
|
|
|
|
const entry = createRoot((dispose) => ({
|
|
|
- value: createTerminalSession(sdk, dir, id),
|
|
|
+ value: createTerminalSession(sdk, dir, session),
|
|
|
dispose,
|
|
|
}))
|
|
|
|
|
|
@@ -185,18 +196,18 @@ export const { use: useTerminal, provider: TerminalProvider } = createSimpleCont
|
|
|
return entry.value
|
|
|
}
|
|
|
|
|
|
- const session = createMemo(() => load(params.dir!, params.id))
|
|
|
+ const workspace = createMemo(() => load(params.dir!, params.id))
|
|
|
|
|
|
return {
|
|
|
- ready: () => session().ready(),
|
|
|
- all: () => session().all(),
|
|
|
- active: () => session().active(),
|
|
|
- new: () => session().new(),
|
|
|
- update: (pty: Partial<LocalPTY> & { id: string }) => session().update(pty),
|
|
|
- clone: (id: string) => session().clone(id),
|
|
|
- open: (id: string) => session().open(id),
|
|
|
- close: (id: string) => session().close(id),
|
|
|
- move: (id: string, to: number) => session().move(id, to),
|
|
|
+ ready: () => workspace().ready(),
|
|
|
+ all: () => workspace().all(),
|
|
|
+ active: () => workspace().active(),
|
|
|
+ new: () => workspace().new(),
|
|
|
+ update: (pty: Partial<LocalPTY> & { id: string }) => workspace().update(pty),
|
|
|
+ clone: (id: string) => workspace().clone(id),
|
|
|
+ open: (id: string) => workspace().open(id),
|
|
|
+ close: (id: string) => workspace().close(id),
|
|
|
+ move: (id: string, to: number) => workspace().move(id, to),
|
|
|
}
|
|
|
},
|
|
|
})
|