Skip to content

Comments

Add Custom Window Controls for Linux and Windows#68

Merged
iamEvanYT merged 9 commits intomainfrom
evan/custom-window-controls
May 25, 2025
Merged

Add Custom Window Controls for Linux and Windows#68
iamEvanYT merged 9 commits intomainfrom
evan/custom-window-controls

Conversation

@iamEvanYT
Copy link
Member

@iamEvanYT iamEvanYT commented May 25, 2025

Summary by CodeRabbit

  • New Features

    • Introduced interactive window control buttons (minimize, maximize/restore, close) for Windows and Linux platforms, with dynamic state and visual feedback.
    • Added support for querying and reacting to window state changes (maximized/fullscreen) throughout the app.
    • Enabled event-driven updates for window state, allowing UI components to respond to changes in real time.
  • Style

    • Updated layout by removing extra top padding on Windows for improved appearance.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented May 25, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

This update introduces comprehensive window control functionality across the application. It adds IPC handlers, interface methods, and UI components to support minimizing, maximizing, closing, and querying the window state. The Sidebar UI now features interactive window control buttons for Windows and Linux, and window state changes are propagated throughout the app.

Changes

File(s) Change Summary
src/main/browser/window.ts Adjusted titleBarStyle for macOS, added event handlers to fire window state changes on maximize/fullscreen events.
src/main/ipc/browser/interface.ts Added IPC handlers and exported fireWindowStateChanged for window controls and state broadcasting.
src/preload/index.ts Exposed window control methods and window state listener via interfaceAPI.
src/renderer/src/components/browser-ui/main.tsx Removed Windows-specific top padding class from main container.
src/renderer/src/components/browser-ui/sidebar/header/window-controls.tsx Enhanced SidebarWindowControls with state, event listeners, and interactive window control buttons.
src/shared/flow/interfaces/browser/interface.ts Extended FlowInterfaceAPI with window control methods and a window state event listener.
src/shared/flow/types.ts Added new exported type alias WindowState with isMaximized and isFullscreen.

Sequence Diagram(s)

sequenceDiagram
    participant Renderer
    participant Preload
    participant MainProcess
    participant BrowserWindow

    Renderer->>Preload: flow.interface.minimizeWindow()
    Preload->>MainProcess: IPC minimizeWindow
    MainProcess->>BrowserWindow: minimize()
    MainProcess->>MainProcess: fireWindowStateChanged()
    MainProcess->>Renderer: Send window state changed event

    Renderer->>Preload: flow.interface.maximizeWindow()
    Preload->>MainProcess: IPC maximizeWindow
    MainProcess->>BrowserWindow: maximize()/unmaximize()
    MainProcess->>MainProcess: fireWindowStateChanged()
    MainProcess->>Renderer: Send window state changed event

    Renderer->>Preload: flow.interface.getWindowState()
    Preload->>MainProcess: IPC getWindowState
    MainProcess->>BrowserWindow: get state
    MainProcess->>Preload: Return state
    Preload->>Renderer: Return state

    Renderer->>Preload: flow.interface.onWindowStateChanged(callback)
    MainProcess-->>Renderer: Emit window state changed events on state changes
Loading

Possibly related PRs

Suggested labels

enhancement

Poem

A window hops, it opens wide,
With buttons now on every side.
Minimize, maximize, close with glee,
State updates sent so instantly!
Sidebar smiles with every click,
The rabbit’s code is clean and slick—
Window control, a magic trick! 🪟✨


📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between d826544 and 0b9b626.

📒 Files selected for processing (1)
  • src/renderer/src/components/browser-ui/sidebar/header/window-controls.tsx (2 hunks)
✨ 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.
    • Explain this complex logic.
    • 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 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 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.

@github-actions
Copy link
Contributor

github-actions bot commented May 25, 2025

Build artifacts for all platforms are ready! 🚀

Download the artifacts from:

(execution 15240415784 / attempt 1)

@iamEvanYT iamEvanYT marked this pull request as ready for review May 25, 2025 17:28
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 (1)
src/main/ipc/browser/interface.ts (1)

67-90: Well-implemented window control handlers with good safety checks.

The IPC handlers properly check for window existence before performing operations and implement intuitive toggle behavior for the maximize function. The implementation follows the existing code patterns in the file.

Consider adding try-catch blocks around the window operations to handle potential exceptions:

 ipcMain.on("interface:minimize-window", (event) => {
   const win = browser?.getWindowFromWebContents(event.sender);
   if (win) {
+    try {
       win.window.minimize();
+    } catch (error) {
+      console.error("Failed to minimize window:", error);
+    }
   }
 });
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between e6fb4f2 and d826544.

📒 Files selected for processing (7)
  • src/main/browser/window.ts (3 hunks)
  • src/main/ipc/browser/interface.ts (2 hunks)
  • src/preload/index.ts (2 hunks)
  • src/renderer/src/components/browser-ui/main.tsx (1 hunks)
  • src/renderer/src/components/browser-ui/sidebar/header/window-controls.tsx (2 hunks)
  • src/shared/flow/interfaces/browser/interface.ts (2 hunks)
  • src/shared/flow/types.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (5)
src/main/ipc/browser/interface.ts (2)
src/main/index.ts (1)
  • browser (14-14)
src/main/browser/window.ts (1)
  • TabbedBrowserWindow (30-284)
src/main/browser/window.ts (1)
src/main/ipc/browser/interface.ts (1)
  • fireWindowStateChanged (107-109)
src/shared/flow/interfaces/browser/interface.ts (1)
src/shared/flow/types.ts (2)
  • WindowState (8-11)
  • IPCListener (13-13)
