feat: implement authentication state management and routing logic#340
feat: implement authentication state management and routing logic#340webdevcody merged 5 commits intomainfrom
Conversation
- Added a new auth store using Zustand to manage authentication state, including `authChecked` and `isAuthenticated`. - Updated `LoginView` to set authentication state upon successful login and navigate based on setup completion. - Enhanced `RootLayoutContent` to enforce routing rules based on authentication status, redirecting users to login or setup as necessary. - Improved error handling and loading states during authentication checks.
|
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. 📝 WalkthroughWalkthroughCentralizes UI auth in a new Zustand store, updates login/root to set and gate on auth/setup state, defers WebSocket startup by environment, and adds a persisted skipSandboxWarning setting with UI and dialog controls. Changes
Sequence Diagram(s)sequenceDiagram
rect rgba(235,245,255,0.35)
participant Browser as Browser (Renderer)
participant Root as Root Route
participant AuthStore as useAuthStore
participant HttpClient as HttpApiClient
participant Server as API / WebSocket
end
Note over Browser,Root: App startup (Web mode)
Browser->>Root: mount
Root->>AuthStore: initAuth() [guarded by authCheckRunning]
AuthStore->>HttpClient: verifySession / getServerUrlSync
HttpClient->>Server: GET /api/health
alt session valid
Server-->>HttpClient: 200
HttpClient-->>AuthStore: setAuthState(isAuthenticated: true, authChecked: true)
Root->>Browser: render app or navigate /setup (based on setupComplete)
else unauthenticated
HttpClient-->>AuthStore: setAuthState(isAuthenticated: false, authChecked: true)
Root->>Browser: redirect to /login
end
Note over Browser,HttpClient: Event subscription (deferred)
Browser->>HttpClient: subscribeToEvents()
alt Web mode
HttpClient->>Server: open WebSocket (deferred until subscription)
else Electron mode
HttpClient->>AuthStore: await API key
AuthStore-->>HttpClient: API key available
HttpClient->>Server: open WebSocket (with API key)
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested labels
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
📜 Recent review detailsConfiguration used: defaults Review profile: CHILL Plan: Pro 📒 Files selected for processing (2)
🧰 Additional context used📓 Path-based instructions (2)**/*.{ts,tsx,js,jsx}📄 CodeRabbit inference engine (CLAUDE.md)
Files:
**/*.{ts,tsx}📄 CodeRabbit inference engine (CLAUDE.md)
Files:
🧠 Learnings (1)📓 Common learnings⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
🔇 Additional comments (2)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Summary of ChangesHello @webdevcody, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request significantly overhauls the application's authentication and routing mechanisms, particularly for web mode. It establishes a centralized authentication state using Zustand, ensuring consistent tracking of user login status and whether an authentication check has been performed. This new system, combined with refined routing logic in the root layout, guarantees that users are seamlessly directed to the appropriate views—login, setup, or the main application—based on their authentication status and setup completion. Additionally, it includes several robustness improvements to the HTTP API client, especially concerning Electron environment detection and WebSocket connection handling. Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request introduces a new useAuthStore (Zustand) to centralize authentication state management, replacing local state in LoginView and __root.tsx. The LoginView now uses this store to determine navigation after successful login, redirecting to /setup if initial setup is incomplete. Significant changes were made to __root.tsx to implement robust routing rules for web mode: unauthenticated users are forced to /login, and authenticated users with incomplete setup are directed to /setup. The http-api-client.ts file was updated to refine Electron mode detection, improve server URL initialization, and make WebSocket connection conditional based on the environment (immediate in Electron, deferred in web). Additionally, the sandbox risk acknowledgment logic was modified to no longer persist user choices via sessionStorage, causing the confirmation dialog to appear on every page refresh, which a reviewer noted could lead to a frustrating user experience. Other minor changes include adding a backlog-plan:event type, ensuring proper headers for logout requests, and updating a CSS utility class.
| // Always start from pending on a fresh page load so the user sees the prompt | ||
| // each time the app is launched/refreshed (unless running in a container). | ||
| const [sandboxStatus, setSandboxStatus] = useState<SandboxStatus>('pending'); |
There was a problem hiding this comment.
This change causes the sandbox confirmation dialog to appear on every page refresh, as the user's choice is no longer persisted in sessionStorage. While the comment suggests this is intentional, it may lead to a frustrating user experience. Consider restoring the use of sessionStorage to remember the user's confirmation for the duration of their session.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
apps/ui/src/lib/http-api-client.ts (1)
454-474: Potential reconnect timer leak on rapid calls.If
connectWebSocket()is called multiple times in quick succession whileapiKeyis unavailable, each call could potentially schedule its own timer before the previous one fires. The guardif (!this.reconnectTimer)mitigates this, but there's a small window whereisConnectingis set tofalsebefore the timer check.Consider verifying
isConnectingis only cleared after the timer decision:🔎 Suggested improvement
if (!apiKey) { console.warn( '[HttpApiClient] Electron mode: API key not ready, delaying WebSocket connect' ); - this.isConnecting = false; if (!this.reconnectTimer) { this.reconnectTimer = setTimeout(() => { this.reconnectTimer = null; this.connectWebSocket(); }, 250); } + this.isConnecting = false; return; }apps/ui/src/routes/__root.tsx (1)
44-47: Sandbox status resets on every page refresh.The comment clarifies this is intentional—users see the sandbox confirmation prompt each time. If this becomes a UX friction point, consider persisting the confirmation in sessionStorage for the browser session.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
apps/ui/src/components/views/login-view.tsxapps/ui/src/lib/http-api-client.tsapps/ui/src/routes/__root.tsxapps/ui/src/store/auth-store.ts
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Always import from shared packages (@automaker/*), never from old relative paths
Files:
apps/ui/src/store/auth-store.tsapps/ui/src/components/views/login-view.tsxapps/ui/src/routes/__root.tsxapps/ui/src/lib/http-api-client.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use
resolveModelString()from @automaker/model-resolver to convert model aliases (haiku, sonnet, opus) to full model names
Files:
apps/ui/src/store/auth-store.tsapps/ui/src/components/views/login-view.tsxapps/ui/src/routes/__root.tsxapps/ui/src/lib/http-api-client.ts
🧠 Learnings (4)
📚 Learning: 2025-12-30T01:02:07.114Z
Learnt from: illia1f
Repo: AutoMaker-Org/automaker PR: 324
File: apps/ui/src/components/views/board-view/components/kanban-card/kanban-card.tsx:122-131
Timestamp: 2025-12-30T01:02:07.114Z
Learning: Tailwind CSS v4 uses postfix syntax for the important modifier: append ! at the end of the utility class (e.g., backdrop-blur-[0px]! or hover:bg-red-500!). The older v3 style used a prefix (!) at the start (e.g., !backdrop-blur-[0px]); prefer the postfix form for consistency across TSX files.
Applied to files:
apps/ui/src/components/views/login-view.tsxapps/ui/src/routes/__root.tsx
📚 Learning: 2025-12-28T05:07:48.147Z
Learnt from: CR
Repo: AutoMaker-Org/automaker PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-28T05:07:48.147Z
Learning: Frontend UI must use TanStack Router for file-based routing, organize components in components/views/, implement stores with Zustand, and use custom hooks in hooks/ directory
Applied to files:
apps/ui/src/routes/__root.tsx
📚 Learning: 2025-12-28T05:07:48.147Z
Learnt from: CR
Repo: AutoMaker-Org/automaker PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-28T05:07:48.147Z
Learning: Store project-specific rules in `.automaker/context/` and load them into agent prompts via `loadContextFiles()` from automaker/utils
Applied to files:
apps/ui/src/routes/__root.tsx
📚 Learning: 2025-12-28T05:07:48.147Z
Learnt from: CR
Repo: AutoMaker-Org/automaker PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-28T05:07:48.147Z
Learning: Applies to apps/server/src/**/*.{ts,tsx} : Use `createEventEmitter()` from `lib/events.ts` for all server operations to emit events that stream to frontend via WebSocket
Applied to files:
apps/ui/src/lib/http-api-client.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: e2e
🔇 Additional comments (11)
apps/ui/src/lib/http-api-client.ts (4)
43-53: LGTM on the Electron API narrowing.The
as anycast is documented and necessary to access Electron-only helpers not in the shared interface. The null-safe checks (electron?.getServerUrl) protect against non-browser environments.
114-122: Consider simplifying the Electron mode detection.The check
api?.isElectron === true || !!api?.getApiKeyhas redundancy—ifisElectronis the stable marker,getApiKeyavailability shouldn't be needed as a fallback. However, the comment explains this guards against early-startup timing issues, so the defensive approach is reasonable.
317-322: Empty body on logout is unusual but harmless.Adding
body: '{}'to the fire-and-forget logout request is not strictly necessary for a POST without payload, but it ensures compatibility with servers that expect a body. No functional issue.
391-407: WebSocket initialization strategy looks correct.Deferring WebSocket in web mode until subscription avoids 401 errors on unauthenticated routes. The
.catch()fallback ensures WebSocket attempts proceed even if API key init fails—reasonable resilience.apps/ui/src/components/views/login-view.tsx (1)
14-20: LGTM on auth store integration.The selectors correctly pull
setAuthStateandsetupCompletefrom their respective stores, enabling centralized state management.apps/ui/src/store/auth-store.ts (1)
1-29: Clean, minimal auth store implementation.The design correctly separates UI auth state from the server's cookie-based source of truth. The non-persisted approach ensures fresh auth checks on each page load.
apps/ui/src/routes/__root.tsx (5)
36-41: Good use of derived route flags.Computing
isSetupRouteandisLoginRoutefromlocation.pathnamekeeps the conditional rendering logic readable.
149-195: Auth initialization guard is well-designed.The
authCheckRunningref correctly prevents concurrent auth checks without causing re-renders. Directly callinguseAuthStore.getState().setAuthState()outside React's render cycle is the correct pattern for async operations.
218-242: Routing rules are comprehensive and correctly ordered.The logic properly:
- Waits for hydration
- Waits for auth check (web mode)
- Forces
/loginfor unauthenticated users- Forces
/setupfor authenticated but incomplete setup- Redirects away from
/setupwhen complete
252-264: Health check timeout is a good addition.Using
AbortSignal.timeout(2000)prevents the health check from hanging indefinitely in web mode. This improves resilience.
331-348: Loading and redirect states provide good UX.The intermediate "Loading..." and "Redirecting to login..." states prevent layout flash and provide user feedback during async transitions.
| try { | ||
| const result = await login(apiKey.trim()); | ||
| if (result.success) { | ||
| // Redirect to home/board on success | ||
| navigate({ to: '/' }); | ||
| // Mark as authenticated for this session (cookie-based auth) | ||
| setAuthState({ isAuthenticated: true, authChecked: true }); | ||
|
|
||
| // After auth, determine if setup is needed or go to app | ||
| navigate({ to: setupComplete ? '/' : '/setup' }); |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check if useSetupStore has persist middleware and how it's initialized
ast-grep --pattern 'useSetupStore = create($$$)'
echo "---"
rg -n 'persist' apps/ui/src/store/setup-store.tsRepository: AutoMaker-Org/automaker
Length of output: 133
🏁 Script executed:
#!/bin/bash
# Read setup-store.ts to understand persist configuration
cat -n apps/ui/src/store/setup-store.ts | head -150
echo "---"
# Check login-view.tsx for context around the login logic
cat -n apps/ui/src/components/views/login-view.tsx | sed -n '1,50p'Repository: AutoMaker-Org/automaker
Length of output: 6985
🏁 Script executed:
#!/bin/bash
# Read more of setup-store.ts to see persist configuration
cat -n apps/ui/src/store/setup-store.ts | sed -n '125,170p'
echo "---"
# Check __root.tsx for hydration handling
fd --type f -name "__root.tsx" apps/ui/src/ -x cat -n {}Repository: AutoMaker-Org/automaker
Length of output: 1875
🏁 Script executed:
#!/bin/bash
# Find and read __root.tsx
fd --type f -name "__root.tsx" apps/ui/src/ | head -5
echo "---"
# Also try root.tsx or Root.tsx
fd --type f -name "*root.tsx" apps/ui/src/ | head -10Repository: AutoMaker-Org/automaker
Length of output: 549
🏁 Script executed:
#!/bin/bash
# Find root files correctly
fd --type f "root\.tsx" apps/ui/src/
echo "---"
# Check router or layout structure
fd --type f -name "*.tsx" apps/ui/src/ | grep -E "(root|main|app|layout)" | head -10
echo "---"
# Check full persist config in setup-store.ts
cat apps/ui/src/store/setup-store.ts | tail -50Repository: AutoMaker-Org/automaker
Length of output: 1768
🏁 Script executed:
#!/bin/bash
# Read __root.tsx to check for hydration handling
wc -l apps/ui/src/routes/__root.tsx
echo "---"
cat apps/ui/src/routes/__root.tsxRepository: AutoMaker-Org/automaker
Length of output: 13665
Wait for setup store hydration before reading setupComplete in post-login redirect.
The setupComplete value from useSetupStore is read without checking hydration status. If the user logs in before the persisted store hydrates from storage, setupComplete defaults to false, causing an incorrect redirect to /setup even when setup was previously completed. While __root.tsx will eventually correct this redirect after hydration completes, it creates an unnecessary navigation flicker.
Consider checking useSetupStore.persist?.hasHydrated?.() before or alongside reading setupComplete, or deferring the redirect decision to __root.tsx which already has proper hydration guards in place.
🤖 Prompt for AI Agents
In apps/ui/src/components/views/login-view.tsx around lines 30 to 37, the
post-login redirect reads useSetupStore().setupComplete before the persisted
setup store is hydrated which can cause a false negative redirect to /setup;
update the logic to either (a) check the store hydration status via
useSetupStore.persist?.hasHydrated?.() and only decide/navigate based on
setupComplete after hydration, or (b) skip immediate redirect here and let
__root.tsx (which already guards on hydration) perform the final routing
decision after hydration completes; implement the chosen approach so the
redirect does not happen prematurely.
- Introduced a new function, runNpmAndWait, to execute npm commands and wait for their completion, enhancing error handling. - Updated the main function to build shared packages before starting the backend server, ensuring necessary dependencies are ready. - Adjusted server and web process commands to use a consistent naming convention.
- Updated the SandboxRiskDialog to include a checkbox for users to opt-out of future warnings, passing the state to the onConfirm callback. - Modified SettingsView to manage the skipSandboxWarning state, allowing users to reset the warning preference. - Enhanced DangerZoneSection to display a message when the sandbox warning is disabled and provide an option to reset this setting. - Updated RootLayoutContent to respect the user's choice regarding the sandbox warning, auto-confirming if the user opts to skip it. - Added skipSandboxWarning state management to the app store for persistent user preferences.
…r into fix-web-mode-auth
There was a problem hiding this comment.
Actionable comments posted: 1
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
apps/ui/src/components/dialogs/sandbox-risk-dialog.tsxapps/ui/src/components/views/settings-view.tsxapps/ui/src/components/views/settings-view/danger-zone/danger-zone-section.tsxapps/ui/src/routes/__root.tsxapps/ui/src/store/app-store.ts
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Always import from shared packages (@automaker/*), never from old relative paths
Files:
apps/ui/src/components/dialogs/sandbox-risk-dialog.tsxapps/ui/src/components/views/settings-view.tsxapps/ui/src/store/app-store.tsapps/ui/src/routes/__root.tsxapps/ui/src/components/views/settings-view/danger-zone/danger-zone-section.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use
resolveModelString()from @automaker/model-resolver to convert model aliases (haiku, sonnet, opus) to full model names
Files:
apps/ui/src/components/dialogs/sandbox-risk-dialog.tsxapps/ui/src/components/views/settings-view.tsxapps/ui/src/store/app-store.tsapps/ui/src/routes/__root.tsxapps/ui/src/components/views/settings-view/danger-zone/danger-zone-section.tsx
🧠 Learnings (3)
📓 Common learnings
Learnt from: CR
Repo: AutoMaker-Org/automaker PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-28T05:07:48.147Z
Learning: Frontend UI must use TanStack Router for file-based routing, organize components in components/views/, implement stores with Zustand, and use custom hooks in hooks/ directory
📚 Learning: 2025-12-30T01:02:07.114Z
Learnt from: illia1f
Repo: AutoMaker-Org/automaker PR: 324
File: apps/ui/src/components/views/board-view/components/kanban-card/kanban-card.tsx:122-131
Timestamp: 2025-12-30T01:02:07.114Z
Learning: Tailwind CSS v4 uses postfix syntax for the important modifier: append ! at the end of the utility class (e.g., backdrop-blur-[0px]! or hover:bg-red-500!). The older v3 style used a prefix (!) at the start (e.g., !backdrop-blur-[0px]); prefer the postfix form for consistency across TSX files.
Applied to files:
apps/ui/src/components/dialogs/sandbox-risk-dialog.tsxapps/ui/src/components/views/settings-view.tsxapps/ui/src/routes/__root.tsxapps/ui/src/components/views/settings-view/danger-zone/danger-zone-section.tsx
📚 Learning: 2025-12-28T05:07:48.147Z
Learnt from: CR
Repo: AutoMaker-Org/automaker PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-28T05:07:48.147Z
Learning: Frontend UI must use TanStack Router for file-based routing, organize components in components/views/, implement stores with Zustand, and use custom hooks in hooks/ directory
Applied to files:
apps/ui/src/routes/__root.tsx
🧬 Code graph analysis (4)
apps/ui/src/components/dialogs/sandbox-risk-dialog.tsx (2)
apps/ui/src/components/dialogs/index.ts (1)
SandboxRiskDialog(7-7)apps/ui/src/components/ui/button.tsx (1)
Button(108-108)
apps/ui/src/store/app-store.ts (1)
apps/ui/src/hooks/use-settings-migration.ts (1)
syncSettingsToServer(198-248)
apps/ui/src/routes/__root.tsx (5)
apps/ui/src/store/setup-store.ts (1)
useSetupStore(125-184)apps/ui/src/store/auth-store.ts (1)
useAuthStore(25-29)apps/ui/src/lib/http-api-client.ts (2)
initApiKey(130-165)isElectronMode(114-122)apps/ui/tests/utils/project/setup.ts (1)
setupComplete(756-771)apps/ui/src/lib/electron.ts (2)
isElectron(676-686)getElectronAPI(728-737)
apps/ui/src/components/views/settings-view/danger-zone/danger-zone-section.tsx (2)
apps/ui/src/components/ui/button.tsx (1)
Button(108-108)apps/ui/src/lib/utils.ts (1)
cn(5-7)
🔇 Additional comments (15)
apps/ui/src/components/views/settings-view.tsx (1)
58-59: LGTM!Clean integration of the
skipSandboxWarningstate from the app store and proper wiring toDangerZoneSection. The pattern follows the existing conventions in this file for passing store state to child components.Also applies to: 189-191
apps/ui/src/components/dialogs/sandbox-risk-dialog.tsx (3)
34-38: Good practice: resetting checkbox state after confirmation.Resetting
skipInFuturetofalseafter confirmation ensures the dialog starts fresh if reopened, preventing stale state from persisting.
105-132: Well-structured footer layout with accessibility considerations.Good use of
htmlForlinking the label to the checkbox,data-testidattributes for testing, and proper semantic structure. The flex layout handles responsive behavior appropriately withsm:breakpoint variants.
22-26: All callers ofSandboxRiskDialoghave been properly updated to handle the newonConfirmsignature. ThehandleSandboxConfirmcallback inapps/ui/src/routes/__root.tsxcorrectly accepts the(skipInFuture: boolean)parameter and uses it to set the skip warning state. No breaking changes remain.apps/ui/src/store/app-store.ts (1)
490-491: LGTM - State, initial value, and persistence are properly configured.The
skipSandboxWarningflag is correctly:
- Typed as
booleaninAppState- Initialized to
false(safe default - shows warning)- Included in
partializefor local persistence across sessionsAlso applies to: 981-981, 2933-2933
apps/ui/src/components/views/settings-view/danger-zone/danger-zone-section.tsx (3)
6-18: LGTM - Props interface and function signature properly updated.The new props
skipSandboxWarningandonResetSandboxWarningare correctly typed and destructured. The interface extension maintains consistency with the existing component pattern.
39-68: Well-designed sandbox warning reset UI.Good implementation details:
- Conditional rendering only shows the panel when
skipSandboxWarningis true- Uses
Shieldicon to visually differentiate from the destructive delete actionoutlinevariant for Reset button is appropriate since this is a non-destructive action- Includes
data-testidfor test automation
99-104: Good UX: Empty state prevents confusion.The empty state message provides helpful feedback when neither the sandbox warning reset nor project delete options are available.
apps/ui/src/routes/__root.tsx (7)
168-214: Good use of ref guard to prevent concurrent auth checks.The
authCheckRunningref prevents multiple simultaneous auth initialization calls, which could otherwise cause race conditions during React's strict mode double-invocation or rapid remounts.
102-134: Sandbox check effect may re-run unexpectedly whenskipSandboxWarningchanges.The effect depends on
skipSandboxWarning, but the early return only checkssandboxStatus !== 'pending'. If a user resets the sandbox warning (settingskipSandboxWarningtofalse) whilesandboxStatusis'confirmed', the effect won't re-trigger the warning because the status is no longer'pending'.This is likely acceptable behavior (the warning only shows on fresh page loads), but consider documenting this explicitly or resetting
sandboxStatusto'pending'whenskipSandboxWarningchanges fromtruetofalseif the intention is to show the warning again immediately.
234-261: Routing logic is well-structured with proper guards.The routing effect correctly:
- Waits for store hydration before acting
- Waits for auth check completion in web mode
- Prioritizes login redirect over setup redirect
- Handles the setup → app transition when setup completes
The dependency array includes all relevant state values.
271-283: Web mode health check is a reasonable fallback for IPC connectivity.Using
/api/healthendpoint with a 2-second timeout provides a lightweight way to check backend availability in web mode without instantiating the full HTTP client.
51-53: Intentional: Sandbox warning shows on every page refresh unless skipped.This design ensures users are reminded of the risks each time they launch the app outside a container. The
skipSandboxWarningpreference provides an opt-out for users who have acknowledged and accepted the risk.Note: This addresses the past review comment about sessionStorage removal - the behavior is intentional per the code comments.
Also applies to: 115-129
137-145: Callback correctly persists user's "skip" preference.When the user confirms with the checkbox checked,
setSkipSandboxWarning(true)is called to persist the preference. This integrates properly with the app store's async action which handles both local persistence and server sync.
359-367: Good UX: Loading state during redirect prevents flash of content.Showing "Redirecting to login..." while the navigation is in progress provides a better user experience than briefly showing protected content before the redirect completes.
- Introduced skipSandboxWarning property in GlobalSettings interface to manage user preference for sandbox risk warnings. - Updated syncSettingsToServer function to include skipSandboxWarning in the settings synchronization process. - Set default value for skipSandboxWarning to false in DEFAULT_GLOBAL_SETTINGS.
authCheckedandisAuthenticated.LoginViewto set authentication state upon successful login and navigate based on setup completion.RootLayoutContentto enforce routing rules based on authentication status, redirecting users to login or setup as necessary.Summary by CodeRabbit
Bug Fixes
New Features
Chores
✏️ Tip: You can customize this high-level summary in your review settings.