Merge pull request #3519 from retcurve/quarterclock

New app: Quarter Clock
pull/3532/head
Rob Pilling 2024-08-02 18:39:44 +01:00 committed by GitHub
commit d99a841fc8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 229 additions and 0 deletions

View File

@ -0,0 +1 @@
require("heatshrink").decompress(atob("mEw4X/AwX48AFCqoAEC4oL/Bf4L/Bf4LTAH4A/ADGqAAIL/Bf4LD"))

142
apps/quarterclock/app.js Normal file
View File

@ -0,0 +1,142 @@
{
const minute_boxes = [
{x:0.5, y:0},
{x:0.5, y:0.5},
{x:0, y:0.5},
{x:0, y:0},
];
const hour_boxes = [
{x:0.5, y:0},
{x:0.75, y:0},
{x:0.75, y:0.25},
{x:0.75, y:0.5},
{x:0.75, y:0.75},
{x:0.5, y:0.75},
{x:0.25, y:0.75},
{x:0, y:0.75},
{x:0, y:0.5},
{x:0, y:0.25},
{x:0, y:0},
{x:0.25, y:0},
];
let drawTimeout;
// schedule a draw for the next 15 minute period
let queueDraw = function queueDraw() {
if (drawTimeout) clearTimeout(drawTimeout);
drawTimeout = setTimeout(function() {
drawTimeout = undefined;
draw();
}, (60000 * 15) - (Date.now() % (60000 * 15)));
};
// Main draw function
let draw = function draw() {
var d = new Date();
var h = d.getHours(), m = d.getMinutes();
g.setBgColor(settings.backgroundColour);
g.clearRect(Bangle.appRect);
if (settings.showBattery) {
drawBattery();
}
// Draw minute box
drawBox(Math.floor(m/15), minute_boxes, Bangle.appRect.h/2, settings.minuteColour);
// Draw an hour box or write the number
if (settings.digital) {
g.setColor(settings.hourColour);
g.setFont("Vector:60");
g.setFontAlign(0,0);
g.drawString(h, Bangle.appRect.x + Bangle.appRect.w/2, Bangle.appRect.y + Bangle.appRect.h/2);
} else {
drawBox(h % 12, hour_boxes, Bangle.appRect.h/4, settings.hourColour);
}
queueDraw();
};
// Draw battery box
let drawBattery = function drawBattery() {
// Round battery up to 10% interval
let battery = Math.min((Math.floor(E.getBattery()/10)+1)/10, 1);
// Maximum battery box
let batterySize = 30;
// Draw outer box at full brightness
g.setColor(settings.batteryColour);
g.drawRect(
(Bangle.appRect.w / 2) - batterySize,
(Bangle.appRect.h / 2) - batterySize + Bangle.appRect.y,
(Bangle.appRect.w / 2) + batterySize,
(Bangle.appRect.h / 2) + batterySize + Bangle.appRect.y
);
// Fade battery colour and draw inner box
g.setColor(settings.batteryColour.split('').map((c) => {
return c=='f' ? Math.ceil(15 * battery).toString(16) : c;
}).join(''));
g.fillRect(
(Bangle.appRect.w / 2) - (batterySize * battery),
(Bangle.appRect.h / 2) - (batterySize * battery) + Bangle.appRect.y,
(Bangle.appRect.w / 2) + (batterySize * battery),
(Bangle.appRect.h / 2) + (batterySize * battery) + Bangle.appRect.y
);
};
// Draw hour or minute boxes
let drawBox = function drawBox(current, boxes, size, colour) {
let x1 = (boxes[current].x * Bangle.appRect.h) + (Bangle.appRect.y/2);
let y1 = (boxes[current].y * Bangle.appRect.h) + Bangle.appRect.y;
let x2 = x1 + size;
let y2 = y1 + size;
g.setColor(colour);
g.fillRect(x1, y1, x2, y2);
};
let settings = Object.assign({
// Default values
minuteColour: '#f00',
hourColour: '#ff0',
backgroundColour: 'theme',
showWidgets: true,
showBattery: true,
digital: false,
batteryColour: '#0f0'
}, require('Storage').readJSON('quarterclock.json', true) || {});
if (settings.backgroundColour == 'theme') {
settings.backgroundColour = g.theme.bg;
}
// Set minuteColour to a darker shade if same as hourColour
if (settings.minuteColour == settings.hourColour) {
settings.minuteColour = settings.minuteColour.split('').map((c) => {
return c=='f' ? '7' : c;
}).join('');
}
// Show launcher when middle button pressed
// Remove handler to allow fast loading
Bangle.setUI({mode:"clock", remove:function() {
if (drawTimeout) clearTimeout(drawTimeout);
require("widget_utils").show();
}});
// Load and display widgets
Bangle.loadWidgets();
if (settings.showWidgets) {
require("widget_utils").show();
} else {
require("widget_utils").hide();
}
// draw initial boxes and queue subsequent redraws
draw();
}

