Add two new configurable session settings to improve multi-session management:
1. Maximum Concurrent Sessions (1-20, default: 10)
- Controls the maximum number of simultaneous connections
- Configurable via settings UI with validation
- Applied in session manager during session creation
2. Observer Cleanup Timeout (30-600 seconds, default: 120)
- Automatically removes inactive observer sessions with closed RPC channels
- Prevents accumulation of zombie observer sessions
- Runs during periodic cleanup checks
- Configurable timeout displayed in minutes in UI
Backend changes:
- Add MaxSessions and ObserverTimeout fields to SessionSettings struct
- Update setSessionSettings RPC handler to persist new settings
- Implement observer cleanup logic in cleanupInactiveSessions
- Apply maxSessions limit in NewSessionManager with proper fallback chain
Frontend changes:
- Add numeric input controls for both settings in multi-session settings page
- Include validation and user-friendly error messages
- Display friendly units (sessions, seconds/minutes)
- Maintain consistent styling with existing settings
Also includes defensive nil checks in writeJSONRPCEvent to prevent
"No HDMI Signal" errors when RPC channels close during reconnection.
This commit addresses multiple CRITICAL and HIGH severity security issues
identified during the multi-session implementation review.
CRITICAL Fixes:
- Fix race condition in session approval handlers (jsonrpc.go)
Previously approveNewSession and denyNewSession directly mutated
session.Mode without holding the SessionManager.mu lock, potentially
causing data corruption during concurrent access.
- Add validation to ApprovePrimaryRequest (session_manager.go:795-810)
Now verifies that requester session exists and is in Queued mode
before approving transfer, preventing invalid state transitions.
- Close dual-primary window during reconnection (session_manager.go:208)
Added explicit primaryExists check to prevent brief window where two
sessions could both be primary during reconnection.
HIGH Priority Fixes:
- Add nickname uniqueness validation (session_manager.go:152-159)
Prevents multiple sessions from having the same nickname, both in
AddSession and updateSessionNickname RPC handler.
Code Quality:
- Remove debug scaffolding from cloud.go (lines 515-520, 530)
Cleaned up temporary debug logs that are no longer needed.
Thread Safety:
- Add centralized ApproveSession() method (session_manager.go:870-890)
- Add centralized DenySession() method (session_manager.go:894-912)
Both methods properly acquire locks and validate session state.
- Update RPC handlers to use thread-safe methods
approveNewSession and denyNewSession now call sessionManager methods
instead of direct session mutation.
All changes have been verified with linters (golangci-lint: 0 issues).
Backend improvements:
- Keep denied sessions alive in pending mode instead of removing them
- Add requestSessionApproval RPC method for re-requesting access
- Fix security issue: preserve pending mode on reconnection for denied sessions
- Add MaxRejectionAttempts field to SessionSettings (default: 3, configurable 1-10)
Frontend improvements:
- Change "Try Again" button to "Request Access Again" that re-requests approval
- Add rejection counter with configurable maximum attempts
- Hide modal after max rejections; session stays pending in SessionPopover
- Add "Dismiss" button for primary to hide approval requests without deciding
- Add MaxRejectionAttempts control in multi-session settings page
- Reset rejection count when session is approved
This improves the user experience by allowing denied users to retry without
page reloads, while preventing spam with configurable rejection limits.
Address all linting warnings and errors in both backend and frontend code:
**Go (golangci-lint):**
- Add error checking for ignored return values (errcheck)
- Remove unused RPC functions (unused)
- Fix import formatting (goimports)
**TypeScript/React (eslint):**
- Replace all 'any' and 'Function' types with proper type definitions
- Add RpcSendFunction type for consistent JSON-RPC callback signatures
- Fix React Hook exhaustive-deps warnings by adding missing dependencies
- Wrap functions in useCallback where needed to stabilize dependencies
- Remove unused variables and imports
- Remove empty code blocks
- Suppress exhaustive-deps warnings where intentional (with comments)
All linting now passes with 0 errors and 0 warnings.
* feat: release keyPress automatically
* send keepalive when pressing the key
* remove logging
* clean up logging
* chore: use unreliable channel to send keepalive events
* chore: use ordered unreliable channel for pointer events
* chore: adjust auto release key interval
* chore: update logging for kbdAutoReleaseLock
* chore: update comment for KEEPALIVE_INTERVAL
* fix: should cancelAutorelease when pressed is true
* fix: handshake won't happen if webrtc reconnects
* chore: add trace log for writeWithTimeout
* chore: add timeout for KeypressReport
* chore: use the proper key to send release command
* refactor: simplify HID RPC keyboard input handling and improve key state management
- Updated `handleHidRPCKeyboardInput` to return errors directly instead of keys down state.
- Refactored `rpcKeyboardReport` and `rpcKeypressReport` to return errors instead of states.
- Introduced a queue for managing key down state updates in the `Session` struct to prevent input handling stalls.
- Adjusted the `UpdateKeysDown` method to handle state changes more efficiently.
- Removed unnecessary logging and commented-out code for clarity.
* refactor: enhance keyboard auto-release functionality and key state management
* fix: correct Windows default auto-repeat delay comment from 1ms to 1s
* refactor: send keypress as early as possible
* refactor: replace console.warn with console.info for HID RPC channel events
* refactor: remove unused NewKeypressKeepAliveMessage function from HID RPC
* fix: handle error in key release process and log warnings
* fix: log warning on keypress report failure
* fix: update auto-release keyboard interval to 225
* refactor: enhance keep-alive handling and jitter compensation in HID RPC
- Implemented staleness guard to ignore outdated keep-alive packets.
- Added jitter compensation logic to adjust timer extensions based on packet arrival times.
- Introduced new methods for managing keep-alive state and reset functionality in the Session struct.
- Updated auto-release delay mechanism to use dynamic durations based on keep-alive timing.
- Adjusted keep-alive interval in the UI to improve responsiveness.
* gofmt
* clean up code
* chore: use dynamic duration for scheduleAutoRelease
* Use harcoded timer reset value for now
* fix: prevent nil pointer dereference when stopping timers in Close method
* refactor: remove nil check for kbdAutoReleaseTimers in DelayAutoReleaseWithDuration
* refactor: optimize dependencies in useHidRpc hooks
* refactor: streamline keep-alive timer management in useKeyboard hook
* refactor: clarify comments in useKeyboard hook for resetKeyboardState function
* refactor: reduce keysDownStateQueueSize
* refactor: close and reset keysDownStateQueue in newSession function
* chore: resolve conflicts
* resolve conflicts
---------
Co-authored-by: Adam Shiervani <adam.shiervani@gmail.com>
* chore/Deprecate browser mount
No longer supported.
* Remove device-side go code
* Removed diskChannel and localFile
* Removed RemoteVirtualMediaState.WebRTC
Also removed dead go code (to make that lint happy!)
Remove LED sync source option and add keypress reporting while still working with devices that haven't been upgraded
We return the modifiers as the valid bitmask so that the VirtualKeyboard and InfoBar can represent the correct keys as down. This is important when we have strokes like Left-Control + Right-Control + Keypad-1 (used in switching KVMs and such).
Fix handling of modifier keys in client and also removed the extraneous resetKeyboardState.
Manage state to eliminate rerenders by judicious use of useMemo.
Centralized keyboard layout and localized display maps
Move keyboardOptions to useKeyboardLayouts
Added translations for display maps.
Add documentation on the legacy support.
Return the KeysDownState from keyboardReport
Clear out the hidErrorRollOver once sent to reset the keyboard to nothing down.
Handles the returned KeysDownState from keyboardReport
Now passes all logic through handleKeyPress.
If we get a state back from a keyboardReport, use it and also enable keypressReport because we now know it's an upgraded device.
Added exposition on isoCode management
Fix de-DE chars to reflect German E2 keyboard.
https://kbdlayout.info/kbdgre2/overview+virtualkeys
Ran go modernize
Morphs Interface{} to any
Ranges over SplitSeq and FieldSeq for iterating splits
Used min for end calculation remote_mount.Read
Used range 16 in wol.createMagicPacket
DID NOT apply the Omitempty cleanup.
Strong typed in the typescript realm.
Cleanup react state management to enable upgrading Zustand
* feat: add timezone support to jiggler and fix custom settings persistence
- Add timezone field to JigglerConfig with comprehensive IANA timezone list
- Fix custom settings not loading current values
- Remove business hours preset, add as examples in custom settings
- Improve error handling for invalid cron expressions
* fix: format jiggler.go with gofmt
* fix: add embedded timezone data and validation
- Import time/tzdata to embed timezone database in binary
- Add timezone validation in runJigglerCronTab() to gracefully fallback to UTC
- Add timezone to debug logging in rpcSetJigglerConfig
- Fixes 'unknown time zone' errors when system lacks timezone data
* refactor: add timezone field comments from jiggler options
* chore: move tzdata to backend
* refactor: fix JigglerSetting linting
- Adjusted useEffect dependency to include send function for better data fetching
- Modified layout classes for improved responsiveness and consistency
- Cleaned up code formatting for better readability
---------
Co-authored-by: Siyuan Miao <i@xswan.net>
* feat: add local web server loopback mode configuration
- Introduced a new configuration option `LocalWebServerLoopbackOnly` to restrict the web server to listen only on the loopback interface.
- Added RPC methods `rpcGetLocalWebServerLoopbackOnly` and `rpcSetLocalWebServerLoopbackOnly` for retrieving and updating this setting.
- Updated the web server startup logic to bind to the appropriate address based on the new configuration.
- Modified the `LocalDevice` struct to include the loopback setting in the response.
* remove extra logs
* chore: add VSCode extensions for improved development environment
* refactor: rename LocalWebServerLoopbackOnly to LocalLoopbackOnly
- Updated the configuration struct and related RPC methods to use the new name `LocalLoopbackOnly` for clarity.
- Adjusted the web server binding logic and device response structure to reflect this change.
* feat: add loopback-only mode functionality to UI
- Implemented a new setting for enabling loopback-only mode, restricting web interface access to localhost.
- Added a confirmation dialog to warn users before enabling this feature.
- Updated the ConfirmDialog component to accept React nodes for the description prop.
- Refactored imports and adjusted component structure for clarity.
* refactor: optimize device settings handlers for better performance
- Refactored the `handleDevChannelChange` and `handleLoopbackOnlyModeChange` functions to use `useCallback` for improved performance and to prevent unnecessary re-renders.
- Consolidated the logic for applying loopback-only mode into a separate `applyLoopbackOnlyMode` function, enhancing code clarity and maintainability.
- Updated the confirmation flow for enabling loopback-only mode to ensure user warnings are displayed appropriately.
* Enable multiple keyboard layouts for paste text from host
* Trema is the more robust method for capital umlauts
* Improve error handling and pre-loading
* Improve accent handling
* Remove obscure Alt-Gr keys, unsure if they are supported everywhere
* Add Swiss French
* Change line ordering
* Fix whitespace
* Add French (France)
* Add English (UK)
* Add Swedish
* Add Spanish
* Fix fr_FR special characters
* Add more keys to Spanish
* Remove default value shift: false
* Add Norwegian
* Operator precedence 🤦
* Add Italian
* Add Czech
* Move guard statements outside of loop
* Move language name definitions into the keyboard layout files
* Change the locale names to their native language
German->Deutsch et. al.
* Move hold key handling into Go backend analogous to https://www.kernel.org/doc/Documentation/usb/gadget_hid.txt
* Remove trailing whitespace
* Fix
* Add Belgisch Nederlands
* Add JSONRPC handling
* Use useSettingsStore
* Revert "Move hold key handling into Go backend analogous to https://www.kernel.org/doc/Documentation/usb/gadget_hid.txt"
This reverts commit 146cee9309.
* Move FeatureFlag to navigation
* Fix: flip Y/Z
* Add useEffect dependencies
* Embolden language
* Add to useCallback dependencies
---------
Co-authored-by: Marc Brooks <IDisposable@gmail.com>
Added a wrapper around the callRPCHandler function to recover from panic and translate that to and error so that the RPC thread doesn't just die when something malformed comes in. This should keep the Jet flying.
- Removed scroll sensitivity state and associated functions from jsonrpc.go and WebRTCVideo component.
- Cleaned up device settings store by eliminating unused scroll sensitivity logic.
- Updated mouse settings route to reflect the removal of scroll sensitivity feature.
- Simplified mouse wheel event handling in WebRTCVideo component.
- Implement scroll sensitivity settings with low, default, and high modes
- Add RPC methods for getting and setting scroll sensitivity
- Enhance wheel event handling with device-specific sensitivity and clamping
- Create a new device settings store for managing scroll and trackpad parameters
- Update mouse settings route to include scroll sensitivity selection
* feat(ui): Add other session handling route and modal
* feat(ui): Add dedicated update route and refactor update dialog state management
* feat(ui): Add local authentication route
* refactor(ui): Remove LocalAuthPasswordDialog component and clean up related code
* refactor(ui): Remove OtherSessionConnectedModal component
* feat(ui): Add dedicated mount route and refactor mount media dialog
* refactor(ui): Simplify Escape key navigation in device route
* refactor(ui): Add TODO comments for future URL-based state migration
* refactor(ui): Migrate settings and update routes to dedicated routes
This commit introduces a comprehensive refactoring of the UI routing and state management:
- Removed sidebar-based settings view
- Replaced global modal state with URL-based routing
- Added dedicated routes for settings, including general, security, and update sections
- Simplified modal and sidebar interactions
- Improved animation and transition handling using motion library
- Removed deprecated components and simplified route structure
* fix(ui): Add TODO comment for modal session interaction
* refactor(ui): Move USB configuration to new settings setup
This commit introduces several improvements to the USB configuration workflow:
- Refactored USB configuration dialog component
- Simplified USB config state management
- Moved USB configuration to hardware settings route
- Updated JSON-RPC type definitions
- Cleaned up unused imports and components
- Improved error handling and notifications
* refactor(ui): Replace react-router-dom navigation with custom navigation hook
This commit introduces a new custom navigation hook `useDeviceUiNavigation` to replace direct usage of `useNavigate` across multiple components:
- Removed direct `useNavigate` imports in various components
- Added `navigateTo` method from new navigation hook
- Updated navigation calls in ActionBar, MountPopover, UpdateInProgressStatusCard, and other routes
- Simplified navigation logic and prepared for potential future navigation enhancements
- Removed console logs and unnecessary comments
* refactor(ui): Remove unused react-router-dom import
Clean up unnecessary import of `useNavigate` from react-router-dom in device settings route
* feat(ui): Improve mobile navigation and scrolling in device settings
* refactor(ui): Reorganize device access and security settings
This commit introduces several changes to the device access and security settings:
- Renamed "Security" section to "Access" in settings navigation
- Moved local authentication routes from security to access
- Removed deprecated security settings route
- Added new route for device access settings with cloud and local authentication management
- Updated cloud URL and adoption logic to be part of the access settings
- Simplified routing and component structure for better user experience
* fix(ui): Update logout button hover state color
* fix(ui): Adjust device de-registration button size to small
* fix(ui): Update appearance settings section header and description
* refactor(ui): Replace SectionHeader with new SettingsPageHeader and SettingsSectionHeader components
This commit introduces two new header components for settings pages:
- Created SettingsPageHeader for main page headers
- Created SettingsSectionHeader for subsection headers
- Replaced all existing SectionHeader imports with new components
- Updated styling and type definitions to support more flexible header rendering
* feat(ui): Add dev channel toggle to advanced settings
Move dev channel update option from general settings to advanced settings
- Introduced new state and handler for dev channel toggle
- Removed dev channel option from general settings route
- Added dev channel toggle in advanced settings with error handling
* rebasing on dev branch
* fixed formatting
* fixed formatting
* removed query params
* moved usb settings to hardware setting
* swapped from error to log
* added fix for any change to product name now resulting in show the spinner as custom on page reload
* formatting
---------
Co-authored-by: JackTheRooster <adrian@rydeas.com>
Co-authored-by: Adam Shiervani <adam.shiervani@gmail.com>
* feat(cloud): Add custom cloud API URL configuration support
- Implement RPC methods to set, get, and reset cloud URL
- Update cloud registration to remove hardcoded cloud API URL
- Modify UI to allow configuring custom cloud API URL in developer settings
- Remove environment-specific cloud configuration files
- Simplify cloud URL configuration in UI config
* fix(ui): Update cloud app URL to production environment in device mode
* refactor(ui): Remove SIGNAL_API env & Rename to DEVICE_API to make clear distinction between CLOUD_API and DEVICE_API.
* feat(ui): Only show Cloud API URL Change on device mode
* fix(cloud): Don't override the CloudURL on deregistration from the cloud.