Skip to content

Comments

Set as Default Browser#31

Merged
iamEvanYT merged 19 commits intomainfrom
evan/set-as-default-browser
May 4, 2025
Merged

Set as Default Browser#31
iamEvanYT merged 19 commits intomainfrom
evan/set-as-default-browser

Conversation

@iamEvanYT
Copy link
Member

@iamEvanYT iamEvanYT commented May 2, 2025

Summary by CodeRabbit

  • New Features

    • Added the ability to set the application as the default browser directly from the app menu and settings.
    • Introduced a new settings interface to display and manage default browser status, with real-time status updates and interactive controls.
    • Expanded supported file associations and improved protocol handling for better integration with the operating system.
  • Improvements

    • Enhanced onboarding visuals with smoother, canvas-based animated backgrounds for improved performance and aesthetics.
    • Updated sidebar settings and onboarding text for clarity.
  • Platform Support

    • Improved Windows support for default browser registration without requiring administrator rights.
    • Enhanced macOS and Linux integration for default browser and file associations.
  • Other Changes

    • Updated configuration and documentation for better system compatibility and categorization.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented May 2, 2025

Walkthrough

This update introduces cross-platform support for setting the application as the default browser, including UI, backend, and configuration changes. A new module manages default browser registration logic for Windows, macOS, and Linux, with a Windows-specific batch script and registration function. IPC handlers and preload methods enable communication between the renderer and main process for default browser status and registration. The settings UI now includes a dedicated control and feedback for setting the app as the default browser. The onboarding screen’s animated background is refactored to use a performant canvas-based system. Configuration and documentation are updated to support new protocols and file associations.

Changes

File(s) Change Summary
src/main/browser/utility/menu/items/app.ts Added a checkbox menu item "Set as Default Browser" to the app menu, reflecting and controlling default browser status using new helper functions.
src/main/ipc/app/app.ts, src/preload/index.ts Added IPC handlers and preload methods for setting and querying default browser status, enabling renderer-to-main communication for these actions.
src/main/modules/default-browser.ts New module implementing platform-specific logic for checking and setting the app as the default browser, exporting isDefaultBrowser and setDefaultBrowser functions.
src/main/modules/default-browser-windows.ts, assets/default-app/register_app_user_template.bat New Windows-specific module and batch script template for registering the app as the default browser for the current user, including registry modifications and user prompts.
src/main/modules/basic-settings.ts, src/renderer/src/components/settings/sections/general/basic-settings-cards.tsx, src/renderer/src/components/settings/sections/general/set-as-default-browser-setting.tsx Updated settings structure and UI to include a new "Set as Default Browser" control, with a new React component handling status display, periodic refresh, and user interaction.
src/shared/flow/interfaces/app/app.ts Extended FlowAppAPI interface with asynchronous methods for setting and getting default browser status.
electron-builder.json Updated protocol and file association configuration for installer, including new file extensions and macOS app category.
src/main/modules/paths.ts Added ROOT property to the Paths interface and PATHS constant.
src/renderer/src/components/onboarding/screen.tsx Refactored animated background from multiple motion.divs to a single canvas-based animation system with improved performance and path interpolation.
src/renderer/src/components/onboarding/stages/onboarding-drag-disabler.tsx Removed a full-screen drag-disabling overlay div from the onboarding drag disabler component.
src/renderer/src/components/onboarding/stages/sidebar-collapse-mode.tsx Updated card lookup and UI text from "Sidebar Collapse Mode" to "Sidebar Settings".
build/entitlements.mac.plist Removed document type associations from the macOS entitlements plist.
src/main/index.ts Added URL validation and refactored URL handling logic for opening URLs on startup and second-instance events, improving robustness and reuse.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Renderer
    participant Preload
    participant Main
    participant OS

    User->>Renderer: Click "Set as Default Browser" button
    Renderer->>Preload: flow.app.setDefaultBrowser()
    Preload->>Main: IPC "app:set-default-browser"
    Main->>OS: setDefaultBrowser()
    OS-->>Main: Result (true/false)
    Main-->>Preload: Result
    Preload-->>Renderer: Result
    Renderer-->>User: Update UI (success/failure)
Loading
sequenceDiagram
    participant Renderer
    participant Preload
    participant Main
    participant OS

    Renderer->>Preload: flow.app.getDefaultBrowser()
    Preload->>Main: IPC "app:get-default-browser"
    Main->>OS: isDefaultBrowser()
    OS-->>Main: Status (true/false)
    Main-->>Preload: Status
    Preload-->>Renderer: Status
Loading

Suggested labels

enhancement

Poem

A bunny hops with code anew,
Now Flow can be your browser too!
With menus, scripts, and settings bright,
It claims the web both day and night.
On Windows, Mac, or Linux land,
The rabbit lends a helping hand.
So set as default, let’s begin—
The world wide warren, hop right in! 🐇🌐

✨ Finishing Touches
  • 📝 Generate Docstrings

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:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • 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 generate unit testing code for this file.
    • @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 generate unit testing code.
    • @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 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.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

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.

@iamEvanYT iamEvanYT marked this pull request as ready for review May 2, 2025 16:00
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: 2

🧹 Nitpick comments (2)
src/main/browser/utility/menu/items/app.ts (1)

16-24: Good implementation of the menu checkbox with proper state handling.

The checkbox menu item is well implemented with:

  • Appropriate label "Set as Default Browser"
  • Click handler that calls setDefaultBrowser()
  • Dynamic checked state based on isDefaultBrowser()
  • Disabling the checkbox when the app is already the default browser

Consider adding error handling or user feedback in case setting the default browser fails:

  click: () => {
-   setDefaultBrowser();
+   const success = setDefaultBrowser();
+   if (!success) {
+     // Show notification or log error
+   }
  },
