History

Prepare datamodel for multi-environment (#1765)

Julius Marminge committed 7 months ago

Commit b96308f1 parent 72b7f90121 files · +10206 −4969Browse files

Showing the changes to apps/web/src/threadSelectionStore.ts (1 of 121 files). Show all

Unified · Split

apps/web/src/threadSelectionStore.ts+51−53
@@ -4,121 +4,119 @@ · 3 unmodified lines
44 * Supports Cmd/Ctrl+Click (toggle individual), Shift+Click (range select),
55 * and bulk actions on the selected set.
66 */
7−
8−import type { ThreadId } from "@t3tools/contracts";
97 import { create } from "zustand";
108
119 export interface ThreadSelectionState {
12− /** Currently selected thread IDs. */
13− selectedThreadIds: ReadonlySet<ThreadId>;
14− /** The thread ID that anchors shift-click range selection. */
15− anchorThreadId: ThreadId | null;
10+ /** Currently selected scoped thread keys. */
11+ selectedThreadKeys: ReadonlySet<string>;
12+ /** The scoped thread key that anchors shift-click range selection. */
13+ anchorThreadKey: string | null;
1614 }
1715
1816 interface ThreadSelectionStore extends ThreadSelectionState {
19− /** Toggle a single thread in the selection (Cmd/Ctrl+Click). */
20− toggleThread: (threadId: ThreadId) => void;
17+ /** Toggle a single scoped thread key in the selection (Cmd/Ctrl+Click). */
18+ toggleThread: (threadKey: string) => void;
2119 /**
2220 * Select a range of threads (Shift+Click).
23− * Requires the ordered list of thread IDs within the same project
21+ * Requires the ordered list of scoped thread keys within the same project
2422 * so the store can compute which threads fall between anchor and target.
2523 */
26− rangeSelectTo: (threadId: ThreadId, orderedThreadIds: readonly ThreadId[]) => void;
24+ rangeSelectTo: (threadKey: string, orderedThreadKeys: readonly string[]) => void;
2725 /** Clear all selection state. */
2826 clearSelection: () => void;
29− /** Remove specific thread IDs from the selection (e.g. after deletion). */
30− removeFromSelection: (threadIds: readonly ThreadId[]) => void;
27+ /** Remove specific scoped thread keys from the selection (e.g. after deletion). */
28+ removeFromSelection: (threadKeys: readonly string[]) => void;
3129 /** Set the anchor thread without adding it to the selection (e.g. on plain-click navigate). */
32− setAnchor: (threadId: ThreadId) => void;
30+ setAnchor: (threadKey: string) => void;
3331 /** Check if any threads are selected. */
3432 hasSelection: () => boolean;
3533 }
3634
37−const EMPTY_SET = new Set<ThreadId>();
35+const EMPTY_SET = new Set<string>();
3836
3937 export const useThreadSelectionStore = create<ThreadSelectionStore>((set, get) => ({
40− selectedThreadIds: EMPTY_SET,
41− anchorThreadId: null,
38+ selectedThreadKeys: EMPTY_SET,
39+ anchorThreadKey: null,
4240
43− toggleThread: (threadId) => {
41+ toggleThread: (threadKey) => {
4442 set((state) => {
45− const next = new Set(state.selectedThreadIds);
46− if (next.has(threadId)) {
47− next.delete(threadId);
43+ const next = new Set(state.selectedThreadKeys);
44+ if (next.has(threadKey)) {
45+ next.delete(threadKey);
4846 } else {
49− next.add(threadId);
47+ next.add(threadKey);
5048 }
5149 return {
52− selectedThreadIds: next,
53− anchorThreadId: next.has(threadId) ? threadId : state.anchorThreadId,
50+ selectedThreadKeys: next,
51+ anchorThreadKey: next.has(threadKey) ? threadKey : state.anchorThreadKey,
5452 };
5553 });
5654 },
5755
58− rangeSelectTo: (threadId, orderedThreadIds) => {
56+ rangeSelectTo: (threadKey, orderedThreadKeys) => {
5957 set((state) => {
60− const anchor = state.anchorThreadId;
58+ const anchor = state.anchorThreadKey;
6159 if (anchor === null) {
6260 // No anchor yet — treat as a single toggle
63− const next = new Set(state.selectedThreadIds);
64− next.add(threadId);
65− return { selectedThreadIds: next, anchorThreadId: threadId };
61+ const next = new Set(state.selectedThreadKeys);
62+ next.add(threadKey);
63+ return { selectedThreadKeys: next, anchorThreadKey: threadKey };
6664 }
6765
68− const anchorIndex = orderedThreadIds.indexOf(anchor);
69− const targetIndex = orderedThreadIds.indexOf(threadId);
66+ const anchorIndex = orderedThreadKeys.indexOf(anchor);
67+ const targetIndex = orderedThreadKeys.indexOf(threadKey);
7068 if (anchorIndex === -1 || targetIndex === -1) {
7169 // Anchor or target not in this list (different project?) — fallback to toggle
72− const next = new Set(state.selectedThreadIds);
73− next.add(threadId);
74− return { selectedThreadIds: next, anchorThreadId: threadId };
70+ const next = new Set(state.selectedThreadKeys);
71+ next.add(threadKey);
72+ return { selectedThreadKeys: next, anchorThreadKey: threadKey };
7573 }
7674
7775 const start = Math.min(anchorIndex, targetIndex);
7876 const end = Math.max(anchorIndex, targetIndex);
79− const next = new Set(state.selectedThreadIds);
77+ const next = new Set(state.selectedThreadKeys);
8078 for (let i = start; i <= end; i++) {
81− const id = orderedThreadIds[i];
82− if (id !== undefined) {
83− next.add(id);
79+ const key = orderedThreadKeys[i];
80+ if (key !== undefined) {
81+ next.add(key);
8482 }
8583 }
8684 // Keep anchor stable so subsequent shift-clicks extend from the same point
87− return { selectedThreadIds: next, anchorThreadId: anchor };
85+ return { selectedThreadKeys: next, anchorThreadKey: anchor };
8886 });
8987 },
9088
9189 clearSelection: () => {
9290 const state = get();
93− if (state.selectedThreadIds.size === 0 && state.anchorThreadId === null) return;
94− set({ selectedThreadIds: EMPTY_SET, anchorThreadId: null });
91+ if (state.selectedThreadKeys.size === 0 && state.anchorThreadKey === null) return;
92+ set({ selectedThreadKeys: EMPTY_SET, anchorThreadKey: null });
9593 },
9694
97− setAnchor: (threadId) => {
98− if (get().anchorThreadId === threadId) return;
99− set({ anchorThreadId: threadId });
95+ setAnchor: (threadKey) => {
96+ if (get().anchorThreadKey === threadKey) return;
97+ set({ anchorThreadKey: threadKey });
10098 },
10199
102− removeFromSelection: (threadIds) => {
100+ removeFromSelection: (threadKeys) => {
103101 set((state) => {
104− const toRemove = new Set(threadIds);
102+ const toRemove = new Set(threadKeys);
105103 let changed = false;
106− const next = new Set<ThreadId>();
107− for (const id of state.selectedThreadIds) {
108− if (toRemove.has(id)) {
104+ const next = new Set<string>();
105+ for (const key of state.selectedThreadKeys) {
106+ if (toRemove.has(key)) {
109107 changed = true;
110108 } else {
111− next.add(id);
109+ next.add(key);
112110 }
113111 }
114112 if (!changed) return state;
115113 const newAnchor =
116− state.anchorThreadId !== null && toRemove.has(state.anchorThreadId)
114+ state.anchorThreadKey !== null && toRemove.has(state.anchorThreadKey)
117115 ? null
118− : state.anchorThreadId;
119− return { selectedThreadIds: next, anchorThreadId: newAnchor };
116+ : state.anchorThreadKey;
117+ return { selectedThreadKeys: next, anchorThreadKey: newAnchor };
120118 });
121119 },
122120
123− hasSelection: () => get().selectedThreadIds.size > 0,
121+ hasSelection: () => get().selectedThreadKeys.size > 0,
124122 }));

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t