From c215c42fe0e42f360e74f012c249657c0c2f22c5 Mon Sep 17 00:00:00 2001 From: Brendan Allan Date: Wed, 15 Jul 2026 14:48:28 +0000 Subject: [PATCH] refactor(app): initialize feature visibility at runtime --- packages/app/src/context/settings.test.ts | 37 ++++++----------------- packages/app/src/context/settings.tsx | 33 +++++--------------- 2 files changed, 17 insertions(+), 53 deletions(-) diff --git a/packages/app/src/context/settings.test.ts b/packages/app/src/context/settings.test.ts index 961440ec7d..c53756963e 100644 --- a/packages/app/src/context/settings.test.ts +++ b/packages/app/src/context/settings.test.ts @@ -3,44 +3,25 @@ import { isAppUpgrade, layoutTransitionState, maximumSunsetTimeout, - migrateSettings, newLayoutDesignsDefault, nextSunsetCheckDelay, resolveNewLayoutDesigns, shouldDisplayTabsToast, shouldEnableNewLayout, + shouldEnableFeatureVisibility, } from "./settings" describe("feature visibility", () => { - test("enables features once for profiles created before the visibility defaults", () => { - expect( - migrateSettings({ - general: { - showFileTree: false, - showSearch: false, - showStatus: false, - showCustomAgents: false, - }, - }), - ).toEqual({ - general: { - showFileTree: true, - showSearch: true, - showStatus: true, - showCustomAgents: true, - featureVisibilityInitialized: true, - }, - }) + test("enables features for profiles with persisted settings", () => { + expect(shouldEnableFeatureVisibility("{}", undefined)).toBe(true) }) - test("preserves preferences after the visibility defaults are initialized", () => { - const value = { - general: { - showFileTree: false, - featureVisibilityInitialized: true, - }, - } - expect(migrateSettings(value)).toBe(value) + test("enables features for profiles with a recorded app version", () => { + expect(shouldEnableFeatureVisibility(null, "1.18.1")).toBe(true) + }) + + test("keeps features hidden for new profiles", () => { + expect(shouldEnableFeatureVisibility(null, undefined)).toBe(false) }) }) diff --git a/packages/app/src/context/settings.tsx b/packages/app/src/context/settings.tsx index 7bb175c2ef..e6d7b840c4 100644 --- a/packages/app/src/context/settings.tsx +++ b/packages/app/src/context/settings.tsx @@ -63,25 +63,11 @@ export const newLayoutDesignsDefault = true export const oldInterfaceSunset = new Date(2026, 8, 14) const newLayoutDesignsUpgradeCutoff = "1.17.19" -function isRecord(value: unknown): value is Record { - return typeof value === "object" && value !== null && !Array.isArray(value) -} - -export function migrateSettings(value: unknown) { - if (!isRecord(value)) return value - const general = isRecord(value.general) ? value.general : {} - if (general.featureVisibilityInitialized === true) return value - return { - ...value, - general: { - ...general, - showFileTree: true, - showSearch: true, - showStatus: true, - showCustomAgents: true, - featureVisibilityInitialized: true, - }, - } +export function shouldEnableFeatureVisibility( + settings: string | Promise | null, + previousVersion: string | undefined, +) { + return settings !== null || previousVersion !== undefined } function compareVersions(a: string, b: string) { @@ -242,10 +228,7 @@ export const { use: useSettings, provider: SettingsProvider } = createSimpleCont gate: false, init: () => { const platform = usePlatform() - const [store, setStore, _, ready] = persisted( - { key: "settings.v3", migrate: migrateSettings }, - createStore(defaultSettings), - ) + const [store, setStore, settingsInit, ready] = persisted("settings.v3", createStore(defaultSettings)) const [launch, setLaunch, , launchReady] = persisted( "app-version.v1", createStore<{ version?: string }>({ version: undefined }), @@ -354,8 +337,8 @@ export const { use: useSettings, provider: SettingsProvider } = createSimpleCont }) createEffect(() => { - if (!ready() || platform.platform === "desktop") return - initializeFeatureVisibility(false) + if (!ready() || !launchState.classified || platform.platform === "desktop") return + initializeFeatureVisibility(shouldEnableFeatureVisibility(settingsInit, launchState.previous)) }) createEffect(() => {