src/renderer/src/components/settings/sections/general/set-as-default-browser-setting.tsx (1)

9-18: Polling interval might be too aggressive.

While the implementation works correctly, polling every 2 seconds (2000ms) could potentially cause unnecessary IPC traffic.

Consider using a slightly longer interval (e.g., 5000ms) to reduce overhead while still providing timely updates:

-   const interval = setInterval(refetchDefaultBrowser, 2000);
+   const interval = setInterval(refetchDefaultBrowser, 5000);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3bcf781 and 41b7662.

📒 Files selected for processing (8)
  • src/main/browser/utility/menu/items/app.ts (2 hunks)
  • src/main/ipc/app/app.ts (2 hunks)
  • src/main/modules/basic-settings.ts (1 hunks)
  • src/main/modules/default-browser.ts (1 hunks)
  • src/preload/index.ts (1 hunks)
  • src/renderer/src/components/settings/sections/general/basic-settings-cards.tsx (2 hunks)
  • src/renderer/src/components/settings/sections/general/set-as-default-browser-setting.tsx (1 hunks)
  • src/shared/flow/interfaces/app/app.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (4)
src/main/browser/utility/menu/items/app.ts (1)
src/main/modules/default-browser.ts (2)
  • setDefaultBrowser (10-15)
  • isDefaultBrowser (3-8)
src/main/ipc/app/app.ts (1)
src/main/modules/default-browser.ts (2)
  • setDefaultBrowser (10-15)
  • isDefaultBrowser (3-8)
src/renderer/src/components/settings/sections/general/set-as-default-browser-setting.tsx (1)
src/main/modules/default-browser.ts (1)
  • setDefaultBrowser (10-15)
src/renderer/src/components/settings/sections/general/basic-settings-cards.tsx (1)
src/renderer/src/components/settings/sections/general/set-as-default-browser-setting.tsx (1)
  • SetAsDefaultBrowserSetting (6-42)
🔇 Additional comments (12)
src/main/modules/basic-settings.ts (1)

131-131: LGTM! Good integration of the default browser setting.

The addition of "internal_setAsDefaultBrowser" to the General Settings card looks good. The "internal_" prefix indicates this is handled by internal UI components rather than being stored as a typical user setting.

src/preload/index.ts (1)

333-338: Good implementation of the default browser API methods.

The setDefaultBrowser and getDefaultBrowser methods follow the established patterns in the file and are correctly implemented as wrappers around IPC calls.

src/main/browser/utility/menu/items/app.ts (1)

3-3: Proper import of the new default browser module.

The import statement correctly brings in the necessary functions from the default-browser module.

src/shared/flow/interfaces/app/app.ts (1)

26-34: Well-documented API interface extensions.

The new methods are properly documented and have appropriate return types. The Promise return type correctly indicates the asynchronous nature of these operations and their success/failure status.

src/renderer/src/components/settings/sections/general/basic-settings-cards.tsx (2)

10-10: Clean import of the new component.

This import correctly brings in the new SetAsDefaultBrowserSetting component that will be used in the BasicSettingsCard component.


64-67: Good handling of the special case for default browser setting.

The conditional check correctly renders the custom component before falling through to the default logic. This approach maintains the existing pattern while adding specific handling for the new setting type.

src/main/ipc/app/app.ts (3)

1-1: Clean import of the default browser module functions.

The import correctly brings in the two functions needed for the IPC handlers.


16-18: IPC handler for setting default browser status.

This handler correctly calls the setDefaultBrowser function and returns its result.


20-22: IPC handler for checking default browser status.

This handler correctly calls the isDefaultBrowser function and returns its result.

src/main/modules/default-browser.ts (1)

1-8: Good implementation of the default browser check.

The isDefaultBrowser function correctly checks if the app is set as the default for both HTTP and HTTPS protocols, which is the appropriate behavior for a web browser.

src/renderer/src/components/settings/sections/general/set-as-default-browser-setting.tsx (2)

6-8: Clean function definition with proper state initialization.

The component correctly initializes isDefault to null which allows for displaying a loading state.


24-41: Well-designed UI with clear state indicators.

The component provides an excellent user experience with different UI states for loading, not default, and default states. The use of relevant icons enhances the visual feedback.

Comment on lines +20 to +22
const setDefaultBrowser = () => {
flow.app.setDefaultBrowser();
};
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

Missing error handling for the API call.

The setDefaultBrowser function doesn't handle potential errors that might occur during the API call.

Consider adding error handling:

  const setDefaultBrowser = () => {
-   flow.app.setDefaultBrowser();
+   flow.app.setDefaultBrowser().catch((error) => {
+     console.error("Failed to set as default browser:", error);
+     // Optionally add user notification here
+   });
  };
📝 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
const setDefaultBrowser = () => {
flow.app.setDefaultBrowser();
};
const setDefaultBrowser = () => {
flow.app.setDefaultBrowser().catch((error) => {
console.error("Failed to set as default browser:", error);
// Optionally add user notification here
});
};

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: 5

♻️ Duplicate comments (1)
src/main/modules/default-browser.ts (1)

16-19: Potential logical inconsistency in return value.

The function returns a Promise that resolves to true if either HTTP or HTTPS protocol was successfully set, but isDefaultBrowser() returns true only if both are set. This could lead to confusing behavior where setDefaultBrowser() returns true but immediately calling isDefaultBrowser() returns false.

Consider changing the return value to ensure consistency:

