feat(realtime): remote-control input capture + data-channel transport (LC-184, controller) #228
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/lc-184-remote-control-input-capture"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Controller-side half of the TeamViewer-style remote-control story (LC-181). A controller captures their pointer + keyboard over a verified, consented 1:1 call and ships a compact input stream peer-to-peer over a WebRTC data channel. Native OS injection is LC-185; kill-switch / audit / abuse limits are LC-186. The request/grant/deny/revoke consent gate (both peers email-verified, neither blocked) is already enforced server-side in LC-183 (#227); this PR wires the client half.
What lands
call.jsopens anlc-controlchannel (negotiated, id 0) on both peers increatePc, so it rides the initial SDP and never triggers a mid-callonnegotiationneededrenegotiation. Input rides this channel peer-to-peer, off the signaling WS.<video>, keys at the window withpreventDefault(so the controller's own browser shortcuts do not fire on their machine). Pointer-move is rAF-coalesced; clicks/keys send immediately.normCoordsmaps a viewport point on the letterboxedobject-containvideo to normalized[0,1]surface coordinates and drops points in the letterbox bars, keeping the protocol resolution/DPI-independent (the controlled side maps[0,1]back to absolute screen pixels).none -> requesting -> controlling, with a 12s request timeout so a server-dropped request (unverified/blocked peer) self-reverts;Request control<->Stop controllingtoggle; auto-stop on remote-video drop, inboundrevoke, and call teardown.lc:control-start/lc:control-end, and re-emits each inbound data-channel frame aslc:control-input(the LC-185 bridge seam). Channelonclose/onerrorends the session on both roles as a fast path on abrupt drop.#lc-control-busslot (static target for the OOB consent fragment from LC-183), the grant/deny prompt overlay, and the Request-control affordance.lc:control-*DOM-event seam recorded for LC-185.Wire frames (controller -> controlled)
{t:'m',x,y}move,{t:'d',x,y,b}down,{t:'u',x,y,b}up,{t:'w',x,y,dx,dy}wheel,{t:'k',c,m}key down,{t:'K',c,m}key up.x,ynormalized[0,1];bmouse button;cisKeyboardEvent.code(physical key, layout-independent);mmodifier bitmask (ctrl=1, shift=2, alt=4, meta=8).Out of scope (later subtasks)
SendInputfirst) + the JS->native bridge re-asserting grant before injecting.Verification
cargo check -p lets-chat-serverclean (askama template compile).call.jsbundles clean viabun build(no syntax errors).just testandjust test-saasboth green (no Rust logic changed; JS + template + doc only).onclose/onerrorfast-path end. The flagged wheelremoveEventListener"leak" is a non-issue (removal matches on thecaptureflag only, which matches).