feat(v0.6): auto-group Projects by namespace + Active-now band + cross-device prefs
The flat Projects grid was overwhelming at 50-100 repos. Explored the UX with 4 parallel agents (auto-grouping / manual folders / density-segmentation / competitive research); all converged on namespace auto-grouping as the primary fix — the dotted repo names (Billo.Platform.*, Billo.Infrastructure.*) already encode the hierarchy, so it's a string-split, not a taxonomy the user builds. Frontend: - groupProjects(): depth-2 namespace grouping, >=2-member threshold (singletons fall to "Other"), degrade-to-flat when repos share no prefix, running projects duplicated into a pinned "Active now" section. - displayLabel(): cards show the namespace tail (Payment, not Billo.Platform.Payment); full name in Active/Other. - Collapsible sticky group headers with an "N active" badge so a collapsed section never hides running work; search force-expands matching groups. - public/prefs.ts: server-first load with a localStorage offline mirror, migrates the legacy per-device proj-favs. Backend (server-side prefs so favourites + collapse-state follow the user across devices — localStorage was per-device, which broke the multi-device premise): - src/http/prefs-store.ts: ~/.web-terminal-prefs.json store (mirrors push-store), every field bounded + sanitized. - GET /prefs (read-only) + PUT /prefs (Origin-guarded); UiPrefs type + PREFS_STORE_PATH config. Tests: +12 prefs-store, +21 groupProjects/displayLabel. Full suite 1227 passed. Verified live: grouping renders, collapse persists to the server and survives a full page reload (cross-device sync proven end-to-end).
This commit is contained in:
@@ -325,6 +325,8 @@ export function loadConfig(env: EnvLike): Config {
|
||||
const pushStorePath =
|
||||
env['PUSH_STORE_PATH'] || path.join(homeDir, '.web-terminal-push-subs.json')
|
||||
const pushMaxSubs = parseNonNegativeInt(env['PUSH_MAX_SUBS'], 'PUSH_MAX_SUBS', DEFAULT_PUSH_MAX_SUBS)
|
||||
const prefsStorePath =
|
||||
env['PREFS_STORE_PATH'] || path.join(homeDir, '.web-terminal-prefs.json')
|
||||
const notifyDone = parseBool(env['NOTIFY_DONE'], true) // default on
|
||||
const notifyDnd = parseBool(env['NOTIFY_DND'], false) // default off (do not disturb)
|
||||
// DECISION_TOKEN_TTL_MS defaults to permTimeoutMs (parsed after it, order matters)
|
||||
@@ -416,6 +418,7 @@ export function loadConfig(env: EnvLike): Config {
|
||||
vapidSubject,
|
||||
pushStorePath,
|
||||
pushMaxSubs,
|
||||
prefsStorePath,
|
||||
notifyDone,
|
||||
notifyDnd,
|
||||
decisionTokenTtlMs,
|
||||
|
||||
Reference in New Issue
Block a user