1
0
Fork 0

Merge branch 'espruino:master' into master

master
xxDUxx 2023-01-18 11:59:20 +01:00 committed by GitHub
commit 5f442c0e18
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 165 additions and 27 deletions

View File

@ -1,2 +1,3 @@
0.01: First release 0.01: First release
0.02: Move translations to locale module (removed watch settings, now pick language in Bangle App Loader, More..., Settings) 0.02: Move translations to locale module (removed watch settings, now pick language in Bangle App Loader, More..., Settings)
0.03: Change for fast loading, use widget_utils to hide widgets

View File

@ -1,4 +1,6 @@
// adapted from https://github.com/hallettj/Fuzzy-Text-International/ // adapted from https://github.com/hallettj/Fuzzy-Text-International/
{
const SETTINGS_FILE = "fuzzyw.settings.json";
let fuzzy_string = { let fuzzy_string = {
"hours":[ "hours":[
@ -35,7 +37,11 @@ let text_scale = 3.5;
let timeout = 2.5*60; let timeout = 2.5*60;
let drawTimeout; let drawTimeout;
function queueDraw(seconds) { let loadSettings = function() {
settings = require("Storage").readJSON(SETTINGS_FILE,1)|| {'showWidgets': false};
}
let queueDraw = function(seconds) {
let millisecs = seconds * 1000; let millisecs = seconds * 1000;
if (drawTimeout) clearTimeout(drawTimeout); if (drawTimeout) clearTimeout(drawTimeout);
drawTimeout = setTimeout(function() { drawTimeout = setTimeout(function() {
@ -47,7 +53,7 @@ function queueDraw(seconds) {
const h = g.getHeight(); const h = g.getHeight();
const w = g.getWidth(); const w = g.getWidth();
function getTimeString(date) { let getTimeString = function(date) {
let segment = Math.round((date.getMinutes()*60 + date.getSeconds() + 1)/300); let segment = Math.round((date.getMinutes()*60 + date.getSeconds() + 1)/300);
let hour = date.getHours() + Math.floor(segment/12); let hour = date.getHours() + Math.floor(segment/12);
f_string = fuzzy_string.minutes[segment % 12]; f_string = fuzzy_string.minutes[segment % 12];
@ -59,7 +65,7 @@ function getTimeString(date) {
return f_string; return f_string;
} }
function draw() { let draw = function() {
let time_string = getTimeString(new Date()).replace('*', ''); let time_string = getTimeString(new Date()).replace('*', '');
// print(time_string); // print(time_string);
g.setFont('Vector', (h-24*2)/text_scale); g.setFont('Vector', (h-24*2)/text_scale);
@ -71,7 +77,7 @@ function draw() {
} }
g.clear(); g.clear();
draw(); loadSettings();
// Stop updates when LCD is off, restart when on // Stop updates when LCD is off, restart when on
Bangle.on('lcdPower',on=>{ Bangle.on('lcdPower',on=>{
@ -83,6 +89,22 @@ Bangle.on('lcdPower',on=>{
} }
}); });
Bangle.setUI('clock'); Bangle.setUI({
mode : 'clock',
remove : function() {
// Called to unload all of the clock app
if (drawTimeout) clearTimeout(drawTimeout);
drawTimeout = undefined;
require('widget_utils').show(); // re-show widgets
}
});
Bangle.loadWidgets(); Bangle.loadWidgets();
if (settings.showWidgets) {
Bangle.drawWidgets(); Bangle.drawWidgets();
} else {
require("widget_utils").swipeOn(); // hide widgets, make them visible with a swipe
}
draw();
}

View File

@ -0,0 +1,33 @@
(function(back) {
const SETTINGS_FILE = "fuzzy.settings.json";
// initialize with default settings...
let s = {'showWidgets': false}
// ...and overwrite them with any saved values
// This way saved values are preserved if a new version adds more settings
const storage = require('Storage')
let settings = storage.readJSON(SETTINGS_FILE, 1) || s;
const saved = settings || {}
for (const key in saved) {
s[key] = saved[key]
}
function save() {
settings = s
storage.write(SETTINGS_FILE, settings)
}
E.showMenu({
'': { 'title': 'Fuzzy Word Clock' },
'< Back': back,
'Show Widgets': {
value: settings.showWidgets,
format: () => (settings.showWidgets ? 'Yes' : 'No'),
onchange: () => {
settings.showWidgets = !settings.showWidgets;
save();
}
},
});
})

View File

@ -2,7 +2,7 @@
"id":"fuzzyw", "id":"fuzzyw",
"name":"Fuzzy Text Clock", "name":"Fuzzy Text Clock",
"shortName": "Fuzzy Text", "shortName": "Fuzzy Text",
"version": "0.02", "version": "0.03",
"description": "An imprecise clock for when you're not in a rush", "description": "An imprecise clock for when you're not in a rush",
"readme": "README.md", "readme": "README.md",
"icon":"fuzzyw.png", "icon":"fuzzyw.png",
@ -13,6 +13,10 @@
"allow_emulator": true, "allow_emulator": true,
"storage": [ "storage": [
{"name":"fuzzyw.app.js","url":"fuzzyw.app.js"}, {"name":"fuzzyw.app.js","url":"fuzzyw.app.js"},
{"name":"fuzzyw.settings.js","url":"fuzzyw.settings.js"},
{"name":"fuzzyw.img","url":"fuzzyw.icon.js","evaluate":true} {"name":"fuzzyw.img","url":"fuzzyw.icon.js","evaluate":true}
],
"data": [
{"name":"fuzzyw.settings.json"}
] ]
} }

View File

@ -1,2 +1,3 @@
0.01: First release 0.01: First release
0.02: Use locale time 0.02: Use locale time
0.03: Change for fast loading, use widget_utils to hide widgets

View File

@ -4,7 +4,7 @@ A fabulously colourful clock!
* Clearly shows the time on a colourful background that changes every minute. * Clearly shows the time on a colourful background that changes every minute.
* Dark and Light theme compatible, with a setting to override the digit colour scheme. * Dark and Light theme compatible, with a setting to override the digit colour scheme.
* Show or hide widgets with a setting (default shows widgets). * Show or hide widgets with a setting (default hides widgets, swipe down to show them thanks to `widget_utils`).
![](mosaic-scr1.png) ![](mosaic-scr1.png)
![](mosaic-scr2.png) ![](mosaic-scr2.png)

View File

@ -2,7 +2,7 @@
"id":"mosaic", "id":"mosaic",
"name":"Mosaic Clock", "name":"Mosaic Clock",
"shortName": "Mosaic Clock", "shortName": "Mosaic Clock",
"version": "0.02", "version": "0.03",
"description": "A fabulously colourful clock", "description": "A fabulously colourful clock",
"readme": "README.md", "readme": "README.md",
"icon":"mosaic.png", "icon":"mosaic.png",
@ -15,5 +15,8 @@
{"name":"mosaic.app.js","url":"mosaic.app.js"}, {"name":"mosaic.app.js","url":"mosaic.app.js"},
{"name":"mosaic.settings.js","url":"mosaic.settings.js"}, {"name":"mosaic.settings.js","url":"mosaic.settings.js"},
{"name":"mosaic.img","url":"mosaic.icon.js","evaluate":true} {"name":"mosaic.img","url":"mosaic.icon.js","evaluate":true}
],
"data": [
{"name":"mosaic.settings.json"}
] ]
} }

View File

@ -2,6 +2,7 @@ Array.prototype.sample = function(){
return this[Math.floor(Math.random()*this.length)]; return this[Math.floor(Math.random()*this.length)];
}; };
{
const SETTINGS_FILE = "mosaic.settings.json"; const SETTINGS_FILE = "mosaic.settings.json";
let settings; let settings;
let theme; let theme;
@ -24,11 +25,11 @@ let digits = [
E.toArrayBuffer(atob("BQcB/Gsex+A=")) E.toArrayBuffer(atob("BQcB/Gsex+A="))
]; ];
function loadSettings() { let loadSettings = function() {
settings = require("Storage").readJSON(SETTINGS_FILE,1)|| {'showWidgets': false, 'theme':'System'}; settings = require("Storage").readJSON(SETTINGS_FILE,1)|| {'showWidgets': false, 'theme':'System'};
} }
function loadThemeColors() { let loadThemeColors = function() {
theme = {fg: g.theme.fg, bg: g.theme.bg}; theme = {fg: g.theme.fg, bg: g.theme.bg};
if (settings.theme === "Dark") { if (settings.theme === "Dark") {
theme.fg = g.toColor(1,1,1); theme.fg = g.toColor(1,1,1);
@ -40,7 +41,7 @@ function loadThemeColors() {
} }
} }
function queueDraw(seconds) { let queueDraw = function(seconds) {
let millisecs = seconds * 1000; let millisecs = seconds * 1000;
if (drawTimeout) clearTimeout(drawTimeout); if (drawTimeout) clearTimeout(drawTimeout);
drawTimeout = setTimeout(function() { drawTimeout = setTimeout(function() {
@ -49,7 +50,7 @@ function queueDraw(seconds) {
}, millisecs - (Date.now() % millisecs)); }, millisecs - (Date.now() % millisecs));
} }
function draw() { let draw = function() {
// draw colourful grid // draw colourful grid
for (let i_x = 0; i_x < num_squares_w; i_x++) { for (let i_x = 0; i_x < num_squares_w; i_x++) {
for (let i_y = 0; i_y < num_squares_h; i_y++) { for (let i_y = 0; i_y < num_squares_h; i_y++) {
@ -87,8 +88,6 @@ let o_h = Math.floor((g.getHeight() - num_squares_h * s+offset_widgets)/2);
let mid_x = Math.floor(num_squares_w/2); let mid_x = Math.floor(num_squares_w/2);
let mid_y = Math.floor((num_squares_h-1)/2); let mid_y = Math.floor((num_squares_h-1)/2);
draw();
Bangle.on('lcdPower',on=>{ Bangle.on('lcdPower',on=>{
if (on) { if (on) {
draw(); // draw immediately, queue redraw draw(); // draw immediately, queue redraw
@ -98,8 +97,23 @@ Bangle.on('lcdPower',on=>{
} }
}); });
Bangle.setUI('clock'); Bangle.setUI({
if (settings.showWidgets) { mode : 'clock',
Bangle.loadWidgets(); remove : function() {
Bangle.drawWidgets(); // Called to unload all of the clock app
if (drawTimeout) clearTimeout(drawTimeout);
drawTimeout = undefined;
delete Array.prototype.sample;
require('widget_utils').show(); // re-show widgets
}
});
Bangle.loadWidgets();
if (settings.showWidgets) {
Bangle.drawWidgets();
} else {
require("widget_utils").swipeOn(); // hide widgets, make them visible with a swipe
}
draw();
} }

View File

@ -1,2 +1,3 @@
0.01: first release 0.01: first release
0.02: added interface for configuration from app loader 0.02: added interface for configuration from app loader
0.03: merged save state and interpolating non-defined numeric slides

View File

@ -26,8 +26,12 @@ The only requirement is that timings are increasing,
so slides number don't have to be consecutive, so slides number don't have to be consecutive,
some can be skipped and they can even be short texts. some can be skipped and they can even be short texts.
At the moment the app is just quick and dirty In case the series of slide numbers/names is strictly increasing and doesn't
but it should do its job. contain strings, but numbers are not consecutive integers, the app will
interpolate intermediate slides (i.e. the first slide in the csv is 5 at minute
5, the app will add slide 1 at minute 1, slide 2 at minute 2, etc.)
At the moment the app is just quick and dirty but it should do its job.
## Screenshots ## Screenshots

View File

@ -1,7 +1,7 @@
{ {
"id": "presentation_timer", "id": "presentation_timer",
"name": "Presentation Timer", "name": "Presentation Timer",
"version": "0.02", "version": "0.03",
"description": "A touch based presentation timer for Bangle JS 2", "description": "A touch based presentation timer for Bangle JS 2",
"icon": "presentation_timer.png", "icon": "presentation_timer.png",
"screenshots": [{"url":"screenshot1.png"},{"url":"screenshot2.png"},{"url":"screenshot3.png"},{"url":"screenshot4.png"}], "screenshots": [{"url":"screenshot1.png"},{"url":"screenshot2.png"},{"url":"screenshot3.png"},{"url":"screenshot4.png"}],
@ -13,5 +13,8 @@
{"name":"presentation_timer.app.js","url":"presentation_timer.app.js"}, {"name":"presentation_timer.app.js","url":"presentation_timer.app.js"},
{"name":"presentation_timer.img","url":"presentation_timer.icon.js","evaluate":true} {"name":"presentation_timer.img","url":"presentation_timer.icon.js","evaluate":true}
], ],
"data": [{ "name": "presentation_timer.csv" }] "data": [
{"name":"presentation_timer.json"},
{ "name": "presentation_timer.csv" }
]
} }

View File

@ -1,9 +1,21 @@
const CONFIGFILE = "presentation_timer.json";
const now = Date.now();
const config = Object.assign({
state: {
total: now,
start: now,
current: now,
running: false,
}
}, require("Storage").readJSON(CONFIGFILE,1) || {});
let w = g.getWidth(); let w = g.getWidth();
let h = g.getHeight(); let h = g.getHeight();
let tTotal = Date.now(); let tTotal = config.state.total;
let tStart = tTotal; let tStart = config.state.start;
let tCurrent = tTotal; let tCurrent = config.state.current;
let running = false; let running = config.state.running;
let timeY = 2*h/5; let timeY = 2*h/5;
let displayInterval; let displayInterval;
let redrawButtons = true; let redrawButtons = true;
@ -15,6 +27,14 @@ const pause_img = atob("GBiBAf////////////////wYP/wYP/wYP/wYP/wYP/wYP/wYP/wYP/wY
const play_img = atob("GBjBAP//AAAAAAAAAAAIAAAOAAAPgAAP4AAP+AAP/AAP/wAP/8AP//AP//gP//gP//AP/8AP/wAP/AAP+AAP4AAPgAAOAAAIAAAAAAAAAAA="); const play_img = atob("GBjBAP//AAAAAAAAAAAIAAAOAAAPgAAP4AAP+AAP/AAP/wAP/8AP//AP//gP//gP//AP/8AP/wAP/AAP+AAP4AAPgAAOAAAIAAAAAAAAAAA=");
const reset_img = atob("GBiBAf////////////AAD+AAB+f/5+f/5+f/5+cA5+cA5+cA5+cA5+cA5+cA5+cA5+cA5+f/5+f/5+f/5+AAB/AAD////////////w=="); const reset_img = atob("GBiBAf////////////AAD+AAB+f/5+f/5+f/5+cA5+cA5+cA5+cA5+cA5+cA5+cA5+cA5+f/5+f/5+f/5+AAB/AAD////////////w==");
function saveState() {
config.state.total = tTotal;
config.state.start = tStart;
config.state.current = tCurrent;
config.state.running = running;
require("Storage").writeJSON(CONFIGFILE, config);
}
const margin = 0.5; //half a minute tolerance const margin = 0.5; //half a minute tolerance
//dummy default values //dummy default values
@ -29,6 +49,25 @@ function log_debug(o) {
//console.log(o); //console.log(o);
} }
function fillBlanks(slides) {
start = 1;
time = 0;
let arr = [];
for(let idx in slides) {
s = slides[idx];
if(s[1] != start) {
step = (s[0] - time) / (s[1] - start + 1);
for(let i=0; i<s[1]-start; ++i) {
arr.push([+(step*(i+1)+time).toFixed(2), start+i]);
}
}
arr.push([s[0],+s[1]]);
start = (+s[1]) + 1;
time = s[0];
}
return arr;
}
//first must be a number //first must be a number
function readSlides() { function readSlides() {
let csv = require("Storage").read("presentation_timer.csv"); let csv = require("Storage").read("presentation_timer.csv");
@ -36,6 +75,11 @@ function readSlides() {
let lines = csv.split("\n").filter(e=>e); let lines = csv.split("\n").filter(e=>e);
log_debug("Loading "+lines.length+" slides"); log_debug("Loading "+lines.length+" slides");
slides = lines.map(line=>{let s=line.split(";");return [+s[0],s[1]];}); slides = lines.map(line=>{let s=line.split(";");return [+s[0],s[1]];});
//all numbers and always strictly increasing
if(slides.filter(s=>isNaN(+s[1])).length == 0 &&
slides.map((p,i,a)=>p[1]-(a[i-1]?a[i-1][1]:undefined)).filter(p=>p<=0).length == 0) {
slides = fillBlanks(slides);
}
} }
@ -147,6 +191,7 @@ function stopStart() {
} else { } else {
draw(); draw();
} }
saveState();
} }
function setButtonImages() { function setButtonImages() {
@ -171,6 +216,7 @@ function lapReset() {
g.clearRect(0,24,w,h); g.clearRect(0,24,w,h);
draw(); draw();
} }
saveState();
} }
// simple on screen button class // simple on screen button class
@ -268,5 +314,10 @@ g.fillRect(0,0,w,h);
Bangle.loadWidgets(); Bangle.loadWidgets();
Bangle.drawWidgets(); Bangle.drawWidgets();
readSlides(); readSlides();
setButtonImages();
if (running) {
startTimer();
} else {
draw(); draw();
}
setWatch(() => load(), BTN, { repeat: false, edge: "falling" }); setWatch(() => load(), BTN, { repeat: false, edge: "falling" });

View File

@ -145,4 +145,5 @@ exports.swipeOn = function(autohide) {
}; };
Bangle.on("swipe", exports.swipeHandler); Bangle.on("swipe", exports.swipeHandler);
Bangle.drawWidgets();
}; };