qmsched: switch theme

fixes #1266
pull/1283/head
Richard de Boer 2022-01-12 19:08:19 +01:00
parent 6adb217512
commit 73062edf83
No known key found for this signature in database
GPG Key ID: 8721727971871937
7 changed files with 93 additions and 21 deletions

View File

@ -3919,8 +3919,8 @@
"id": "qmsched", "id": "qmsched",
"name": "Quiet Mode Schedule and Widget", "name": "Quiet Mode Schedule and Widget",
"shortName": "Quiet Mode", "shortName": "Quiet Mode",
"version": "0.06", "version": "0.07",
"description": "Automatically turn Quiet Mode on or off at set times, and change LCD options while Quiet Mode is active.", "description": "Automatically turn Quiet Mode on or off at set times, change theme and LCD options while Quiet Mode is active.",
"icon": "app.png", "icon": "app.png",
"screenshots": [{"url":"screenshot_b1_main.png"},{"url":"screenshot_b1_edit.png"},{"url":"screenshot_b1_lcd.png"}, "screenshots": [{"url":"screenshot_b1_main.png"},{"url":"screenshot_b1_edit.png"},{"url":"screenshot_b1_lcd.png"},
{"url":"screenshot_b2_main.png"},{"url":"screenshot_b2_edit.png"},{"url":"screenshot_b2_lcd.png"}], {"url":"screenshot_b2_main.png"},{"url":"screenshot_b2_edit.png"},{"url":"screenshot_b2_lcd.png"}],

View File

@ -3,4 +3,5 @@
0.03: Bangle.js 2 support 0.03: Bangle.js 2 support
0.04: Move Quiet Mode LCD options from global settings to this app 0.04: Move Quiet Mode LCD options from global settings to this app
0.05: Avoid immediately redrawing widgets on load 0.05: Avoid immediately redrawing widgets on load
0.06: Fix: don't try to redraw widget when widgets not loaded 0.06: Fix: don't try to redraw widget when widgets not loaded
0.07: Option to switch theme

View File

@ -9,6 +9,11 @@ Automatically turn Quiet Mode on or off at set times, and display a widget when
| ![Edit Schedule menu](screenshot_b1_edit.png) | ![Edit Schedule menu](screenshot_b2_edit.png) | | ![Edit Schedule menu](screenshot_b1_edit.png) | ![Edit Schedule menu](screenshot_b2_edit.png) |
| ![LCD Options menu](screenshot_b1_lcd.png) | ![LCD Options menu](screenshot_b2_lcd.png) | | ![LCD Options menu](screenshot_b1_lcd.png) | ![LCD Options menu](screenshot_b2_lcd.png) |
### Switch Theme:
Switch to dark theme during Quiet Mode.
* **NOTE**: This switches between the default "Dark BW" and "Light BW" themes, so custom theme settings will be lost.
### LCD Settings: ### LCD Settings:
If set, these override the default LCD settings while Quiet Mode is active. If set, these override the default LCD settings while Quiet Mode is active.

View File

