commit
8707307195
|
|
@ -0,0 +1,21 @@
|
||||||
|
# Description
|
||||||
|
|
||||||
|
A music control widget based on [Swipe Bluetooth Music Controls] (based on [Bluetooth Music Controls]).
|
||||||
|
By operating as a widget, you can control music without leaving your current app (e.g. on a run, bike ride or just watching the clock).
|
||||||
|
|
||||||
|
|
||||||
|
[Swipe Bluetooth Music Controls]: https://github.com/espruino/BangleApps/tree/master/apps/hidmsicswipe
|
||||||
|
[Bluetooth Music Controls]: https://github.com/espruino/BangleApps/tree/master/apps/hidmsic
|
||||||
|
|
||||||
|
# Usage
|
||||||
|
|
||||||
|
Swipe down to enable - note the icon changes from blue to orange, indicating it's listening for your instruction. Then drag up/down for volume, left/right for previous and next and tap for play/pause.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
|
||||||
|
# Setup / Technical details
|
||||||
|
|
||||||
|
Note that HID must be enabled in settings. Then provided you're paired with your phone/computer, the widget icon will appear and you can control music from your clock face!
|
||||||
|
|
||||||
|
The app disables all other drag and tap handlers while this widget is "active" (in a similar manner to [`backswipe`](https://github.com/espruino/BangleApps/pull/2524#issuecomment-1406230564) and [`lightswitch`](https://github.com/espruino/Espruino/issues/2151#issuecomment-1042423211)).
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
require("heatshrink").decompress(atob("mEwwkBiIA/AEhtDNSSHGCyIbFGJ0QFAowIA48QE4oGBBAomBHAxXHA4IJED5IXJCAcQIAxGGC4YKEI44HCBAxAGO4wXBB4JYGNRBfHC/6HFB4wXHUA6YIC4oOCGA6YGU4quHJ5LXGdJIXNF65fIC5AQFQorHJXxwXJK5xGJC65GsgJG/Iw4uUfgIuUC4QWTIwIusLq4WBFy50tC1YXBCyoA/ADw="))
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 2.1 KiB |
|
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"id": "widhid",
|
||||||
|
"name": "Bluetooth Music Swipe Control Widget",
|
||||||
|
"shortName": "BLE Swipe Widget",
|
||||||
|
"version": "0.01",
|
||||||
|
"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",
|
||||||
|
"type": "widget",
|
||||||
|
"tags": "widget,bluetooth,music",
|
||||||
|
"supports": ["BANGLEJS2"],
|
||||||
|
"storage": [
|
||||||
|
{"name":"widhid.wid.js","url":"wid.js"},
|
||||||
|
{"name":"widhid.img","url":"icon.js","evaluate":true}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,176 @@
|
||||||
|
(function () {
|
||||||
|
var settings = require("Storage").readJSON("setting.json", true) || { HID: false };
|
||||||
|
if (settings.HID !== "kbmedia") {
|
||||||
|
console.log("widhid: can't enable, HID setting isn't \"kbmedia\"");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
delete settings;
|
||||||
|
var anchor = { x: 0, y: 0 };
|
||||||
|
var start = { x: 0, y: 0 };
|
||||||
|
var dragging = false;
|
||||||
|
var activeTimeout;
|
||||||
|
var waitForRelease = true;
|
||||||
|
var onSwipe = (function (_lr, ud) {
|
||||||
|
if (Bangle.CLKINFO_FOCUS)
|
||||||
|
return;
|
||||||
|
if (!activeTimeout && ud > 0) {
|
||||||
|
listen();
|
||||||
|
Bangle.buzz(20);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var onDrag = (function (e) {
|
||||||
|
if (Bangle.CLKINFO_FOCUS)
|
||||||
|
return;
|
||||||
|
if (e.b === 0) {
|
||||||
|
var wasDragging = dragging;
|
||||||
|
dragging = false;
|
||||||
|
if (waitForRelease) {
|
||||||
|
waitForRelease = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!wasDragging
|
||||||
|
|| (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;
|
||||||
|
}
|
||||||
|
var dx = e.x - start.x;
|
||||||
|
var dy = e.y - start.y;
|
||||||
|
if (Math.abs(dy) > 25 && Math.abs(dx) > 25) {
|
||||||
|
setStart(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var setStart = function (_a) {
|
||||||
|
var x = _a.x, y = _a.y;
|
||||||
|
start.x = x;
|
||||||
|
start.y = y;
|
||||||
|
};
|
||||||
|
var onEvent = function () {
|
||||||
|
Bangle.buzz(20);
|
||||||
|
listen();
|
||||||
|
};
|
||||||
|
var listen = function () {
|
||||||
|
var wasActive = !!activeTimeout;
|
||||||
|
if (!wasActive) {
|
||||||
|
suspendOthers();
|
||||||
|
waitForRelease = true;
|
||||||
|
Bangle.on("drag", onDrag);
|
||||||
|
redraw();
|
||||||
|
}
|
||||||
|
if (activeTimeout)
|
||||||
|
clearTimeout(activeTimeout);
|
||||||
|
activeTimeout = setTimeout(function () {
|
||||||
|
activeTimeout = undefined;
|
||||||
|
Bangle.removeListener("drag", onDrag);
|
||||||
|
resumeOthers();
|
||||||
|
redraw();
|
||||||
|
}, 3000);
|
||||||
|
};
|
||||||
|
var redraw = function () { return setTimeout(Bangle.drawWidgets, 50); };
|
||||||
|
var connected = NRF.getSecurityStatus().connected;
|
||||||
|
WIDGETS["hid"] = {
|
||||||
|
area: "tr",
|
||||||
|
sortorder: -20,
|
||||||
|
draw: function () {
|
||||||
|
if (this.width === 0)
|
||||||
|
return;
|
||||||
|
g.drawImage(activeTimeout
|
||||||
|
? require("heatshrink").decompress(atob("jEYxH+AEfH44XXAAYXXDKIXZDYp3pC/6KHUMwWHC/4XvUy4YGdqoA/AFoA=="))
|
||||||
|
: require("heatshrink").decompress(atob("jEYxH+AEcdjoXXAAYXXDKIXZDYp3pC/6KHUMwWHC/4XvUy4YGdqoA/AFoA==")), this.x + 2, this.y + 2);
|
||||||
|
},
|
||||||
|
width: connected ? 24 : 0,
|
||||||
|
};
|
||||||
|
if (connected)
|
||||||
|
Bangle.on("swipe", onSwipe);
|
||||||
|
delete connected;
|
||||||
|
NRF.on("connect", function () {
|
||||||
|
WIDGETS["hid"].width = 24;
|
||||||
|
Bangle.on("swipe", onSwipe);
|
||||||
|
redraw();
|
||||||
|
});
|
||||||
|
NRF.on("disconnect", function () {
|
||||||
|
WIDGETS["hid"].width = 0;
|
||||||
|
Bangle.removeListener("swipe", onSwipe);
|
||||||
|
redraw();
|
||||||
|
});
|
||||||
|
var sendHid = function (code) {
|
||||||
|
NRF.sendHIDReport([1, code], function () { return NRF.sendHIDReport([1, 0]); });
|
||||||
|
};
|
||||||
|
var next = function () { return sendHid(0x01); };
|
||||||
|
var prev = function () { return sendHid(0x02); };
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
@ -0,0 +1,199 @@
|
||||||
|
(() => {
|
||||||
|
const settings: Settings = require("Storage").readJSON("setting.json", true) || { HID: false } as Settings;
|
||||||
|
if (settings.HID !== "kbmedia") {
|
||||||
|
console.log("widhid: can't enable, HID setting isn't \"kbmedia\"");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// @ts-ignore
|
||||||
|
delete settings;
|
||||||
|
|
||||||
|
let anchor = {x:0,y:0};
|
||||||
|
let start = {x:0,y:0};
|
||||||
|
let dragging = false;
|
||||||
|
let activeTimeout: number | undefined;
|
||||||
|
let waitForRelease = true;
|
||||||
|
|
||||||
|
const onSwipe = ((_lr, ud) => {
|
||||||
|
if((Bangle as BangleExt).CLKINFO_FOCUS) return;
|
||||||
|
|
||||||
|
if(!activeTimeout && ud! > 0){
|
||||||
|
listen();
|
||||||
|
Bangle.buzz(20);
|
||||||
|
}
|
||||||
|
}) satisfies SwipeCallback;
|
||||||
|
|
||||||
|
const onDrag = (e => {
|
||||||
|
if((Bangle as BangleExt).CLKINFO_FOCUS) return;
|
||||||
|
|
||||||
|
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);
|
||||||
|
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); }
|
||||||
|
}) satisfies DragCallback;
|
||||||
|
|
||||||
|
const setStart = ({ x, y }: { x: number, y: number }) => {
|
||||||
|
start.x = x;
|
||||||
|
start.y = y;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onEvent = () => {
|
||||||
|
Bangle.buzz(20); // feedback event sent
|
||||||
|
listen(); // had an event, keep listening for more
|
||||||
|
};
|
||||||
|
|
||||||
|
const listen = () => {
|
||||||
|
const wasActive = !!activeTimeout;
|
||||||
|
if(!wasActive){
|
||||||
|
suspendOthers();
|
||||||
|
waitForRelease = true; // wait for first touch up before accepting gestures
|
||||||
|
Bangle.on("drag", onDrag);
|
||||||
|
redraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(activeTimeout) clearTimeout(activeTimeout);
|
||||||
|
activeTimeout = setTimeout(() => {
|
||||||
|
activeTimeout = undefined;
|
||||||
|
|
||||||
|
Bangle.removeListener("drag", onDrag);
|
||||||
|
resumeOthers();
|
||||||
|
|
||||||
|
redraw();
|
||||||
|
}, 3000);
|
||||||
|
};
|
||||||
|
|
||||||
|
const redraw = () => setTimeout(Bangle.drawWidgets, 50);
|
||||||
|
|
||||||
|
const connected = NRF.getSecurityStatus().connected;
|
||||||
|
WIDGETS["hid"] = {
|
||||||
|
area: "tr",
|
||||||
|
sortorder: -20,
|
||||||
|
draw: function() {
|
||||||
|
if(this.width === 0) return;
|
||||||
|
g.drawImage(
|
||||||
|
activeTimeout
|
||||||
|
? require("heatshrink").decompress(atob("jEYxH+AEfH44XXAAYXXDKIXZDYp3pC/6KHUMwWHC/4XvUy4YGdqoA/AFoA=="))
|
||||||
|
: require("heatshrink").decompress(atob("jEYxH+AEcdjoXXAAYXXDKIXZDYp3pC/6KHUMwWHC/4XvUy4YGdqoA/AFoA==")),
|
||||||
|
this.x! + 2,
|
||||||
|
this.y! + 2
|
||||||
|
);
|
||||||
|
},
|
||||||
|
width: connected ? 24 : 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
if(connected)
|
||||||
|
Bangle.on("swipe", onSwipe);
|
||||||
|
// @ts-ignore
|
||||||
|
delete connected;
|
||||||
|
|
||||||
|
NRF.on("connect", () => {
|
||||||
|
WIDGETS["hid"]!.width = 24;
|
||||||
|
Bangle.on("swipe", onSwipe);
|
||||||
|
redraw();
|
||||||
|
});
|
||||||
|
NRF.on("disconnect", () => {
|
||||||
|
WIDGETS["hid"]!.width = 0;
|
||||||
|
Bangle.removeListener("swipe", onSwipe);
|
||||||
|
redraw();
|
||||||
|
});
|
||||||
|
|
||||||
|
//const DEBUG = true;
|
||||||
|
const sendHid = (code: number) => {
|
||||||
|
//if(DEBUG) return;
|
||||||
|
NRF.sendHIDReport(
|
||||||
|
[1, code],
|
||||||
|
() => NRF.sendHIDReport([1, 0]),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})()
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 739 B |
Binary file not shown.
|
After Width: | Height: | Size: 738 B |
|
|
@ -57,3 +57,7 @@ declare module ClockInfo {
|
||||||
focus: boolean,
|
focus: boolean,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface BangleExt {
|
||||||
|
CLKINFO_FOCUS?: true;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1584,7 +1584,7 @@ declare class NRF {
|
||||||
* @param {any} callback - A callback function to be called when the data is sent
|
* @param {any} callback - A callback function to be called when the data is sent
|
||||||
* @url http://www.espruino.com/Reference#l_NRF_sendHIDReport
|
* @url http://www.espruino.com/Reference#l_NRF_sendHIDReport
|
||||||
*/
|
*/
|
||||||
static sendHIDReport(data: any, callback: any): void;
|
static sendHIDReport(data: number[], callback?: () => void): void
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if Apple Notification Center Service (ANCS) is currently active on the BLE
|
* Check if Apple Notification Center Service (ANCS) is currently active on the BLE
|
||||||
|
|
@ -3188,8 +3188,10 @@ declare class Puck {
|
||||||
* Check out [the Puck.js page on the
|
* Check out [the Puck.js page on the
|
||||||
* accelerometer](http://www.espruino.com/Puck.js#on-board-peripherals) for more
|
* accelerometer](http://www.espruino.com/Puck.js#on-board-peripherals) for more
|
||||||
* information.
|
* information.
|
||||||
|
* **Note:** Puck.js cannot currently read every sample from the
|
||||||
|
* accelerometer at sample rates above 208Hz.
|
||||||
*
|
*
|
||||||
* @param {number} samplerate - The sample rate in Hz, or undefined
|
* @param {number} samplerate - The sample rate in Hz, or `undefined` (default is 12.5 Hz)
|
||||||
* @url http://www.espruino.com/Reference#l_Puck_accelOn
|
* @url http://www.espruino.com/Reference#l_Puck_accelOn
|
||||||
*/
|
*/
|
||||||
static accelOn(samplerate: number): void;
|
static accelOn(samplerate: number): void;
|
||||||
|
|
@ -3819,6 +3821,9 @@ declare class Bangle {
|
||||||
* and polling rate may not be exact. The algorithm's filtering is tuned for
|
* and polling rate may not be exact. The algorithm's filtering is tuned for
|
||||||
* 20-40ms poll intervals, so higher/lower intervals may effect the reliability
|
* 20-40ms poll intervals, so higher/lower intervals may effect the reliability
|
||||||
* of the BPM reading.
|
* of the BPM reading.
|
||||||
|
* * `hrmSportMode` - on the newest Bangle.js 2 builds with with the proprietary
|
||||||
|
* heart rate algorithm, this is the sport mode passed to the algorithm. See `libs/misc/vc31_binary/algo.h`
|
||||||
|
* for more info. 0 = normal (default), 1 = running, 2 = ...
|
||||||
* * `seaLevelPressure` (Bangle.js 2) Normally 1013.25 millibars - this is used for
|
* * `seaLevelPressure` (Bangle.js 2) Normally 1013.25 millibars - this is used for
|
||||||
* calculating altitude with the pressure sensor
|
* calculating altitude with the pressure sensor
|
||||||
* Where accelerations are used they are in internal units, where `8192 = 1g`
|
* Where accelerations are used they are in internal units, where `8192 = 1g`
|
||||||
|
|
@ -13222,7 +13227,7 @@ declare module "Storage" {
|
||||||
* @returns {any} An object containing parsed JSON from the file, or undefined
|
* @returns {any} An object containing parsed JSON from the file, or undefined
|
||||||
* @url http://www.espruino.com/Reference#l_Storage_readJSON
|
* @url http://www.espruino.com/Reference#l_Storage_readJSON
|
||||||
*/
|
*/
|
||||||
function readJSON(name: string, noExceptions: boolean): any;
|
function readJSON(name: string, noExceptions: ShortBoolean): any;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read a file from the flash storage area that has been written with
|
* Read a file from the flash storage area that has been written with
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
type Settings = {
|
||||||
|
beep: boolean,
|
||||||
|
vibrate: boolean,
|
||||||
|
quiet: number,
|
||||||
|
|
||||||
|
ble: boolean,
|
||||||
|
blerepl: boolean,
|
||||||
|
HID?: false | "kbmedia" | "kb" | "com" | "joy",
|
||||||
|
|
||||||
|
passkey?: string,
|
||||||
|
whitelist_disabled?: boolean,
|
||||||
|
whitelist: string[],
|
||||||
|
|
||||||
|
theme: Theme,
|
||||||
|
|
||||||
|
brightness: number,
|
||||||
|
timeout: number,
|
||||||
|
rotate: number,
|
||||||
|
|
||||||
|
options: SettingsOptions,
|
||||||
|
|
||||||
|
timezone: number,
|
||||||
|
log: number,
|
||||||
|
|
||||||
|
clock: string,
|
||||||
|
clockHasWidgets: boolean,
|
||||||
|
launcher: string,
|
||||||
|
};
|
||||||
|
|
||||||
|
type SettingsTheme = {
|
||||||
|
fg: string,
|
||||||
|
bg: string,
|
||||||
|
fg2: string,
|
||||||
|
bg2: string,
|
||||||
|
fgH: string,
|
||||||
|
bgH: string,
|
||||||
|
dark: boolean,
|
||||||
|
};
|
||||||
|
|
||||||
|
type SettingsOptions = {
|
||||||
|
wakeOnBTN1: boolean,
|
||||||
|
wakeOnBTN2: boolean,
|
||||||
|
wakeOnBTN3: boolean,
|
||||||
|
wakeOnFaceUp: boolean,
|
||||||
|
wakeOnTouch: boolean,
|
||||||
|
|
||||||
|
wakeOnTwist: boolean,
|
||||||
|
twistThreshold: number,
|
||||||
|
twistMaxY: number,
|
||||||
|
twistTimeout: number,
|
||||||
|
};
|
||||||
Loading…
Reference in New Issue