Skip to content

Conversation

@AnthonyRonning
Copy link
Contributor

@AnthonyRonning AnthonyRonning commented Nov 4, 2025

Fixes #294

Summary

Adds error handling to the OAuth desktop redirect flow for Tauri apps. Previously, if the deep link redirect failed, users would be stuck on the success page indefinitely.

Changes

  • Added 5-second timeout to detect failed deep link redirects
  • Display error UI with manual fallback options when redirect fails
  • Provide copyable deep link and manual 'Open Maple App' button
  • Add 'Back to Login' button for user recovery

Testing

  1. Start OAuth flow in desktop Tauri app
  2. Complete OAuth on web
  3. If deep link fails, you'll see error UI after 5 seconds
  4. Try "Open Maple App" button or copy deep link manually

Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Improved authentication redirect failure handling with a fallback UI option to manually open the Maple app when automatic redirect fails.
    • Enhanced error recovery during authentication callbacks with better timeout detection and fallback mechanisms.

- Add 5-second timeout to detect failed deep link redirects
- Display error UI with manual fallback options when redirect fails
- Provide copyable deep link and manual 'Open Maple App' button
- Add 'Back to Login' button for user recovery
- Fixes issue where users were stuck on success page indefinitely

Fixes #294

Co-authored-by: Anthony <AnthonyRonning@users.noreply.github.com>
@coderabbitai
Copy link

coderabbitai bot commented Nov 4, 2025

Walkthrough

The PR enhances OAuth callback error handling in the desktop Tauri flow by adding detection for redirect failures. A 5-second timer flags when redirection doesn't complete, triggering fallback UI that allows users to manually open the Maple app via a stored deep link URL.

Changes

Cohort / File(s) Summary
OAuth Callback Error Handling
frontend/src/routes/auth.$provider.callback.tsx
Adds redirectFailed and deepLinkUrl state; wraps handleSuccessfulAuth in useCallback; implements 5-second timer to detect failed redirects; adds error handling with timer cleanup; renders fallback UI with manual deep link option when redirect fails; extends dependency arrays.

Sequence Diagram

sequenceDiagram
    participant User
    participant WebCallback as Web Callback Page
    participant Tauri as Tauri App
    participant Timer as 5s Timeout

    User->>WebCallback: Completes OAuth
    WebCallback->>WebCallback: handleSuccessfulAuth triggered
    
    rect rgb(200, 220, 255)
        note over WebCallback: New: Initialize timer & redirect attempt
        WebCallback->>WebCallback: Store deepLinkUrl in state
        WebCallback->>Tauri: Attempt redirect to native app
        WebCallback->>Timer: Start 5-second timer
    end

    alt Redirect Succeeds
        Tauri->>User: Opens in Maple app (before timer fires)
    else Redirect Fails (timer fires)
        Timer->>WebCallback: Timeout reached
        WebCallback->>WebCallback: Set redirectFailed = true
        rect rgb(255, 220, 200)
            note over WebCallback: New: Fallback UI shown
            WebCallback->>User: Display "Redirect Failed" with manual link
        end
        User->>User: Manually opens deep link
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

  • Focus areas: Timer cleanup logic in error paths to prevent memory leaks; dependency array completeness for useCallback and effects; fallback UI rendering conditions and state management
  • Verify: The 5-second timeout value is intentional; error handling paths clear timers correctly; deep link URL storage and retrieval logic is sound

Possibly related PRs

Poem

🐰 A hop, a skip, when redirects delay,
Now fallback links show the way,
With timers ticking, five seconds wise,
We catch the failures, eyes open wide,
Manual paths when tech won't bend,
A safer journey, friend to friend! 🔗

Pre-merge checks and finishing touches

✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely describes the main change: adding error handling for OAuth desktop redirect failures, which is the primary focus of the changeset.
Linked Issues check ✅ Passed The PR implements all coding requirements from issue #294: detects redirect failures with a 5-second timeout, surfaces errors with a dedicated UI state, and provides manual fallback options (copy link, open app button, back to login).
Out of Scope Changes check ✅ Passed All changes are scoped to the OAuth desktop redirect flow in the auth callback component, directly addressing issue #294 requirements with no unrelated modifications.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch claude/issue-294-20251102-2209

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ec3a9db and 21f034d.

📒 Files selected for processing (1)
  • frontend/src/routes/auth.$provider.callback.tsx (5 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx,js,jsx}: Use 2-space indentation, double quotes, and a 100-character line limit for formatting
Use camelCase for variable and function names
Use try/catch with specific error types for error handling

Files:

  • frontend/src/routes/auth.$provider.callback.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use strict TypeScript typing and avoid any when possible

Files:

  • frontend/src/routes/auth.$provider.callback.tsx
🧠 Learnings (2)
📚 Learning: 2025-07-19T21:31:44.925Z
Learnt from: CR
Repo: OpenSecretCloud/Maple PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-07-19T21:31:44.925Z
Learning: Applies to src/components/**/*.{tsx} : Use React functional components with hooks

Applied to files:

  • frontend/src/routes/auth.$provider.callback.tsx
📚 Learning: 2025-07-19T21:31:44.925Z
Learnt from: CR
Repo: OpenSecretCloud/Maple PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-07-19T21:31:44.925Z
Learning: Applies to src/**/*.{tsx} : Use React context for global state management when needed

