mirror of https://github.com/espruino/BangleApps
Update app.js
* Improve handling of default local options. * Add timeout to internal menu. * Allow menus to be lazified (as in the Round face). * Rename options.active to activeFg, restoring consistency and avoiding a name collision. * Fix broken bounding box logic for drags. * Defer screen clear on face reset to reduce blinking.pull/1070/head
parent
15db7a3953
commit
47eb4a6346
|
@ -1,3 +1,4 @@
|
|||
/* -*- mode: Javascript; c-basic-offset: 2; indent-tabs-mode: nil; coding: latin-1 -*- */
|
||||
// pooqRoman
|
||||
//
|
||||
// Copyright (c) 2021 Stephen P Spackman
|
||||
|
@ -54,8 +55,9 @@ class Options {
|
|||
this.id = this.constructor.id;
|
||||
this.file = `${this.id}.json`;
|
||||
this.backing = storage.readJSON(this.file, true) || {};
|
||||
this.defaults = this.constructor.defaults;
|
||||
Object.keys(this.defaults).forEach(k => this.bless(k));
|
||||
Object.setPrototypeOf(this.backing, this.constructor.defaults);
|
||||
this.reactivator = _ => this.active();
|
||||
Object.keys(this.constructor.defaults).forEach(k => this.bless(k));
|
||||
}
|
||||
|
||||
writeBack(delay) {
|
||||
|
@ -71,29 +73,41 @@ class Options {
|
|||
|
||||
bless(k) {
|
||||
Object.defineProperty(this, k, {
|
||||
get: () => this.backing[k] == null ? this.defaults[k] : this.backing[k],
|
||||
get: () => this.backing[k],
|
||||
set: v => {
|
||||
this.backing[k] = v;
|
||||
// Ten second writeback delay, since the user will roll values up and down.
|
||||
this.writeBack(10000);
|
||||
return this.backing[k] = v;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
showMenu(m) {
|
||||
if (m instanceof Function) m = m();
|
||||
if (m) {
|
||||
for (const k in m) if ('init' in m[k]) m[k].value = m[k].init();
|
||||
m[''].selected = -1; // Workaround for self-selection bug.
|
||||
Bangle.on('drag', this.reactivator);
|
||||
this.active();
|
||||
} else {
|
||||
if (this.bored) clearTimeout(this.bored);
|
||||
this.bored = null;
|
||||
Bangle.removeListener('drag', this.reactivator);
|
||||
this.emit('done');
|
||||
}
|
||||
g.clear(true);
|
||||
E.showMenu(m);
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.backing = {};
|
||||
this.writeBack(0);
|
||||
active() {
|
||||
if (this.bored) clearTimeout(this.bored);
|
||||
this.bored = setTimeout(_ => this.showMenu(), 15000);
|
||||
}
|
||||
|
||||
interact() {this.showMenu(this.menu);}
|
||||
reset() {
|
||||
this.backing = {__proto__: this.constructor.defaults};
|
||||
this.writeBack(0);
|
||||
}
|
||||
}
|
||||
|
||||
class RomanOptions extends Options {
|
||||
|
@ -101,7 +115,7 @@ class RomanOptions extends Options {
|
|||
super();
|
||||
this.menu = {
|
||||
'': {title: '* face options *'},
|
||||
'< Back': _ => {this.showMenu(); this.emit('done');},
|
||||
'< Back': _ => this.showMenu(),
|
||||
Ticks: {
|
||||
init: _ => this.resolution,
|
||||
min: 0, max: 3,
|
||||
|
@ -124,9 +138,11 @@ class RomanOptions extends Options {
|
|||
onchange: x => this.calendric = x,
|
||||
format: x => ['none', 'day', 'date'][x]
|
||||
},
|
||||
Defaults: _ => {this.reset();}
|
||||
Defaults: _ => {this.reset(); this.interact();}
|
||||
};
|
||||
}
|
||||
|
||||
interact() {this.showMenu(this.menu);}
|
||||
}
|
||||
|
||||
RomanOptions.id = 'pooqroman';
|
||||
|
@ -147,7 +163,7 @@ RomanOptions.defaults = {
|
|||
hubFg: g.theme.fg,
|
||||
alarmFg: '#f00',
|
||||
timerFg: '#0f0',
|
||||
active: g.theme.fg2,
|
||||
activeFg: g.theme.fg2,
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -434,7 +450,7 @@ class Sidebar {
|
|||
}
|
||||
static gpsColour(o) {
|
||||
const fix = Bangle.getGPSFix();
|
||||
return fix && fix.fix ? o.active : o.barFg;
|
||||
return fix && fix.fix ? o.activeFg : o.barFg;
|
||||
}
|
||||
doPower() {
|
||||
const c = Bangle.isCharging();
|
||||
|
@ -455,7 +471,7 @@ class Sidebar {
|
|||
if (Bangle.isCompassOn()) {
|
||||
const c = Bangle.getCompass();
|
||||
const a = c && this.rate <= 1000;
|
||||
this.g.setColor(a ? this.options.active : this.options.barFg).drawImage(
|
||||
this.g.setColor(a ? this.options.activeFg : this.options.barFg).drawImage(
|
||||
compassI,
|
||||
this.x + 4 + imageWidth(compassI) / 2,
|
||||
this.y + 4 + imageHeight(compassI) / 2,
|
||||
|
@ -470,7 +486,7 @@ class Sidebar {
|
|||
class Roman {
|
||||
constructor(g, events) {
|
||||
this.g = g;
|
||||
this.state = {};
|
||||
this.state = null;
|
||||
const options = this.options = new RomanOptions();
|
||||
this.events = events.loadFromSystem(this.options);
|
||||
this.timescales = [1000, [1000, 60000], 60000, 3600000];
|
||||
|
@ -480,7 +496,7 @@ class Roman {
|
|||
this.seconds = Roman.hand(g, 1, 0.9, 60, _ => options.secondFg);
|
||||
}
|
||||
|
||||
reset() {this.state = {}; this.g.clear(true);}
|
||||
reset() {this.state = null;}
|
||||
|
||||
doIcons(which) {this.state.iconsOk = null;}
|
||||
|
||||
|
@ -544,7 +560,7 @@ class Roman {
|
|||
|
||||
render(d, rate) {
|
||||
const g = this.g;
|
||||
const state = this.state;
|
||||
const state = this.state || (g.clear(true), this.state = {});
|
||||
const options = this.options;
|
||||
const events = this.events;
|
||||
events.clean(d, -39600000); // 11h
|
||||
|
@ -654,8 +670,8 @@ class Clock {
|
|||
drag: e => {
|
||||
if (this.t0) {
|
||||
if (e.b) {
|
||||
e.x > this.xN && (this.xN = e.x) || e.x > this.xX && (this.xX = e.x);
|
||||
e.y > this.yN && (this.yN = e.y) || e.y > this.yX && (this.xY = e.y);
|
||||
e.x < this.xN && (this.xN = e.x) || e.x > this.xX && (this.xX = e.x);
|
||||
e.y < this.yN && (this.yN = e.y) || e.y > this.yX && (this.yX = e.y);
|
||||
} else if (this.xX - this.xN < 20) {
|
||||
if (e.y - this.e0.y < -50) {
|
||||
this.options.resolution > 0 && this.options.resolution--;
|
||||
|
@ -697,6 +713,7 @@ class Clock {
|
|||
this.exception && clearTimeout(this.exception);
|
||||
this.interval && clearInterval(this.interval);
|
||||
this.timeout = this.exception = this.interval = this.rate = null;
|
||||
this.face.reset(); // Cancel any ongoing background rendering
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue