refactor(app): remove window state migration
This commit is contained in:
@@ -45,7 +45,7 @@ export async function installStressSessionTabs(page: Page, input?: { draftID?: s
|
||||
}),
|
||||
)
|
||||
localStorage.setItem(
|
||||
"opencode.global.dat:tabs",
|
||||
"opencode.window.browser.dat:tabs",
|
||||
JSON.stringify([
|
||||
...sessionIDs.map((sessionId) => ({
|
||||
type: "session",
|
||||
|
||||
@@ -14,7 +14,7 @@ test("closing the active server's last tab opens the remaining server tab", asyn
|
||||
localStorage.setItem("settings.v3", JSON.stringify({ general: { newLayoutDesigns: true } }))
|
||||
localStorage.setItem("opencode.global.dat:server", JSON.stringify({ list: [serverB] }))
|
||||
localStorage.setItem(
|
||||
"opencode.global.dat:tabs",
|
||||
"opencode.window.browser.dat:tabs",
|
||||
JSON.stringify([
|
||||
{ type: "session", server: "http://127.0.0.1:4096", sessionId: sessionA },
|
||||
{ type: "session", server: serverB, sessionId: sessionB },
|
||||
@@ -52,7 +52,7 @@ test("legacy session routes preserve an existing tab's server", async ({ page })
|
||||
localStorage.setItem("settings.v3", JSON.stringify({ general: { newLayoutDesigns: true } }))
|
||||
localStorage.setItem("opencode.global.dat:server", JSON.stringify({ list: [serverB] }))
|
||||
localStorage.setItem(
|
||||
"opencode.global.dat:tabs",
|
||||
"opencode.window.browser.dat:tabs",
|
||||
JSON.stringify([{ type: "session", server: serverB, sessionId: sessionB }]),
|
||||
)
|
||||
},
|
||||
|
||||
@@ -145,7 +145,7 @@ async function configurePage(page: Page) {
|
||||
}),
|
||||
)
|
||||
localStorage.setItem(
|
||||
"opencode.global.dat:tabs",
|
||||
"opencode.window.browser.dat:tabs",
|
||||
JSON.stringify(sessionIDs.map((sessionId) => ({ type: "session", server, dirBase64, sessionId }))),
|
||||
)
|
||||
},
|
||||
|
||||
@@ -127,7 +127,7 @@ test.describe("smoke: session timeline", () => {
|
||||
await page.addInitScript(
|
||||
({ dirBase64, sourceID, targetID }) => {
|
||||
localStorage.setItem(
|
||||
"opencode.global.dat:tabs",
|
||||
"opencode.window.browser.dat:tabs",
|
||||
JSON.stringify(
|
||||
[sourceID, targetID].map((sessionId) => ({
|
||||
type: "session",
|
||||
@@ -253,7 +253,7 @@ test.describe("smoke: session timeline", () => {
|
||||
await page.addInitScript(
|
||||
({ dirBase64, sourceID, targetID }) => {
|
||||
localStorage.setItem(
|
||||
"opencode.global.dat:tabs",
|
||||
"opencode.window.browser.dat:tabs",
|
||||
JSON.stringify(
|
||||
[sourceID, targetID].map((sessionId) => ({
|
||||
type: "session",
|
||||
|
||||
@@ -67,9 +67,6 @@ type PlatformBase = {
|
||||
/** Stable platform window identity for window-scoped persistence */
|
||||
windowID?: string
|
||||
|
||||
/** Whether window-scoped persistence should migrate legacy global values */
|
||||
migrateGlobalWindowState?: boolean
|
||||
|
||||
/** Application-global desktop updater */
|
||||
updater?: UpdaterPlatform
|
||||
|
||||
|
||||
@@ -210,13 +210,12 @@ describe("persist localStorage resilience", () => {
|
||||
expect(Persist.serverGlobal("a:b" as ServerScope, "c")).not.toEqual(Persist.serverGlobal("a" as ServerScope, "b:c"))
|
||||
})
|
||||
|
||||
test("window target scopes browser storage and migrates global values", () => {
|
||||
test("window target scopes browser storage", () => {
|
||||
const target = persistTesting.resolveTarget(Persist.window("tabs"), { platform: "web" } as ResolvePlatform)
|
||||
|
||||
expect(target).toEqual({
|
||||
scope: "window",
|
||||
storage: persistTesting.windowStorage("browser"),
|
||||
legacyStorageNames: ["opencode.global.dat"],
|
||||
key: "tabs",
|
||||
legacy: undefined,
|
||||
})
|
||||
@@ -226,13 +225,11 @@ describe("persist localStorage resilience", () => {
|
||||
const target = persistTesting.resolveTarget(Persist.window("tabs"), {
|
||||
platform: "desktop",
|
||||
windowID: "window-a",
|
||||
migrateGlobalWindowState: false,
|
||||
} as ResolvePlatform)
|
||||
|
||||
expect(target).toEqual({
|
||||
scope: "window",
|
||||
storage: persistTesting.windowStorage("window-a"),
|
||||
legacyStorageNames: undefined,
|
||||
key: "tabs",
|
||||
legacy: undefined,
|
||||
})
|
||||
@@ -241,7 +238,6 @@ describe("persist localStorage resilience", () => {
|
||||
test("window target preserves global desktop storage without a window id", () => {
|
||||
const target = persistTesting.resolveTarget(Persist.window("tabs"), {
|
||||
platform: "desktop",
|
||||
migrateGlobalWindowState: true,
|
||||
} as ResolvePlatform)
|
||||
|
||||
expect(target).toEqual({
|
||||
@@ -251,14 +247,4 @@ describe("persist localStorage resilience", () => {
|
||||
legacy: undefined,
|
||||
})
|
||||
})
|
||||
|
||||
test("window target lets one desktop window migrate global values", () => {
|
||||
const target = persistTesting.resolveTarget(Persist.window("tabs"), {
|
||||
platform: "desktop",
|
||||
windowID: "window-a",
|
||||
migrateGlobalWindowState: true,
|
||||
} as ResolvePlatform)
|
||||
|
||||
expect(target.legacyStorageNames).toEqual(["opencode.global.dat"])
|
||||
})
|
||||
})
|
||||
|
||||
@@ -519,11 +519,9 @@ function resolveTarget(target: PersistTarget, platform: Platform): PersistTarget
|
||||
if (target.scope !== "window") return target
|
||||
if (platform.platform === "desktop" && !platform.windowID) return { ...target, storage: GLOBAL_STORAGE }
|
||||
const windowID = platform.platform === "desktop" ? (platform.windowID ?? "browser") : "browser"
|
||||
const shouldMigrate = platform.platform !== "desktop" || platform.migrateGlobalWindowState === true
|
||||
return {
|
||||
...target,
|
||||
storage: windowStorage(windowID),
|
||||
legacyStorageNames: shouldMigrate ? [GLOBAL_STORAGE, ...(target.legacyStorageNames ?? [])] : target.legacyStorageNames,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ import { getStore } from "./store"
|
||||
import {
|
||||
getPinchZoomEnabled,
|
||||
getWindowID,
|
||||
getWindowMigrateGlobalState,
|
||||
setPinchZoomEnabled,
|
||||
setTitlebar,
|
||||
updateTitlebar,
|
||||
@@ -205,12 +204,6 @@ export function registerIpcHandlers(deps: Deps) {
|
||||
return id
|
||||
})
|
||||
|
||||
ipcMain.handle("get-window-migrate-global-state", (event: IpcMainInvokeEvent) => {
|
||||
const win = BrowserWindow.fromWebContents(event.sender)
|
||||
if (!win) return false
|
||||
return getWindowMigrateGlobalState(win)
|
||||
})
|
||||
|
||||
ipcMain.handle("get-window-focused", (event: IpcMainInvokeEvent) => {
|
||||
const win = BrowserWindow.fromWebContents(event.sender)
|
||||
return win?.isFocused() ?? false
|
||||
|
||||
@@ -3,4 +3,3 @@ export const DEFAULT_SERVER_URL_KEY = "defaultServerUrl"
|
||||
export const WSL_SERVERS_KEY = "wslServers"
|
||||
export const PINCH_ZOOM_ENABLED_KEY = "pinchZoomEnabled"
|
||||
export const WINDOW_IDS_KEY = "windowIds"
|
||||
export const WINDOW_GLOBAL_STATE_MIGRATION_ID_KEY = "windowGlobalStateMigrationId"
|
||||
|
||||
@@ -9,7 +9,7 @@ import { fileURLToPath, pathToFileURL } from "node:url"
|
||||
import type { TitlebarTheme } from "../preload/types"
|
||||
import { exportDebugLogs, write as writeLog } from "./logging"
|
||||
import { getStore } from "./store"
|
||||
import { PINCH_ZOOM_ENABLED_KEY, WINDOW_GLOBAL_STATE_MIGRATION_ID_KEY, WINDOW_IDS_KEY } from "./store-keys"
|
||||
import { PINCH_ZOOM_ENABLED_KEY, WINDOW_IDS_KEY } from "./store-keys"
|
||||
import { createUnresponsiveSampler } from "./unresponsive"
|
||||
|
||||
const root = dirname(fileURLToPath(import.meta.url))
|
||||
@@ -45,7 +45,6 @@ let relaunchHandler = () => {
|
||||
}
|
||||
let appQuitting = false
|
||||
let lastFocusedWindowID: string | undefined
|
||||
let windowGlobalStateMigrationID: string | undefined
|
||||
const titlebarThemes = new WeakMap<BrowserWindow, Partial<TitlebarTheme>>()
|
||||
const pinchZoomEnabled = new WeakMap<BrowserWindow, boolean>()
|
||||
const windowIDs = new WeakMap<BrowserWindow, string>()
|
||||
@@ -125,10 +124,6 @@ export function getWindowID(win: BrowserWindow) {
|
||||
return windowIDs.get(win)
|
||||
}
|
||||
|
||||
export function getWindowMigrateGlobalState(win: BrowserWindow) {
|
||||
return getWindowID(win) === windowGlobalStateMigrationID
|
||||
}
|
||||
|
||||
export function getLastFocusedWindow() {
|
||||
const focused = BrowserWindow.getFocusedWindow()
|
||||
if (focused) return focused
|
||||
@@ -140,9 +135,7 @@ export function getLastFocusedWindow() {
|
||||
|
||||
export function restoreMainWindows() {
|
||||
const ids = readWindowIDs()
|
||||
const next = ids.length ? ids : [randomUUID()]
|
||||
windowGlobalStateMigrationID = readWindowGlobalStateMigrationID(next)
|
||||
return next.map((id) => createMainWindow(id))
|
||||
return (ids.length ? ids : [randomUUID()]).map((id) => createMainWindow(id))
|
||||
}
|
||||
|
||||
export function setDockIcon() {
|
||||
@@ -252,14 +245,6 @@ function removeWindowID(id: string) {
|
||||
writeWindowIDs(readWindowIDs().filter((item) => item !== id))
|
||||
}
|
||||
|
||||
function readWindowGlobalStateMigrationID(ids: string[]) {
|
||||
const value = getStore().get(WINDOW_GLOBAL_STATE_MIGRATION_ID_KEY)
|
||||
if (typeof value === "string" && ids.includes(value)) return value
|
||||
const next = ids[0]
|
||||
if (next) getStore().set(WINDOW_GLOBAL_STATE_MIGRATION_ID_KEY, next)
|
||||
return next
|
||||
}
|
||||
|
||||
export function registerRendererProtocol() {
|
||||
if (protocol.isProtocolHandled(rendererProtocol)) return
|
||||
|
||||
|
||||
@@ -74,7 +74,6 @@ const api: ElectronAPI = {
|
||||
|
||||
getWindowCount: () => ipcRenderer.invoke("get-window-count"),
|
||||
getWindowID: () => ipcRenderer.invoke("get-window-id"),
|
||||
getWindowMigrateGlobalState: () => ipcRenderer.invoke("get-window-migrate-global-state"),
|
||||
onMenuCommand: (cb) => {
|
||||
const handler = (_: unknown, id: string) => cb(id)
|
||||
ipcRenderer.on("menu-command", handler)
|
||||
|
||||
@@ -63,7 +63,6 @@ export type ElectronAPI = {
|
||||
|
||||
getWindowCount: () => Promise<number>
|
||||
getWindowID: () => Promise<string>
|
||||
getWindowMigrateGlobalState: () => Promise<boolean>
|
||||
onMenuCommand: (cb: (id: string) => void) => () => void
|
||||
onDeepLink: (cb: (urls: string[]) => void) => () => void
|
||||
|
||||
|
||||
@@ -63,11 +63,9 @@ const [updaterState, setUpdaterState] = createSignal<UpdaterState>({ status: "di
|
||||
void window.api.updater.subscribe(setUpdaterState)
|
||||
|
||||
const deepLinkEvent = "opencode:deep-link"
|
||||
const lastActiveUrlKey = "opencode.desktop.last-active-url"
|
||||
|
||||
type DesktopWindowState = {
|
||||
id?: string
|
||||
migrateGlobalWindowState: boolean
|
||||
}
|
||||
|
||||
const emitDeepLinks = (urls: string[]) => {
|
||||
@@ -87,12 +85,10 @@ function windowLastActiveUrlKey(windowID: string) {
|
||||
return `opencode.desktop.window.${windowID}.last-active-url`
|
||||
}
|
||||
|
||||
function getLastActiveUrl(windowID: string, migrateGlobalWindowState: boolean) {
|
||||
function getLastActiveUrl(windowID: string) {
|
||||
if (typeof localStorage !== "object") return "/"
|
||||
try {
|
||||
const value =
|
||||
localStorage.getItem(windowLastActiveUrlKey(windowID)) ??
|
||||
(migrateGlobalWindowState ? localStorage.getItem(lastActiveUrlKey) : null)
|
||||
const value = localStorage.getItem(windowLastActiveUrlKey(windowID))
|
||||
if (value?.startsWith("/") && !value.startsWith("//")) return value
|
||||
} catch {}
|
||||
return "/"
|
||||
@@ -105,9 +101,9 @@ function setLastActiveUrl(windowID: string, value: string) {
|
||||
} catch {}
|
||||
}
|
||||
|
||||
function DesktopMemoryRouter(props: BaseRouterProps & { windowID: string; migrateGlobalWindowState: boolean }) {
|
||||
function DesktopMemoryRouter(props: BaseRouterProps & { windowID: string }) {
|
||||
const history = createMemoryHistory()
|
||||
const initialUrl = getLastActiveUrl(props.windowID, props.migrateGlobalWindowState)
|
||||
const initialUrl = getLastActiveUrl(props.windowID)
|
||||
if (initialUrl !== "/") history.set({ value: initialUrl, replace: true, scroll: false })
|
||||
onCleanup(history.listen((value) => setLastActiveUrl(props.windowID, value)))
|
||||
return <MemoryRouter {...props} history={history} />
|
||||
@@ -173,7 +169,6 @@ const createPlatform = (windowState: DesktopWindowState): Platform => {
|
||||
os,
|
||||
version: pkg.version,
|
||||
windowID: windowState.id,
|
||||
migrateGlobalWindowState: windowState.migrateGlobalWindowState,
|
||||
|
||||
async openDirectoryPickerDialog(opts) {
|
||||
return window.api.openDirectoryPicker({
|
||||
@@ -349,13 +344,7 @@ function DesktopRoot(props: { windowState: DesktopWindowState }) {
|
||||
|
||||
const [defaultServer] = createResource(() => platform.getDefaultServer?.())
|
||||
const [locale] = createResource(loadLocale)
|
||||
const router = (props: BaseRouterProps) => (
|
||||
<DesktopMemoryRouter
|
||||
{...props}
|
||||
windowID={platform.windowID ?? "browser"}
|
||||
migrateGlobalWindowState={platform.migrateGlobalWindowState === true}
|
||||
/>
|
||||
)
|
||||
const router = (props: BaseRouterProps) => <DesktopMemoryRouter {...props} windowID={platform.windowID ?? "browser"} />
|
||||
|
||||
function handleClick(e: MouseEvent) {
|
||||
const link = (e.target as HTMLElement).closest("a.external-link") as HTMLAnchorElement | null
|
||||
@@ -443,13 +432,8 @@ render(() => {
|
||||
const [windowState] = createResource(async () => {
|
||||
const api = window.api as typeof window.api & {
|
||||
getWindowID?: () => Promise<string>
|
||||
getWindowMigrateGlobalState?: () => Promise<boolean>
|
||||
}
|
||||
const id = await api.getWindowID?.()
|
||||
return {
|
||||
id,
|
||||
migrateGlobalWindowState: id ? await (api.getWindowMigrateGlobalState?.() ?? false) : false,
|
||||
}
|
||||
return { id: await api.getWindowID?.() }
|
||||
})
|
||||
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user