Skip to content

Commit 0148504

Browse files
Extract BootstrapError component and simplify useRevealMainWindow
Move the reveal latch into the hook so callers just pass readiness and get back a boolean. Extract bootstrap error UI into its own component. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 763c27d commit 0148504

3 files changed

Lines changed: 34 additions & 31 deletions

File tree

app/src/app.tsx

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { type CSSProperties, useEffect, useState } from "react";
1+
import { type CSSProperties, useState } from "react";
22

33
import { useTheme } from "@/shared/hooks/use-theme";
44
import { Bar, Container, Section } from "@column-resizer/react";
@@ -16,6 +16,7 @@ import { Toaster } from "@/shared/ui/sonner";
1616
import { AccountSwitcherDialog } from "@/features/settings/account-switcher-dialog";
1717
import { SettingsDialog } from "@/features/settings/settings-dialog";
1818
import { CommandPalette } from "@/features/command-palette";
19+
import { BootstrapError } from "@/features/shell/ui/bootstrap-error";
1920
import { EditorPane } from "@/features/shell/editor-pane";
2021
import { NoteHistoryDialog } from "@/features/shell/note-history-dialog";
2122
import { NotesPane } from "@/features/notes/ui/notes-pane";
@@ -30,7 +31,6 @@ import { conflictDialogCopy } from "@/shared/lib/conflict-dialog-copy";
3031
function App() {
3132
useTheme();
3233
const [isMacos] = useState(() => navigator.userAgent.includes("Mac"));
33-
const [revealed, setRevealed] = useState(false);
3434
const {
3535
bootstrapError,
3636
chooseConflictDialogProps,
@@ -52,31 +52,15 @@ function App() {
5252
setCommandPaletteOpen,
5353
} = useAppShortcuts({ onCreateNote: notesPaneProps.onCreateNote });
5454

55-
useEffect(() => {
56-
if (readyToRevealWindow) setRevealed(true);
57-
}, [readyToRevealWindow]);
58-
59-
useRevealMainWindow(!revealed);
55+
const revealed = useRevealMainWindow(readyToRevealWindow);
6056

6157
const sidebarVisible = useUIStore((s) => s.sidebarVisible);
6258
const notesPanelVisible = useUIStore((s) => s.notesPanelVisible);
6359

6460
if (!revealed) return null;
6561

6662
if (bootstrapError) {
67-
return (
68-
<div className="text-foreground flex min-h-screen items-center justify-center">
69-
<div className="border-border bg-card flex max-w-lg min-w-96 flex-col gap-4 rounded-xl border px-5 py-5 shadow-sm">
70-
<div className="space-y-1">
71-
<p className="font-semibold">Couldn&apos;t load your notes</p>
72-
<p className="text-muted-foreground text-sm">{bootstrapError}</p>
73-
</div>
74-
<div>
75-
<Button onClick={retryBootstrap}>Try again</Button>
76-
</div>
77-
</div>
78-
</div>
79-
);
63+
return <BootstrapError error={bootstrapError} onRetry={retryBootstrap} />;
8064
}
8165

8266
const chooseConflictDialog = conflictDialogCopy(
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { Button } from "@/shared/ui/button";
2+
3+
interface BootstrapErrorProps {
4+
error: string;
5+
onRetry: () => void;
6+
}
7+
8+
export function BootstrapError({ error, onRetry }: BootstrapErrorProps) {
9+
return (
10+
<div className="text-foreground flex min-h-screen items-center justify-center">
11+
<div className="border-border bg-card flex max-w-lg min-w-96 flex-col gap-4 rounded-xl border px-5 py-5 shadow-sm">
12+
<div className="space-y-1">
13+
<p className="font-semibold">Couldn&apos;t load your notes</p>
14+
<p className="text-muted-foreground text-sm">{error}</p>
15+
</div>
16+
<div>
17+
<Button onClick={onRetry}>Try again</Button>
18+
</div>
19+
</div>
20+
</div>
21+
);
22+
}
Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,15 @@
11
import { invoke } from "@tauri-apps/api/core";
2-
import { useEffect, useRef } from "react";
2+
import { useEffect, useState } from "react";
33

4-
export function useRevealMainWindow(bootstrapLoading: boolean) {
5-
const hasRevealedWindowRef = useRef(false);
4+
export function useRevealMainWindow(ready: boolean) {
5+
const [revealed, setRevealed] = useState(false);
66

77
useEffect(() => {
8-
// The Tauri main window starts hidden to avoid startup flash. Reveal it only
9-
// once the initial shell state is ready, and never re-run that reveal during
10-
// later note/query transitions.
11-
if (bootstrapLoading || hasRevealedWindowRef.current) {
12-
return;
13-
}
8+
if (!ready || revealed) return;
149

15-
hasRevealedWindowRef.current = true;
10+
setRevealed(true);
1611
void invoke("reveal_main_window");
17-
}, [bootstrapLoading]);
12+
}, [ready, revealed]);
13+
14+
return revealed;
1815
}

0 commit comments

Comments
 (0)