feat: virtual encoder controls (click/drag dial widget and touch simulation)#313
Draft
KatsuJinCode wants to merge 2 commits intonekename:mainfrom
Draft
feat: virtual encoder controls (click/drag dial widget and touch simulation)#313KatsuJinCode wants to merge 2 commits intonekename:mainfrom
KatsuJinCode wants to merge 2 commits intonekename:mainfrom
Conversation
Full Stream Deck + touch strip support implementing the SDK feedback layout spec. ## Backend (Rust) - 200x100 LCD rendering per encoder slot (was a 72x72 thumbnail). - setFeedback handler merges payload into persistent per-instance feedback state and notifies the frontend. - setFeedbackLayout handler records the layout, resets feedback state (spec-level keys differ per layout so stale state would render wrong), and notifies the frontend. - ActionInstance gains feedback_layout + feedback fields; preserved through DiskActionInstance so layouts survive restart. - Action manifest parser now reads the Encoder.layout property so the plugin-declared default layout applies on instance creation. - get_feedback_layout Tauri command reads custom layout JSON from the plugin folder with a canonical-path check against traversal. - Touch screen press / long-press mapped to SDK touchTap events; touchTap outbound event carries coordinates, settings, and hold. ## Frontend (Svelte / TypeScript) - feedbackLayouts.ts: the six built-in layouts ($X1, $A0, $A1, $B1, $B2, $C1) as TypeScript objects, verbatim from the SDK docs. - feedbackRenderer.ts: Canvas 2D renderer for the four item types (pixmap, text, bar, gbar). Supports all five bar subtypes (Rectangle, DoubleRectangle, Trapezoid, DoubleTrapezoid, Groove), gradient colour specs, z-order, opacity, text alignment, and clip/ellipsis overflow. Pixmaps preserve aspect ratio except for the $A0 'full-canvas' item which is explicitly 200x100. - Key.svelte: encoder slots with a feedback_layout render via the layout renderer and push the composed 200x100 pixmap to the device via update_image. Icon and title fall back to the action's state.image and state.text when the plugin hasn't provided its own, matching the 'Reserved Layout Item Keys' behaviour in the docs. - Edge-to-edge encoder strip UI matching the physical 800x100 LCD. - Dark theme CSS for Property Inspector select elements. The virtual encoder UI widget is split to a separate PR.
…lation) UI-only layer on top of nekename#306 that lets users interact with the encoder from OpenDeck itself, without needing the physical device. Frontend: - EncoderDial component per encoder: 30-detent visual indicator, click-drag to rotate, click to press/release, long-press for touch-and-hold, double-click for touchTap. - Physical device rotation reflected in the UI dial (encoder_rotated event). Backend: - trigger_virtual_rotate, trigger_virtual_encoder_down/up, trigger_virtual_touch Tauri commands feed the same inbound handlers as real device events; plugins see no difference. - encoder_rotated frontend event emitted from encoder_change so the dial indicator tracks physical rotation. - TicksPayload made Serialize + Clone for emit to webview. Depends on nekename#306 for touch_tap handler.
Owner
|
I'm sorry, but there is no way I will be able to review or merge a PR that changes over 1,300 lines of code. |
Owner
|
Just looking at the diff, and it seems like this PR contains all of the changes from #306 as well. If this is intended to be merged after that PR, then it needs to be marked as a draft. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Per @Terrorwolf01's request to split the virtual encoder out: this PR adds a UI-only layer on top of #306 that lets users interact with the encoder from OpenDeck itself, without needing the physical device.
Depends on #306 (the touch_tap handler used by
trigger_virtual_touchlives there).Frontend (Svelte)
EncoderDialcomponent per encoder: 30-detent visual indicator, click-drag to rotate, click to press / release, long-press for touch-and-hold, double-click for touchTap.encoder_rotatedevent, so the indicator tracks real hardware too.Backend (Rust)
trigger_virtual_rotate,trigger_virtual_encoder_down/_up,trigger_virtual_touchTauri commands. They feed the same inbound handlers as real device events, so plugins see no difference between virtual and physical input.encoder_rotatedfrontend event emitted fromencoder_changeso the dial indicator can track physical rotation in real time.TicksPayloadmadeSerialize + Cloneso it can be emitted to the webview.Why split this out
@Terrorwolf01 noted the official Stream Deck software uses a circular dial UI for encoder slots; this PR gives OpenDeck the equivalent. The visible LCD strip rendering (PR #306) is independent of this -- you can ship that without this PR if you'd prefer to keep OpenDeck's encoder UX more minimal.