fix: the sidebar remembers detaching per role, not per account

Whether the sidebar starts detached depends on the role: an operator gets it out
of the way, a developer gets it docked. That default held only until the control
was pressed once, because the choice went to a single key read before the role.
From then on both roles wore whichever was pressed last, and the one that had
not asked for it could never get its own default back — switch a workspace where
you are an operator for one where you are a developer, and the sidebar stayed
detached.

Each role now keeps its own choice, and falls back to its own default until it
has one.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Guilhem Lemouel
2026-10-06 02:38:54 -07:00
co-authored by Claude Opus 5
parent 7024eee329
commit a8de7859cc
@@ -2,19 +2,27 @@ import { fromStore } from 'svelte/store'
import { userStore } from '$lib/stores'
import { useLocalStorageValue } from '$lib/svelte5Utils.svelte'
// Empty until the user presses detach or attach once. Until then operators start detached:
// many of them navigate through a workspace's own app, and a docked sidebar would take its width.
const pref = useLocalStorageValue<string>('nav_detached', '', 'string')
// One preference per role rather than one per account. The same person is both — an operator in
// one workspace, a developer in the next — and the two want different things from the sidebar, so
// a single key would carry whichever was pressed last into the other role and never give it back.
// Empty until that role presses detach or attach once.
const operatorPref = useLocalStorageValue<string>('nav_detached_operator', '', 'string')
const devPref = useLocalStorageValue<string>('nav_detached_dev', '', 'string')
const user = fromStore(userStore)
/** Whether the sidebar is detached: hidden behind a floating button that slides it in over the page. */
export const navDetached = {
get val(): boolean {
// Unasked, operators start detached: many of them navigate through a workspace's own app,
// and a docked sidebar would take its width.
const operator = !!user.current?.operator
const pref = operator ? operatorPref : devPref
if (pref.val === 'true') return true
if (pref.val === 'false') return false
return !!user.current?.operator
return operator
},
set val(detached: boolean) {
const pref = user.current?.operator ? operatorPref : devPref
pref.val = String(detached)
}
}