* chore(ui): migrate to Vite 8, oxlint, and oxfmt
Replace esbuild+Rollup with Oxc+Rolldown (Vite 8), ESLint with oxlint
(with type-aware linting), and Prettier with oxfmt. No source code
changes — formatting and lint fixes will roll out incrementally via
lint-staged as files are touched.
* fix(ui): resolve oxlint errors in existing code
Fix errors caught by oxlint: useless rename, redundant undefined on
optional params, duplicate union type constituent, and unsafe toString
on union type.
* [FEATURE] Added copy text to clipboard from kvm using OCR
* fix: make OCR overlay cover full viewport
Change the semi-transparent background from absolute to fixed
positioning so it extends to the viewport edges, covering the
letterbox/pillarbox areas outside the video container.
* refactor: use Card component for OCR selection size indicator
Replace the manually-styled div with the Card component for the
selection size indicator, consistent with the project's component
library.
* feat: use ConfirmDialog for OCR processing indicator
* refactor: use ConfirmDialog for OCR result panel
* fix: make OCR result textarea readonly with text pre-selected
* refactor: use Cancel and Copy CTAs for OCR dialogs
* chore: machine translate OCR localization keys
* fix: address OCR copy-paste review feedback
- Fix cursor-pointer showing on disabled button in ConfirmDialog
- Change CTA from "Copy" to "Copy text" for clarity
- Fix selection breaking when mouse leaves viewport during drag
- Add children prop to ConfirmDialog; use description for helper text
- Fix clipboard.writeText failing in insecure contexts with fallback
* fix: address remaining OCR review feedback
- Merge processing and result into a single ConfirmDialog so the modal
doesn't flicker when OCR completes quickly
- Add dark:text-white to the selection size pill Card
- Remove duplicate toast in the execCommand fallback (the copy event
listener already handles it)
- Sequence dialog close → unmount so HeadlessUI's leave transition plays
* fix: prevent OCR dialog content flash during close animation
When closing the OCR result dialog, the title briefly flashed back to
"Recognizing text..." during the exit animation. This happened because
closeOverlay reset status to "idle" to close the dialog, but the
dialog content ternaries also depended on status, causing them to
evaluate incorrectly during the 200ms HeadlessUI leave transition.
Fix by introducing an isClosing flag that controls the dialog's open
prop independently, leaving status unchanged so dialog content remains
stable during the exit animation.
Add SVG and ICO to cacheable files.
Emit robots.txt directly.
Recognize WOFF2 (font) files as assets (so the get the immutable treatment)
Pre-gzip the entire /static/ directory (not just /static/assets/) and include SVG, ICO, and HTML files
Ensure fonts.css is processed by vite/rollup so that the preload and css reference the same immutable files (which get long-cached with hashes)
Add CircularXXWeb-Black to the preload list as it is used in the hot-path.
Handle system-driven color-scheme changes from dark to light correctly.
* chore: Upgrade UI vite and tailwind packages
Vite 5.2.0 -> 6.3.5
@vitejs/plugin-basic-ssl 1.2.0 -> 2.0.0
cva: 1.0.0-beta.1 -> 1.0.0-beta.3
focus-trap-react 10.2.3 -> 11.0.3
framer-motion 11.15.0 -> 12.11.0
@tailwindcss/postcss 4.1.6
@tailwindcss/vite 4.1.6
tailwind 3.4.17 -> 4.1.6
tailwind-merge 2.5.5 -> 3.3.0
Minor updates:
@headlessui/react 2.2.2 -> 2.2.3
@types/react 19.1.3 -> 19.1.4
@types/react-dom 19.1.3 -> 19.1.5
@typescript-eslint/eslint-plugin 8.32.0 -> 8.32.1
@typescript-eslint/parser 8.32.0 -> 8.32.1
react-simple-keyboard 3.8.71 -> 3.8.72
The new version of vite required an Node 22.15 (since that's current LTS and node 21.x is EOL)
The changes to css due to the tailwind 3 to 4 upgrade were done following [the upgrade guide](https://tailwindcss.com/docs/upgrade-guide#changes-from-v3)
Done in this order (important):
`shadow-sm` -> `shadow-xs`
`shadow` -> `shadown-sm`
`rounded` -> `rounded-sm`
`outline-none` -> `outline-hidden`
`32rem_32rem_at_center` -> `center_at_32rem_32rem` (revised order of gradient props)
`ring-1 ring-black ring-opacity-5` -> `ring-1 ring-black/50`
`flex-shrink-0` -> `shrink-0`
`flex-grow-0` -> `grow-0`
`outline outline-1` -> `outline-1`
ALSO removed the **extra** `opacity-0` on the video element (trips up latest tailwind causing the video to be invisible)
FocusTrap is now not exported as the default, so change those imports
headlessui's Menu completely changed, so upgrade to the new syntax which necessitated a reorganization of the Header.tsx to enable the "menu" to still work
* Update eslint config and fix errors
* feat: implement pointer-lock and keyboard-lock
* feat: Add Pointer lock functionality and SSL support in dev mode
- Introduced @vitejs/plugin-basic-ssl for enabling SSL in development.
- Added a new script `dev:ssl` to run the development server with SSL.
- Implemented pointer lock feature in the WebRTCVideo component, enhancing user interaction.
- Added a PointerLockBar component to guide users on enabling mouse control.
- Cleaned up the VideoOverlay and WebRTCVideo components for better readability and functionality.
---------
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.