Files
plane/todesktop.json
T
a9985ca802 [WEB-5579] feat: add desktop app with OAuth authentication (#5438)
* feat: add desktop app with OAuth authentication

- Add Electron desktop app with vite-plugin-electron
- Add desktop OAuth endpoints for Google and GitHub
- Add token exchange endpoint for desktop auth flow
- Add /d/auth route for handling OAuth callbacks
- Update OAuth hook to detect desktop app and use appropriate flow
- Remove deprecated IS_HEROKU setting
- Fix sign-out navigation in desktop app

* refactor: move tab bar from React to native Electron WebContentsView

Move the tab bar UI from the web app React component to a dedicated
Electron WebContentsView. This prevents the tab bar from flashing
during page navigation since it's now rendered in its own view that
persists independently of the content area.

Changes:
- Add tab-bar.html with self-contained UI matching Figma design
- Add tab-bar-preload.ts for IPC communication with main process
- Update ViewManager to create and manage tab bar WebContentsView
- Simplify IPCBridge to remove broadcasts to content views
- Remove DesktopTabBar React component from web app
- Simplify use-desktop.ts hooks (remove tab-related hooks)
- Update preload.ts to remove tab-related APIs

* refactor: desktop OAuth to use plane:// protocol handoff

- OAuth flow now opens in external browser for better UX (uses existing sessions)
- Browser callback page redirects to plane:// which hands off to Electron app
- Electron navigates to /d/auth/ on the instance to exchange token for session
- Add CSRF exemption to desktop token exchange endpoint
- Fix TypeScript types for electron-store with pnpm

* improvement: minor updates for tab bar HTML structure and styles

- Refined CSS variables for light mode and added primary color.
- Enhanced tab bar styles for better alignment and responsiveness.
- Improved hover effects and transitions for navigation buttons and tabs.

* feat: temporarily disable theme switcher on desktop

- Added logic to disable the theme switcher on desktop platforms, providing a tooltip to inform users that customization is not supported yet.
- Updated ThemeSwitch component to accept `isDisabled` and `tooltipContent` props for better user experience.
- Adjusted preferences commands to ensure theme switching is disabled on desktop.
- Implemented fallback to system theme for desktop users in the StoreWrapper component.

* feat: update color variables and improve layout in setup and tab bar HTML

- Replaced traditional color definitions with oklch color space for better color management.
- Enhanced layout and styling in setup.html for improved user experience, including adjustments to flex properties and background colors.
- Updated tab-bar.html to align with new color variables and improve responsiveness.
- Introduced a new InfoSection component in the auth page for better error handling and user feedback during authentication.

* refactor: add desktop build script and update dependencies

- Introduced a new build script for the desktop application in package.json.
- Updated @todesktop/cli dependency to version 1.20.2.
- Removed obsolete todesktop.json file and adjusted desktop package.json for improved dependency management.
- Updated various dependencies in the desktop app for better compatibility and performance.

* feat: update color variables and improve layout in setup and tab bar HTML

- Refactored color definitions to use oklch color space for better color management.
- Enhanced layout and styling in setup.html, including adjustments to background colors and semantic tokens.
- Updated tab-bar.html to align with new color variables and improve responsiveness, including hover effects and transitions.
- Improved overall user experience with refined CSS variables and layout structures.

* chore: enable pnpm catalog for desktop app and build fixes

* feat: enhance IPCBridge with structured event handling and cleanup

- Introduced constants for IPC channel names to improve code readability and maintainability.
- Added handler references for IPC events to facilitate proper cleanup during the destroy process.
- Refactored IPC event listeners to use the new constants and handler references, ensuring better organization and management of IPC communication.
- Improved the destroy method to remove event listeners and handlers, preventing potential memory leaks.

* feat: implement dynamic layout mode handling in ViewManager

- Introduced WindowLayoutMode type to manage application layout states ('setup' and 'app').
- Enhanced ViewManager to compute and update layout mode based on instance URL configuration.
- Updated tab bar visibility and height dynamically according to the current layout mode.
- Subscribed to instance store changes to ensure layout updates are reflected in real-time.

* fix: properly destroy WebContentsView renderer processes on tab close and window close

The desktop app had memory leaks where renderer processes persisted after:
1. Tab closure - tabs that had been visited kept their renderer processes alive
2. macOS window close - all renderers remained when window closed (app in dock)
3. Instance URL change - old renderers were never destroyed

Root causes:
- closeTab() only called removeChildView() without destroying the WebContentsView
- destroy() only unsubscribed from stores, didn't destroy any views
- Window used 'closed' event (fires after close) instead of 'close' event

Changes:
- Add #destroyView() helper that properly destroys WebContentsView instances
  by removing from parent, clearing event listeners, and calling
  webContents.close({ waitForBeforeUnload: false })
- Add #destroyTabBarView() for tab bar cleanup
- Update destroy() to clean up all views, tab bar, and resize handler
- Update closeTab() and handleInstanceUrlChanged() to use #destroyView()
- Switch from 'closed' to 'close' event for cleanup while window is valid
- Add will-quit handler to unregister global shortcuts

* refactor: standardize undefined usage across stores and managers

Replace null with undefined for optional values (instanceUrl, activeTabId) to improve type safety and consistency throughout the desktop app. This change:

- Unifies optional value handling in InstanceStore, TabStore, and related types
- Updates IPCBridge and ViewManager to handle undefined instance URLs correctly
- Simplifies type definitions and reduces null-checking complexity
- Aligns with TypeScript best practices for optional values

* feat(desktop): handle asset downloads with native save dialog

- Add isAssetPath helper to detect asset URLs by path patterns and file extensions
- Trigger native file save dialog for asset downloads instead of opening new tabs
- Fix electron-store usage: use delete() instead of set(undefined)
- Add favicon error handling with fallback to Plane logo
- Validate favicon URLs to only accept http, https, or data URIs
- Refactor view-manager to use guard-first approach throughout

* fix(desktop): register download handler once at app level instead of per-tab

All tabs share the same default session, so registering the will-download
handler per-tab caused duplicate handlers and multiple save dialogs.

* feat(desktop): update tab navigation shortcuts and add last tab functionality

- Changed tab navigation shortcuts from "CommandOrControl" to "Control" for consistency.
- Added a new shortcut for switching to the last tab, enhancing user experience in tab management.

* chore: disabled un-supported oauth options for desktop

* feat(desktop): multi-window tabs and React tab bar

* feat(desktop): multi-window tabs, React tab bar, and Chrome-like restore

* fix(desktop): resolve relative OAuth URLs against instance URL for self-managed deployments

* feat(desktop): handle deep links before app readiness and update tab navigation shortcuts

- Introduced a mechanism to process deep links that arrive before the app is fully initialized, enhancing user experience by ensuring deep links are handled appropriately.
- Changed tab navigation shortcuts from "CommandOrControl" to "Control" for both "Next Tab" and "Previous Tab" to ensure uniformity across the application.

* feat(auth): implement PKCE support for OAuth flows in desktop app

- Added PKCE challenge storage and validation in the authentication process.
- Updated OAuth endpoints for GitHub, GitLab, Gitea, and Google to handle PKCE.
- Introduced IPC methods for generating code_verifier and code_challenge in the desktop app.
- Enhanced token exchange process to include PKCE verification.

* chore: update copyright/license headers in desktop and web files

* fix: add missing copyright checks

* fix: build

---------

Co-authored-by: Prateek Shourya <prateekshourya29@gmail.com>
Co-authored-by: sriramveeraghanta <veeraghanta.sriram@gmail.com>
2026-03-03 21:39:42 +05:30

10 lines
174 B
JSON

{
"appPath": "./apps/desktop",
"bundleWorkspacePackages": {
"enabled": true
},
"icon": "./apps/desktop/icon.png",
"id": "260130r75i625",
"schemaVersion": 1
}