* 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>
37 lines
1.1 KiB
TypeScript
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,
|
|
},
|
|
),
|
|
);
|