mirror of https://github.com/espruino/BangleApps
Merge pull request #2743 from bobrippling/widhid-exception
widhid: avoid clashing with other swipe/drag handlerspull/2758/head
commit
ced3783ae5
|
@ -0,0 +1,3 @@
|
|||
0.01: New widget - music control via a swipe
|
||||
0.02: Improve interactivity - avoid responding to swipes when a menu or
|
||||
launcher is active.
|
|
@ -13,6 +13,7 @@ Swipe down to enable - note the icon changes from blue to orange, indicating it'
|
|||
|
||||
All other watch interaction is disabled for 3 seconds, to prevent clashing taps/drags - this period is extended as you continue to alter the volume, play/pause and jump between tracks.
|
||||
|
||||
Requires espruino firmware > 2v17 to avoid event handler clashes.
|
||||
|
||||
# Setup / Technical details
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"id": "widhid",
|
||||
"name": "Bluetooth Music Swipe Control Widget",
|
||||
"shortName": "BLE Swipe Widget",
|
||||
"version": "0.01",
|
||||
"version": "0.02",
|
||||
"description": "Based on Swipe Bluetooth Music Controls (based on Bluetooth Music Controls). Swipe down to enable, then swipe up/down for volume, left/right for previous and next and tap for play/pause. Enable HID in settings, pair with your phone/computer, then use this widget to control music from your watch!",
|
||||
"icon": "icon.png",
|
||||
"readme": "README.md",
|
||||
|
|
|
@ -11,16 +11,13 @@
|
|||
var activeTimeout;
|
||||
var waitForRelease = true;
|
||||
var onSwipe = (function (_lr, ud) {
|
||||
if (Bangle.CLKINFO_FOCUS)
|
||||
return;
|
||||
if (!activeTimeout && ud > 0) {
|
||||
if (ud > 0 && !activeTimeout && !Bangle.CLKINFO_FOCUS) {
|
||||
listen();
|
||||
Bangle.buzz(20);
|
||||
}
|
||||
});
|
||||
var onDrag = (function (e) {
|
||||
if (Bangle.CLKINFO_FOCUS)
|
||||
return;
|
||||
E.stopEventPropagation && E.stopEventPropagation();
|
||||
if (e.b === 0) {
|
||||
var wasDragging = dragging;
|
||||
dragging = false;
|
||||
|
@ -82,9 +79,9 @@
|
|||
var listen = function () {
|
||||
var wasActive = !!activeTimeout;
|
||||
if (!wasActive) {
|
||||
suspendOthers();
|
||||
waitForRelease = true;
|
||||
Bangle.on("drag", onDrag);
|
||||
Bangle["#ondrag"] = [onDrag].concat(Bangle["#ondrag"].filter(function (f) { return f !== onDrag; }));
|
||||
redraw();
|
||||
}
|
||||
if (activeTimeout)
|
||||
|
@ -92,7 +89,6 @@
|
|||
activeTimeout = setTimeout(function () {
|
||||
activeTimeout = undefined;
|
||||
Bangle.removeListener("drag", onDrag);
|
||||
resumeOthers();
|
||||
redraw();
|
||||
}, 3000);
|
||||
};
|
||||
|
@ -131,46 +127,4 @@
|
|||
var toggle = function () { return sendHid(0x10); };
|
||||
var up = function () { return sendHid(0x40); };
|
||||
var down = function () { return sendHid(0x80); };
|
||||
var touchEvents = {
|
||||
tap: null,
|
||||
gesture: null,
|
||||
aiGesture: null,
|
||||
swipe: null,
|
||||
touch: null,
|
||||
drag: null,
|
||||
stroke: null,
|
||||
};
|
||||
var suspendOthers = function () {
|
||||
for (var event in touchEvents) {
|
||||
var handlers = Bangle["#on".concat(event)];
|
||||
if (!handlers)
|
||||
continue;
|
||||
var newEvents = void 0;
|
||||
if (handlers instanceof Array)
|
||||
newEvents = handlers.slice();
|
||||
else
|
||||
newEvents = [handlers];
|
||||
for (var _i = 0, newEvents_1 = newEvents; _i < newEvents_1.length; _i++) {
|
||||
var handler = newEvents_1[_i];
|
||||
Bangle.removeListener(event, handler);
|
||||
}
|
||||
touchEvents[event] = newEvents;
|
||||
}
|
||||
};
|
||||
var resumeOthers = function () {
|
||||
for (var event in touchEvents) {
|
||||
var handlers = touchEvents[event];
|
||||
touchEvents[event] = null;
|
||||
if (handlers)
|
||||
for (var _i = 0, handlers_1 = handlers; _i < handlers_1.length; _i++) {
|
||||
var handler = handlers_1[_i];
|
||||
try {
|
||||
Bangle.on(event, handler);
|
||||
}
|
||||
catch (e) {
|
||||
console.log("couldn't restore \"".concat(event, "\" handler:"), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
|
|
@ -14,16 +14,16 @@
|
|||
let waitForRelease = true;
|
||||
|
||||
const onSwipe = ((_lr, ud) => {
|
||||
if((Bangle as BangleExt).CLKINFO_FOCUS) return;
|
||||
|
||||
if(!activeTimeout && ud! > 0){
|
||||
// do these checks in order of cheapness
|
||||
if(ud! > 0 && !activeTimeout && !(Bangle as BangleExt).CLKINFO_FOCUS){
|
||||
listen();
|
||||
Bangle.buzz(20);
|
||||
}
|
||||
}) satisfies SwipeCallback;
|
||||
|
||||
const onDrag = (e => {
|
||||
if((Bangle as BangleExt).CLKINFO_FOCUS) return;
|
||||
// Espruino/35c8cb9be11
|
||||
(E as any).stopEventPropagation && (E as any).stopEventPropagation();
|
||||
|
||||
if(e.b === 0){
|
||||
// released
|
||||
|
@ -81,9 +81,14 @@
|
|||
const listen = () => {
|
||||
const wasActive = !!activeTimeout;
|
||||
if(!wasActive){
|
||||
suspendOthers();
|
||||
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
|
||||
(Bangle as any)["#ondrag"] = [onDrag].concat(
|
||||
(Bangle as any)["#ondrag"].filter((f: unknown) => f !== onDrag)
|
||||
);
|
||||
|
||||
redraw();
|
||||
}
|
||||
|
||||
|
@ -92,7 +97,6 @@
|
|||
activeTimeout = undefined;
|
||||
|
||||
Bangle.removeListener("drag", onDrag);
|
||||
resumeOthers();
|
||||
|
||||
redraw();
|
||||
}, 3000);
|
||||
|
@ -147,53 +151,4 @@
|
|||
const toggle = () => /*DEBUG ? console.log("toggle") : */ sendHid(0x10);
|
||||
const up = () => /*DEBUG ? console.log("up") : */ sendHid(0x40);
|
||||
const down = () => /*DEBUG ? console.log("down") : */ sendHid(0x80);
|
||||
|
||||
// similarly to the lightswitch app, we tangle with the listener arrays to
|
||||
// disable event handlers
|
||||
type Handler = () => void;
|
||||
const touchEvents: {
|
||||
[key: string]: null | Handler[]
|
||||
} = {
|
||||
tap: null,
|
||||
gesture: null,
|
||||
aiGesture: null,
|
||||
swipe: null,
|
||||
touch: null,
|
||||
drag: null,
|
||||
stroke: null,
|
||||
};
|
||||
|
||||
const suspendOthers = () => {
|
||||
for(const event in touchEvents){
|
||||
const handlers: Handler[] | Handler | undefined
|
||||
= (Bangle as any)[`#on${event}`];
|
||||
|
||||
if(!handlers) continue;
|
||||
|
||||
let newEvents;
|
||||
if(handlers instanceof Array)
|
||||
newEvents = handlers.slice();
|
||||
else
|
||||
newEvents = [handlers /* single fn */];
|
||||
|
||||
for(const handler of newEvents)
|
||||
Bangle.removeListener(event, handler);
|
||||
|
||||
touchEvents[event] = newEvents;
|
||||
}
|
||||
};
|
||||
const resumeOthers = () => {
|
||||
for(const event in touchEvents){
|
||||
const handlers = touchEvents[event];
|
||||
touchEvents[event] = null;
|
||||
|
||||
if(handlers)
|
||||
for(const handler of handlers)
|
||||
try{
|
||||
Bangle.on(event as any, handler);
|
||||
}catch(e){
|
||||
console.log(`couldn't restore "${event}" handler:`, e);
|
||||
}
|
||||
}
|
||||
};
|
||||
})()
|
||||
|
|
Loading…
Reference in New Issue