BIN
apps/quarterclock/app.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 B

View File

@ -0,0 +1,20 @@
{
"id": "quarterclock",
"name": "Quarter Clock",
"shortName":"Quarter Clock",
"icon": "app.png",
"screenshots" : [ { "url":"screenshot.png" } ],
"version":"0.01",
"description": "For those lazy days when the exact time doesn't matter. Small square shows the hour, large square shows the fifteen minute period, and centre square shows the battery level.",
"type": "clock",
"tags": "clock",
"supports": ["BANGLEJS2"],
"storage": [
{"name":"quarterclock.app.js","url":"app.js"},
{"name":"quarterclock.settings.js","url":"settings.js"},
{"name":"quarterclock.img","url":"app-icon.js","evaluate":true}
],
"data": [
{"name":"quarterclock.json"}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1,66 @@
(function(back) {
var FILE = 'quarterclock.json';
// Load settings
var settings = Object.assign({
minuteColour: '#f00',
hourColour: '#ff0',
backgroundColour: 'theme',
showWidgets: true,
showBattery: true,
digital: false,
batteryColour: '#0f0',
}, require('Storage').readJSON(FILE, true) || {});
function setSetting(key,value) {
settings[key] = value;
require('Storage').writeJSON(FILE, settings);
}
// Helper method which uses int-based menu item for set of string values and their labels
function stringItems(key, startvalue, values, labels) {
return {
value: (startvalue === undefined ? 0 : values.indexOf(startvalue)),
format: v => labels[v],
min: 0,
max: values.length - 1,
wrap: true,
step: 1,
onchange: v => {
setSetting(key,values[v]);
}
};
}
// Helper method which breaks string set settings down to local settings object
function stringInSettings(name, values, labels) {
return stringItems(name,settings[name], values, labels);
}
// Show the menu
E.showMenu({
'' : { 'title' : 'Quarter Clock' },
'< Back' : () => back(),
'Hour Colour': stringInSettings('hourColour', ['#f00', '#0f0', '#00f', '#ff0', '#0ff', '#f0f'], ['Red', 'Green', 'Blue', 'Yellow', 'Cyan', 'Magenta']),
'Minute Colour': stringInSettings('minuteColour', ['#f00', '#0f0', '#00f', '#ff0', '#0ff', '#f0f'], ['Red', 'Green', 'Blue', 'Yellow', 'Cyan', 'Magenta']),
'Background Colour': stringInSettings('backgroundColour', ['theme', '#000', '#fff'],['theme', 'Black', 'White']),
'Digital': {
value: !!settings.digital, // !! converts undefined to false
onchange: v => {
setSetting('digital', v);
},
},
'Show Widgets': {
value: !!settings.showWidgets,
onchange: v => {
setSetting('showWidgets', v);
},
},
'Show Battery': {
value: !!settings.showBattery,
onchange: v => {
setSetting('showBattery', v);
},
},
'Battery Colour': stringInSettings('batteryColour', ['#f00', '#0f0', '#00f', '#ff0', '#0ff', '#f0f'], ['Red', 'Green', 'Blue', 'Yellow', 'Cyan', 'Magenta']),
});
})