src/renderer/src/components/browser-ui/sidebar/header/window-controls.tsx (1)
src/renderer/src/lib/utils.ts (1)
  • cn (5-7)
src/preload/index.ts (1)
src/shared/flow/types.ts (1)
  • WindowState (8-11)
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: build (windows-latest)
  • GitHub Check: build (ubuntu-24.04-arm)
  • GitHub Check: build (ubuntu-latest)
🔇 Additional comments (16)
src/shared/flow/types.ts (1)

8-11: Clean and well-defined type structure.

The WindowState type provides a clear contract for window state communication across the application. The boolean properties are appropriately named and typed.

src/renderer/src/components/browser-ui/main.tsx (1)

89-89:

Details

❓ Verification inconclusive

Appropriate removal of Windows titlebar padding.

Removing the Windows-specific titlebar padding aligns with the custom window controls implementation. Since custom controls are being added, the native titlebar spacing is no longer needed.

Please verify that the layout remains correct on Windows after this change, especially ensuring that:

  1. Content doesn't overlap with the custom window controls
  2. The drag area functions properly
  3. No visual gaps or spacing issues occur

🏁 Script executed:

#!/bin/bash
# Description: Check for other references to titlebar area calculations that might need updating

# Search for other uses of titlebar area environment variables
rg -A 3 -B 3 "titlebar-area|env\(titlebar"

Length of output: 1436


Approve removal of Windows titlebar padding in main UI

The Windows-specific
pt-[calc(env(titlebar-area-y)+env(titlebar-area-height))] padding was intentionally removed from
src/renderer/src/components/browser-ui/main.tsx to support the new custom window controls. A project-wide search found no other references to those titlebar environment variables in the main UI (only the onboarding drag-disabler still uses it by design).

Please manually verify on Windows that:

  • Main window content and custom controls remain correctly spaced
  • The drag region still functions as expected
  • No unintended gaps or overlaps appear in both the main UI and the onboarding flow
src/main/browser/window.ts (2)

14-14: Good platform-specific titlebar configuration.

The conditional titleBarStyle setting is appropriate - hiding the titlebar on macOS while keeping it undefined (default) on other platforms aligns with the PR objective of adding custom controls for Linux and Windows specifically.

Also applies to: 54-54


93-93: Comprehensive window state change broadcasting.

The fireWindowStateChanged calls are properly placed after state changes occur and cover all relevant window state transitions (fullscreen enter/exit, maximize/unmaximize). This ensures consistent state synchronization across the application.

Also applies to: 99-99, 103-106

src/main/ipc/browser/interface.ts (3)

3-3: Necessary import for window state broadcasting.

The import of sendMessageToListenersInWindow is required for implementing the window state change notification system.


92-105: Clean window state query implementation.

The getWindowState helper function correctly maps to the WindowState type, and the IPC handler properly handles edge cases by returning false when no window is found. The implementation is straightforward and reliable.


107-109: Effective window state broadcasting implementation.

The fireWindowStateChanged function correctly uses the existing IPC messaging infrastructure to broadcast window state changes to all listeners in the window. This provides real-time state synchronization for UI components.

src/shared/flow/interfaces/browser/interface.ts (2)

1-1: LGTM: Clean import addition.

The WindowState type import is correctly added to support the new window management methods.


59-82: LGTM: Well-designed window management interface.

The new window control methods are well-designed with:

  • Clear, descriptive method names following existing conventions
  • Appropriate return types (void for actions, Promise for async operations)
  • Consistent JSDoc documentation
  • Proper use of the IPCListener pattern for state change events

The interface additions integrate seamlessly with the existing API structure.

src/preload/index.ts (2)

16-16: LGTM: Proper type import.

The WindowState type import is correctly added to support the new window state callback typing.


312-327: LGTM: Solid IPC implementation of window controls.

The implementation correctly follows established patterns:

  • Uses ipcRenderer.send for fire-and-forget window control commands
  • Uses ipcRenderer.invoke for async window state queries
  • Uses listenOnIPCChannel helper for event subscription
  • IPC channel names follow consistent interface:* convention
  • Proper typing with WindowState for the callback parameter

The integration with the existing interfaceAPI structure is seamless.

src/renderer/src/components/browser-ui/sidebar/header/window-controls.tsx (5)

2-3: LGTM: Proper imports for enhanced functionality.

Good addition of necessary imports for utility functions and React hooks to support the window controls implementation.


5-6: LGTM: Well-defined shared styling constant.

The shared button classes provide consistent styling and the remove-app-drag class correctly prevents drag behavior on interactive buttons.


8-61: LGTM: Clean and accessible icon components.

The SVG icon implementations are well-designed:

  • Consistent sizing and styling across all icons
  • Proper responsive design with dark mode support
  • WindowsMaximize correctly toggles between maximize/restore states
  • Clean, semantic SVG markup

The icons follow Windows design conventions and will work well for Linux too as intended.


107-117: LGTM: Simple and correct event handlers.

The event handlers are clean and straightforward, directly calling the appropriate interface methods without unnecessary complexity.


119-167: LGTM: Well-structured responsive UI with good UX.

The component rendering is well-designed:

  • Proper platform-specific styling with Tailwind classes
  • Good responsive behavior (hidden on fullscreen for macOS)
  • Appropriate hover states and visual feedback
  • Semantic button elements with proper titles for accessibility
  • Clean conditional rendering for Windows/Linux vs macOS

The UI follows platform conventions and provides a polished user experience.

@iamEvanYT iamEvanYT merged commit 165da63 into main May 25, 2025
3 of 4 checks passed
@iamEvanYT iamEvanYT deleted the evan/custom-window-controls branch May 25, 2025 17:41
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