qmsched: manage LCD options
Also migrates old settings file: we now store options in qmsched.json, instead of in the global setting.json.pull/951/head
|
@ -3797,10 +3797,11 @@
|
|||
"id": "qmsched",
|
||||
"name": "Quiet Mode Schedule and Widget",
|
||||
"shortName": "Quiet Mode",
|
||||
"version": "0.03",
|
||||
"description": "Automatically turn Quiet Mode on or off at set times",
|
||||
"version": "0.04",
|
||||
"description": "Automatically turn Quiet Mode on or off at set times, and change LCD options while Quiet Mode is active.",
|
||||
"icon": "app.png",
|
||||
"screenshots": [{"url":"screenshot_edit.png"},{"url":"screenshot_main.png"},{"url":"screenshot_widget_alarms.png"},{"url":"screenshot_widget_silent.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"}],
|
||||
"tags": "tool,widget",
|
||||
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
0.01: First version
|
||||
0.02: Add widget
|
||||
0.03: Bangle.js 2 support
|
||||
0.04: Move Quiet Mode LCD options from global settings to this app
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
# Quiet Mode Schedule and Widget
|
||||
|
||||
Automatically turn Quiet Mode on or off at set times, and display a widget when enabled.
|
||||
Automatically turn Quiet Mode on or off at set times, and display a widget when Quiet Mode is active.
|
||||
|
||||
### Edit Schedule:
|
||||
 
|
||||
| Bangle.js 1 | Bangle.js 2 |
|
||||
|:---------------------------------------------:|:---------------------------------------------:|
|
||||
| (widget: Silent mode) | (widget: Alarms mode) |
|
||||
|  |  |
|
||||
|  |  |
|
||||
|  |  |
|
||||
|
||||
### Widget:
|
||||
 
