soulseek: nav sections, search results subpanel, stable client deps
- split into nav (vertical section menu) + view panels via soulseek:section channel - search view: history list + input, opens results subpanel for a past search - search results load stored responses (no re-run), session-cached, ranked - remove client from effect/callback deps (useClient is a fresh object per render) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -4,15 +4,15 @@ import { WorkspaceView } from 'officerdev';
|
||||
import { useDashboardState } from 'state/useDashboardState';
|
||||
import { defaultLayout } from './defaultLayout';
|
||||
|
||||
// /soulseek uses the Workspace/Panel system (like /chat and /music): two panels — the search browser
|
||||
// (soulseek-search) and the download queue (soulseek-transfers) — coordinating via the 'soulseek:refresh'
|
||||
// panel channel. Both talk to slskd through the /api/slskd auth proxy.
|
||||
// /soulseek uses the Workspace/Panel system (like /chat and /music): a section nav (soulseek-nav) on
|
||||
// the left and a section view (soulseek-view) on the right, coordinating via the 'soulseek:section'
|
||||
// channel. Both talk to slskd through the /api/slskd auth proxy.
|
||||
|
||||
const ALLOWED_APP_TYPES = new Set<string | null>(['soulseek-search', 'soulseek-transfers', null]);
|
||||
const ALLOWED_APP_TYPES = new Set<string | null>(['soulseek-nav', 'soulseek-view', null]);
|
||||
|
||||
function normalizeLayout(node: LayoutNode): LayoutNode {
|
||||
if (node.type === 'panel') {
|
||||
return ALLOWED_APP_TYPES.has(node.appType) ? node : { ...node, appType: 'soulseek-search' };
|
||||
return ALLOWED_APP_TYPES.has(node.appType) ? node : { ...node, appType: 'soulseek-view' };
|
||||
}
|
||||
const children = node.children.map((c) => {
|
||||
const fixed = normalizeLayout(c.node);
|
||||
@@ -23,7 +23,9 @@ function normalizeLayout(node: LayoutNode): LayoutNode {
|
||||
}
|
||||
|
||||
export const SoulseekScreen = () => {
|
||||
const rawWorkspace = useDashboardState<LayoutNode>('screens/soulseek', defaultLayout);
|
||||
// v2: nav + view (replaced the earlier search + transfers split) — new key so the old persisted
|
||||
// layout doesn't resurrect as two mismatched panels.
|
||||
const rawWorkspace = useDashboardState<LayoutNode>('screens/soulseek-v2', defaultLayout);
|
||||
|
||||
const workspace = useMemo(() => {
|
||||
const fixed = normalizeLayout(rawWorkspace.value);
|
||||
|
||||
@@ -5,7 +5,7 @@ export const defaultLayout: LayoutNode = {
|
||||
id: 'soulseek-root',
|
||||
direction: 'horizontal',
|
||||
children: [
|
||||
{ node: { type: 'panel', id: 'soulseek-search', appType: 'soulseek-search' }, size: 55 },
|
||||
{ node: { type: 'panel', id: 'soulseek-transfers', appType: 'soulseek-transfers' }, size: 45 },
|
||||
{ node: { type: 'panel', id: 'soulseek-nav', appType: 'soulseek-nav' }, size: 22 },
|
||||
{ node: { type: 'panel', id: 'soulseek-view', appType: 'soulseek-view' }, size: 78 },
|
||||
],
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user