Applied to files:

  • frontend/src/routes/auth.$provider.callback.tsx
🧬 Code graph analysis (1)
frontend/src/routes/auth.$provider.callback.tsx (3)
frontend/src/components/ui/card.tsx (4)
  • Card (56-56)
  • CardHeader (56-56)
  • CardTitle (56-56)
  • CardContent (56-56)
frontend/src/components/AlertDestructive.tsx (1)
  • AlertDestructive (5-15)
frontend/src/components/ui/button.tsx (1)
  • Button (62-62)
⏰ 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). (4)
  • GitHub Check: build-linux
  • GitHub Check: build-macos (universal-apple-darwin)
  • GitHub Check: build-android
  • GitHub Check: build-ios

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Greptile Overview

Greptile Summary

Adds timeout-based error detection for OAuth desktop redirect failures. When the deep link redirect fails silently, users now see an error UI after 5 seconds with manual fallback options.

Key changes:

  • Added 5-second timeout to detect when deep link redirect doesn't navigate away from page
  • New error UI displays with manual "Open Maple App" button and copyable deep link
  • Added "Back to Login" recovery option
  • Stores deep link URL in state for manual fallback

Issues found:

  • Critical: Timer cleanup missing - if redirect succeeds, the 5s timer still fires and calls state setters on unmounted component
  • Critical: UI conditional logic bug - localStorage flag is removed before timeout completes, causing UI to switch from Tauri success screen back to web flow prematurely

Confidence Score: 2/5

  • This PR has critical logic bugs that will cause runtime errors and incorrect UI behavior
  • The implementation addresses the core issue but introduces two critical bugs: (1) missing timer cleanup leads to calling state setters on unmounted components, and (2) the localStorage flag is cleared before checking it in the UI conditional, breaking the success screen display
  • frontend/src/routes/auth.$provider.callback.tsx requires fixes for timer cleanup and state management logic

Important Files Changed

File Analysis

Filename Score Overview
frontend/src/routes/auth.$provider.callback.tsx 2/5 Added timeout-based error handling for failed OAuth deep link redirects, but has critical logic bugs with state management and timer cleanup

Sequence Diagram

sequenceDiagram
    participant User
    participant TauriApp as Tauri App
    participant Browser as Web Browser
    participant OAuthProvider
    participant CallbackPage
    
    User->>TauriApp: Start OAuth flow
    TauriApp->>Browser: Open web OAuth
    Browser->>OAuthProvider: Request authentication
    User->>OAuthProvider: Complete login
    OAuthProvider->>CallbackPage: Return with code
    CallbackPage->>CallbackPage: Process callback
    CallbackPage->>CallbackPage: Start 5s timer
    
    alt Redirect succeeds
        CallbackPage->>TauriApp: Deep link redirect
        TauriApp->>TauriApp: Handle redirect
        Note over CallbackPage: Timer still active
    else Redirect fails
        CallbackPage->>CallbackPage: Timer expires
        CallbackPage->>User: Show error UI
        User->>CallbackPage: Manual retry
        CallbackPage->>TauriApp: Retry redirect
    end
Loading

1 file reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

Comment on lines +61 to +64
const redirectTimer = setTimeout(() => {
setRedirectFailed(true);
setIsProcessing(false);
}, 5000);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: The redirectTimer is never cleaned up if the redirect succeeds and the page unloads. If the deep link works, the timer will still fire 5 seconds later (potentially in the background), calling state setters on an unmounted component.

Suggested change
const redirectTimer = setTimeout(() => {
setRedirectFailed(true);
setIsProcessing(false);
}, 5000);
// Set a timeout to detect if the redirect failed
// If the user is still on this page after 5 seconds, show error
const redirectTimer = setTimeout(() => {
if (document.visibilityState === 'visible') {
setRedirectFailed(true);
setIsProcessing(false);
}
}, 5000);
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src/routes/auth.$provider.callback.tsx
Line: 61:64

Comment:
**logic:** The `redirectTimer` is never cleaned up if the redirect succeeds and the page unloads. If the deep link works, the timer will still fire 5 seconds later (potentially in the background), calling state setters on an unmounted component.

```suggestion
      // Set a timeout to detect if the redirect failed
      // If the user is still on this page after 5 seconds, show error
      const redirectTimer = setTimeout(() => {
        if (document.visibilityState === 'visible') {
          setRedirectFailed(true);
          setIsProcessing(false);
        }
      }, 5000);
```

How can I resolve this? If you propose a fix, please make it concise.


// If this is a Tauri app auth flow (desktop or mobile), show a different UI
if (localStorage.getItem("redirect-to-native") === "true") {
if (localStorage.getItem("redirect-to-native") === "true" || redirectFailed) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: This condition checks localStorage on every render. Since localStorage.removeItem("redirect-to-native") is called on line 43, this will be false after the first execution, causing the UI to switch from the Tauri success screen back to the web flow screen before the 5-second timer completes.

Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src/routes/auth.$provider.callback.tsx
Line: 185:185

Comment:
**logic:** This condition checks `localStorage` on every render. Since `localStorage.removeItem("redirect-to-native")` is called on line 43, this will be `false` after the first execution, causing the UI to switch from the Tauri success screen back to the web flow screen before the 5-second timer completes.

How can I resolve this? If you propose a fix, please make it concise.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Handle errors on oauth desktop flow

2 participants