forked from FOSS/BangleApps
ctrlpad: changing code from swipes to interact
parent
6c19423c24
commit
d9c2bc94dd
|
@ -1,4 +1,22 @@
|
|||
(() => {
|
||||
if(!Bangle.prependListener){
|
||||
type Event<T> = T extends `#on${infer Evt}` ? Evt : never;
|
||||
|
||||
Bangle.prependListener = function(
|
||||
evt: Event<keyof BangleEvents>,
|
||||
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<any>).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,27 +102,27 @@
|
|||
}
|
||||
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.b && !touchDown){ // no need to check Bangle.CLKINFO_FOCUS
|
||||
if(e.y <= 40){
|
||||
state = State.TopDrag
|
||||
startY = e.y;
|
||||
|
@ -108,6 +130,7 @@
|
|||
}else{
|
||||
console.log(" ignoring this drag (too low @ " + e.y + ")");
|
||||
state = State.IgnoreCurrent;
|
||||
overlay = undefined
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -115,125 +138,64 @@
|
|||
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;
|
||||
overlay!.setBottom(g.getHeight() - dist);
|
||||
}
|
||||
|
||||
if(!wasDragging // i.e. tap
|
||||
|| (Math.abs(e.x - anchor.x) < 2 && Math.abs(e.y - anchor.y) < 2))
|
||||
{
|
||||
toggle();
|
||||
onEvent();
|
||||
return;
|
||||
}else if(e.b === 0 && startY > dragDistance){
|
||||
deactivate();
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
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),
|
||||
};
|
||||
})()
|
||||
|
|
Loading…
Reference in New Issue