asdf98 commited on
Commit
79c663f
·
verified ·
1 Parent(s): b287e40

fix: apply theme variables to root app shell and overlays

Browse files
Files changed (1) hide show
  1. src/App.tsx +18 -32
src/App.tsx CHANGED
@@ -12,21 +12,10 @@ import { listen } from '@tauri-apps/api/event';
12
  const BrowserPanel = lazy(() => import('./components/BrowserPanel').then(m => ({ default: m.BrowserPanel })));
13
  const LibraryPanel = lazy(() => import('./components/LibraryPanel').then(m => ({ default: m.LibraryPanel })));
14
  const SettingsPanel = lazy(() => import('./components/SettingsPanel').then(m => ({ default: m.SettingsPanel })));
15
-
16
  const appWindow = getCurrentWindow();
17
 
18
  const MainApp = () => {
19
- const {
20
- currentScreen, setIsBrowserOpen, setIsLibraryOpen, isBrowserOpen, isLibraryOpen,
21
- isSettingsOpen, setIsSettingsOpen, isAlwaysOnTop, setIsAlwaysOnTop, bgOpacity,
22
- isAnnotationMode, setIsAnnotationMode, globalDesaturate, setGlobalDesaturate,
23
- setZoom, setPan, pan, zoom, images, setImages, setTextNotes, selectedNodeIds, setSelectedNodeIds,
24
- annotationColor, setAnnotationColor, annotationSize, setAnnotationSize,
25
- isEraser, setIsEraser, isHighlighter, setIsHighlighter, undo, redo,
26
- focusedImageId, setFocusedImageId, valueMirrorIds, setValueMirrorIds,
27
- isZoomLensActive, setIsZoomLensActive, isWhisperBrowser, setIsWhisperBrowser,
28
- showMinimap,
29
- } = useAppStore();
30
  const [toastMsg, setToastMsg] = useState<string | null>(null);
31
  const [isCapturing, setIsCapturing] = useState(false);
32
  const lastBPress = useRef(0);
@@ -39,8 +28,9 @@ const MainApp = () => {
39
  const data = event.payload;
40
  if (!data || !data.url) return;
41
  const img = new Image();
42
- img.onload = () => { const ratio = img.width / img.height; const w = Math.min(400, img.width); const h = w / ratio; setImages(prev => [...prev, { id: data.id || crypto.randomUUID(), url: data.url, x: (-pan.x + window.innerWidth / 3 + Math.random() * 80) / zoom, y: (-pan.y + window.innerHeight / 3 + Math.random() * 80) / zoom, width: w, height: h, aspectRatio: ratio }]); setToastMsg('✓ Image added'); };
43
- img.onerror = () => { const w = Math.min(400, data.width || 300); const h = data.height ? w * (data.height / data.width) : w; setImages(prev => [...prev, { id: data.id || crypto.randomUUID(), url: data.url, x: (-pan.x + window.innerWidth / 3 + Math.random() * 80) / zoom, y: (-pan.y + window.innerHeight / 3 + Math.random() * 80) / zoom, width: w, height: h, aspectRatio: w / h }]); setToastMsg('✓ Image added'); };
 
44
  img.src = data.url;
45
  });
46
  return () => { unlisten.then(fn => fn()); };
@@ -70,7 +60,6 @@ const MainApp = () => {
70
  if (key === 'l' && !ctrl && !e.shiftKey) { setIsLibraryOpen(p => !p); return; }
71
  if (ctrl && key === ',') { e.preventDefault(); setIsSettingsOpen(p => !p); return; }
72
  if (key === 'a' && !ctrl && !e.shiftKey) { setIsAnnotationMode(p => !p); return; }
73
- if (key === 'g' && !ctrl && !e.shiftKey) { window.dispatchEvent(new CustomEvent('muse:toggle-grid', { detail: true })); return; }
74
  if (key === 'd' && !ctrl) { if (e.shiftKey) setGlobalDesaturate(p => !p); else if (selectedNodeIds.length > 0) setImages(prev => prev.map(i => selectedNodeIds.includes(i.id) ? { ...i, isDesaturated: !i.isDesaturated } : i)); return; }
75
  if (key === 't' && !ctrl && !e.shiftKey) { setIsAlwaysOnTop(p => !p); return; }
76
  if (e.key === 'Escape') { setIsBrowserOpen(false); setIsLibraryOpen(false); setIsSettingsOpen(false); setSelectedNodeIds([]); setFocusedImageId(null); return; }
@@ -85,24 +74,21 @@ const MainApp = () => {
85
  }, [selectedNodeIds, images, pan, zoom, focusedImageId, undo, redo]);
86
 
87
  const handleCtxMenu = (e: React.MouseEvent) => { if (!(e.target instanceof HTMLInputElement) && !(e.target instanceof HTMLTextAreaElement) && !(e.target as HTMLElement).isContentEditable) e.preventDefault(); };
 
