mirror of https://github.com/espruino/BangleApps
Add files via upload
parent
9fa101b934
commit
f314eabe20
|
@ -1 +1 @@
|
||||||
|
0.01: New App!
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
# Theme Switcher
|
||||||
|
|
||||||
|
Switch Dark/Light theme based on time or on sunrise/sunset
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
When activated, switches automaticaly the theme based on time or on sunrise/sunset.
|
||||||
|
|
||||||
|
## Controls
|
||||||
|
|
||||||
|
In the app you can:
|
||||||
|
|
||||||
|
-activate / deactivate the general functionality
|
||||||
|
|
||||||
|
-manualy switch dark/light theme
|
||||||
|
|
||||||
|
-define times for light / dark switch (at the moment 1 --> dark and 1 --> light switch time)
|
||||||
|
|
||||||
|
-set automatic witching based on sunrise/sunset times privided by the [suncalc](https://github.com/jla-42/BangleApps/blob/master/modules/suncalc.js) module
|
||||||
|
|
||||||
|
## Creator
|
||||||
|
|
||||||
|
[jla-42](https://github.com/jla-42)
|
||||||
|
|
||||||
|
## Note
|
||||||
|
The app functionality is inspired by the [Quiet Mode Schedule and Widget](https://github.com/espruino/BangleApps/tree/master/apps/qmsched) app, where i missed the sunrise/sunset functionality, and wanted an indipendent switch of the theme and notifications.
|
||||||
|
|
||||||
|
## ToDos
|
||||||
|
-further code clean up
|
||||||
|
|
||||||
|
-optimization of code (and check if needed)
|
||||||
|
|
||||||
|
-transfer of configuration into settings, so app can be used as a shortcut to switch theme.
|
||||||
|
|
||||||
|
-feedback is always welcome
|
|
@ -0,0 +1 @@
|
||||||
|
require("heatshrink").decompress(atob("mEwgIWTj/4Aof//4ECgYFB4AFBh4FB+AWCAoIYCn///18AoN/BYMeEQf/h8AgIFCg+AFAX/gfAAocB4EHAofgAocA8A6CAoPwAolwAopGC/wFGnAFI/gFKMgIFDOAIFJ8AFERAJBDOoIFCGgIFDRoXwMoIcBMoJ/BAgJxBgYFDQYKwCAYINBAoIVCWwShBgF4AQKtCnwCBXIUfwEBG4UPSQIaCborpFCQT/HABY="))
|
|
@ -0,0 +1,217 @@
|
||||||
|
const SETTINGS_FILE = "themeSwitch.json";
|
||||||
|
const storage = require("Storage");
|
||||||
|
var sunrise, sunset, date;
|
||||||
|
var SunCalc = require("suncalc"); // from modules folder
|
||||||
|
const locale = require("locale");
|
||||||
|
let settings = storage.readJSON('setting.json', 1);
|
||||||
|
let saved = storage.readJSON(SETTINGS_FILE, 1) || {};
|
||||||
|
if (settings.theme.fg >0) {
|
||||||
|
saved.darkModeActive = 1
|
||||||
|
}else {
|
||||||
|
saved.darkModeActive = 0
|
||||||
|
}
|
||||||
|
if (require("Storage").readJSON("themeSwitch.json",1) !== undefined){
|
||||||
|
dmH = parseInt(saved.darkModeAt.split(":")[0]| 0);
|
||||||
|
dmM = parseInt(saved.darkModeAt.split(":")[1] |0);
|
||||||
|
lmH = parseInt(saved.lightModeAt.split(":")[0] |0);
|
||||||
|
lmM = parseInt(saved.lightModeAt.split(":")[1] |0);
|
||||||
|
}else{
|
||||||
|
dmH = 0;
|
||||||
|
dmM = 0;
|
||||||
|
lmH = 0;
|
||||||
|
lmM = 0;
|
||||||
|
}
|
||||||
|
// Main menu
|
||||||
|
|
||||||
|
var mainmenu = {
|
||||||
|
"" : {
|
||||||
|
"title" : "Theme Switch"
|
||||||
|
},
|
||||||
|
"< Back" : function() {load();},
|
||||||
|
"Automatic Dark Mode" : {
|
||||||
|
value : saved.darkMode | false,
|
||||||
|
format : v => v?"On":"Off",
|
||||||
|
min:0,max:1,step:1,
|
||||||
|
onchange :v=>{
|
||||||
|
saved.darkMode = v;
|
||||||
|
storage.writeJSON(SETTINGS_FILE,saved);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Dark Mode Active" : {
|
||||||
|
value : saved.darkModeActive | false,
|
||||||
|
format : v => v?"On":"Off",
|
||||||
|
min:0,max:1,step:1,
|
||||||
|
onchange :v=>{
|
||||||
|
saved.darkModeActive = v;
|
||||||
|
storage.writeJSON(SETTINGS_FILE,saved);
|
||||||
|
if (v!==0) {
|
||||||
|
setDarkTheme();
|
||||||
|
Bangle.drawWidgets();
|
||||||
|
delete m.lastIdx;
|
||||||
|
}else {
|
||||||
|
setLightTheme();
|
||||||
|
Bangle.drawWidgets();
|
||||||
|
delete m.lastIdx;}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Dark Mode by Sun" : {
|
||||||
|
value : saved.darkModeBySun | false,
|
||||||
|
format : v => v?"On":"Off",
|
||||||
|
min:0,max:1,step:1,
|
||||||
|
onchange : v =>{
|
||||||
|
saved.darkModeBySun =v;
|
||||||
|
if (v!==0) {
|
||||||
|
//print("calculating sun times");
|
||||||
|
calculateSunTimes();
|
||||||
|
saved.lightModeAt = sunrise;
|
||||||
|
saved.darkModeAt = sunset;
|
||||||
|
//print("sunrise" +sunrise);
|
||||||
|
//print("sunset" +sunset);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
storage.writeJSON(SETTINGS_FILE,saved);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"light mode at" : {
|
||||||
|
value : saved.lightModeAt,
|
||||||
|
format: v => saved.lightModeAt,
|
||||||
|
onchange :function(){
|
||||||
|
if(saved.darkModeBySun===0){
|
||||||
|
E.showMenu(lightModeAtMenu);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
E.showAlert("Deactivate dark mode first!", "Action Blocked").then(
|
||||||
|
function() {E.showMenu(mainmenu);});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dark mode at" : {
|
||||||
|
value : saved.darkModeAt ,
|
||||||
|
format: v => saved.darkModeAt,
|
||||||
|
onchange :function(){
|
||||||
|
if(saved.darkModeBySun===0){
|
||||||
|
E.showMenu(darkModeAtMenu);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
E.showAlert("Deactivate dark mode first!", "Action Blocked").then( function() {E.showMenu(mainmenu);});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Exit" : function() {load();},
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
var lightModeAtMenu = {
|
||||||
|
"" : {
|
||||||
|
"title" : "light mode at"
|
||||||
|
},
|
||||||
|
"Hour" : {
|
||||||
|
value : lmH,
|
||||||
|
min:0,max:23,step:1,
|
||||||
|
onchange : v => { lmH=v; }},
|
||||||
|
"Minute" : {
|
||||||
|
value : lmM,
|
||||||
|
min:0,max:59,step:1,
|
||||||
|
onchange : v => { lmM=v; }},
|
||||||
|
"< Back" : function() { saved.lightModeAt = fixTime(lmH,lmM);
|
||||||
|
storage.writeJSON(SETTINGS_FILE,saved);
|
||||||
|
E.showMenu(mainmenu); },
|
||||||
|
};
|
||||||
|
|
||||||
|
var darkModeAtMenu = {
|
||||||
|
"" : {
|
||||||
|
"title" : "dark mode at"
|
||||||
|
},
|
||||||
|
"Hour" : {
|
||||||
|
value : dmH,
|
||||||
|
min:0,max:23,step:1,
|
||||||
|
onchange : v => { dmH=v; }},
|
||||||
|
"Minute" : {
|
||||||
|
value : dmM,
|
||||||
|
min:0,max:59,step:1,
|
||||||
|
onchange : v => { dmM=v; }},
|
||||||
|
"< Back" : function() {saved.darkModeAt = fixTime(dmH,dmM);
|
||||||
|
storage.writeJSON(SETTINGS_FILE,saved);
|
||||||
|
E.showMenu(mainmenu); },
|
||||||
|
};
|
||||||
|
|
||||||
|
// Actually display the menu
|
||||||
|
E.showMenu(mainmenu);
|
||||||
|
|
||||||
|
// Function to fix time format
|
||||||
|
function fixTime(h, m) {
|
||||||
|
if (h.toString().length <2) {
|
||||||
|
h = "0" + h.toString();
|
||||||
|
}
|
||||||
|
if (m.toString().length <2) {
|
||||||
|
m = "0" + m.toString();
|
||||||
|
}
|
||||||
|
return h.toString() +":" + m.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
function calculateSunTimes() {
|
||||||
|
var location = require("Storage").readJSON("mylocation.json",1)||{};
|
||||||
|
location.lat = location.lat||51.5072;
|
||||||
|
location.lon = location.lon||0.1276; // London
|
||||||
|
date = new Date(Date.now());
|
||||||
|
var times = SunCalc.getTimes(date, location.lat, location.lon);
|
||||||
|
sunrise = fixTime(times.sunrise.getHours() , times.sunrise.getMinutes());
|
||||||
|
sunset = fixTime(times.sunset.getHours() ,times.sunset.getMinutes());
|
||||||
|
/* do we want to re-calculate this every day? Or we just assume
|
||||||
|
that 'show' will get called once a day? */
|
||||||
|
}
|
||||||
|
|
||||||
|
function cl(x) { return g.setColor(x).getColor(); }
|
||||||
|
|
||||||
|
function upd(th) {
|
||||||
|
g.theme = th;
|
||||||
|
settings.theme = th;
|
||||||
|
storage.write('setting.json', settings);
|
||||||
|
delete g.reset;
|
||||||
|
g._reset = g.reset;
|
||||||
|
g.reset = function(n) { return g._reset().setColor(th.fg).setBgColor(th.bg); };
|
||||||
|
g.clear = function(n) { if (n) g.reset(); return g.clearRect(0,0,g.getWidth(),g.getHeight()); };
|
||||||
|
g.clear(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function flipTheme() {
|
||||||
|
if (!g.theme.dark) {
|
||||||
|
upd({
|
||||||
|
fg:cl("#fff"), bg:cl("#000"),
|
||||||
|
fg2:cl("#fff"), bg2:cl("#004"),
|
||||||
|
fgH:cl("#fff"), bgH:cl("#00f"),
|
||||||
|
dark:true
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
upd({
|
||||||
|
fg:cl("#000"), bg:cl("#fff"),
|
||||||
|
fg2:cl("#000"), bg2:cl("#cff"),
|
||||||
|
fgH:cl("#000"), bgH:cl("#0ff"),
|
||||||
|
dark:false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setDarkTheme() {
|
||||||
|
if (!g.theme.dark) {
|
||||||
|
upd({
|
||||||
|
fg:cl("#fff"), bg:cl("#000"),
|
||||||
|
fg2:cl("#fff"), bg2:cl("#004"),
|
||||||
|
fgH:cl("#fff"), bgH:cl("#00f"),
|
||||||
|
dark:true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setLightTheme() {
|
||||||
|
if (g.theme.dark) {
|
||||||
|
upd({
|
||||||
|
fg:cl("#000"), bg:cl("#fff"),
|
||||||
|
fg2:cl("#000"), bg2:cl("#cff"),
|
||||||
|
fgH:cl("#000"), bgH:cl("#0ff"),
|
||||||
|
dark:false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
After Width: | Height: | Size: 879 B |
|
@ -0,0 +1,115 @@
|
||||||
|
(function dm() {
|
||||||
|
function selectRightMode(lt,dt,at) {
|
||||||
|
if (at < lt && at < dt ) {
|
||||||
|
return "lightT";
|
||||||
|
}else if (at > lt && at < dt) {
|
||||||
|
return "darkT";
|
||||||
|
}else if (at >lt && at > dt) {
|
||||||
|
return "lightN";}
|
||||||
|
}
|
||||||
|
function setDarkTheme() {
|
||||||
|
if (!g.theme.dark) {
|
||||||
|
upd({
|
||||||
|
fg:cl("#fff"), bg:cl("#000"),
|
||||||
|
fg2:cl("#fff"), bg2:cl("#004"),
|
||||||
|
fgH:cl("#fff"), bgH:cl("#00f"),
|
||||||
|
dark:true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setLightTheme() {
|
||||||
|
if (g.theme.dark) {
|
||||||
|
upd({
|
||||||
|
fg:cl("#000"), bg:cl("#fff"),
|
||||||
|
fg2:cl("#000"), bg2:cl("#cff"),
|
||||||
|
fgH:cl("#000"), bgH:cl("#0ff"),
|
||||||
|
dark:false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function fixTime(h, m) {
|
||||||
|
if (h.toString().length <2) {
|
||||||
|
h = "0" + h.toString();
|
||||||
|
}
|
||||||
|
if (m.toString().length <2) {
|
||||||
|
m = "0" + m.toString();
|
||||||
|
}
|
||||||
|
return h.toString() +":" + m.toString();
|
||||||
|
}
|
||||||
|
function calculateSunTimes() {
|
||||||
|
var location = require("Storage").readJSON("mylocation.json",1)||{};
|
||||||
|
location.lat = location.lat||51.5072;
|
||||||
|
location.lon = location.lon||0.1276; // London
|
||||||
|
date = new Date(Date.now());
|
||||||
|
var times = SunCalc.getTimes(date, location.lat, location.lon);
|
||||||
|
sunrise = fixTime(times.sunrise.getHours() , times.sunrise.getMinutes());
|
||||||
|
sunset = fixTime(times.sunset.getHours() ,times.sunset.getMinutes());
|
||||||
|
/* do we want to re-calculate this every day? Or we just assume
|
||||||
|
that 'show' will get called once a day? */
|
||||||
|
}
|
||||||
|
function cl(x) { return g.setColor(x).getColor(); }
|
||||||
|
function upd(th) {
|
||||||
|
g.theme = th;
|
||||||
|
settings = storage.readJSON('setting.json',1)
|
||||||
|
settings.theme = th;
|
||||||
|
storage.write('setting.json', settings);
|
||||||
|
delete g.reset;
|
||||||
|
g._reset = g.reset;
|
||||||
|
g.reset = function(n) { return g._reset().setColor(th.fg).setBgColor(th.bg); };
|
||||||
|
g.clear = function(n) { if (n) g.reset(); return g.clearRect(0,0,g.getWidth(),g.getHeight()); };
|
||||||
|
g.clear(1);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (Bangle.dmTimeout) clearTimeout(Bangle.dmTimeout); // so the app can eval() this file to apply changes right away
|
||||||
|
delete Bangle.dmTimeout;
|
||||||
|
} catch (e) {
|
||||||
|
print("Bangle.dmTimeout does not exist");
|
||||||
|
}
|
||||||
|
const SETTINGS_FILE = "themeSwitch.json";
|
||||||
|
const storage = require("Storage");
|
||||||
|
var sunrise, sunset, date;
|
||||||
|
var SunCalc = require("suncalc"); // from modules folder
|
||||||
|
const locale = require("locale");
|
||||||
|
let bSettings = storage.readJSON(SETTINGS_FILE,true)||{};
|
||||||
|
const now = new Date();
|
||||||
|
hr = now.getHours()+(now.getMinutes()/60)+(now.getSeconds()/3600); // current (decimal) hour
|
||||||
|
dmH = parseFloat(bSettings.darkModeAt.split(":")[0]);
|
||||||
|
dmM = parseFloat(bSettings.darkModeAt.split(":")[1]);
|
||||||
|
lmH = parseFloat(bSettings.lightModeAt.split(":")[0]);
|
||||||
|
lmM = parseFloat(bSettings.lightModeAt.split(":")[1]);
|
||||||
|
print("reading switch timeslots.....");
|
||||||
|
let dmDec = parseFloat(dmH)+parseFloat(dmM)/parseFloat(60);
|
||||||
|
let lmDec = parseFloat(lmH)+parseFloat(lmM)/parseFloat(60);
|
||||||
|
targetMode = selectRightMode(parseFloat(lmDec),parseFloat(dmDec),parseFloat(hr));
|
||||||
|
if (targetMode === "lightT" || targetMode === "lightN" ){
|
||||||
|
nextH = lmH;
|
||||||
|
nextM = lmM;
|
||||||
|
} else {
|
||||||
|
nextH = dmH;
|
||||||
|
nextM = dmM;
|
||||||
|
}
|
||||||
|
nextDecH = parseFloat(nextH) + parseFloat(nextM)/parseFloat(60);
|
||||||
|
let t = 3600000*(nextDecH-hr); // timeout in milliseconds
|
||||||
|
if (t<0) {t += 86400000;} // scheduled for tomorrow: add a day
|
||||||
|
/* update theme mode at the correct time. */
|
||||||
|
Bangle.dmTimeout=setTimeout(() => {
|
||||||
|
if (bSettings.darkMode !==0){
|
||||||
|
if (targetMode === "lightT" || targetMode === "lightN" ){
|
||||||
|
setLightTheme();
|
||||||
|
}else {
|
||||||
|
setDarkTheme();
|
||||||
|
}
|
||||||
|
Bangle.loadWidgets();
|
||||||
|
Bangle.drawWidgets();
|
||||||
|
setTimeout(load, 20);
|
||||||
|
if (bSettings.darkModeBySun !==0){
|
||||||
|
calculateSunTimes();
|
||||||
|
bSettings.lightModeAt = sunrise;
|
||||||
|
bSettings.darkModeAt = sunset;
|
||||||
|
storage.writeJSON(SETTINGS_FILE, bSettings);
|
||||||
|
}
|
||||||
|
dm(); // schedule next update
|
||||||
|
}
|
||||||
|
}, t);
|
||||||
|
})();
|
|
@ -0,0 +1,15 @@
|
||||||
|
{ "id": "thmswtch",
|
||||||
|
"name": "Theme Switcher",
|
||||||
|
"shortName":"Theme Switcher",
|
||||||
|
"version":"0.01",
|
||||||
|
"description": "change theme based on time or sunset/sunrise",
|
||||||
|
"icon": "app.png",
|
||||||
|
"tags": "tool",
|
||||||
|
"supports" : ["BANGLEJS2"],
|
||||||
|
"readme": "README.md",
|
||||||
|
"storage": [
|
||||||
|
{"name":"thmswtch.app.js","url":"app.js"},
|
||||||
|
{"name":"thmswtch.boot.js","url":"boot.js"},
|
||||||
|
{"name":"thmswtch.img","url":"app-icon.js","evaluate":true}
|
||||||
|
]
|
||||||
|
}
|
Loading…
Reference in New Issue