refactor(app): initialize feature visibility at runtime

This commit is contained in:
Brendan Allan 2026-07-15 14:48:28 +00:00
commit c215c42fe0
2 changed files with 17 additions and 53 deletions

View file

@ -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)
})
})

View file

@ -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<string, unknown> {
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<string> | 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<Settings>(defaultSettings),
)
const [store, setStore, settingsInit, ready] = persisted("settings.v3", createStore<Settings>(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(() => {