Skip to content

Onboarding reboot#1218

Merged
duckduckhero merged 22 commits intomainfrom
onboarding-reboot
Jul 27, 2025
Merged

Onboarding reboot#1218
duckduckhero merged 22 commits intomainfrom
onboarding-reboot

Conversation

@duckduckhero
Copy link
Contributor

No description provided.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jul 27, 2025

📝 Walkthrough

Walkthrough

This update introduces a comprehensive, multi-step onboarding flow to the desktop application, adding new React components for audio permissions, calendar permissions, language selection, and model download progress. The onboarding sequence and UI are restructured, with new logic for permission handling, model downloads, microphone muting during onboarding, and improved user feedback. Supporting localization, documentation, and styling updates are included.

Changes

File(s) / Group Change Summary
apps/desktop/src/components/editor-area/note-header/listen-button.tsx Added React Query hook to check any STT model existence during onboarding; updated microphone muting logic and start button disabled state and UI feedback for onboarding sessions.
apps/desktop/src/components/settings/components/ai/stt-view.tsx Updated STT model intelligence rating and description strings.
apps/desktop/src/components/welcome-modal/audio-permissions-view.tsx Added AudioPermissionsView React component managing microphone and system audio permission requests with polling and UI feedback.
apps/desktop/src/components/welcome-modal/calendar-permissions-view.tsx Added CalendarPermissionsView React component for macOS calendar and contacts access permissions with polling and request handling.
apps/desktop/src/components/welcome-modal/download-progress-view.tsx Added DownloadProgressView React component to track and display STT and LLM model download progress, errors, and completion with UI updates and server startup.
apps/desktop/src/components/welcome-modal/language-selection-view.tsx Added LanguageSelectionView React component for multi-language selection with searchable popover and badge UI.
apps/desktop/src/components/welcome-modal/model-selection-view.tsx Simplified model selection UI by removing carousel and toast notification logic; replaced with responsive flex layout.
apps/desktop/src/components/welcome-modal/rating-display.tsx Adjusted responsive styling and spacing for rating display icons and labels.
apps/desktop/src/components/welcome-modal/welcome-view.tsx Changed animated text content from "The AI Meeting Notepad" to "Where Conversations Stay Yours".
apps/desktop/src/components/welcome-modal/index.tsx Replaced two-step modal with multi-step onboarding flow; added step state management, handlers for new views, async model/server setup, and conditional rendering.
apps/desktop/src/locales/en/messages.po Added and updated English localization strings for onboarding steps, permissions, language selection, and download progress UI.
apps/desktop/src/locales/ko/messages.po Added and updated Korean localization entries corresponding to new onboarding UI components and messages.
apps/desktop/src/routes/app.tsx Added onboarding completion navigation to a thank-you session page using onboardingSessionId if available.
apps/desktop/src/styles/globals.css Added new CSS keyframe animation fadeInOut for opacity and vertical position transitions.
crates/db-user/assets/onboarding-raw.html Updated onboarding HTML content with new instructions, warnings, and links reflecting onboarding changes.
crates/db-user/assets/thank-you.md Enhanced thank-you markdown with formatting and clarifications about STT and LLM model download completion and feature availability.
plugins/local-llm/assets/onboarding-enhanced.md Expanded onboarding documentation with clearer app introduction, workflow, features, and updated links.
crates/file/src/lib.rs Updated test case URL for S3 hosted model file to new domain.
plugins/local-llm/src/model.rs Updated model download URLs to new domain prefix for LLM models.
plugins/local-stt/src/model.rs Updated model download URLs to new domain prefix for STT models.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant WelcomeModal
    participant ModelSelectionView
    participant DownloadProgressView
    participant AudioPermissionsView
    participant LanguageSelectionView
    participant CalendarPermissionsView
    participant App

    User->>WelcomeModal: Open onboarding modal
    WelcomeModal->>User: Show welcome view
    User->>WelcomeModal: Continue
    WelcomeModal->>ModelSelectionView: Show model selection
    User->>ModelSelectionView: Select model, continue
    WelcomeModal->>DownloadProgressView: Show download progress
    DownloadProgressView->>WelcomeModal: Notify on download complete
    User->>WelcomeModal: Continue
    WelcomeModal->>AudioPermissionsView: Show audio permissions
    AudioPermissionsView->>WelcomeModal: Notify on permissions granted
    User->>WelcomeModal: Continue
    WelcomeModal->>LanguageSelectionView: Show language selection
    User->>LanguageSelectionView: Select languages, continue
    WelcomeModal->>CalendarPermissionsView: Show calendar permissions
    CalendarPermissionsView->>WelcomeModal: Notify on permissions granted or skipped
    User->>WelcomeModal: Finish onboarding
    WelcomeModal->>App: Close modal, start servers, navigate if onboardingSessionId exists
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.


