- Add stopStreamTracks() call in catch block to release any partially
acquired media tracks when camera access fails
- Prevents privacy and resource leaks from orphaned media streams
- Add refreshVueWidgets call in hideWidgets to sync Vue state on mount
- Update stop camera button with rounded container and square icon
- Use bg-destructive-background design token for stop button
- Clear captured image and restart camera preview when toggling to On Run
- Restore capture button when switching back to Manual mode
- Ensures smooth UX when changing capture modes
- Add refreshVueWidgets function to GraphNodeManager for manually syncing
LiteGraph widget changes with Vue reactive state
- Use refreshVueWidgets after widget modifications (capture, retake, show)
- Fixes retake button not appearing after capturing an image
- Add updateVueWidgetOptions to GraphNodeManager to update widget options
and trigger Vue reactivity
- Implement capture button visibility toggle based on capture_on_queue value
- Default capture mode to 'Manually' (false)
- Use Vue watch to reactively hide/show capture button when mode changes
Mutate widget objects in place instead of creating new instances to fix
a reactivity issue where serializeValue closure captured stale widget
references. Also adds persistent video element for background capture
when UI video is hidden.
Fixes capture_on_queue toggle not being read correctly during serialization.
## Summary
- add workflow to tag merged backport-labeled PRs into cloud/* with
cloud/v<package.json version>
- validate branch/version alignment and skip when tag already exists
- use .nvmrc (Node 24) for setup-node
## Question
- This workflow expects the version bump to already be in the PR when
you merge, as it fails if the tag already exists to keep immutability.
Should we autobump in this case?
## Summary
Catch more user visible (or audible) text that isn't
internationalizable.
## Changes
- **What**: Linter now checks other attributes for raw text.
## Review Focus
What other properties have leaked English text to non-English locales
that aren't in here?
This pull request introduces improvements to widget customization and UI
consistency in the application. The most notable changes are the
addition of support for icon classes in widget options, updates to
button rendering logic, and enhanced visual consistency for button
components.
Widget customization enhancements:
* Added an optional `iconClass` property to the `IWidgetOptions`
interface in `widgets.ts`, allowing widgets to specify custom icons.
UI and rendering updates:
* Updated `WidgetButton.vue` to render the widget label and, if
provided, an icon using the new `iconClass` option. Also standardized
button styling and label usage.
* Improved button styling in `WidgetRecordAudio.vue` for better visual
consistency with other components.
<img width="662" height="534" alt="Screenshot 2025-11-25 at 01 36 45"
src="https://github.com/user-attachments/assets/43bbe226-07fd-48be-9b98-78b08a726b1b"
/>
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6900-Style-button-widgets-2b66d73d3650818ebeadd9315a47ba0f)
by [Unito](https://www.unito.io)
Updated button widget to support icon display and improved styling to match design system.
- Add icon rendering using widget.options.iconClass
- Update styling to use semantic tokens
- Use widget.label for display instead of widget.name
- Apply consistent button styling with design system tokens
Added programmatic capture button that appears when camera is turned on. The button uses node.addWidget() to integrate with LiteGraph canvas.
- Add captureImage() function to draw video frame to canvas and store in node.imgs
- Add capture button widget in showWidgets() using node.addWidget()
- Create canvas element at module level for efficient reuse
- Widget restoration handled by existing restoreWidgets() cleanup
Add video preview functionality with hover overlay that allows users to:
- Click button to start camera and show live preview
- Hover over video to see stop overlay
- Click anywhere on video to hide preview (keeps camera active)
- Click button again to re-show preview without re-requesting permissions
Uses VueUse's useElementHover for automatic hover detection and proper
MediaStream handling with cleanup on unmount.
Use toRaw() and markRaw() when modifying widget objects to prevent Vue's
reactive proxy from wrapping them. This fixes errors when LiteGraph tries
to access private class members like #value in BaseWidget.
## Summary
Allow the Storybook workflow to run on every PR branch instead of only
`main`.
## Changes
- **What**: remove the `branches: [main]` filter from the Storybook CI
workflow so it triggers for all pull_request events.
## Review Focus
- Confirm broader triggering is desired for all branches while Chromatic
deployment remains restricted to `version-bump-*` or manual runs.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6880-Run-Storybook-CI-on-all-pull-requests-2b56d73d36508169a32afcf50f8e8fd8)
by [Unito](https://www.unito.io)
Co-authored-by: sno <snomiao@gmail.com>
## Summary
- add `data-testid="startup-status-text"` to the status text in
StartupDisplay
- keep the status element targetable for Playwright masks
## Why
Desktop’s Playwright tests mask the troubleshooting version line; this
test id is needed there to keep screenshots stable across releases.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6882-Add-test-id-for-startup-status-text-2b56d73d365081b6a2e4ddca9aa985a4)
by [Unito](https://www.unito.io)