export function setDefaultBrowser() {
-  app.setAsDefaultProtocolClient("http");
-  app.setAsDefaultProtocolClient("https");
+  const httpSucceed = app.setAsDefaultProtocolClient("http");
+  const httpsSucceed = app.setAsDefaultProtocolClient("https");
+  const bothSucceed = httpSucceed && httpsSucceed;

  return new Promise((resolve) => {

Then use bothSucceed in your platform-specific logic.

🧹 Nitpick comments (2)
assets/default-app/windows.bat (1)

87-88: Consider security implications of self-deletion.

While the self-deletion feature is commented out, implementing it could lead to confusion if users need to run the script again. Additionally, it removes evidence of what changed the system configuration, which could complicate troubleshooting.

Either remove this commented code or add more context about when self-deletion would be appropriate.

src/main/modules/default-browser-windows.ts (1)

10-13: Consider fetching app description from package.json.

The app description is hardcoded in this file. For better maintainability, consider extracting it from your package.json file.

const APP_NAME_SHORT = "flow"; 
const APP_NAME = app.getName(); 
- const APP_DESCRIPTION = "An experimental browser built on Electron."; 
+ // Get description from package.json
+ const APP_DESCRIPTION = require("../../../package.json").description || "An experimental browser built on Electron.";
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d1dd7b6 and f65d76a.

📒 Files selected for processing (6)
  • assets/default-app/windows.bat (1 hunks)
  • electron-builder.json (2 hunks)
  • src/main/ipc/app/app.ts (2 hunks)
  • src/main/modules/default-browser-windows.ts (1 hunks)
  • src/main/modules/default-browser.ts (1 hunks)
  • src/main/modules/paths.ts (2 hunks)
✅ Files skipped from review due to trivial changes (1)
  • src/main/modules/paths.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • electron-builder.json
  • src/main/ipc/app/app.ts
🧰 Additional context used
🧬 Code Graph Analysis (2)
src/main/modules/default-browser.ts (1)
src/main/modules/default-browser-windows.ts (1)
  • registerAppForCurrentUserOnWindows (25-89)
src/main/modules/default-browser-windows.ts (1)
src/main/modules/paths.ts (1)
  • PATHS (18-23)
🪛 Biome (1.9.4)
src/main/modules/default-browser-windows.ts

[error] 31-88: Promise executor functions should not be async.

(lint/suspicious/noAsyncPromiseExecutor)

🔇 Additional comments (9)
assets/default-app/windows.bat (5)

1-7: Well-structured batch script with proper header information.

The script has clear header comments explaining its purpose, attribution, and the fact that it doesn't require administrator privileges.


14-25: Robust input validation and error handling.

The script properly validates all required arguments and checks if the executable exists before proceeding. This prevents potential errors from propagating and provides clear error messages to users.


67-75: Good association capability structure.

The script creates the necessary registry structure but doesn't force specific associations, instead allowing users to choose their preferences via the Windows settings UI. This is a user-friendly approach that respects user choice.


84-86: Appropriate UI integration.

Opening the Default Apps settings page after registration is a good UX choice that helps users complete the process of setting the app as their default browser.


92-106: Excellent usage documentation.

The script includes clear usage instructions, examples, and notes about argument formatting. This makes it easier for developers to use the script correctly.

src/main/modules/default-browser.ts (2)

30-32: Well-structured Windows implementation.

The code properly delegates Windows-specific implementation to a dedicated module, which helps with maintainability and separation of concerns.


33-37: Good platform detection logic.

The code correctly handles platform-specific implementations with clear separation and appropriate fallbacks.

src/main/modules/default-browser-windows.ts (2)

57-66: Well-implemented argument quoting for PowerShell.

The code correctly handles complex quoting rules for PowerShell and the batch script. The comments explaining the quoting strategy are very helpful.


80-86: Good temporary file cleanup.

The code properly cleans up the temporary file after execution, even if there's an error, which is a good practice to prevent accumulation of temporary files.

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: 1

🧹 Nitpick comments (3)
assets/default-app/register_app_user.bat (2)

18-25: Consider enhancing executable validation with additional checks.

The executable existence check is good, but could be enhanced for robustness.

rem Check if executable exists
if not exist "%APP_PATH%" (
    echo ERROR: Executable not found at "%APP_PATH%"
    pause
    goto :eof
)
+rem Ensure the path has .exe extension for an application
+if /i not "%APP_PATH:~-4%" == ".exe" (
+    echo WARNING: The specified path does not end with .exe: "%APP_PATH%"
+    echo This might not be a valid application.
+    pause
+)

84-88: Consider fallback for older Windows versions.

The script tries to open Settings using ms-settings:defaultapps, which works on Windows 10/11, but might fail on older Windows versions.

rem Try opening the modern Default Apps settings page (Win 10/11)
start "" ms-settings:defaultapps

+rem Fallback for older Windows versions if the above fails
+if %ERRORLEVEL% NEQ 0 (
+    echo Falling back to classic Control Panel for Default Programs...
+    control /name Microsoft.DefaultPrograms /page pageDefaultProgram
+)

rem Optional: Self-deletion - remove the 'rem' below if you want the script to delete itself
rem (goto) 2>nul & del "%~f0"
src/main/modules/default-browser.ts (1)

29-32: Document macOS behavior for better maintainability.

On macOS, the function assumes Electron's API shows the default app request dialog, but this should be better documented.

    } else if (process.platform === "darwin") {
-      // Electron API should be enough to show a popup for default app request
+      // On macOS, calling setAsDefaultProtocolClient shows a system dialog
+      // asking the user for permission. We've already called it above.
+      // Reference: https://www.electronjs.org/docs/latest/api/app#appsetasdefaultprotocolclientprotocol-path-args
      resolve(true);
      return;
    }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f65d76a and 0212fcf.

📒 Files selected for processing (2)
  • assets/default-app/register_app_user.bat (1 hunks)
  • src/main/modules/default-browser.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/main/modules/default-browser.ts (1)
src/main/modules/default-browser-windows.ts (1)
  • registerAppForCurrentUserOnWindows (25-89)
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: release (ubuntu-latest)
  • GitHub Check: release (windows-latest)
  • GitHub Check: release (macos-latest)
🔇 Additional comments (3)
assets/default-app/register_app_user.bat (1)

1-107: Well-structured Windows registry script that follows best practices.

This batch script is well-designed for registering the application as a default browser on Windows at the user level (without requiring admin rights). The script:

  • Properly validates input parameters
  • Uses HKCU registry keys (current user only, safer approach)
  • Includes informative comments
  • Has good error handling
  • Opens Windows Default Apps settings for the user to complete the process
src/main/modules/default-browser.ts (2)

5-10: Good implementation of the isDefaultBrowser function.

The function correctly checks if both HTTP and HTTPS protocols are registered to this application, which aligns with browser functionality expectations.


18-18:

Details

❓ Verification inconclusive

Verify the .desktop filename for Linux.

Ensure flow.desktop is the correct filename for your application's desktop entry on Linux systems.


🏁 Script executed:

#!/bin/bash
# Check if we can find any .desktop files related to the application
find . -name "*.desktop" | grep -i flow

# Check the typical installation location for desktop files
echo "Standard locations for .desktop files that might be relevant:"
echo "- ~/.local/share/applications/"
echo "- /usr/share/applications/"

Length of output: 308


Verify and update the Linux .desktop filename

I didn’t find a flow.desktop entry in the repo. Please ensure that:

  • Your build or packaging step installs a flow.desktop file (or whatever your desktop entry is named) to one of these locations:
    ~/.local/share/applications/
    /usr/share/applications/
  • The name you pass to xdg-settings set default-web-browser <name>.desktop exactly matches the installed .desktop filename.
  • If your desktop entry uses a different name (e.g. myapp.desktop), update the command accordingly:
- exec("xdg-settings set default-web-browser flow.desktop", (err) => {
+ exec("xdg-settings set default-web-browser <your-app>.desktop", (err) => {

Comment on lines +12 to +38
export function setDefaultBrowser() {
app.setAsDefaultProtocolClient("http");
app.setAsDefaultProtocolClient("https");

return new Promise((resolve) => {
if (process.platform === "linux" || process.platform.includes("bsd")) {
exec("xdg-settings set default-web-browser flow.desktop", (err) => {
if (err?.message) {
resolve(false);
} else {
resolve(true);
}
});
return;
} else if (process.platform === "win32") {
registerAppForCurrentUserOnWindows().then(resolve);
return;
} else if (process.platform === "darwin") {
// Electron API should be enough to show a popup for default app request
resolve(true);
return;
}

// If we don't know how to set the default browser, return false
resolve(false);
});
}
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

Improve error handling in the setDefaultBrowser function.

The function attempts to set protocol handlers before platform-specific logic runs, which is good. However, error handling could be improved, especially for Linux.

export function setDefaultBrowser() {
  const httpResult = app.setAsDefaultProtocolClient("http");
  const httpsResult = app.setAsDefaultProtocolClient("https");
+ 
+ // Log if initial protocol registration fails
+ if (!httpResult || !httpsResult) {
+   console.warn(`Protocol registration partial success or failure: HTTP=${httpResult}, HTTPS=${httpsResult}`);
+ }

  return new Promise((resolve) => {
    if (process.platform === "linux" || process.platform.includes("bsd")) {
      exec("xdg-settings set default-web-browser flow.desktop", (err) => {
-        if (err?.message) {
+        if (err) {
+          console.error(`Linux/BSD default browser setting failed:`, err.message || err);
          resolve(false);
        } else {
+          console.log("Successfully set as default browser on Linux/BSD");
          resolve(true);
        }
      });
      return;
    } else if (process.platform === "win32") {
+      console.log("Attempting to set as default browser on Windows...");
      registerAppForCurrentUserOnWindows().then(resolve);
      return;
    } else if (process.platform === "darwin") {
      // Electron API should be enough to show a popup for default app request
+      console.log("Default browser request initiated on macOS");
      resolve(true);
      return;
    }

    // If we don't know how to set the default browser, return false
+    console.warn(`Unsupported platform for default browser: ${process.platform}`);
    resolve(false);
  });
}

Committable suggestion skipped: line range outside the PR's diff.

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 (1)
src/renderer/src/components/onboarding/screen.tsx (1)

180-188: Per-shape filter: blur() is a GPU hotspot

Applying ctx.filter = 'blur(...)' inside the inner drawing loop triggers
a state change for every shape, which is one of the slowest canvas
operations – especially noticeable when targetShapeCount creeps towards
maxShapes.

Consider:

  1. Drawing each shape to an off-screen canvas once and blitting it.
  2. Moving the blur to CSS by layering an extra <canvas> with
    filter: blur(...) applied globally.
  3. Dialling down the blur or only applying it to circles, which benefit
    visually the most.
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bcf1a13 and 1c01068.

📒 Files selected for processing (4)
  • src/main/modules/basic-settings.ts (2 hunks)
  • src/renderer/src/components/onboarding/screen.tsx (3 hunks)
  • src/renderer/src/components/onboarding/stages/onboarding-drag-disabler.tsx (0 hunks)
  • src/renderer/src/components/onboarding/stages/sidebar-collapse-mode.tsx (2 hunks)
💤 Files with no reviewable changes (1)
  • src/renderer/src/components/onboarding/stages/onboarding-drag-disabler.tsx
✅ Files skipped from review due to trivial changes (1)
  • src/renderer/src/components/onboarding/stages/sidebar-collapse-mode.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/modules/basic-settings.ts
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: release (ubuntu-latest)
  • GitHub Check: release (windows-latest)
🔇 Additional comments (1)
src/renderer/src/components/onboarding/screen.tsx (1)

427-430: Total duration mis-calculates when speed is “per segment”

totalDuration = path.x.length * speed * 1000 counts the points, not
the segments. For an n-point path there are n − 1 segments, so the
animation finishes speed seconds early.

-const totalDuration = path.x.length * speed * 1000;
+const totalDuration = (path.x.length - 1) * speed * 1000;

If the current timing matches your visual spec, add a clarifying comment
so future maintainers know it’s deliberate.

Comment on lines +1 to +2
import React, { useEffect, useState, useRef, useCallback } from "react";
import { motion } from "motion/react"; // Used for backdrop blur and gradient orbs
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

Incorrect package import – likely to break at runtime

"motion/react" is not a published entry-point in either Motion One or Framer-Motion.
• Motion One’s React bindings are published as @motionone/react
• Framer-Motion is imported as framer-motion

Unless you have a patched fork published under that name, this will throw Cannot find module 'motion/react' in production.

-import { motion } from "motion/react";
+// If you use Motion One:
+import { motion } from "@motionone/react";
+// …or if you meant Framer Motion:
+// import { motion } from "framer-motion";
📝 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
import React, { useEffect, useState, useRef, useCallback } from "react";
import { motion } from "motion/react"; // Used for backdrop blur and gradient orbs
import React, { useEffect, useState, useRef, useCallback } from "react";
// If you use Motion One:
import { motion } from "@motionone/react";
// …or if you meant Framer Motion:
// import { motion } from "framer-motion";

Comment on lines +110 to +123
canvas.width = windowSize.width * dpr;
canvas.height = windowSize.height * dpr;

// Set display size of canvas
canvas.style.width = `${windowSize.width}px`;
canvas.style.height = `${windowSize.height}px`;

const ctx = canvas.getContext("2d");
if (!ctx) return;

// Scale the drawing context to handle HiDPI displays correctly
// All drawing operations below will be scaled automatically
ctx.scale(dpr, dpr);

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

Progressive over-scaling on Hi-DPI resize

ctx.scale(dpr, dpr) is executed every time the window resizes, but the
canvas transform is multiplicative.
Scaling twice on a 2× DPR screen → 4×, three times → 8×, etc., quickly pushing everything off-screen.

Reset the transform before re-scaling:

-const ctx = canvas.getContext("2d");
-if (ctx) {
-  ctx.scale(dpr, dpr);
-}
+const ctx = canvas.getContext("2d");
+if (ctx) {
+  ctx.setTransform(1, 0, 0, 1, 0, 0); // reset
+  ctx.scale(dpr, dpr);
+}

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +245 to 251
if (animationFrameId.current) {
cancelAnimationFrame(animationFrameId.current);
}
};
// Re-run the effect if the shapes array, window size, or canvas ref instance changes
}, [shapes, windowSize, canvasRef]);
};
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

Effect restarts every shape tick – unnecessary re-initialisation

useEffect depends on shapes; each time the shape array mutates (every
2 s, plus initial burst) the effect tears down and recreates the entire
animation loop, causing:

• superfluous cancelAnimationFrame / requestAnimationFrame churn
• potential one-frame flicker on low-end devices

Store shapes in a ref instead, and keep the draw loop stable:

-const useCanvasShapes = (canvasRef, shapes, windowSize) => {
+const useCanvasShapes = (canvasRef, shapes, windowSize) => {
   const shapesRef = useRef<ShapeData[]>([]);
   shapesRef.current = shapes;        // update ref on every render
@@
-}, [shapes, windowSize, canvasRef]);
+}, [windowSize, canvasRef]);          // remove `shapes` from deps

Committable suggestion skipped: line range outside the PR's diff.

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: 2

♻️ Duplicate comments (2)
src/main/modules/default-browser-windows.ts (2)

17-17: ⚠️ Potential issue

File path mismatch for batch script.

The code is looking for register_app_user.bat but according to a previous review comment, the actual file is named windows.bat. This path mismatch will cause the registration process to fail.

- const scriptPath = path.join(PATHS.ASSETS, "default-app", "register_app_user.bat");
+ const scriptPath = path.join(PATHS.ASSETS, "default-app", "windows.bat");

30-31: ⚠️ Potential issue

Avoid using async Promise executor.

Using an async function as a Promise executor is problematic because errors thrown from the async function can't be caught by the Promise's catch handler. This pattern is discouraged and flagged by static analysis tools.

- // eslint-disable-next-line no-async-promise-executor
- return new Promise(async (resolve) => {
+ return new Promise((resolve) => {
+   (async () => {
      let scriptContents: Buffer | string;
      try {
        // Implementation...
+   })().catch(err => {
+     console.error("Unexpected error in registerAppForCurrentUserOnWindows:", err);
+     resolve(false);
+   });
🧹 Nitpick comments (1)
src/main/modules/default-browser-windows.ts (1)

76-77: Add timeout handling for the script execution.

Currently, there's no timeout for the script execution, which could potentially hang indefinitely. Consider adding a timeout mechanism to ensure the operation completes within a reasonable timeframe.

exec(command, async (err) => {
  if (err) {
    // Log the specific error from the exec call
    console.error("Error executing registration script:", err.message);
    resolve(false);
  } else {
    console.log(`Registration script executed successfully for "${APP_NAME}". Check Default Apps settings.`);
+   // Consider observing if the default browser setting has actually changed
    resolve(true);
  }

You could also implement a timeout with something like:

const execWithTimeout = (command: string, timeoutMs = 30000): Promise<boolean> => {
  return new Promise((resolve) => {
    const process = exec(command);
    
    const timeoutId = setTimeout(() => {
      if (process.pid) {
        // Kill the process if it's still running
        exec(`taskkill /pid ${process.pid} /f /t`);
      }
      console.error("Registration script execution timed out");
      resolve(false);
    }, timeoutMs);
    
    process.on('exit', (code) => {
      clearTimeout(timeoutId);
      resolve(code === 0);
    });
    
    process.on('error', (err) => {
      clearTimeout(timeoutId);
      console.error("Error executing registration script:", err.message);
      resolve(false);
    });
  });
};
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1c01068 and 3ada5fe.

📒 Files selected for processing (2)
  • build/entitlements.mac.plist (0 hunks)
  • src/main/modules/default-browser-windows.ts (1 hunks)
💤 Files with no reviewable changes (1)
  • build/entitlements.mac.plist
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/main/modules/default-browser-windows.ts (1)
src/main/modules/paths.ts (1)
  • PATHS (18-23)
🪛 Biome (1.9.4)
src/main/modules/default-browser-windows.ts

[error] 31-88: Promise executor functions should not be async.

(lint/suspicious/noAsyncPromiseExecutor)

Comment on lines 57 to 60
const arg1 = `"""${appExecutablePath}"""`; // Path to exe
const arg2 = `"${APP_NAME_SHORT}"`; // Short name (quotes optional if no spaces)
const arg3 = `"""${APP_NAME}"""`; // Full name
const arg4 = `"""${APP_DESCRIPTION}"""`; // Description
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

Consider input validation for strings that will be used in command execution.

The application name, description, and paths are directly incorporated into a command string. Though you've added quotes to handle spaces, it's good practice to validate or sanitize these inputs to prevent potential command injection issues.

+ // Sanitize inputs to prevent command injection
+ const sanitizeForCommand = (input: string): string => {
+   // Remove characters that could break command execution
+   return input.replace(/[&<>^|()%]/g, '');
+ };
+
- const arg1 = `"""${appExecutablePath}"""`;
- const arg2 = `"${APP_NAME_SHORT}"`;
- const arg3 = `"""${APP_NAME}"""`;
- const arg4 = `"""${APP_DESCRIPTION}"""`;
+ const arg1 = `"""${sanitizeForCommand(appExecutablePath)}"""`;
+ const arg2 = `"${sanitizeForCommand(APP_NAME_SHORT)}"`;
+ const arg3 = `"""${sanitizeForCommand(APP_NAME)}"""`;
+ const arg4 = `"""${sanitizeForCommand(APP_DESCRIPTION)}"""`;
📝 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
const arg1 = `"""${appExecutablePath}"""`; // Path to exe
const arg2 = `"${APP_NAME_SHORT}"`; // Short name (quotes optional if no spaces)
const arg3 = `"""${APP_NAME}"""`; // Full name
const arg4 = `"""${APP_DESCRIPTION}"""`; // Description
// Sanitize inputs to prevent command injection
const sanitizeForCommand = (input: string): string => {
// Remove characters that could break command execution
return input.replace(/[&<>^|()%]/g, '');
};
const arg1 = `"""${sanitizeForCommand(appExecutablePath)}"""`; // Path to exe
const arg2 = `"${sanitizeForCommand(APP_NAME_SHORT)}"`; // Short name (quotes optional if no spaces)
const arg3 = `"""${sanitizeForCommand(APP_NAME)}"""`; // Full name
const arg4 = `"""${sanitizeForCommand(APP_DESCRIPTION)}"""`; // Description

@iamEvanYT iamEvanYT marked this pull request as draft May 4, 2025 12:50
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

♻️ Duplicate comments (2)
src/main/modules/default-browser-windows.ts (2)

53-54: ⚠️ Potential issue

Avoid using async Promise executor.

Using an async function as a Promise executor is problematic because errors thrown from the async function can't be caught by the Promise's catch handler. This was previously flagged in a review.

- // eslint-disable-next-line no-async-promise-executor
- return new Promise(async (resolve) => {
+ return new Promise((resolve) => {
+   (async () => {
      let scriptTemplate: string;
      try {
        // Implementation...
+   })().catch(err => {
+     console.error("Unexpected error in registerAppForCurrentUserOnWindows:", err);
+     resolve(false);
+   });

113-117: ⚠️ Potential issue

Input validation needed for command execution.

The application name, description, and paths are directly incorporated into a command string without validation or sanitization. This could lead to command injection issues if any of these values contain special characters.

+ // Sanitize inputs to prevent command injection
+ const sanitizeForCommand = (input: string): string => {
+   // Remove characters that could break command execution
+   return input.replace(/[&<>^|()%]/g, '');
+ };
+
- const arg1 = `"""${appExecutablePath}"""`;
- const arg2 = `"${APP_NAME_SHORT}"`;
- const arg3 = `"""${APP_NAME}"""`;
- const arg4 = `"""${APP_DESCRIPTION}"""`;
+ const arg1 = `"""${sanitizeForCommand(appExecutablePath)}"""`;
+ const arg2 = `"${sanitizeForCommand(APP_NAME_SHORT)}"`;
+ const arg3 = `"""${sanitizeForCommand(APP_NAME)}"""`;
+ const arg4 = `"""${sanitizeForCommand(APP_DESCRIPTION)}"""`;
🧹 Nitpick comments (4)
src/main/modules/default-browser-windows.ts (2)

119-120: Consider removing PowerShell window after execution.

The current command doesn't hide the PowerShell window. Adding the -WindowStyle Hidden parameter would make the registration process more seamless for users.

- const command = `Powershell -NoProfile -ExecutionPolicy Bypass -Command "Start-Process -FilePath '${tempFile}' -ArgumentList ${arg1}, ${arg2}, ${arg3}, ${arg4}"`;
+ const command = `Powershell -NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -Command "Start-Process -FilePath '${tempFile}' -ArgumentList ${arg1}, ${arg2}, ${arg3}, ${arg4}"`;

145-154: Remove commented example code in production.

The commented example code at the end of the file should be removed before production deployment as it serves no functional purpose and may confuse future developers.

- // --- Example Usage ---
- /*
- registerAppForCurrentUser().then(success => {
-   if (success) {
-     console.log("Application registration process completed successfully.");
-   } else {
-     console.error("Application registration process failed.");
-   }
- });
- */
assets/default-app/register_app_user_template.bat (2)

84-85: Consider fallback for older Windows versions.

The script only attempts to open the modern Settings app with ms-settings:defaultapps, which may not work on older Windows versions (pre-Windows 10). Consider adding a fallback for compatibility.

rem Try opening the modern Default Apps settings page (Win 10/11)
start "" ms-settings:defaultapps

+ rem Fallback for older Windows versions (Win 7/8)
+ if %ERRORLEVEL% neq 0 (
+     start control /name Microsoft.DefaultPrograms /page pageDefaultProgram
+ )

87-88: Self-deletion mechanism may be unnecessary.

Since the script is being called from Node.js which already handles the temporary file deletion (in the TypeScript code), this self-deletion mechanism is redundant and can be removed.

- rem Optional: Self-deletion - remove the 'rem' below if you want the script to delete itself
- rem (goto) 2>nul & del "%~f0"
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3ada5fe and a0705fa.

📒 Files selected for processing (2)
  • assets/default-app/register_app_user_template.bat (1 hunks)
  • src/main/modules/default-browser-windows.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/main/modules/default-browser-windows.ts (1)
src/main/modules/paths.ts (1)
  • PATHS (18-23)
🪛 Biome (1.9.4)
src/main/modules/default-browser-windows.ts

[error] 54-142: Promise executor functions should not be async.

(lint/suspicious/noAsyncPromiseExecutor)

⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: release (macos-latest)
  • GitHub Check: release (windows-latest)
  • GitHub Check: release (ubuntu-latest)
🔇 Additional comments (4)
assets/default-app/register_app_user_template.bat (4)

1-8: LGTM: Well-structured batch script with clear documentation.

The script header provides clear documentation about its purpose, requirements, and attribution. It properly sets up the environment with setlocal enabledelayedexpansion which is a good practice for batch scripts.


15-26: Robust input validation with clear error messaging.

The script properly validates all required arguments and checks if the executable exists before proceeding. The error messages are clear and helpful.


41-52: Well-organized registry modifications for file and URL associations.

The registry entries are properly organized and include all necessary keys for file type and URL protocol handlers. The use of >nul to suppress output is appropriate for a cleaner user experience.


73-78: Good use of placeholders for dynamic associations.

The script uses clear placeholder markers that can be easily identified and replaced by the calling script. The comments make it clear what each placeholder is for.

@iamEvanYT iamEvanYT marked this pull request as ready for review May 4, 2025 19:08
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: 2

♻️ Duplicate comments (3)
src/main/modules/default-browser-windows.ts (3)

124-134: Improve error handling in exec callback.

The current error handling in the exec callback only logs the error message. Providing more detailed error information would aid in troubleshooting.

- exec(command, async (err, stdout) => {
+ exec(command, async (err, stdout, stderr) => {
  if (err) {
-   console.error("Error executing registration script:", err.message);
+   console.error("Error executing registration script:", {
+     message: err.message,
+     code: err.code,
+     stderr: stderr.trim()
+   });
    resolve(false);
  } else {
    console.log(`Registration script executed successfully for "${APP_NAME}". Check Default Apps settings.`);
    console.log("Output:", stdout);
    resolve(true);
  }

53-54: ⚠️ Potential issue

Fix the async Promise executor pattern.

Using an async function as a Promise executor is problematic because errors thrown from the async function can't be caught by the Promise's catch handler.

Apply this fix:

- // eslint-disable-next-line no-async-promise-executor
- return new Promise(async (resolve) => {
+ return new Promise((resolve) => {
+   (async () => {
      let scriptTemplate: string;
      try {
        // ...implementation...
+   })().catch(err => {
+     console.error("Unexpected error in registerAppForCurrentUserOnWindows:", err);
+     resolve(false);
+   });

113-118: ⚠️ Potential issue

Add input validation for command execution.

The application name, description, and paths are directly incorporated into a command string without validation. This could potentially lead to command injection issues if these values contain special characters.

Add a sanitization function:

+ // Sanitize inputs to prevent command injection
+ const sanitizeForCommand = (input: string): string => {
+   // Remove characters that could break command execution
+   return input.replace(/[&<>^|()%]/g, '');
+ };
+
- const arg1 = `"""${appExecutablePath}"""`;
- const arg2 = `"${APP_NAME_SHORT}"`;
- const arg3 = `"""${APP_NAME}"""`;
- const arg4 = `"""${APP_DESCRIPTION}"""`;
+ const arg1 = `"""${sanitizeForCommand(appExecutablePath)}"""`;
+ const arg2 = `"${sanitizeForCommand(APP_NAME_SHORT)}"`;
+ const arg3 = `"""${sanitizeForCommand(APP_NAME)}"""`;
+ const arg4 = `"""${sanitizeForCommand(APP_DESCRIPTION)}"""`;
🧹 Nitpick comments (2)
src/main/index.ts (2)

152-153: Fix typo in comment.

There's a typo in the comment "Hnadle" instead of "Handle".

- // Hnadle command line arguments
+ // Handle command line arguments

94-130: Consider adding a timeout parameter to the handleOpenUrl function.

The current implementation tries to find a window 5 times with a fixed 50ms delay. This approach might not be flexible enough for different system conditions.

Consider refactoring the retry logic to be more configurable:

- const handleOpenUrl = async (url: string) => {
+ const handleOpenUrl = async (url: string, maxRetries = 5, retryDelay = 50) => {
  if (!browser) return;

  if (!app.isReady) {
    await app.whenReady();
  }

  let window: TabbedBrowserWindow | null = null;

- for (let i = 0; i < 5; i++) {
+ for (let i = 0; i < maxRetries; i++) {
    // Check if there is a focused window
    const focusedWindow = browser.getFocusedWindow();
    if (focusedWindow) {
      window = focusedWindow;
      break;
    }

    // Check for any window
    const firstWindow = browser.getWindows()[0];
    if (firstWindow) {
      window = firstWindow;
      break;
    }

-   await sleep(50);
+   await sleep(retryDelay);
  }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a0705fa and 98c0025.

📒 Files selected for processing (3)
  • electron-builder.json (3 hunks)
  • src/main/index.ts (3 hunks)
  • src/main/modules/default-browser-windows.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • electron-builder.json
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/main/modules/default-browser-windows.ts (1)
src/main/modules/paths.ts (1)
  • PATHS (18-23)
🪛 Biome (1.9.4)
src/main/modules/default-browser-windows.ts

[error] 54-143: Promise executor functions should not be async.

(lint/suspicious/noAsyncPromiseExecutor)

🔇 Additional comments (1)
src/main/modules/default-browser-windows.ts (1)

79-91: 🛠️ Refactor suggestion

Use URL constructor instead of deprecated URL.parse.

The URL.parse() method is deprecated. Use the URL constructor instead for better reliability and standards compliance.

function isValidOpenerUrl(url: string): boolean {
  // Check if the URL is a valid URL
- const urlObject = URL.parse(url);
- if (!urlObject) {
-   return false;
- }
+ try {
+   const urlObject = new URL(url);
+   const VALID_PROTOCOLS = ["http:", "https:"];
+   // Check if the URL has a valid protocol
+   return VALID_PROTOCOLS.includes(urlObject.protocol);
+ } catch (e) {
+   return false;
+ }
-
- const VALID_PROTOCOLS = ["http:", "https:"];
- // Check if the URL has a valid protocol
- if (!VALID_PROTOCOLS.includes(urlObject.protocol)) {
-   return false;
- }
-
- return true;
}

Likely an incorrect or invalid review comment.

Comment on lines 173 to 177
const url = commandLine.pop();
if (url) {
if (url && isValidOpenerUrl(url)) {
// Handle the URL if it is valid
handleOpenUrl(url);
}
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

Improve second-instance URL handling consistency.

Similar to the issue above, the second-instance handler pops the last argument which might not always be the URL.

- const url = commandLine.pop();
- if (url && isValidOpenerUrl(url)) {
-   // Handle the URL if it is valid
-   handleOpenUrl(url);
- }
+ // Look for a URL in the command line arguments
+ for (const arg of commandLine) {
+   if (isValidOpenerUrl(arg)) {
+     // Handle the URL if it is valid
+     handleOpenUrl(arg);
+     break; // Handle only the first valid URL
+   }
+ }
📝 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
const url = commandLine.pop();
if (url) {
if (url && isValidOpenerUrl(url)) {
// Handle the URL if it is valid
handleOpenUrl(url);
}
// Look for a URL in the command line arguments
for (const arg of commandLine) {
if (isValidOpenerUrl(arg)) {
// Handle the URL if it is valid
handleOpenUrl(arg);
break; // Handle only the first valid URL
}
}

Comment on lines +154 to +158
const targetUrl = commandLine.pop();
if (targetUrl && isValidOpenerUrl(targetUrl)) {
// Handle the URL if it is valid
handleOpenUrl(targetUrl);
}
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

Improve command line URL handling.

The current implementation pops the last argument and checks if it's a URL, which might not be reliable. Command-line arguments don't always have the URL as the last item.

- const commandLine = process.argv.slice(1);
- const targetUrl = commandLine.pop();
- if (targetUrl && isValidOpenerUrl(targetUrl)) {
-   // Handle the URL if it is valid
-   handleOpenUrl(targetUrl);
- }
+ const commandLine = process.argv.slice(1);
+ // Look for a URL in the command line arguments
+ for (const arg of commandLine) {
+   if (isValidOpenerUrl(arg)) {
+     // Handle the URL if it is valid
+     handleOpenUrl(arg);
+     break; // Handle only the first valid URL
+   }
+ }
📝 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
const targetUrl = commandLine.pop();
if (targetUrl && isValidOpenerUrl(targetUrl)) {
// Handle the URL if it is valid
handleOpenUrl(targetUrl);
}
const commandLine = process.argv.slice(1);
// Look for a URL in the command line arguments
for (const arg of commandLine) {
if (isValidOpenerUrl(arg)) {
// Handle the URL if it is valid
handleOpenUrl(arg);
break; // Handle only the first valid URL
}
}

@iamEvanYT iamEvanYT merged commit 75f226e into main May 4, 2025
4 checks passed
@iamEvanYT iamEvanYT deleted the evan/set-as-default-browser branch May 4, 2025 19:14
@coderabbitai coderabbitai bot mentioned this pull request May 13, 2025
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