📜 Recent review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ecff736 and 2552bda.

📒 Files selected for processing (10)
  • apps/desktop/src/components/settings/components/ai/stt-view.tsx (2 hunks)
  • apps/desktop/src/components/welcome-modal/audio-permissions-view.tsx (1 hunks)
  • apps/desktop/src/components/welcome-modal/language-selection-view.tsx (1 hunks)
  • apps/desktop/src/locales/en/messages.po (29 hunks)
  • apps/desktop/src/locales/ko/messages.po (29 hunks)
  • crates/db-user/assets/onboarding-raw.html (1 hunks)
  • crates/file/src/lib.rs (1 hunks)
  • plugins/local-llm/assets/onboarding-enhanced.md (1 hunks)
  • plugins/local-llm/src/model.rs (1 hunks)
  • plugins/local-stt/src/model.rs (1 hunks)
✅ Files skipped from review due to trivial changes (4)
  • apps/desktop/src/components/settings/components/ai/stt-view.tsx
  • crates/file/src/lib.rs
  • plugins/local-llm/src/model.rs
  • plugins/local-stt/src/model.rs
🚧 Files skipped from review as they are similar to previous changes (6)
  • apps/desktop/src/locales/ko/messages.po
  • apps/desktop/src/components/welcome-modal/language-selection-view.tsx
  • apps/desktop/src/locales/en/messages.po
  • crates/db-user/assets/onboarding-raw.html
  • apps/desktop/src/components/welcome-modal/audio-permissions-view.tsx
  • plugins/local-llm/assets/onboarding-enhanced.md
⏰ 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). (3)
  • GitHub Check: ci (macos, macos-latest)
  • GitHub Check: ci (windows, windows-latest)
  • GitHub Check: ci
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch onboarding-reboot

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.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

‼️ IMPORTANT
Auto-reply has been disabled for this repository in the CodeRabbit settings. The CodeRabbit bot will not respond to your replies unless it is explicitly tagged.

  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (5)
apps/desktop/src/components/welcome-modal/language-selection-view.tsx (2)

122-126: Remove unreachable code condition.

The condition checking selectedLanguages.length === 0 is unreachable because English is always present and cannot be removed (enforced in handleRemoveLanguage). This creates dead code.

-              {selectedLanguages.length === 0 && (
-                <p className="text-sm text-muted-foreground">
-                  <Trans>Select at least one language</Trans>
-                </p>
-              )}

178-178: Remove redundant disabled condition.

The disabled={selectedLanguages.length === 0} condition is redundant since selectedLanguages will always contain at least English (which cannot be removed).

-        disabled={selectedLanguages.length === 0}
apps/desktop/src/components/welcome-modal/calendar-permissions-view.tsx (2)

86-87: Consider reducing polling frequency for permission status.

Polling every 500ms for permission status may be unnecessarily aggressive and could impact performance. Consider increasing the interval to 1-2 seconds since permission changes are user-initiated actions that don't require sub-second responsiveness.

-    refetchInterval: 500,
+    refetchInterval: 1000,

12-26: Consider adding loading state to PermissionItem interface.

The PermissionItem component could benefit from a loading state to provide visual feedback during permission requests, similar to the pattern used in the AudioPermissionsView component.

 interface PermissionItemProps {
   icon: React.ReactNode;
   title: string;
   description: string;
   done: boolean | undefined;
+  isLoading?: boolean;
   onRequest: () => void;
 }
apps/desktop/src/components/welcome-modal/audio-permissions-view.tsx (1)

