@cryptiklemur/lattice 0.0.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/release.yml +4 -4
- package/.releaserc.json +2 -1
- package/client/src/components/auth/PassphrasePrompt.tsx +70 -70
- package/client/src/components/mesh/NodeBadge.tsx +24 -24
- package/client/src/components/mesh/PairingDialog.tsx +281 -281
- package/client/src/components/panels/FileBrowser.tsx +241 -241
- package/client/src/components/panels/StickyNotes.tsx +187 -187
- package/client/src/components/project-settings/ProjectMemory.tsx +471 -0
- package/client/src/components/project-settings/ProjectSettingsView.tsx +6 -0
- package/client/src/components/settings/Appearance.tsx +151 -151
- package/client/src/components/settings/MeshStatus.tsx +145 -145
- package/client/src/components/settings/SettingsView.tsx +57 -57
- package/client/src/components/setup/SetupWizard.tsx +750 -750
- package/client/src/components/sidebar/AddProjectModal.tsx +432 -0
- package/client/src/components/sidebar/ProjectRail.tsx +8 -4
- package/client/src/components/sidebar/SettingsSidebar.tsx +2 -1
- package/client/src/components/ui/ErrorBoundary.tsx +56 -56
- package/client/src/hooks/useSidebar.ts +16 -0
- package/client/src/router.tsx +453 -391
- package/client/src/stores/sidebar.ts +28 -0
- package/client/vite.config.ts +20 -20
- package/package.json +1 -1
- package/server/src/daemon.ts +1 -0
- package/server/src/handlers/chat.ts +194 -194
- package/server/src/handlers/fs.ts +159 -0
- package/server/src/handlers/memory.ts +179 -0
- package/server/src/handlers/settings.ts +114 -109
- package/shared/src/messages.ts +97 -2
- package/shared/src/project-settings.ts +1 -1
- package/themes/amoled.json +20 -20
- package/themes/ayu-light.json +9 -9
- package/themes/catppuccin-latte.json +9 -9
- package/themes/catppuccin-mocha.json +9 -9
- package/themes/clay-light.json +10 -10
- package/themes/clay.json +10 -10
- package/themes/dracula.json +9 -9
- package/themes/everforest-light.json +9 -9
- package/themes/everforest.json +9 -9
- package/themes/github-light.json +9 -9
- package/themes/gruvbox-dark.json +9 -9
- package/themes/gruvbox-light.json +9 -9
- package/themes/monokai.json +9 -9
- package/themes/nord-light.json +9 -9
- package/themes/nord.json +9 -9
- package/themes/one-dark.json +9 -9
- package/themes/one-light.json +9 -9
- package/themes/rose-pine-dawn.json +9 -9
- package/themes/rose-pine.json +9 -9
- package/themes/solarized-dark.json +9 -9
- package/themes/solarized-light.json +9 -9
- package/themes/tokyo-night-light.json +9 -9
- package/themes/tokyo-night.json +9 -9
- package/.serena/project.yml +0 -138
package/client/src/router.tsx
CHANGED
|
@@ -1,391 +1,453 @@
|
|
|
1
|
-
import { createRouter, createRootRoute, createRoute, createMemoryHistory } from "@tanstack/react-router";
|
|
2
|
-
import { Outlet } from "@tanstack/react-router";
|
|
3
|
-
import { useState, useEffect, useRef } from "react";
|
|
4
|
-
import { Sidebar } from "./components/sidebar/Sidebar";
|
|
5
|
-
import { ChatView } from "./components/chat/ChatView";
|
|
6
|
-
import { SetupWizard } from "./components/setup/SetupWizard";
|
|
7
|
-
import { SettingsView } from "./components/settings/SettingsView";
|
|
8
|
-
import { ProjectSettingsView } from "./components/project-settings/ProjectSettingsView";
|
|
9
|
-
import { DashboardView } from "./components/dashboard/DashboardView";
|
|
10
|
-
import { ProjectDashboardView } from "./components/dashboard/ProjectDashboardView";
|
|
11
|
-
import { NodeSettingsModal } from "./components/sidebar/NodeSettingsModal";
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
var
|
|
19
|
-
var [
|
|
20
|
-
var
|
|
21
|
-
var
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
var
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
var
|
|
58
|
-
var
|
|
59
|
-
var
|
|
60
|
-
var
|
|
61
|
-
var
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
canvas.
|
|
65
|
-
canvas.
|
|
66
|
-
canvas.style.
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
var
|
|
71
|
-
var
|
|
72
|
-
var
|
|
73
|
-
var
|
|
74
|
-
var
|
|
75
|
-
var
|
|
76
|
-
var
|
|
77
|
-
var
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
var
|
|
87
|
-
var
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
var
|
|
100
|
-
var
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
var
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
var
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
var
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
var
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
var
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
var
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
connectedSet.add(c.
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
var
|
|
177
|
-
|
|
178
|
-
ctx!.
|
|
179
|
-
ctx!.
|
|
180
|
-
ctx!.
|
|
181
|
-
ctx!.
|
|
182
|
-
ctx!.
|
|
183
|
-
ctx!.
|
|
184
|
-
ctx!.
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
ctx!.
|
|
195
|
-
ctx!.
|
|
196
|
-
ctx!.
|
|
197
|
-
ctx!.
|
|
198
|
-
ctx!.
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
var
|
|
203
|
-
|
|
204
|
-
[logoLeft
|
|
205
|
-
[logoLeft
|
|
206
|
-
[logoLeft
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
var
|
|
211
|
-
|
|
212
|
-
ctx!.
|
|
213
|
-
ctx!.
|
|
214
|
-
ctx!.
|
|
215
|
-
ctx!.
|
|
216
|
-
ctx!.
|
|
217
|
-
ctx!.
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
: "
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
<
|
|
246
|
-
|
|
247
|
-
<span className="text-[
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
return
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
var
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
1
|
+
import { createRouter, createRootRoute, createRoute, createMemoryHistory } from "@tanstack/react-router";
|
|
2
|
+
import { Outlet } from "@tanstack/react-router";
|
|
3
|
+
import { useState, useEffect, useRef } from "react";
|
|
4
|
+
import { Sidebar } from "./components/sidebar/Sidebar";
|
|
5
|
+
import { ChatView } from "./components/chat/ChatView";
|
|
6
|
+
import { SetupWizard } from "./components/setup/SetupWizard";
|
|
7
|
+
import { SettingsView } from "./components/settings/SettingsView";
|
|
8
|
+
import { ProjectSettingsView } from "./components/project-settings/ProjectSettingsView";
|
|
9
|
+
import { DashboardView } from "./components/dashboard/DashboardView";
|
|
10
|
+
import { ProjectDashboardView } from "./components/dashboard/ProjectDashboardView";
|
|
11
|
+
import { NodeSettingsModal } from "./components/sidebar/NodeSettingsModal";
|
|
12
|
+
import { AddProjectModal } from "./components/sidebar/AddProjectModal";
|
|
13
|
+
import { useSidebar } from "./hooks/useSidebar";
|
|
14
|
+
import { useWebSocket } from "./hooks/useWebSocket";
|
|
15
|
+
import { exitSettings, getSidebarStore, handlePopState, closeDrawer } from "./stores/sidebar";
|
|
16
|
+
|
|
17
|
+
function LoadingScreen() {
|
|
18
|
+
var ws = useWebSocket();
|
|
19
|
+
var [dataReceived, setDataReceived] = useState(false);
|
|
20
|
+
var [minTimeElapsed, setMinTimeElapsed] = useState(false);
|
|
21
|
+
var canvasRef = useRef<HTMLCanvasElement>(null);
|
|
22
|
+
var frameRef = useRef<number>(0);
|
|
23
|
+
|
|
24
|
+
useEffect(function () {
|
|
25
|
+
var timer = setTimeout(function () {
|
|
26
|
+
setMinTimeElapsed(true);
|
|
27
|
+
}, 600);
|
|
28
|
+
return function () { clearTimeout(timer); };
|
|
29
|
+
}, []);
|
|
30
|
+
|
|
31
|
+
useEffect(function () {
|
|
32
|
+
if (ws.status !== "connected") return;
|
|
33
|
+
function handleProjects() {
|
|
34
|
+
setDataReceived(true);
|
|
35
|
+
}
|
|
36
|
+
ws.subscribe("projects:list", handleProjects);
|
|
37
|
+
return function () { ws.unsubscribe("projects:list", handleProjects); };
|
|
38
|
+
}, [ws]);
|
|
39
|
+
|
|
40
|
+
var ready = dataReceived && minTimeElapsed;
|
|
41
|
+
var [visible, setVisible] = useState(true);
|
|
42
|
+
|
|
43
|
+
useEffect(function () {
|
|
44
|
+
if (!ready) return;
|
|
45
|
+
var timer = setTimeout(function () {
|
|
46
|
+
setVisible(false);
|
|
47
|
+
}, 300);
|
|
48
|
+
return function () { clearTimeout(timer); };
|
|
49
|
+
}, [ready]);
|
|
50
|
+
|
|
51
|
+
useEffect(function () {
|
|
52
|
+
var canvas = canvasRef.current;
|
|
53
|
+
if (!canvas) return;
|
|
54
|
+
var ctx = canvas.getContext("2d");
|
|
55
|
+
if (!ctx) return;
|
|
56
|
+
|
|
57
|
+
var gridSize = 9;
|
|
58
|
+
var spacing = 26;
|
|
59
|
+
var dotRadius = 3.5;
|
|
60
|
+
var padding = 20;
|
|
61
|
+
var canvasSize = padding * 2 + (gridSize - 1) * spacing;
|
|
62
|
+
var dpr = window.devicePixelRatio || 1;
|
|
63
|
+
|
|
64
|
+
canvas.width = canvasSize * dpr;
|
|
65
|
+
canvas.height = canvasSize * dpr;
|
|
66
|
+
canvas.style.width = canvasSize + "px";
|
|
67
|
+
canvas.style.height = canvasSize + "px";
|
|
68
|
+
ctx.scale(dpr, dpr);
|
|
69
|
+
|
|
70
|
+
var centerX = canvasSize / 2;
|
|
71
|
+
var centerY = canvasSize / 2;
|
|
72
|
+
var logoSquare = 14;
|
|
73
|
+
var logoGap = 4;
|
|
74
|
+
var logoHalf = (logoSquare * 2 + logoGap) / 2;
|
|
75
|
+
var logoLeft = centerX - logoHalf;
|
|
76
|
+
var logoTop = centerY - logoHalf;
|
|
77
|
+
var logoRight = centerX + logoHalf;
|
|
78
|
+
var logoBottom = centerY + logoHalf;
|
|
79
|
+
|
|
80
|
+
var primary = "oklch(55% 0.25 280)";
|
|
81
|
+
|
|
82
|
+
type Dot = { x: number; y: number; col: number; row: number; hidden: boolean; brightness: number };
|
|
83
|
+
var dots: Dot[] = [];
|
|
84
|
+
for (var row = 0; row < gridSize; row++) {
|
|
85
|
+
for (var col = 0; col < gridSize; col++) {
|
|
86
|
+
var x = padding + col * spacing;
|
|
87
|
+
var y = padding + row * spacing;
|
|
88
|
+
var hidden = x + dotRadius > logoLeft && x - dotRadius < logoRight &&
|
|
89
|
+
y + dotRadius > logoTop && y - dotRadius < logoBottom;
|
|
90
|
+
dots.push({ x: x, y: y, col: col, row: row, hidden: hidden, brightness: 0.08 });
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
type Connection = {
|
|
95
|
+
a: number; b: number;
|
|
96
|
+
birth: number; duration: number;
|
|
97
|
+
fadeIn: number; fadeOut: number;
|
|
98
|
+
};
|
|
99
|
+
var connections: Connection[] = [];
|
|
100
|
+
var maxConnections = 10;
|
|
101
|
+
var now = performance.now();
|
|
102
|
+
|
|
103
|
+
function getNeighbors(idx: number): number[] {
|
|
104
|
+
var d = dots[idx];
|
|
105
|
+
var result: number[] = [];
|
|
106
|
+
for (var dr = -1; dr <= 1; dr++) {
|
|
107
|
+
for (var dc = -1; dc <= 1; dc++) {
|
|
108
|
+
if (dr === 0 && dc === 0) continue;
|
|
109
|
+
var nr = d.row + dr;
|
|
110
|
+
var nc = d.col + dc;
|
|
111
|
+
if (nr >= 0 && nr < gridSize && nc >= 0 && nc < gridSize) {
|
|
112
|
+
var ni = nr * gridSize + nc;
|
|
113
|
+
if (!dots[ni].hidden) result.push(ni);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return result;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function animate() {
|
|
121
|
+
now = performance.now();
|
|
122
|
+
ctx!.clearRect(0, 0, canvasSize, canvasSize);
|
|
123
|
+
|
|
124
|
+
if (connections.length < maxConnections && Math.random() < 0.04) {
|
|
125
|
+
var candidates: number[] = [];
|
|
126
|
+
for (var i = 0; i < dots.length; i++) {
|
|
127
|
+
if (!dots[i].hidden) candidates.push(i);
|
|
128
|
+
}
|
|
129
|
+
var attempts = 0;
|
|
130
|
+
while (attempts < 5 && connections.length < maxConnections) {
|
|
131
|
+
var ai = candidates[Math.floor(Math.random() * candidates.length)];
|
|
132
|
+
var neighbors = getNeighbors(ai);
|
|
133
|
+
if (neighbors.length > 0) {
|
|
134
|
+
var bi = neighbors[Math.floor(Math.random() * neighbors.length)];
|
|
135
|
+
var exists = false;
|
|
136
|
+
for (var j = 0; j < connections.length; j++) {
|
|
137
|
+
if ((connections[j].a === ai && connections[j].b === bi) ||
|
|
138
|
+
(connections[j].a === bi && connections[j].b === ai)) {
|
|
139
|
+
exists = true;
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
if (!exists) {
|
|
144
|
+
connections.push({
|
|
145
|
+
a: ai, b: bi,
|
|
146
|
+
birth: now,
|
|
147
|
+
duration: 2000 + Math.random() * 3000,
|
|
148
|
+
fadeIn: 400,
|
|
149
|
+
fadeOut: 400,
|
|
150
|
+
});
|
|
151
|
+
break;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
attempts++;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
var connectedSet = new Set<number>();
|
|
159
|
+
var keep: Connection[] = [];
|
|
160
|
+
for (var ci = 0; ci < connections.length; ci++) {
|
|
161
|
+
var c = connections[ci];
|
|
162
|
+
var age = now - c.birth;
|
|
163
|
+
if (age > c.duration) continue;
|
|
164
|
+
keep.push(c);
|
|
165
|
+
|
|
166
|
+
var alpha = 1.0;
|
|
167
|
+
if (age < c.fadeIn) {
|
|
168
|
+
alpha = age / c.fadeIn;
|
|
169
|
+
} else if (age > c.duration - c.fadeOut) {
|
|
170
|
+
alpha = (c.duration - age) / c.fadeOut;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
connectedSet.add(c.a);
|
|
174
|
+
connectedSet.add(c.b);
|
|
175
|
+
|
|
176
|
+
var da = dots[c.a];
|
|
177
|
+
var db = dots[c.b];
|
|
178
|
+
ctx!.beginPath();
|
|
179
|
+
ctx!.moveTo(da.x, da.y);
|
|
180
|
+
ctx!.lineTo(db.x, db.y);
|
|
181
|
+
ctx!.strokeStyle = primary;
|
|
182
|
+
ctx!.globalAlpha = alpha * 0.35;
|
|
183
|
+
ctx!.lineWidth = 1.5;
|
|
184
|
+
ctx!.stroke();
|
|
185
|
+
ctx!.globalAlpha = 1.0;
|
|
186
|
+
}
|
|
187
|
+
connections = keep;
|
|
188
|
+
|
|
189
|
+
for (var di = 0; di < dots.length; di++) {
|
|
190
|
+
var dot = dots[di];
|
|
191
|
+
if (dot.hidden) continue;
|
|
192
|
+
var targetBrightness = connectedSet.has(di) ? 0.7 : 0.08;
|
|
193
|
+
dot.brightness += (targetBrightness - dot.brightness) * 0.08;
|
|
194
|
+
ctx!.beginPath();
|
|
195
|
+
ctx!.arc(dot.x, dot.y, dotRadius, 0, Math.PI * 2);
|
|
196
|
+
ctx!.fillStyle = primary;
|
|
197
|
+
ctx!.globalAlpha = dot.brightness;
|
|
198
|
+
ctx!.fill();
|
|
199
|
+
ctx!.globalAlpha = 1.0;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
var pulse = 0.4 + 0.2 * Math.sin(now / 800);
|
|
203
|
+
var squares = [
|
|
204
|
+
[logoLeft, logoTop],
|
|
205
|
+
[logoLeft + logoSquare + logoGap, logoTop],
|
|
206
|
+
[logoLeft, logoTop + logoSquare + logoGap],
|
|
207
|
+
[logoLeft + logoSquare + logoGap, logoTop + logoSquare + logoGap],
|
|
208
|
+
];
|
|
209
|
+
for (var si = 0; si < squares.length; si++) {
|
|
210
|
+
var sx = squares[si][0];
|
|
211
|
+
var sy = squares[si][1];
|
|
212
|
+
ctx!.save();
|
|
213
|
+
ctx!.shadowColor = primary;
|
|
214
|
+
ctx!.shadowBlur = 8 + pulse * 6;
|
|
215
|
+
ctx!.fillStyle = primary;
|
|
216
|
+
ctx!.globalAlpha = 0.85 + pulse * 0.15;
|
|
217
|
+
ctx!.fillRect(sx, sy, logoSquare, logoSquare);
|
|
218
|
+
ctx!.restore();
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
frameRef.current = requestAnimationFrame(animate);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
frameRef.current = requestAnimationFrame(animate);
|
|
225
|
+
|
|
226
|
+
return function () {
|
|
227
|
+
cancelAnimationFrame(frameRef.current);
|
|
228
|
+
};
|
|
229
|
+
}, []);
|
|
230
|
+
|
|
231
|
+
if (!visible) {
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
var statusText = ws.status === "connecting" ? "Connecting..."
|
|
236
|
+
: ws.status === "disconnected" ? "Reconnecting..."
|
|
237
|
+
: "Loading projects...";
|
|
238
|
+
|
|
239
|
+
return (
|
|
240
|
+
<div
|
|
241
|
+
className="fixed inset-0 z-[9999] flex flex-col items-center justify-center bg-base-100"
|
|
242
|
+
style={{ opacity: ready ? 0 : 1, transition: "opacity 300ms ease-out", pointerEvents: ready ? "none" : "auto" }}
|
|
243
|
+
>
|
|
244
|
+
<div className="flex flex-col items-center gap-7">
|
|
245
|
+
<canvas ref={canvasRef} />
|
|
246
|
+
<div className="flex flex-col items-center gap-2">
|
|
247
|
+
<span className="text-[16px] font-mono font-bold text-base-content tracking-tight">Lattice</span>
|
|
248
|
+
<span className="text-[12px] text-base-content/40">{statusText}</span>
|
|
249
|
+
</div>
|
|
250
|
+
</div>
|
|
251
|
+
</div>
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function RemoveProjectConfirm() {
|
|
256
|
+
var sidebar = useSidebar();
|
|
257
|
+
var ws = useWebSocket();
|
|
258
|
+
var slug = sidebar.confirmRemoveSlug;
|
|
259
|
+
|
|
260
|
+
if (!slug) return null;
|
|
261
|
+
|
|
262
|
+
var projects = (function () {
|
|
263
|
+
try {
|
|
264
|
+
var store = getSidebarStore();
|
|
265
|
+
return store.state;
|
|
266
|
+
} catch {
|
|
267
|
+
return null;
|
|
268
|
+
}
|
|
269
|
+
})();
|
|
270
|
+
|
|
271
|
+
return (
|
|
272
|
+
<div className="fixed inset-0 z-[9999] flex items-center justify-center">
|
|
273
|
+
<div className="absolute inset-0 bg-black/50" onClick={sidebar.closeConfirmRemove} />
|
|
274
|
+
<div className="relative bg-base-200 border border-base-content/15 rounded-2xl shadow-2xl w-full max-w-sm mx-4 overflow-hidden">
|
|
275
|
+
<div className="px-5 py-4 border-b border-base-content/15">
|
|
276
|
+
<h2 className="text-[15px] font-mono font-bold text-base-content">Remove Project</h2>
|
|
277
|
+
</div>
|
|
278
|
+
<div className="px-5 py-4">
|
|
279
|
+
<p className="text-[13px] text-base-content/60">
|
|
280
|
+
Remove <span className="font-semibold text-base-content">{slug}</span> from Lattice? This won't delete any files on disk.
|
|
281
|
+
</p>
|
|
282
|
+
</div>
|
|
283
|
+
<div className="px-5 py-3 border-t border-base-content/15 flex justify-end gap-2">
|
|
284
|
+
<button
|
|
285
|
+
onClick={sidebar.closeConfirmRemove}
|
|
286
|
+
className="btn btn-ghost btn-sm text-[12px]"
|
|
287
|
+
>
|
|
288
|
+
Cancel
|
|
289
|
+
</button>
|
|
290
|
+
<button
|
|
291
|
+
onClick={function () {
|
|
292
|
+
ws.send({
|
|
293
|
+
type: "settings:update",
|
|
294
|
+
settings: { removeProject: slug },
|
|
295
|
+
} as any);
|
|
296
|
+
if (sidebar.activeProjectSlug === slug) {
|
|
297
|
+
sidebar.goToDashboard();
|
|
298
|
+
}
|
|
299
|
+
sidebar.closeConfirmRemove();
|
|
300
|
+
}}
|
|
301
|
+
className="btn btn-error btn-sm text-[12px]"
|
|
302
|
+
>
|
|
303
|
+
Remove
|
|
304
|
+
</button>
|
|
305
|
+
</div>
|
|
306
|
+
</div>
|
|
307
|
+
</div>
|
|
308
|
+
);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
function RootLayout() {
|
|
312
|
+
var [setupComplete, setSetupComplete] = useState(function () {
|
|
313
|
+
return localStorage.getItem("lattice-setup-complete") === "1";
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
var sidebar = useSidebar();
|
|
317
|
+
|
|
318
|
+
useEffect(function () {
|
|
319
|
+
function handleKeyDown(e: KeyboardEvent) {
|
|
320
|
+
if (e.key === "Escape") {
|
|
321
|
+
var state = getSidebarStore().state;
|
|
322
|
+
if (state.sidebarMode === "settings") {
|
|
323
|
+
exitSettings();
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
328
|
+
window.addEventListener("popstate", handlePopState);
|
|
329
|
+
return function () {
|
|
330
|
+
document.removeEventListener("keydown", handleKeyDown);
|
|
331
|
+
window.removeEventListener("popstate", handlePopState);
|
|
332
|
+
};
|
|
333
|
+
}, []);
|
|
334
|
+
|
|
335
|
+
if (!setupComplete) {
|
|
336
|
+
return (
|
|
337
|
+
<SetupWizard onComplete={function () { setSetupComplete(true); }} />
|
|
338
|
+
);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
return (
|
|
342
|
+
<div className="flex w-full h-full overflow-hidden bg-base-100">
|
|
343
|
+
<LoadingScreen />
|
|
344
|
+
<div className="drawer lg:drawer-open h-full w-full">
|
|
345
|
+
<input
|
|
346
|
+
id="sidebar-drawer"
|
|
347
|
+
type="checkbox"
|
|
348
|
+
className="drawer-toggle"
|
|
349
|
+
checked={sidebar.drawerOpen}
|
|
350
|
+
onChange={function () {}}
|
|
351
|
+
/>
|
|
352
|
+
|
|
353
|
+
<div className="drawer-content flex flex-col h-full min-w-0 overflow-hidden">
|
|
354
|
+
<Outlet />
|
|
355
|
+
</div>
|
|
356
|
+
|
|
357
|
+
<div className="drawer-side z-50 h-full">
|
|
358
|
+
<label
|
|
359
|
+
htmlFor="sidebar-drawer"
|
|
360
|
+
aria-label="close sidebar"
|
|
361
|
+
className="drawer-overlay"
|
|
362
|
+
onClick={closeDrawer}
|
|
363
|
+
/>
|
|
364
|
+
<div className="h-full w-[284px] flex flex-col overflow-hidden">
|
|
365
|
+
<Sidebar onSessionSelect={closeDrawer} />
|
|
366
|
+
</div>
|
|
367
|
+
</div>
|
|
368
|
+
</div>
|
|
369
|
+
<NodeSettingsModal
|
|
370
|
+
isOpen={sidebar.nodeSettingsOpen}
|
|
371
|
+
onClose={sidebar.closeNodeSettings}
|
|
372
|
+
/>
|
|
373
|
+
<AddProjectModal
|
|
374
|
+
isOpen={sidebar.addProjectOpen}
|
|
375
|
+
onClose={sidebar.closeAddProject}
|
|
376
|
+
/>
|
|
377
|
+
<RemoveProjectConfirm />
|
|
378
|
+
</div>
|
|
379
|
+
);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
function IndexPage() {
|
|
383
|
+
var sidebar = useSidebar();
|
|
384
|
+
if (sidebar.activeView.type === "dashboard") {
|
|
385
|
+
return <DashboardView />;
|
|
386
|
+
}
|
|
387
|
+
if (sidebar.activeView.type === "settings") {
|
|
388
|
+
return <SettingsView />;
|
|
389
|
+
}
|
|
390
|
+
if (sidebar.activeView.type === "project-settings") {
|
|
391
|
+
return <ProjectSettingsView />;
|
|
392
|
+
}
|
|
393
|
+
if (sidebar.activeView.type === "project-dashboard") {
|
|
394
|
+
return <ProjectDashboardView />;
|
|
395
|
+
}
|
|
396
|
+
return <ChatView />;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
var rootRoute = createRootRoute({
|
|
400
|
+
component: RootLayout,
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
var indexRoute = createRoute({
|
|
404
|
+
getParentRoute: function () { return rootRoute; },
|
|
405
|
+
path: "/",
|
|
406
|
+
component: IndexPage,
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
var projectRoute = createRoute({
|
|
410
|
+
getParentRoute: function () { return rootRoute; },
|
|
411
|
+
path: "/$projectSlug",
|
|
412
|
+
component: IndexPage,
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
var sessionRoute = createRoute({
|
|
416
|
+
getParentRoute: function () { return rootRoute; },
|
|
417
|
+
path: "/$projectSlug/$sessionId",
|
|
418
|
+
component: IndexPage,
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
var settingsRoute = createRoute({
|
|
422
|
+
getParentRoute: function () { return rootRoute; },
|
|
423
|
+
path: "/settings/$section",
|
|
424
|
+
component: IndexPage,
|
|
425
|
+
});
|
|
426
|
+
|
|
427
|
+
var settingsIndexRoute = createRoute({
|
|
428
|
+
getParentRoute: function () { return rootRoute; },
|
|
429
|
+
path: "/settings",
|
|
430
|
+
component: IndexPage,
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
var projectSettingsRoute = createRoute({
|
|
434
|
+
getParentRoute: function () { return rootRoute; },
|
|
435
|
+
path: "/$projectSlug/settings/$section",
|
|
436
|
+
component: IndexPage,
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
var projectSettingsIndexRoute = createRoute({
|
|
440
|
+
getParentRoute: function () { return rootRoute; },
|
|
441
|
+
path: "/$projectSlug/settings",
|
|
442
|
+
component: IndexPage,
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
var routeTree = rootRoute.addChildren([indexRoute, settingsIndexRoute, settingsRoute, projectSettingsIndexRoute, projectSettingsRoute, projectRoute, sessionRoute]);
|
|
446
|
+
|
|
447
|
+
export var router = createRouter({ routeTree });
|
|
448
|
+
|
|
449
|
+
declare module "@tanstack/react-router" {
|
|
450
|
+
interface Register {
|
|
451
|
+
router: typeof router;
|
|
452
|
+
}
|
|
453
|
+
}
|