88
 
89
- if (currentScreen === 'hub') return <div className="w-screen h-screen relative overflow-hidden bg-[#0A0A0B]" onContextMenu={handleCtxMenu}><StarterHub /><Suspense fallback={null}>{isSettingsOpen && <SettingsPanel />}</Suspense></div>;
90
-
91
- return (
92
- <div className="w-screen h-screen relative overflow-hidden" style={{ backgroundColor: `rgba(28, 28, 30, ${isAlwaysOnTop ? bgOpacity / 100 : 1})` }} onContextMenu={handleCtxMenu}>
93
- <Canvas />
94
- {(isBrowserOpen || isLibraryOpen || isSettingsOpen) && <div className="absolute inset-0 bg-black/40 pointer-events-none z-30 transition-opacity" />}
95
- <Toolbar />
96
- <Suspense fallback={null}>{isBrowserOpen && <BrowserPanel />}{isLibraryOpen && <LibraryPanel />}{isSettingsOpen && <SettingsPanel />}</Suspense>
97
- {showMinimap && <Minimap />}
98
- <ContextMenu />
99
- <div className="absolute bottom-4 left-4 text-[11px] opacity-40 text-white pointer-events-none select-none z-10 mix-blend-difference">Space+Drag Pan · Scroll Zoom · B Browser · L Library · A Annotate · G Grid · Shift+S Screenshot</div>
100
- {toastMsg && <div className="absolute top-16 left-1/2 -translate-x-1/2 z-50 pointer-events-none"><div className="bg-[#1C1C1E]/90 border border-white/10 text-white font-medium px-4 py-2 rounded-full shadow-2xl backdrop-blur text-xs">{toastMsg}</div></div>}
101
- {globalDesaturate && <div className="absolute top-16 left-1/2 -translate-x-1/2 z-50 pointer-events-none"><div className="bg-yellow-500/20 border border-yellow-500 text-white px-3 py-1 rounded text-xs shadow-lg backdrop-blur">Desaturation Active (Shift+D)</div></div>}
102
- {focusedImageId && <div className="absolute top-4 left-1/2 -translate-x-1/2 z-50 pointer-events-none"><div className="bg-[#0A84FF]/20 border border-[#0A84FF] text-white px-3 py-1 rounded text-xs shadow-lg backdrop-blur">Focus Mode — ←→ cycle, F/Esc exit</div></div>}
103
- {isCapturing && <div className="absolute inset-0 bg-black/50 flex items-center justify-center z-[100] pointer-events-none"><div className="bg-[#2A2A2E] border border-[#3A3A3E] rounded-xl px-6 py-4 shadow-2xl text-white text-sm">Capturing...</div></div>}
104
- </div>
105
- );
106
  };
107
 
108
  export default function App() { return <AppProvider><MainApp /></AppProvider>; }
 
12
  const BrowserPanel = lazy(() => import('./components/BrowserPanel').then(m => ({ default: m.BrowserPanel })));
13
  const LibraryPanel = lazy(() => import('./components/LibraryPanel').then(m => ({ default: m.LibraryPanel })));
14
  const SettingsPanel = lazy(() => import('./components/SettingsPanel').then(m => ({ default: m.SettingsPanel })));
 
15
  const appWindow = getCurrentWindow();
16
 
17
  const MainApp = () => {
18
+ const { currentScreen, setIsBrowserOpen, setIsLibraryOpen, isBrowserOpen, isLibraryOpen, isSettingsOpen, setIsSettingsOpen, isAlwaysOnTop, setIsAlwaysOnTop, bgOpacity, isAnnotationMode, setIsAnnotationMode, globalDesaturate, setGlobalDesaturate, setZoom, setPan, pan, zoom, images, setImages, setTextNotes, selectedNodeIds, setSelectedNodeIds, annotationColor, setAnnotationColor, annotationSize, setAnnotationSize, isEraser, setIsEraser, isHighlighter, setIsHighlighter, undo, redo, focusedImageId, setFocusedImageId, valueMirrorIds, setValueMirrorIds, isZoomLensActive, setIsZoomLensActive, isWhisperBrowser, setIsWhisperBrowser, showMinimap } = useAppStore();
 
 
 
 
 
 
 
 
 
 
19
  const [toastMsg, setToastMsg] = useState<string | null>(null);
20
  const [isCapturing, setIsCapturing] = useState(false);
21
  const lastBPress = useRef(0);
 
28
  const data = event.payload;
29
  if (!data || !data.url) return;
30
  const img = new Image();
31
+ const add = (w0: number, h0: number) => { const ratio = w0 / h0; const w = Math.min(400, w0); const h = w / ratio; setImages(prev => [...prev, { id: data.id || crypto.randomUUID(), url: data.url, x: (-pan.x + window.innerWidth / 3 + Math.random() * 80) / zoom, y: (-pan.y + window.innerHeight / 3 + Math.random() * 80) / zoom, width: w, height: h, aspectRatio: ratio }]); setToastMsg('✓ Image added'); };
32
+ img.onload = () => add(img.width, img.height);
33
+ img.onerror = () => add(data.width || 300, data.height || 200);
34
  img.src = data.url;
35
  });
