import { scopedThreadKey } from "@t3tools/client-runtime/environment"; import type { ScopedThreadRef } from "@t3tools/contracts"; import { create } from "zustand"; export interface PreviewMiniPlayerPosition { readonly x: number; readonly y: number; } export interface PreviewMiniPlayerSize { readonly width: number; readonly height: number; } export interface PreviewMiniPlayerState { readonly tabId: string; readonly position: PreviewMiniPlayerPosition | null; readonly size: PreviewMiniPlayerSize | null; } interface PreviewMiniPlayerStoreState { readonly byThreadKey: Record; readonly open: (ref: ScopedThreadRef, tabId: string) => void; readonly close: (ref: ScopedThreadRef) => void; readonly move: (ref: ScopedThreadRef, tabId: string, position: PreviewMiniPlayerPosition) => void; readonly resize: (ref: ScopedThreadRef, tabId: string, size: PreviewMiniPlayerSize) => void; readonly removeThread: (ref: ScopedThreadRef) => void; } export const usePreviewMiniPlayerStore = create()((set) => ({ byThreadKey: {}, open: (ref, tabId) => set((state) => { const threadKey = scopedThreadKey(ref); const current = state.byThreadKey[threadKey]; if (current?.tabId === tabId) return state; return { byThreadKey: { ...state.byThreadKey, [threadKey]: { tabId, position: current?.position ?? null, size: current?.size ?? null, }, }, }; }), close: (ref) => set((state) => { const threadKey = scopedThreadKey(ref); if (!(threadKey in state.byThreadKey)) return state; const { [threadKey]: _closed, ...byThreadKey } = state.byThreadKey; return { byThreadKey }; }), move: (ref, tabId, position) => set((state) => { const threadKey = scopedThreadKey(ref); const current = state.byThreadKey[threadKey]; if (!current || current.tabId !== tabId) return state; if (current.position?.x === position.x && current.position.y === position.y) return state; return { byThreadKey: { ...state.byThreadKey, [threadKey]: { ...current, position }, }, }; }), resize: (ref, tabId, size) => set((state) => { const threadKey = scopedThreadKey(ref); const current = state.byThreadKey[threadKey]; if (!current || current.tabId !== tabId) return state; if (current.size?.width === size.width && current.size.height === size.height) return state; return { byThreadKey: { ...state.byThreadKey, [threadKey]: { ...current, size }, }, }; }), removeThread: (ref) => set((state) => { const threadKey = scopedThreadKey(ref); if (!(threadKey in state.byThreadKey)) return state; const { [threadKey]: _removed, ...byThreadKey } = state.byThreadKey; return { byThreadKey }; }), })); export function selectThreadPreviewMiniPlayer( byThreadKey: Record, ref: ScopedThreadRef | null | undefined, ): PreviewMiniPlayerState | null { if (!ref) return null; return byThreadKey[scopedThreadKey(ref)] ?? null; }