101-102: Consider reducing polling frequency for permission status.

Similar to the calendar permissions component, polling every 500ms may be unnecessarily aggressive. Consider increasing to 1-2 seconds for better performance.

     refetchInterval: 500,
+    refetchInterval: 1000,

Apply this change to both permission queries.

Also applies to: 107-108

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0b6a5ef and ecff736.

📒 Files selected for processing (17)
  • apps/desktop/src/components/editor-area/note-header/listen-button.tsx (4 hunks)
  • apps/desktop/src/components/settings/components/ai/stt-view.tsx (1 hunks)
  • apps/desktop/src/components/welcome-modal/audio-permissions-view.tsx (1 hunks)
  • apps/desktop/src/components/welcome-modal/calendar-permissions-view.tsx (1 hunks)
  • apps/desktop/src/components/welcome-modal/download-progress-view.tsx (1 hunks)
  • apps/desktop/src/components/welcome-modal/index.tsx (4 hunks)
  • apps/desktop/src/components/welcome-modal/language-selection-view.tsx (1 hunks)
  • apps/desktop/src/components/welcome-modal/model-selection-view.tsx (6 hunks)
  • apps/desktop/src/components/welcome-modal/rating-display.tsx (1 hunks)
  • apps/desktop/src/components/welcome-modal/welcome-view.tsx (1 hunks)
  • apps/desktop/src/locales/en/messages.po (28 hunks)
  • apps/desktop/src/locales/ko/messages.po (28 hunks)
  • apps/desktop/src/routes/app.tsx (3 hunks)
  • apps/desktop/src/styles/globals.css (1 hunks)
  • crates/db-user/assets/onboarding-raw.html (1 hunks)
  • crates/db-user/assets/thank-you.md (1 hunks)
  • plugins/local-llm/assets/onboarding-enhanced.md (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{js,ts,tsx,rs}

⚙️ CodeRabbit Configuration File

**/*.{js,ts,tsx,rs}: 1. No error handling.
2. No unused imports, variables, or functions.
3. For comments, keep it minimal. It should be about "Why", not "What".

Files:

  • apps/desktop/src/components/welcome-modal/welcome-view.tsx
  • apps/desktop/src/components/settings/components/ai/stt-view.tsx
  • apps/desktop/src/components/welcome-modal/index.tsx
  • apps/desktop/src/routes/app.tsx
  • apps/desktop/src/components/welcome-modal/calendar-permissions-view.tsx
  • apps/desktop/src/components/welcome-modal/rating-display.tsx
  • apps/desktop/src/components/welcome-modal/language-selection-view.tsx
  • apps/desktop/src/components/welcome-modal/audio-permissions-view.tsx
  • apps/desktop/src/components/editor-area/note-header/listen-button.tsx
  • apps/desktop/src/components/welcome-modal/model-selection-view.tsx
  • apps/desktop/src/components/welcome-modal/download-progress-view.tsx
⏰ 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). (3)
  • GitHub Check: ci
  • GitHub Check: ci (macos, macos-latest)
  • GitHub Check: ci (windows, windows-latest)
🔇 Additional comments (33)
apps/desktop/src/styles/globals.css (1)

117-135: LGTM! Clean fade-in-out animation implementation.

The keyframe animation is well-structured with smooth opacity and position transitions. The timing progression (0% → 20% → 80% → 100%) provides good visual feedback for UI elements.

apps/desktop/src/components/welcome-modal/rating-display.tsx (1)

13-17: LGTM! Good responsive design improvements.

The responsive styling updates are well-implemented, providing better mobile experience with smaller fonts, spacing, and icons while maintaining good desktop visuals.

Also applies to: 22-22

apps/desktop/src/components/welcome-modal/language-selection-view.tsx (1)

63-84: LGTM! Well-implemented language selection logic.

The component correctly handles language selection with proper validation, prevents duplicate selections, and enforces English as a required language. The state management and event handlers are implemented correctly.

apps/desktop/src/components/welcome-modal/welcome-view.tsx (1)

28-28: LGTM! Clean branding update.

The text content change aligns with the updated messaging for the onboarding flow.

apps/desktop/src/components/settings/components/ai/stt-view.tsx (1)

94-94: LGTM! Improved model description clarity.

The simplified description is more accurate and removes potentially misleading speed comparisons while focusing on the key characteristics.

crates/db-user/assets/onboarding-raw.html (4)

1-2: LGTM: Clear user guidance during model download phase.

The warning messages effectively communicate the wait time during STT&LLM model downloads and set appropriate expectations for users during the onboarding process.


4-4: LGTM: Concise workflow explanation.

The brief explanation "new meeting -> new note and record" effectively communicates the core workflow in simple terms.


9-9: LGTM: Updated feature list aligns with current capabilities.

The change from "extensions => realtime transcript, CRM integrations" to "chat, templates" better reflects the current feature set mentioned in the broader onboarding enhancements.


17-20: LGTM: Documentation link addition improves user resources.

Adding the official documentation link provides users with better access to comprehensive guidance, complementing the existing Discord community link.

apps/desktop/src/routes/app.tsx (3)

21-21: LGTM: Clean import addition for onboarding integration.

The useHypr hook import is appropriately added to support the onboarding completion flow.


42-42: LGTM: Proper hook usage for accessing onboarding session.

The extraction of onboardingSessionId from useHypr follows React best practices and integrates cleanly with the existing component structure.


94-96: LGTM: Well-structured conditional navigation logic.

The conditional navigation to the thank-you session page is properly implemented with appropriate null checking and follows the expected flow after onboarding completion.

crates/db-user/assets/thank-you.md (3)

1-2: LGTM: Improved formatting enhances readability.

The bold formatting for "STT&LLM models" draws appropriate attention to the key concept, and the line break improves visual structure.


4-5: LGTM: Clear explanation of feature availability timeline.

The detailed explanation about when transcription and summarization features become available, including the visual cue about the recording button turning red, provides excellent user guidance during the model download process.


7-7: LGTM: Updated links provide better user resources.

The replacement of previous links with official documentation and blog links offers users more comprehensive and up-to-date resources, while maintaining the onboarding video reference.

apps/desktop/src/components/welcome-modal/model-selection-view.tsx (3)

27-42: LGTM: Well-implemented responsive design for rating display.

The responsive classes with appropriate breakpoints (sm:) provide good mobile and desktop experiences. The sizing and spacing adjustments are properly implemented.


66-68: LGTM: Simplified and focused continue handler.

The streamlined handleContinue function correctly delegates download progress and notifications to subsequent onboarding steps, maintaining good separation of concerns in the modular onboarding flow.


76-129: LGTM: Improved layout with responsive flexbox design.

The replacement of carousel with flexbox provides better usability and the responsive design handles both mobile and desktop well. The model filtering for specific models ("QuantizedTiny", "QuantizedSmall", "QuantizedLargeTurbo") is appropriate for the onboarding experience.

plugins/local-llm/assets/onboarding-enhanced.md (5)

3-4: LGTM: Clear and focused onboarding objectives.

The updated objectives effectively communicate the key value propositions of enhanced summaries and offline functionality, aligning well with the broader onboarding experience.


6-10: LGTM: Excellent step-by-step workflow guidance.

The new Core Workflow section provides clear, actionable steps that guide users through the essential meeting recording and note enhancement process. This complements the UI-driven onboarding flow well.


13-15: LGTM: Strong privacy messaging with technical details.

The enhanced Privacy and Performance section effectively communicates the offline-first architecture and privacy benefits, providing users with confidence in the platform's data handling approach.


17-20: LGTM: Comprehensive feature overview.

The new Features section clearly presents the key capabilities users will encounter, helping set appropriate expectations for the onboarding experience.


23-24: LGTM: Updated community and documentation links.

The simplified Stay Connected section with official documentation and Discord links provides users with the most relevant resources for ongoing support and learning.

apps/desktop/src/locales/en/messages.po (1)

1-1467: LGTM! Comprehensive localization updates for onboarding flow.

The localization file updates properly support the new multi-step onboarding flow with appropriate translation entries for audio permissions, calendar permissions, language selection, and download progress views. The file follows correct gettext .po format conventions and maintains consistency in translation patterns.

apps/desktop/src/components/welcome-modal/audio-permissions-view.tsx (3)

113-114: Good error handling with mutations.

The mutation error handling using onError: console.error is appropriate for debugging, but consider whether user-facing error messages would improve the user experience for permission request failures.

Also applies to: 118-120


122-122: Excellent continue button logic.

The allPermissionsGranted logic properly ensures both permissions are granted before allowing the user to continue, which provides a good user experience and prevents incomplete onboarding.


16-16: Good inclusion of loading state in permission item.

The isPending prop and its usage in the PermissionItem component provides proper visual feedback during permission requests, which is an improvement over the calendar permissions implementation.

Also applies to: 67-67

apps/desktop/src/components/editor-area/note-header/listen-button.tsx (4)

65-76: Well-implemented STT model availability check.

The anySttModelExists query is properly implemented with appropriate polling interval (3 seconds) and conditional enabling for onboarding sessions. The logic to check any available STT model rather than a specific one makes sense for the onboarding flow.


105-108: Good microphone muting logic for onboarding.

Moving the microphone muting logic to the session start handler is a clean approach that ensures the microphone is muted immediately after starting an onboarding session.


142-144: Proper disabled state logic for onboarding.

The updated disabled state logic correctly uses anySttModelExists for onboarding sessions while maintaining the existing logic for regular sessions. This allows onboarding to proceed when any STT model is available.


222-224: Consistent UI feedback improvements.

The updates to show "Wait..." when disabled and the cursor/opacity changes provide consistent visual feedback across onboarding buttons, improving the user experience during model downloads.

Also applies to: 231-231

apps/desktop/src/locales/ko/messages.po (1)

1-1467: LGTM!

The localization file updates are consistent with the new onboarding flow. Only message IDs and source references were updated, with no changes to actual Korean translations.

apps/desktop/src/components/welcome-modal/download-progress-view.tsx (1)

91-137: Fix channel initialization and cleanup issues

The current implementation has several issues:

  1. Channel instances are created in state initialization but used as dependencies in useEffect, causing unnecessary re-renders
  2. No cleanup for channel message handlers
  3. The channels being dependencies will cause the effect to re-run on every state update
 export const DownloadProgressView = ({
   selectedSttModel,
   onContinue,
 }: DownloadProgressViewProps) => {
-  const [sttDownload, setSttDownload] = useState<ModelDownloadProgress>({
-    channel: new Channel(),
-    progress: 0,
-    error: false,
-    completed: false,
-  });
-
-  const [llmDownload, setLlmDownload] = useState<ModelDownloadProgress>({
-    channel: new Channel(),
-    progress: 0,
-    error: false,
-    completed: false,
-  });
+  const [sttDownload, setSttDownload] = useState<ModelDownloadProgress>(() => ({
+    channel: new Channel(),
+    progress: 0,
+    error: false,
+    completed: false,
+  }));
+
+  const [llmDownload, setLlmDownload] = useState<ModelDownloadProgress>(() => ({
+    channel: new Channel(),
+    progress: 0,
+    error: false,
+    completed: false,
+  }));

   const [currentMessageIndex, setCurrentMessageIndex] = useState(0);

   useEffect(() => {
+    const sttChannel = sttDownload.channel;
+    const llmChannel = llmDownload.channel;
+
     localSttCommands.downloadModel(selectedSttModel, sttChannel);
+    localLlmCommands.downloadModel("HyprLLM", llmChannel);

-    localLlmCommands.downloadModel("HyprLLM", llmDownload.channel);
-
-    sttDownload.channel.onmessage = (progress) => {
+    sttChannel.onmessage = (progress) => {
       if (progress < 0) {
         setSttDownload(prev => ({ ...prev, error: true }));
         return;
       }

       setSttDownload(prev => ({
         ...prev,
         progress: Math.max(prev.progress, progress),
         completed: progress >= 100,
       }));
     };

-    llmDownload.channel.onmessage = (progress) => {
+    llmChannel.onmessage = (progress) => {
       if (progress < 0) {
         setLlmDownload(prev => ({ ...prev, error: true }));
         return;
       }

       setLlmDownload(prev => ({
         ...prev,
         progress: Math.max(prev.progress, progress),
         completed: progress >= 100,
       }));
     };
-  }, [selectedSttModel, sttDownload.channel, llmDownload.channel]);
+
+    return () => {
+      // Clean up message handlers
+      sttChannel.onmessage = null;
+      llmChannel.onmessage = null;
+    };
+  }, [selectedSttModel]);

Likely an incorrect or invalid review comment.

Comment on lines +96 to +106
if (getOsType() === "macos") {
appleCalendarCommands
.requestCalendarAccess()
.then(() => {
calendarAccess.refetch();
})
.catch((error) => {
console.error(error);
});
}
}, [calendarAccess]);
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Optimize OS type check and improve error handling.

The OS type check is performed on every permission request. Consider moving this check outside the callback and providing user feedback for errors instead of only console logging.

+const isOnMacOS = getOsType() === "macos";
+
 const handleRequestCalendarAccess = useCallback(() => {
-  if (getOsType() === "macos") {
+  if (isOnMacOS) {
     appleCalendarCommands
       .requestCalendarAccess()
       .then(() => {
         calendarAccess.refetch();
       })
       .catch((error) => {
-        console.error(error);
+        console.error(error);
+        // Consider showing a toast or user-facing error message
       });
   }
 }, [calendarAccess]);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (getOsType() === "macos") {
appleCalendarCommands
.requestCalendarAccess()
.then(() => {
calendarAccess.refetch();
})
.catch((error) => {
console.error(error);
});
}
}, [calendarAccess]);
const isOnMacOS = getOsType() === "macos";
const handleRequestCalendarAccess = useCallback(() => {
if (isOnMacOS) {
appleCalendarCommands
.requestCalendarAccess()
.then(() => {
calendarAccess.refetch();
})
.catch((error) => {
console.error(error);
// Consider showing a toast or user‐facing error message
});
}
}, [calendarAccess]);
🤖 Prompt for AI Agents
In apps/desktop/src/components/welcome-modal/calendar-permissions-view.tsx
around lines 96 to 106, the OS type check is done inside the permission request
callback causing repeated checks, and errors are only logged to the console
without user feedback. Move the getOsType() check outside the callback to avoid
redundant calls, and replace console.error with a user-facing error notification
or message to inform the user of any issues during calendar access requests.

Comment on lines +108 to +119
const handleRequestContactsAccess = useCallback(() => {
if (getOsType() === "macos") {
appleCalendarCommands
.requestContactsAccess()
.then(() => {
contactsAccess.refetch();
})
.catch((error) => {
console.error(error);
});
}
}, [contactsAccess]);
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Apply the same optimization to contacts access handler.

Similar to the calendar access handler, optimize the OS check and consider improving error handling.

 const handleRequestContactsAccess = useCallback(() => {
-  if (getOsType() === "macos") {
+  if (isOnMacOS) {
     appleCalendarCommands
       .requestContactsAccess()
       .then(() => {
         contactsAccess.refetch();
       })
       .catch((error) => {
-        console.error(error);
+        console.error(error);
+        // Consider showing a toast or user-facing error message
       });
   }
 }, [contactsAccess]);
🤖 Prompt for AI Agents
In apps/desktop/src/components/welcome-modal/calendar-permissions-view.tsx
around lines 108 to 119, optimize the OS check in handleRequestContactsAccess by
moving the getOsType() call outside the callback or caching its result to avoid
repeated calls. Also, improve error handling by replacing console.error with a
more user-friendly notification or logging mechanism consistent with the
calendar access handler. Ensure the refetch logic remains intact after
successful access request.

Comment on lines +134 to +160
useEffect(() => {
if (!isOpen && wentThroughDownloads) {
// start servers for mockup & tutorial
localSttCommands.startServer();
localLlmCommands.startServer();

const checkAndShowToasts = async () => {
try {
const sttModelExists = await localSttCommands.isModelDownloaded(selectedSttModel as SupportedModel);
const llmModelExists = await localLlmCommands.isModelDownloaded("HyprLLM");

if (!sttModelExists) {
showSttModelDownloadToast(selectedSttModel, undefined, queryClient);
}

if (!llmModelExists) {
showLlmModelDownloadToast("HyprLLM", undefined, queryClient);
}
} catch (error) {
console.error("Error checking model download status:", error);
}
};

checkAndShowToasts();
}
}, [isOpen, wentThroughDownloads, selectedSttModel, queryClient]);

Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add error handling and prevent potential race condition

The current implementation starts servers immediately but checks download status asynchronously, which could cause issues. Also missing error handling for server startup.

   useEffect(() => {
     if (!isOpen && wentThroughDownloads) {
-      // start servers for mockup & tutorial
-      localSttCommands.startServer();
-      localLlmCommands.startServer();
-
       const checkAndShowToasts = async () => {
         try {
           const sttModelExists = await localSttCommands.isModelDownloaded(selectedSttModel as SupportedModel);
           const llmModelExists = await localLlmCommands.isModelDownloaded("HyprLLM");

+          // Start servers only if models exist
+          if (sttModelExists) {
+            await localSttCommands.startServer();
+          } else {
+            showSttModelDownloadToast(selectedSttModel, undefined, queryClient);
+          }
+
+          if (llmModelExists) {
+            await localLlmCommands.startServer();
+          } else {
+            showLlmModelDownloadToast("HyprLLM", undefined, queryClient);
+          }
-          if (!sttModelExists) {
-            showSttModelDownloadToast(selectedSttModel, undefined, queryClient);
-          }
-
-          if (!llmModelExists) {
-            showLlmModelDownloadToast("HyprLLM", undefined, queryClient);
-          }
         } catch (error) {
           console.error("Error checking model download status:", error);
+          // Consider showing a user-facing error notification here
         }
       };

       checkAndShowToasts();
     }
   }, [isOpen, wentThroughDownloads, selectedSttModel, queryClient]);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
useEffect(() => {
if (!isOpen && wentThroughDownloads) {
// start servers for mockup & tutorial
localSttCommands.startServer();
localLlmCommands.startServer();
const checkAndShowToasts = async () => {
try {
const sttModelExists = await localSttCommands.isModelDownloaded(selectedSttModel as SupportedModel);
const llmModelExists = await localLlmCommands.isModelDownloaded("HyprLLM");
if (!sttModelExists) {
showSttModelDownloadToast(selectedSttModel, undefined, queryClient);
}
if (!llmModelExists) {
showLlmModelDownloadToast("HyprLLM", undefined, queryClient);
}
} catch (error) {
console.error("Error checking model download status:", error);
}
};
checkAndShowToasts();
}
}, [isOpen, wentThroughDownloads, selectedSttModel, queryClient]);
useEffect(() => {
if (!isOpen && wentThroughDownloads) {
const checkAndShowToasts = async () => {
try {
const sttModelExists = await localSttCommands.isModelDownloaded(
selectedSttModel as SupportedModel
);
const llmModelExists = await localLlmCommands.isModelDownloaded(
"HyprLLM"
);
// Start servers only if models exist
if (sttModelExists) {
await localSttCommands.startServer();
} else {
showSttModelDownloadToast(selectedSttModel, undefined, queryClient);
}
if (llmModelExists) {
await localLlmCommands.startServer();
} else {
showLlmModelDownloadToast("HyprLLM", undefined, queryClient);
}
} catch (error) {
console.error("Error checking model download status:", error);
// Consider showing a user-facing error notification here
}
};
checkAndShowToasts();
}
}, [isOpen, wentThroughDownloads, selectedSttModel, queryClient]);
🤖 Prompt for AI Agents
In apps/desktop/src/components/welcome-modal/index.tsx around lines 134 to 160,
add error handling for the localSttCommands.startServer() and
localLlmCommands.startServer() calls by wrapping them in try-catch blocks. Also,
ensure the asynchronous checkAndShowToasts function is awaited or properly
handled to prevent race conditions by making the useEffect callback async or
restructuring the logic to await server startup before checking model downloads.

@duckduckhero duckduckhero merged commit 9fe0332 into main Jul 27, 2025
8 checks passed
@coderabbitai coderabbitai bot mentioned this pull request Nov 13, 2025
@ComputelessComputer ComputelessComputer deleted the onboarding-reboot branch December 14, 2025 15:21
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.

1 participant