● Zion Boggan
repos/Drophawk/frontend/stores/ui.ts
zionboggan.com ↗
55 lines · typescript
History for this file →
1
import { create } from "zustand";
2
import type { Drop } from "@/lib/types";
3
import type { StreamStatus } from "@/lib/sse";
4
 
5
const BUFFER_CAP = 200;
6
 
7
interface UiState {
8
  sidebarCollapsed: boolean;
9
  toggleSidebar: () => void;
10
  setSidebar: (v: boolean) => void;
11
 
12
  commandOpen: boolean;
13
  setCommandOpen: (v: boolean) => void;
14
 
15
  streamStatus: StreamStatus;
16
  setStreamStatus: (s: StreamStatus) => void;
17
 
18
  liveDrops: Drop[];
19
  freshIds: Set<number>;
20
  pushDrop: (drop: Drop) => void;
21
  seedDrops: (drops: Drop[]) => void;
22
  clearFresh: (id: number) => void;
23
}
24
 
25
export const useUiStore = create<UiState>((set) => ({
26
  sidebarCollapsed: false,
27
  toggleSidebar: () => set((s) => ({ sidebarCollapsed: !s.sidebarCollapsed })),
28
  setSidebar: (v) => set({ sidebarCollapsed: v }),
29
 
30
  commandOpen: false,
31
  setCommandOpen: (v) => set({ commandOpen: v }),
32
 
33
  streamStatus: "connecting",
34
  setStreamStatus: (s) => set({ streamStatus: s }),
35
 
36
  liveDrops: [],
37
  freshIds: new Set<number>(),
38
  pushDrop: (drop) =>
39
    set((s) => {
40
      if (s.liveDrops.some((d) => d.id === drop.id)) return s;
41
      const next = [drop, ...s.liveDrops].slice(0, BUFFER_CAP);
42
      const fresh = new Set(s.freshIds);
43
      fresh.add(drop.id);
44
      return { liveDrops: next, freshIds: fresh };
45
    }),
46
  seedDrops: (drops) =>
47
    set(() => ({ liveDrops: drops.slice(0, BUFFER_CAP), freshIds: new Set<number>() })),
48
  clearFresh: (id) =>
49
    set((s) => {
50
      if (!s.freshIds.has(id)) return s;
51
      const fresh = new Set(s.freshIds);
52
      fresh.delete(id);
53
      return { freshIds: fresh };
54
    }),
55
}));