From d9c2bc94dd04a1c731a689be4c1547b3ddb0b5fd Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Fri, 4 Aug 2023 23:18:37 +0100 Subject: [PATCH] ctrlpad: changing code from swipes to interact --- apps/ctrlpad/wid.ts | 188 ++++++++++++++++++-------------------------- 1 file changed, 76 insertions(+), 112 deletions(-) diff --git a/apps/ctrlpad/wid.ts b/apps/ctrlpad/wid.ts index 35b35b295..0580da274 100644 --- a/apps/ctrlpad/wid.ts +++ b/apps/ctrlpad/wid.ts @@ -1,4 +1,22 @@ (() => { + if(!Bangle.prependListener){ + type Event = T extends `#on${infer Evt}` ? Evt : never; + + Bangle.prependListener = function( + evt: Event, + listener: () => void + ){ + // move our drag to the start of the event listener array + const handlers = (Bangle as BangleEvents)[`#on${evt}`] + + if(handlers && typeof handlers !== "function"){ + (Bangle as BangleEvents)[`#on${evt}`] = [listener as any].concat( + (handlers as Array).filter((f: unknown) => f !== listener) + ); + } + }; + } + class Overlay { g2: Graphics; @@ -28,6 +46,10 @@ Bangle.setLCDOverlay(g2, 10, y - 10); } + hide(): void { + Bangle.setLCDOverlay(); + } + renderG2(): void { const g = this.g2; @@ -80,160 +102,100 @@ } let state = State.NoConn; let startY = 0; - const initDistance = 30; - - let anchor = {x:0,y:0}; - let start = {x:0,y:0}; - let dragging = false; - let activeTimeout: TimeoutId | undefined; - let waitForRelease = true; let overlay: Overlay | undefined; + let touchDown = false; const onDrag = (e => { + const dragDistance = 30; + + if (e.b === 0) touchDown = false; + switch (state) { case State.NoConn: break; case State.IgnoreCurrent: - if(e.b === 0) state = State.Idle; + if(e.b === 0){ + state = State.Idle; + overlay = undefined; + } break; case State.Idle: - if(e.b && !activeTimeout){ // no need to check Bangle.CLKINFO_FOCUS - // first touch - if (e.y <= 40){ + if(e.b && !touchDown){ // no need to check Bangle.CLKINFO_FOCUS + if(e.y <= 40){ state = State.TopDrag startY = e.y; console.log(" topdrag detected, starting @ " + startY); }else{ console.log(" ignoring this drag (too low @ " + e.y + ")"); state = State.IgnoreCurrent; + overlay = undefined } - } + } break; case State.TopDrag: if(e.b === 0){ console.log("topdrag stopped, distance: " + (e.y - startY)); - if(e.y > startY + initDistance){ + if(e.y > startY + dragDistance){ console.log("activating"); - state = State.Active; - overlay!.setBottom(g.getHeight()); activate(); break; } console.log("returning to idle"); state = State.Idle; - Bangle.setLCDOverlay(); + overlay?.hide(); + overlay = undefined; }else{ // partial drag, show UI feedback: - const dragOffset = 38; + const dragOffset = 32; - // @ts-ignore - if (!overlay) global.overlay = overlay = new Overlay(); + if (!overlay) overlay = new Overlay(); overlay.setBottom(e.y - dragOffset); } break; case State.Active: console.log("stolen drag handling, do whatever here"); - if(1)return; - // Espruino/35c8cb9be11 - E.stopEventPropagation && E.stopEventPropagation(); + E.stopEventPropagation?.(); + if(e.b){ + if(!touchDown){ + startY = e.y; + }else if(startY){ + const dist = Math.max(0, startY - e.y); - if(e.b === 0){ - // released - const wasDragging = dragging; - dragging = false; - - if(waitForRelease){ - waitForRelease = false; - return; - } - - if(!wasDragging // i.e. tap - || (Math.abs(e.x - anchor.x) < 2 && Math.abs(e.y - anchor.y) < 2)) - { - toggle(); - onEvent(); - return; - } - } - if(waitForRelease) return; - - if(e.b && !dragging){ - dragging = true; - setStart(e); - Object.assign(anchor, start); - return; - } - - const dx = e.x - start.x; - const dy = e.y - start.y; - - if(Math.abs(dy) > 25 && Math.abs(dx) > 25){ - // diagonal, ignore - setStart(e); - waitForRelease = true; - return; - } - - // had a drag in a single axis - if(dx > 40){ next(); onEvent(); waitForRelease = true; } - else if(dx < -40){ prev(); onEvent(); waitForRelease = true; } - else if(dy > 30){ down(); onEvent(); setStart(e); } - else if(dy < -30){ up(); onEvent(); setStart(e); } - break; + overlay!.setBottom(g.getHeight() - dist); + } + }else if(e.b === 0 && startY > dragDistance){ + deactivate(); + } + break; } + if(e.b) touchDown = true; }) satisfies DragCallback; + const onTouch = ((_btn, _xy) => { + // TODO: button presses + }) satisfies TouchCallback; + const activate = () => { - listen(); + state = State.Active; + startY = 0; + Bangle.prependListener("touch", onTouch); Bangle.buzz(20); + overlay!.setBottom(g.getHeight()); }; - const setStart = ({ x, y }: { x: number, y: number }) => { - start.x = x; - start.y = y; - }; + const deactivate = () => { + Bangle.removeListener("touch", onTouch); + state = State.Idle; + overlay?.hide(); + }; - const onEvent = () => { - Bangle.buzz(20); // feedback event sent - listen(); // had an event, keep listening for more - }; + Bangle.prependListener("drag", onDrag); - const listen = () => { - const wasActive = !!activeTimeout; - if(!wasActive){ - waitForRelease = true; // wait for first touch up before accepting gestures - - //Bangle.on("drag", onDrag); - - // move our drag to the start of the event listener array - const dragHandlers = (Bangle as BangleEvents)["#ondrag"] - - if(dragHandlers && typeof dragHandlers !== "function"){ - (Bangle as BangleEvents)["#ondrag"] = [onDrag as undefined | typeof onDrag].concat( - dragHandlers.filter((f: unknown) => f !== onDrag) - ); - } - - redraw(); - } - - if(activeTimeout) clearTimeout(activeTimeout); - activeTimeout = setTimeout(() => { - activeTimeout = undefined; - - //Bangle.removeListener("drag", onDrag); - - redraw(); - }, 3000); - }; - - Bangle.on("drag", onDrag); - - const redraw = () => setTimeout(Bangle.drawWidgets, 50); + const redraw = () => setTimeout(Bangle.drawWidgets, 10); const connected = NRF.getSecurityStatus().connected; WIDGETS["hid"] = { @@ -242,7 +204,7 @@ draw: function() { if(this.width === 0) return; g.drawImage( - activeTimeout + state === State.Active ? require("heatshrink").decompress(atob("jEYxH+AEfH44XXAAYXXDKIXZDYp3pC/6KHUMwWHC/4XvUy4YGdqoA/AFoA==")) : require("heatshrink").decompress(atob("jEYxH+AEcdjoXXAAYXXDKIXZDYp3pC/6KHUMwWHC/4XvUy4YGdqoA/AFoA==")), this.x! + 2, @@ -281,9 +243,11 @@ } }; - const next = () => /*DEBUG ? console.log("next") : */ sendHid(0x01); - const prev = () => /*DEBUG ? console.log("prev") : */ sendHid(0x02); - const toggle = () => /*DEBUG ? console.log("toggle") : */ sendHid(0x10); - const up = () => /*DEBUG ? console.log("up") : */ sendHid(0x40); - const down = () => /*DEBUG ? console.log("down") : */ sendHid(0x80); + const hid = { + next: () => /*DEBUG ? console.log("next") : */ sendHid(0x01), + prev: () => /*DEBUG ? console.log("prev") : */ sendHid(0x02), + toggle: () => /*DEBUG ? console.log("toggle") : */ sendHid(0x10), + up: () => /*DEBUG ? console.log("up") : */ sendHid(0x40), + down: () => /*DEBUG ? console.log("down") : */ sendHid(0x80), + }; })()