|
||||
### LCD Settings:
|
||||
|
||||
If set, these override the default LCD settings while Quiet Mode is active.
|
|
@ -2,27 +2,74 @@ Bangle.loadWidgets();
|
|||
Bangle.drawWidgets();
|
||||
|
||||
const modeNames = ["Off", "Alarms", "Silent"];
|
||||
let scheds = require("Storage").readJSON("qmsched.json", 1);
|
||||
/*scheds = [
|
||||
{ hr : 6.5, // hours + minutes/60
|
||||
mode : 1, // quiet mode (0/1/2)
|
||||
|
||||
// load global brightness setting
|
||||
let bSettings = require('Storage').readJSON('setting.json',true)||{};
|
||||
let current = 0|bSettings.quiet;
|
||||
delete bSettings; // we don't need any other global settings
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Save settings to qmsched.json
|
||||
*/
|
||||
function save() {
|
||||
require('Storage').writeJSON('qmsched.json', settings);
|
||||
}
|
||||
function get(key, def) {
|
||||
return (key in settings) ? settings[key] : def;
|
||||
}
|
||||
function set(key, val) {
|
||||
settings[key] = val; save();
|
||||
scheds = settings.scheds; options = settings.options; // update references
|
||||
}
|
||||
function unset(key) {
|
||||
delete settings[key]; save();
|
||||
}
|
||||
|
||||
let settings,
|
||||
scheds, options; // references for convenience
|
||||
/**
|
||||
* Load settings file, check if we need to migrate old setting formats to new
|
||||
*/
|
||||
function loadSettings() {
|
||||
settings = require('Storage').readJSON("qmsched.json", true) || {};
|
||||
|
||||
if (Array.isArray(settings)) {
|
||||
// migrate old file (plain array of schedules, qmOptions stored in global settings file)
|
||||
require("Storage").erase("qmsched.json"); // need to erase old file, or Things Break, somehow...
|
||||
let bOptions = require('Storage').readJSON('setting.json',true)||{};
|
||||
settings = {
|
||||
options: bOptions.qmOptions || {},
|
||||
scheds: settings,
|
||||
};
|
||||
// store new format
|
||||
save();
|
||||
// and clean up qmOptions from global settings file
|
||||
delete bOptions.qmOptions;
|
||||
require('Storage').writeJSON('setting.json',bOptions);
|
||||
}
|
||||
];*/
|
||||
if (!scheds) {
|
||||
// set default schedule on first load of app
|
||||
scheds = [
|
||||
// apply defaults
|
||||
settings = Object.assign({
|
||||
options: {}, // Bangle options to override during quiet mode, default = none
|
||||
scheds: [
|
||||
// default schedule:
|
||||
{"hr": 8, "mode": 0},
|
||||
{"hr": 22, "mode": 1},
|
||||
];
|
||||
require("Storage").writeJSON("qmsched.json", scheds);
|
||||
}
|
||||
if (scheds.length && scheds.some(s => "last" in s)) {
|
||||
// cleanup: remove "last" values (used by old versions)
|
||||
scheds = scheds.map(s => {
|
||||
],
|
||||
}, settings);
|
||||
scheds = settings.scheds; options = settings.options;
|
||||
|
||||
if (scheds.length && scheds.some(s => "last" in s)) {
|
||||
// cleanup: remove "last" values (used by older versions)
|
||||
set('scheds', scheds.map(s => {
|
||||
delete s.last;
|
||||
return s;
|
||||
});
|
||||
require("Storage").writeJSON("qmsched.json", scheds);
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
function formatTime(t) {
|
||||
|
@ -32,29 +79,35 @@ function formatTime(t) {
|
|||
}
|
||||
|
||||
function showMainMenu() {
|
||||
let menu = {"": {"title": "Quiet Mode"}};
|
||||
let _m, menu = {
|
||||
"": {"title": "Quiet Mode"},
|
||||
"< Exit": () => load()
|
||||
};
|
||||
// "Current Mode""Silent" won't fit on Bangle.js 2
|
||||
menu["Current" + ((process.env.HWVERSION===2)?"":" Mode")]= {
|
||||
value: (require("Storage").readJSON("setting.json", 1) || {}).quiet|0,
|
||||
menu["Current"+((process.env.HWVERSION===2) ? "" : " Mode")] = {
|
||||
value: current,
|
||||
format: v => modeNames[v],
|
||||
onchange: function(v) {
|
||||
if (v<0) {v = 2;}
|
||||
if (v>2) {v = 0;}
|
||||
require("qmsched").setMode(v);
|
||||
current = v;
|
||||
this.value = v;
|
||||
},
|
||||
};
|
||||
scheds.sort((a, b) => (a.hr-b.hr));
|
||||
scheds.forEach((sched, idx) => {
|
||||
const name = modeNames[sched.mode];
|
||||
const txt = formatTime(sched.hr)+" ".repeat(14-name.length)+name;
|
||||
menu[txt] = function() {
|
||||
menu[formatTime(sched.hr)] = {
|
||||
format: () => modeNames[sched.mode], // abuse format to right-align text
|
||||
onchange: function() {
|
||||
_m.draw = ()=> {}; // prevent redraw of main menu over edit menu
|
||||
showEditMenu(idx);
|
||||
}
|
||||
};
|
||||
});
|
||||
menu["Add Schedule"] = () => showEditMenu(-1);
|
||||
menu["< Back"] = () => {load();};
|
||||
return E.showMenu(menu);
|
||||
menu["LCD Settings"] = () => showOptionsMenu();
|
||||
_m = E.showMenu(menu);
|
||||
}
|
||||
|
||||
function showEditMenu(index) {
|
||||
|
@ -69,6 +122,7 @@ function showEditMenu(index) {
|
|||
}
|
||||
const menu = {
|
||||
"": {"title": (isNew ? "Add" : "Edit")+" Schedule"},
|
||||
"< Cancel": () => showMainMenu(),
|
||||
"Hours": {
|
||||
value: hrs,
|
||||
onchange: function(v) {
|
||||
|
@ -110,18 +164,88 @@ function showEditMenu(index) {
|
|||
} else {
|
||||
scheds[index] = getSched();
|
||||
}
|
||||
require("Storage").writeJSON("qmsched.json", scheds);
|
||||
save();
|
||||
showMainMenu();
|
||||
};
|
||||
if (!isNew) {
|
||||
menu["> Delete"] = function() {
|
||||
scheds.splice(index, 1);
|
||||
require("Storage").writeJSON("qmsched.json", scheds);
|
||||
save();
|
||||
showMainMenu();
|
||||
};
|
||||
}
|
||||
menu["< Cancel"] = showMainMenu;
|
||||
return E.showMenu(menu);
|
||||
}
|
||||
|
||||
function showOptionsMenu() {
|
||||
const disabledFormat = v => v ? "Off" : "-";
|
||||
function toggle(option) {
|
||||
// we disable wakeOn* events by setting them to `false` in options
|
||||
// not disabled = not present in options at all
|
||||
if (option in options) {
|
||||
delete options[option];
|
||||
} else {
|
||||
options[option] = false;
|
||||
}
|
||||
save();
|
||||
}
|
||||
let resetTimeout;
|
||||
const oMenu = {
|
||||
"": {"title": "LCD Settings"},
|
||||
"< Back": () => showMainMenu(),
|
||||
"LCD Brightness": {
|
||||
value: get("brightness", 0),
|
||||
min: 0, // 0 = use default
|
||||
max: 1,
|
||||
step: 0.1,
|
||||
format: v => (v>0.05) ? v : "-",
|
||||
onchange: v => {
|
||||
if (v>0.05) { // prevent v=0.000000000000001 bugs
|
||||
set("brightness", v);
|
||||
Bangle.setLCDBrightness(v); // show result, even if not quiet right now
|
||||
// restore brightness after half a second
|
||||
if (resetTimeout) clearTimeout(resetTimeout);
|
||||
resetTimeout = setTimeout(() => {
|
||||
resetTimeout = undefined;
|
||||
require("qmsched").setMode(current);
|
||||
}, 500);
|
||||
} else {
|
||||
unset("brightness");
|
||||
require("qmsched").setMode(current);
|
||||
}
|
||||
},
|
||||
},
|
||||
"LCD Timeout": {
|
||||
value: get("timeout", 0),
|
||||
min: 0, // 0 = use default (no constant on for quiet mode)
|
||||
max: 60,
|
||||
step: 5,
|
||||
format: v => v>1 ? v : "-",
|
||||
onchange: v => {
|
||||
if (v>1) set("timeout", v);
|
||||
else unset("timeout");
|
||||
},
|
||||
},
|
||||
// we disable wakeOn* events by overwriting them as false in options
|
||||
// not disabled = not present in options at all
|
||||
"Wake on FaceUp": {
|
||||
value: "wakeOnFaceUp" in options,
|
||||
format: disabledFormat,
|
||||
onchange: () => {toggle("wakeOnFaceUp");},
|
||||
},
|
||||
"Wake on Touch": {
|
||||
value: "wakeOnTouch" in options,
|
||||
format: disabledFormat,
|
||||
onchange: () => {toggle("wakeOnTouch");},
|
||||
},
|
||||
"Wake on Twist": {
|
||||
value: "wakeOnTwist" in options,
|
||||
format: disabledFormat,
|
||||
onchange: () => {toggle("wakeOnTwist");},
|
||||
},
|
||||
};
|
||||
return E.showMenu(oMenu);
|
||||
}
|
||||
|
||||
loadSettings();
|
||||
showMainMenu();
|
||||
|
|
|
@ -1,7 +1,13 @@
|
|||
// apply Quiet Mode schedules
|
||||
(function qm() {
|
||||
let scheds = require("Storage").readJSON("qmsched.json", 1) || [];
|
||||
if (!scheds.length) { return;}
|
||||
let bSettings = require('Storage').readJSON('setting.json',true)||{};
|
||||
const curr = 0|bSettings.quiet;
|
||||
delete bSettings;
|
||||
if (curr) require("qmsched").applyOptions(curr); // no need to re-apply default options
|
||||
|
||||
let settings = require('Storage').readJSON('qmsched.json',true)||{};
|
||||
let scheds = settings.scheds||[];
|
||||
if (!scheds.length) {return;}
|
||||
const now = new Date(),
|
||||
hr = now.getHours()+(now.getMinutes()/60)+(now.getSeconds()/3600); // current (decimal) hour
|
||||
scheds.sort((a, b) => a.hr-b.hr);
|
||||
|
|
|
@ -1,18 +1,23 @@
|
|||
/**
|
||||
* Apply LCD options for given mode
|
||||
* @param {int} mode Quiet Mode
|
||||
*/
|
||||
exports.applyOptions = function(mode) {
|
||||
const s = require("Storage").readJSON(mode ? "qmsched.json" : "setting.json", 1) || {};
|
||||
const get = (k, d) => k in s ? s[k] : d;
|
||||
Bangle.setOptions(get("options", {}));
|
||||
Bangle.setLCDBrightness(get("brightness", 1));
|
||||
Bangle.setLCDTimeout(get("timeout", 10));
|
||||
};
|
||||
/**
|
||||
* Set new Quiet Mode and apply Bangle options
|
||||
* @param {int} mode Quiet Mode
|
||||
*/
|
||||
exports.setMode = function(mode) {
|
||||
let s = require("Storage").readJSON("setting.json", 1) || {};
|
||||
s.quiet = mode;
|
||||
require("Storage").writeJSON("setting.json", s);
|
||||
if (s.options) Bangle.setOptions(s.options);
|
||||
if (mode && s.qmOptions) Bangle.setOptions(s.qmOptions);
|
||||
if (mode && s.qmBrightness) {
|
||||
if (s.qmBrightness!=1) Bangle.setLCDBrightness(s.qmBrightness);
|
||||
} else {
|
||||
if (s.brightness && s.brightness!=1) Bangle.setLCDBrightness(s.brightness);
|
||||
}
|
||||
if (mode && s.qmTimeout) Bangle.setLCDTimeout(s.qmTimeout);
|
||||
if (typeof (WIDGETS)!=="undefined" && "qmsched" in WIDGETS) {WIDGETS["qmsched"].draw();}
|
||||
require("Storage").writeJSON("setting.json", Object.assign(
|
||||
require("Storage").readJSON("setting.json", 1) || {},
|
||||
{quiet:mode}
|
||||
));
|
||||
exports.applyOptions(mode);
|
||||
if (WIDGETS && "qmsched" in WIDGETS) WIDGETS["qmsched"].draw();
|
||||
};
|
After Width: | Height: | Size: 3.5 KiB |
After Width: | Height: | Size: 4.1 KiB |
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 3.8 KiB |
|
@ -16,9 +16,9 @@ WIDGETS["qmsched"] = {
|
|||
}
|
||||
let x = this.x, y = this.y;
|
||||
g.clearRect(x, y, x+23, y+23);
|
||||
// quiet mode: draw dim red one-way-street sign
|
||||
// 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
|
||||
g.setColor(0.8, 0, 0).fillCircle(x, y, 8);
|
||||
g.setColor(process.env.HWVERSION===2 ? 1 : 0.8, 0, 0).fillCircle(x, y, 8);
|
||||
g.setColor(g.theme.bg).fillRect(x-6, y-2, x+6, y+2);
|
||||
if (mode>1) {return;} // no alarms
|
||||
// alarms still on: draw alarm icon in bottom-right corner
|
||||
|
|