36
  return () => { unlisten.then(fn => fn()); };
 
60
  if (key === 'l' && !ctrl && !e.shiftKey) { setIsLibraryOpen(p => !p); return; }
61
  if (ctrl && key === ',') { e.preventDefault(); setIsSettingsOpen(p => !p); return; }
62
  if (key === 'a' && !ctrl && !e.shiftKey) { setIsAnnotationMode(p => !p); return; }
 
63
  if (key === 'd' && !ctrl) { if (e.shiftKey) setGlobalDesaturate(p => !p); else if (selectedNodeIds.length > 0) setImages(prev => prev.map(i => selectedNodeIds.includes(i.id) ? { ...i, isDesaturated: !i.isDesaturated } : i)); return; }
64
  if (key === 't' && !ctrl && !e.shiftKey) { setIsAlwaysOnTop(p => !p); return; }
65
  if (e.key === 'Escape') { setIsBrowserOpen(false); setIsLibraryOpen(false); setIsSettingsOpen(false); setSelectedNodeIds([]); setFocusedImageId(null); return; }
 
74
  }, [selectedNodeIds, images, pan, zoom, focusedImageId, undo, redo]);
75
 
76
  const handleCtxMenu = (e: React.MouseEvent) => { if (!(e.target instanceof HTMLInputElement) && !(e.target instanceof HTMLTextAreaElement) && !(e.target as HTMLElement).isContentEditable) e.preventDefault(); };
77
+ if (currentScreen === 'hub') return <div className="w-screen h-screen relative overflow-hidden bg-[var(--panel-bg)]" onContextMenu={handleCtxMenu}><StarterHub /><Suspense fallback={null}>{isSettingsOpen && <SettingsPanel />}</Suspense></div>;
78
 
79
+ return <div className="w-screen h-screen relative overflow-hidden bg-[var(--canvas-bg)]" style={{ opacity: isAlwaysOnTop ? bgOpacity / 100 : 1 }} onContextMenu={handleCtxMenu}>
80
+ <Canvas />
81
+ {(isBrowserOpen || isLibraryOpen || isSettingsOpen) && <div className="absolute inset-0 bg-black/40 pointer-events-none z-30 transition-opacity" />}
82
+ <Toolbar />
83
+ <Suspense fallback={null}>{isBrowserOpen && <BrowserPanel />}{isLibraryOpen && <LibraryPanel />}{isSettingsOpen && <SettingsPanel />}</Suspense>
84
+ {showMinimap && <Minimap />}
85
+ <ContextMenu />
86
+ <div className="absolute bottom-4 left-4 text-[11px] opacity-40 text-[var(--ui-primary)] pointer-events-none select-none z-10 mix-blend-difference">Space+Drag Pan · Scroll Zoom · B Browser · L Library · A Annotate · Shift+S Screenshot</div>
87
+ {toastMsg && <div className="absolute top-16 left-1/2 -translate-x-1/2 z-50 pointer-events-none"><div className="bg-[var(--panel-bg)]/90 border border-white/10 text-[var(--ui-primary)] font-medium px-4 py-2 rounded-full shadow-2xl backdrop-blur text-xs">{toastMsg}</div></div>}
88
+ {globalDesaturate && <div className="absolute top-16 left-1/2 -translate-x-1/2 z-50 pointer-events-none"><div className="bg-[var(--accent-amber)]/20 border border-[var(--accent-amber)] text-[var(--ui-primary)] px-3 py-1 rounded text-xs shadow-lg backdrop-blur">Desaturation Active (Shift+D)</div></div>}
89
+ {focusedImageId && <div className="absolute top-4 left-1/2 -translate-x-1/2 z-50 pointer-events-none"><div className="bg-[var(--accent)]/20 border border-[var(--accent)] text-[var(--ui-primary)] px-3 py-1 rounded text-xs shadow-lg backdrop-blur">Focus Mode ←→ cycle, F/Esc exit</div></div>}
90
+ {isCapturing && <div className="absolute inset-0 bg-black/50 flex items-center justify-center z-[100] pointer-events-none"><div className="bg-[var(--panel-surface)] border border-[var(--panel-border)] rounded-xl px-6 py-4 shadow-2xl text-[var(--ui-primary)] text-sm">Capturing...</div></div>}
91
+ </div>;
 
 
 
 
92
  };
93
 
94
  export default function App() { return <AppProvider><MainApp /></AppProvider>; }