Files
openchamber/packages/ui/src/stores/useModelPickerSectionsStore.ts
T
Serhii DziupinandSerhii Dziupin 3e3cd82a47 feat: inherit model-picker reorder/accordion persistence and shift-delete from otto-ui (#1833)
* feat(model-picker): drag-to-reorder providers and persist accordion state

Ports two model/provider picker QoL features from otto-ui:
- Persist collapsed state of picker sections (favorites, recent, each
  provider) via a new persisted zustand store so collapse survives
  remounts and reloads, shared across every picker surface.
- Desktop drag-to-reorder of provider sections (whole header as the
  mouse activator, 8px threshold so a plain click still toggles
  collapse), with the order persisted in useUIStore.providerOrder and
  applied across ModelControls, ModelMultiSelect and ModelSelector.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>

* feat(sessions): shift-click quick action hard-deletes thread without prompt

Ports the shift-quick-delete feature from otto-ui. The sidebar quick
action (normally archive) becomes a no-prompt hard delete while Shift is
held: the icon switches to a trash bin, the affordance turns destructive,
and the click bypasses the confirmation dialog via a new skipConfirm
source flag. A shared useShiftKeyHeld hook (single window listener set,
useSyncExternalStore) keeps only the small action button re-rendering on
Shift state changes, and resets on window blur so the affordance can't
get stuck after alt-tab.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>

---------

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
2026-06-26 19:36:47 +03:00

37 lines
1.1 KiB
TypeScript

import { create } from 'zustand';
import { persist } from 'zustand/middleware';
/**
* Persisted collapsed state for the collapsible sections (accordions) in the
* model/provider picker (`ModelPickerList`): the `favorites` and `recent`
* sections plus each `provider:<id>` group. Section keys are stable and shared
* across every picker surface, so collapsing a provider in one picker is
* remembered everywhere and survives remounts and full page reloads.
*
* Only collapsed keys are stored (presence === collapsed); the default for any
* unknown key is expanded.
*/
type ModelPickerSectionsStore = {
collapsedSections: Record<string, boolean>;
toggleSection: (key: string) => void;
};
export const useModelPickerSectionsStore = create<ModelPickerSectionsStore>()(
persist(
(set) => ({
collapsedSections: {},
toggleSection: (key) =>
set((state) => {
const next = { ...state.collapsedSections };
if (next[key]) delete next[key];
else next[key] = true;
return { collapsedSections: next };
}),
}),
{
name: 'model-picker-collapsed-sections',
version: 1,
},
),
);