@ -3,7 +3,7 @@ Bangle.drawWidgets();
const modeNames = ["Off", "Alarms", "Silent"]; const modeNames = ["Off", "Alarms", "Silent"];
// load global brightness setting // load global settings
let bSettings = require('Storage').readJSON('setting.json',true)||{}; let bSettings = require('Storage').readJSON('setting.json',true)||{};
let current = 0|bSettings.quiet; let current = 0|bSettings.quiet;
delete bSettings; // we don't need any other global settings delete bSettings; // we don't need any other global settings
@ -18,6 +18,7 @@ delete bSettings; // we don't need any other global settings
*/ */
function save() { function save() {
require('Storage').writeJSON('qmsched.json', settings); require('Storage').writeJSON('qmsched.json', settings);
eval(require('Storage').read('qmsched.boot.js')); // apply new schedules right away
} }
function get(key, def) { function get(key, def) {
return (key in settings) ? settings[key] : def; return (key in settings) ? settings[key] : def;
@ -77,37 +78,66 @@ function formatTime(t) {
const mins = Math.round((t-hrs)*60); const mins = Math.round((t-hrs)*60);
return (" "+hrs).substr(-2)+":"+("0"+mins).substr(-2); return (" "+hrs).substr(-2)+":"+("0"+mins).substr(-2);
} }
/**
* Apply theme
*/
function applyTheme() {
const theme = (require("Storage").readJSON("setting.json", 1) || {}).theme;
if (theme && theme.dark===g.theme.dark) return; // already correct
g.theme = theme;
delete g.reset;
g._reset = g.reset;
g.reset = function(n) { return g._reset().setColor(g.theme.fg).setBgColor(g.theme.bg); };
g.clear = function(n) { if (n) g.reset(); return g.clearRect(0,0,g.getWidth(),g.getHeight()); };
g.clear(1);
Bangle.drawWidgets();
delete m.lastIdx; // force redraw
m.draw();
}
/**
* Library uses this to make the app update itself
* @param {int} mode New Quite Mode
*/
function setAppMode(mode) {
if (mode === current) return;
current = mode;
delete m.lastIdx; // force redraw
applyTheme();
if (m.lastIdx===undefined) m.draw(); // applyTheme didn't redraw menu, but we need to show updated mode
}
let m;
function showMainMenu() { function showMainMenu() {
let _m, menu = { let menu = {
"": {"title": "Quiet Mode"}, "": {"title": "Quiet Mode"},
"< Exit": () => load() "< Exit": () => load()
}; };
// "Current Mode""Silent" won't fit on Bangle.js 2 // "Current Mode""Silent" won't fit on Bangle.js 2
menu["Current"+((process.env.HWVERSION===2) ? "" : " Mode")] = { menu["Current"+((process.env.HWVERSION===2) ? "" : " Mode")] = {
value: current, value: current,
format: v => modeNames[v], min:0, max:2, wrap: true,
onchange: function(v) { format: () => modeNames[current],
if (v<0) {v = 2;} onchange: require("qmsched").setMode, // library calls setAppMode(), which updates `current`
if (v>2) {v = 0;}
require("qmsched").setMode(v);
current = v;
this.value = v;
},
}; };
scheds.sort((a, b) => (a.hr-b.hr)); scheds.sort((a, b) => (a.hr-b.hr));
scheds.forEach((sched, idx) => { scheds.forEach((sched, idx) => {
menu[formatTime(sched.hr)] = { menu[formatTime(sched.hr)] = {
format: () => modeNames[sched.mode], // abuse format to right-align text format: () => modeNames[sched.mode], // abuse format to right-align text
onchange: function() { onchange: () => {
_m.draw = ()=> {}; // prevent redraw of main menu over edit menu m.draw = ()=> {}; // prevent redraw of main menu over edit menu (needed because we abuse format/onchange)
showEditMenu(idx); showEditMenu(idx);
} }
}; };
}); });
menu["Add Schedule"] = () => showEditMenu(-1); menu["Add Schedule"] = () => showEditMenu(-1);
menu["Switch Theme"] = {
value: !!get("switchTheme"),
format: v => v ? /*LANG*/"Yes" : /*LANG*/"No",
onchange: v => v ? set("switchTheme", v) : unset("switchTheme"),
};
menu["LCD Settings"] = () => showOptionsMenu(); menu["LCD Settings"] = () => showOptionsMenu();
_m = E.showMenu(menu); m = E.showMenu(menu);
} }
function showEditMenu(index) { function showEditMenu(index) {
@ -174,7 +204,7 @@ function showEditMenu(index) {
showMainMenu(); showMainMenu();
}; };
} }
return E.showMenu(menu); m = E.showMenu(menu);
} }
function showOptionsMenu() { function showOptionsMenu() {
@ -244,7 +274,7 @@ function showOptionsMenu() {
onchange: () => {toggle("wakeOnTwist");}, onchange: () => {toggle("wakeOnTwist");},
}, },
}; };
return E.showMenu(oMenu); m = E.showMenu(oMenu);
} }
loadSettings(); loadSettings();

View File

@ -1,5 +1,7 @@
// apply Quiet Mode schedules // apply Quiet Mode schedules
(function qm() { (function qm() {
if (Bangle.qmTimeout) clearTimeout(Bangle.qmTimeout); // so the app can eval() this file to apply changes right away
delete Bangle.qmTimeout;
let bSettings = require('Storage').readJSON('setting.json',true)||{}; let bSettings = require('Storage').readJSON('setting.json',true)||{};
const curr = 0|bSettings.quiet; const curr = 0|bSettings.quiet;
delete bSettings; delete bSettings;
@ -18,7 +20,7 @@
let t = 3600000*(next.hr-hr); // timeout in milliseconds let t = 3600000*(next.hr-hr); // timeout in milliseconds
if (t<0) {t += 86400000;} // scheduled for tomorrow: add a day if (t<0) {t += 86400000;} // scheduled for tomorrow: add a day
/* update quiet mode at the correct time. */ /* update quiet mode at the correct time. */
setTimeout(() => { Bangle.qmTimeout=setTimeout(() => {
require("qmsched").setMode(mode); require("qmsched").setMode(mode);
qm(); // schedule next update qm(); // schedule next update
}, t); }, t);

View File

@ -1,5 +1,37 @@
/** /**
* Apply LCD options for given mode * Apply appropriate theme for given mode
* @param {int} mode Quiet Mode
*/
function switchTheme(mode) {
if (!!mode === g.theme.dark) return; // nothing to do
let s = require("Storage").readJSON("setting.json", 1) || {};
// default themes, copied from settings.js:showThemeMenu()
function cl(x) { return g.setColor(x).getColor(); }
s.theme = mode ? {
// 'Dark BW'
fg: cl("#fff"), bg: cl("#000"),
fg2: cl("#0ff"), bg2: cl("#000"),
fgH: cl("#fff"), bgH: cl("#00f"),
dark: true
} : {
// 'Light BW'
fg: cl("#000"), bg: cl("#fff"),
fg2: cl("#000"), bg2: cl("#cff"),
fgH: cl("#000"), bgH: cl("#0ff"),
dark: false
};
require("Storage").writeJSON("setting.json", s);
if (typeof __FILE__ === 'string') { // undefined means it loaded the default clock
const info = require("Storage").readJSON(__FILE__.split(".")[0]+".info", 1);
if (info && info.type!=="clock") { // info can have no type (but then it isn't a clock)
return; // not a clock: wait for user to switch apps
}
}
// current app is a clock: reload it with new theme
load(global.__FILE__);
}
/**
* Apply LCD options and theme for given mode
* @param {int} mode Quiet Mode * @param {int} mode Quiet Mode
*/ */
exports.applyOptions = function(mode) { exports.applyOptions = function(mode) {
@ -8,6 +40,7 @@ exports.applyOptions = function(mode) {
Bangle.setOptions(get("options", {})); Bangle.setOptions(get("options", {}));
Bangle.setLCDBrightness(get("brightness", 1)); Bangle.setLCDBrightness(get("brightness", 1));
Bangle.setLCDTimeout(get("timeout", 10)); Bangle.setLCDTimeout(get("timeout", 10));
if ((require("Storage").readJSON("qmsched.json", 1) || {}).switchTheme) switchTheme(mode);
}; };
/** /**
* Set new Quiet Mode and apply Bangle options * Set new Quiet Mode and apply Bangle options
@ -20,4 +53,5 @@ exports.setMode = function(mode) {
)); ));
exports.applyOptions(mode); exports.applyOptions(mode);
if (typeof WIDGETS === "object" && "qmsched" in WIDGETS) WIDGETS["qmsched"].draw(); if (typeof WIDGETS === "object" && "qmsched" in WIDGETS) WIDGETS["qmsched"].draw();
if (global.__FILE__ === "qmsched.app.js") setAppMode(mode);
}; };

View File

@ -18,7 +18,7 @@
return; // drawWidgets will call draw again return; // drawWidgets will call draw again
} }
let x = this.x, y = this.y; let x = this.x, y = this.y;
g.clearRect(x, y, x+23, y+23); g.reset().clearRect(x, y, x+23, y+23);
// quiet mode: draw red one-way-street sign (dim red on Bangle.js 1) // quiet mode: draw red one-way-street sign (dim red on Bangle.js 1)
x = this.x+11;y = this.y+11; // center of widget x = this.x+11;y = this.y+11; // center of widget
g.setColor(process.env.HWVERSION===2 ? 1 : 0.8, 0, 0).fillCircle(x, y, 8); g.setColor(process.env.HWVERSION===2 ? 1 : 0.8, 0, 0).fillCircle(x, y, 8);