Merge branch 'master' of https://github.com/peerdavid/BangleApps
|
|
@ -1,3 +1,4 @@
|
||||||
0.01: Beta version for Bangle 2 (2021/11/28)
|
0.01: Beta version for Bangle 2 (2021/11/28)
|
||||||
0.02: Shows night time on the map (2022/12/28)
|
0.02: Shows night time on the map (2022/12/28)
|
||||||
0.03: Add 1 minute timer with upper taps (2023/01/05)
|
0.03: Add 1 minute timer with upper taps (2023/01/05)
|
||||||
|
1.00: Page to set up custom time zones (2023/01/06)
|
||||||
|
|
@ -8,11 +8,11 @@
|
||||||
* Bottom Left tap: decrease by 5 minutes
|
* Bottom Left tap: decrease by 5 minutes
|
||||||
* Short buzz at T-30, T-20, T-10 ; Double buzz at T
|
* Short buzz at T-30, T-20, T-10 ; Double buzz at T
|
||||||
* Other time zones
|
* Other time zones
|
||||||
* Currently hardcoded to Paris and Tokyo (this will be customizable in a future version)
|
* Showing Paris and Tokyo by default, but you can customize this using the dedicated configuration page on the app store
|
||||||
* World Map
|
* World Map
|
||||||
* The map shows day and night on Earth and the position of the Sun (yellow line)
|
* The map shows day and night on Earth and the position of the Sun (yellow line)
|
||||||
|
|
||||||

|
 
|
||||||
|
|
||||||
## Creator
|
## Creator
|
||||||
[@alainsaas](https://github.com/alainsaas)
|
[@alainsaas](https://github.com/alainsaas)
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,7 @@ function showWelcomeMessage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// time
|
// time
|
||||||
|
var offsets = require("Storage").readJSON("a_clock_timer.settings.json") || [ ["PAR",1], ["TYO",9] ];
|
||||||
var drawTimeout;
|
var drawTimeout;
|
||||||
|
|
||||||
function getGmt() {
|
function getGmt() {
|
||||||
|
|
@ -119,7 +120,7 @@ function draw() {
|
||||||
g.setColor('#ff0').drawLine(x_sun, g.getHeight()-IMAGEHEIGHT, x_sun, g.getHeight());
|
g.setColor('#ff0').drawLine(x_sun, g.getHeight()-IMAGEHEIGHT, x_sun, g.getHeight());
|
||||||
g.reset();
|
g.reset();
|
||||||
|
|
||||||
var x_night_start = 176 - (((gmtHours-6)%24) / 24 * 176 + 4);
|
var x_night_start = (176 - (((gmtHours-6)%24) / 24 * 176 + 4)) % 176;
|
||||||
var x_night_end = 176 - (((gmtHours+6)%24) / 24 * 176 + 4);
|
var x_night_end = 176 - (((gmtHours+6)%24) / 24 * 176 + 4);
|
||||||
g.setColor('#000');
|
g.setColor('#000');
|
||||||
for (let x = x_night_start; x < (x_night_end < x_night_start ? 176 : x_night_end); x+=2) {
|
for (let x = x_night_start; x < (x_night_end < x_night_start ? 176 : x_night_end); x+=2) {
|
||||||
|
|
@ -138,8 +139,8 @@ function draw() {
|
||||||
g.setFont("Michroma36").drawString(locale.time(date,1), g.getWidth()/2, 46);
|
g.setFont("Michroma36").drawString(locale.time(date,1), g.getWidth()/2, 46);
|
||||||
g.setFont("6x8");
|
g.setFont("6x8");
|
||||||
g.drawString(locale.date(new Date(),1), 125, 68);
|
g.drawString(locale.date(new Date(),1), 125, 68);
|
||||||
g.drawString("PAR "+locale.time(getTimeFromTimezone(1),1), 125, 80);
|
g.drawString(offsets[0][0]+" "+locale.time(getTimeFromTimezone(offsets[0][1]),1), 125, 80);
|
||||||
g.drawString("TYO "+locale.time(getTimeFromTimezone(9),1), 125, 88);
|
g.drawString(offsets[1][0]+" "+locale.time(getTimeFromTimezone(offsets[1][1]),1), 125, 88);
|
||||||
|
|
||||||
queueNextDraw();
|
queueNextDraw();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<link rel="stylesheet" href="../../css/spectre.min.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>You can set the 2 additional timezones displayed by the clock.</p>
|
||||||
|
<table id="a_clock_timer-offsets">
|
||||||
|
<tr>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>UTC Offset (Hours)</th>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<p>Click <button id="upload" class="btn btn-primary">Upload</button></p>
|
||||||
|
<script src="../../core/lib/customize.js"></script>
|
||||||
|
<script>
|
||||||
|
var offsets=[];
|
||||||
|
try{
|
||||||
|
var stored = localStorage.getItem('a_clock_timer-offset-list')
|
||||||
|
if(stored) offsets = JSON.parse(stored);
|
||||||
|
if (!offsets || offsets.length!=2) {
|
||||||
|
throw "Offsets invalid";
|
||||||
|
}
|
||||||
|
} catch(e){
|
||||||
|
offsets=[
|
||||||
|
["PAR",1],
|
||||||
|
["TYO",9],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
console.log(offsets);
|
||||||
|
var tbl=document.getElementById("a_clock_timer-offsets");
|
||||||
|
for (var i=0; i<2; i++) {
|
||||||
|
var $offset = document.createElement('tr')
|
||||||
|
$offset.innerHTML = `
|
||||||
|
<td><input type="text" size="4" maxlength="3" id="name_${i}" value="${offsets[i][0]}"></td>
|
||||||
|
<td><input type="number" id="offset_${i}" value="${offsets[i][1]}"></td>`
|
||||||
|
tbl.append($offset);
|
||||||
|
}
|
||||||
|
document.getElementById("upload").addEventListener("click", function() {
|
||||||
|
var storage_offsets=[];
|
||||||
|
var app_offsets=[];
|
||||||
|
for (var i=0; i<2; i++) {
|
||||||
|
var name=document.getElementById("name_"+i).value;
|
||||||
|
var offset=document.getElementById("offset_"+i).value;
|
||||||
|
app_offsets.push([name,offset]);
|
||||||
|
storage_offsets.push([name,offset]);
|
||||||
|
}
|
||||||
|
console.log(storage_offsets);
|
||||||
|
console.log(app_offsets);
|
||||||
|
localStorage.setItem('a_clock_timer-offset-list',JSON.stringify(storage_offsets));
|
||||||
|
sendCustomizedApp({
|
||||||
|
storage:[
|
||||||
|
{name:"a_clock_timer.settings.json", content:JSON.stringify(app_offsets)},
|
||||||
|
]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -1,17 +1,19 @@
|
||||||
{
|
{
|
||||||
"id": "a_clock_timer",
|
"id": "a_clock_timer",
|
||||||
"name": "A Clock with Timer",
|
"name": "A Clock with Timer",
|
||||||
"version": "0.03",
|
"version": "1.00",
|
||||||
"description": "A Clock with Timer, Map and Time Zones",
|
"description": "A Clock with Timer, Map and Time Zones",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"screenshots": [{"url":"screenshot.png"}],
|
"screenshots": [{"url":"screenshot.png"},{"url":"screenshot-1.png"}],
|
||||||
"type": "clock",
|
"type": "clock",
|
||||||
"tags": "clock",
|
"tags": "clock",
|
||||||
"supports": ["BANGLEJS2"],
|
"supports": ["BANGLEJS2"],
|
||||||
"allow_emulator": true,
|
"allow_emulator": true,
|
||||||
"readme": "README.md",
|
"readme": "README.md",
|
||||||
|
"custom": "custom.html",
|
||||||
"storage": [
|
"storage": [
|
||||||
{"name":"a_clock_timer.app.js","url":"app.js"},
|
{"name":"a_clock_timer.app.js","url":"app.js"},
|
||||||
{"name":"a_clock_timer.img","url":"app-icon.js","evaluate":true}
|
{"name":"a_clock_timer.img","url":"app-icon.js","evaluate":true}
|
||||||
]
|
],
|
||||||
|
"data": [{"name":"a_clock_timer.settings.json"}]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
After Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.9 KiB |
|
|
@ -14,3 +14,4 @@
|
||||||
0.14: Use ClockFace_menu.addItems
|
0.14: Use ClockFace_menu.addItems
|
||||||
0.15: Add Power saving option
|
0.15: Add Power saving option
|
||||||
0.16: Support Fast Loading
|
0.16: Support Fast Loading
|
||||||
|
0.17: Hide widgets instead of not loading them at all
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"id": "barclock",
|
"id": "barclock",
|
||||||
"name": "Bar Clock",
|
"name": "Bar Clock",
|
||||||
"version": "0.16",
|
"version": "0.17",
|
||||||
"description": "A simple digital clock showing seconds as a bar",
|
"description": "A simple digital clock showing seconds as a bar",
|
||||||
"icon": "clock-bar.png",
|
"icon": "clock-bar.png",
|
||||||
"screenshots": [{"url":"screenshot.png"},{"url":"screenshot_pm.png"}],
|
"screenshots": [{"url":"screenshot.png"},{"url":"screenshot_pm.png"}],
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,10 @@
|
||||||
(function(back) {
|
(function(back) {
|
||||||
let s = require("Storage").readJSON("barclock.settings.json", true) || {};
|
let s = require("Storage").readJSON("barclock.settings.json", true) || {};
|
||||||
|
// migrate "don't load widgets" to "hide widgets"
|
||||||
|
if (!("hideWidgets" in s) && ("loadWidgets" in s) && !s.loadWidgets) {
|
||||||
|
s.hideWidgets = 1;
|
||||||
|
}
|
||||||
|
delete s.loadWidgets;
|
||||||
|
|
||||||
function save(key, value) {
|
function save(key, value) {
|
||||||
s[key] = value;
|
s[key] = value;
|
||||||
|
|
@ -19,7 +24,7 @@
|
||||||
};
|
};
|
||||||
let items = {
|
let items = {
|
||||||
showDate: s.showDate,
|
showDate: s.showDate,
|
||||||
loadWidgets: s.loadWidgets,
|
hideWidgets: s.hideWidgets,
|
||||||
};
|
};
|
||||||
// Power saving for Bangle.js 1 doesn't make sense (no updates while screen is off anyway)
|
// Power saving for Bangle.js 1 doesn't make sense (no updates while screen is off anyway)
|
||||||
if (process.env.HWVERSION>1) {
|
if (process.env.HWVERSION>1) {
|
||||||
|
|
|
||||||
|
|
@ -28,3 +28,4 @@
|
||||||
0.27: Clean out some leftovers in the remove function after switching to
|
0.27: Clean out some leftovers in the remove function after switching to
|
||||||
clkinfo.addInteractive that would cause ReferenceError.
|
clkinfo.addInteractive that would cause ReferenceError.
|
||||||
0.28: Option to show (1) time only and (2) week of year.
|
0.28: Option to show (1) time only and (2) week of year.
|
||||||
|
0.29: use setItem of clockInfoMenu to change the active item
|
||||||
|
|
@ -327,9 +327,7 @@ Bangle.on('lock', lockListenerBw);
|
||||||
|
|
||||||
let charging = function(charging){
|
let charging = function(charging){
|
||||||
// Jump to battery
|
// Jump to battery
|
||||||
clockInfoMenu.menuA = 0;
|
clockInfoMenu.setItem(0, 2);
|
||||||
clockInfoMenu.menuB = 2;
|
|
||||||
clockInfoMenu.redraw();
|
|
||||||
drawTime();
|
drawTime();
|
||||||
}
|
}
|
||||||
Bangle.on('charging', charging);
|
Bangle.on('charging', charging);
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"id": "bwclk",
|
"id": "bwclk",
|
||||||
"name": "BW Clock",
|
"name": "BW Clock",
|
||||||
"version": "0.28",
|
"version": "0.29",
|
||||||
"description": "A very minimalistic clock.",
|
"description": "A very minimalistic clock.",
|
||||||
"readme": "README.md",
|
"readme": "README.md",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
0.01: New clock
|
0.01: New clock
|
||||||
0.02: Use ClockFace library, add settings
|
0.02: Use ClockFace library, add settings
|
||||||
0.03: Use ClockFace_menu.addSettingsFile
|
0.03: Use ClockFace_menu.addSettingsFile
|
||||||
|
0.04: Hide widgets instead of not loading them at all
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"id": "cogclock",
|
"id": "cogclock",
|
||||||
"name": "Cog Clock",
|
"name": "Cog Clock",
|
||||||
"version": "0.03",
|
"version": "0.04",
|
||||||
"description": "A cross-shaped clock inside a cog",
|
"description": "A cross-shaped clock inside a cog",
|
||||||
"icon": "icon.png",
|
"icon": "icon.png",
|
||||||
"screenshots": [{"url":"screenshot.png"}],
|
"screenshots": [{"url":"screenshot.png"}],
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
/*LANG*/"< Back": back,
|
/*LANG*/"< Back": back,
|
||||||
};
|
};
|
||||||
require("ClockFace_menu").addSettingsFile(menu, "cogclock.settings.json", [
|
require("ClockFace_menu").addSettingsFile(menu, "cogclock.settings.json", [
|
||||||
"showDate", "loadWidgets"
|
"showDate", "hideWidgets"
|
||||||
]);
|
]);
|
||||||
E.showMenu(menu);
|
E.showMenu(menu);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -25,4 +25,6 @@ facilitate 'fast switching' of apps where available.
|
||||||
widgets would still be loaded when they weren't supposed to.
|
widgets would still be loaded when they weren't supposed to.
|
||||||
0.21: Bangle 2: Call Bangle.drawWidgets() early on so that the widget field
|
0.21: Bangle 2: Call Bangle.drawWidgets() early on so that the widget field
|
||||||
immediately follows the correct theme.
|
immediately follows the correct theme.
|
||||||
|
0.22: Bangle 2: Change to not automatically marking the first app on a page
|
||||||
|
when moving pages. Add caching for faster startups.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,20 +13,25 @@
|
||||||
}, require('Storage').readJSON("dtlaunch.json", true) || {});
|
}, require('Storage').readJSON("dtlaunch.json", true) || {});
|
||||||
|
|
||||||
let s = require("Storage");
|
let s = require("Storage");
|
||||||
var apps = s.list(/\.info$/).map(app=>{
|
// Borrowed caching from Icon Launcher, code by halemmerich.
|
||||||
let a=s.readJSON(app,1);
|
let launchCache = s.readJSON("launch.cache.json", true)||{};
|
||||||
return a && {
|
let launchHash = require("Storage").hash(/\.info/);
|
||||||
name:a.name, type:a.type, icon:a.icon, sortorder:a.sortorder, src:a.src
|
if (launchCache.hash!=launchHash) {
|
||||||
};}).filter(
|
launchCache = {
|
||||||
app=>app && (app.type=="app" || (app.type=="clock" && settings.showClocks) || (app.type=="launch" && settings.showLaunchers) || !app.type));
|
hash : launchHash,
|
||||||
|
apps : s.list(/\.info$/)
|
||||||
apps.sort((a,b)=>{
|
.map(app=>{var a=s.readJSON(app,1);return a&&{name:a.name,type:a.type,icon:a.icon,sortorder:a.sortorder,src:a.src};})
|
||||||
let n=(0|a.sortorder)-(0|b.sortorder);
|
.filter(app=>app && (app.type=="app" || (app.type=="clock" && settings.showClocks) || !app.type))
|
||||||
|
.sort((a,b)=>{
|
||||||
|
var n=(0|a.sortorder)-(0|b.sortorder);
|
||||||
if (n) return n; // do sortorder first
|
if (n) return n; // do sortorder first
|
||||||
if (a.name<b.name) return -1;
|
if (a.name<b.name) return -1;
|
||||||
if (a.name>b.name) return 1;
|
if (a.name>b.name) return 1;
|
||||||
return 0;
|
return 0;
|
||||||
});
|
}) };
|
||||||
|
s.writeJSON("launch.cache.json", launchCache);
|
||||||
|
}
|
||||||
|
let apps = launchCache.apps;
|
||||||
apps.forEach(app=>{
|
apps.forEach(app=>{
|
||||||
if (app.icon)
|
if (app.icon)
|
||||||
app.icon = s.read(app.icon); // should just be a link to a memory area
|
app.icon = s.read(app.icon); // should just be a link to a memory area
|
||||||
|
|
@ -90,7 +95,7 @@
|
||||||
|
|
||||||
let swipeListenerDt = function(dirLeftRight, dirUpDown){
|
let swipeListenerDt = function(dirLeftRight, dirUpDown){
|
||||||
updateTimeoutToClock();
|
updateTimeoutToClock();
|
||||||
selected = 0;
|
selected = -1;
|
||||||
oldselected=-1;
|
oldselected=-1;
|
||||||
if(settings.swipeExit && dirLeftRight==1) Bangle.showClock();
|
if(settings.swipeExit && dirLeftRight==1) Bangle.showClock();
|
||||||
if (dirUpDown==-1||dirLeftRight==-1){
|
if (dirUpDown==-1||dirLeftRight==-1){
|
||||||
|
|
@ -154,3 +159,4 @@
|
||||||
updateTimeoutToClock();
|
updateTimeoutToClock();
|
||||||
|
|
||||||
} // end of app scope
|
} // end of app scope
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"id": "dtlaunch",
|
"id": "dtlaunch",
|
||||||
"name": "Desktop Launcher",
|
"name": "Desktop Launcher",
|
||||||
"version": "0.21",
|
"version": "0.22",
|
||||||
"description": "Desktop style App Launcher with six (four for Bangle 2) apps per page - fast access if you have lots of apps installed.",
|
"description": "Desktop style App Launcher with six (four for Bangle 2) apps per page - fast access if you have lots of apps installed.",
|
||||||
"screenshots": [{"url":"shot1.png"},{"url":"shot2.png"},{"url":"shot3.png"}],
|
"screenshots": [{"url":"shot1.png"},{"url":"shot2.png"},{"url":"shot3.png"}],
|
||||||
"icon": "icon.png",
|
"icon": "icon.png",
|
||||||
|
|
|
||||||
|
|
@ -18,3 +18,5 @@
|
||||||
0.17: Add automatic translation of bar chart labels
|
0.17: Add automatic translation of bar chart labels
|
||||||
0.18: Show step goal in daily step chart
|
0.18: Show step goal in daily step chart
|
||||||
0.19: Can show notification when daily step goal is reached
|
0.19: Can show notification when daily step goal is reached
|
||||||
|
0.20: Fix the settings page, it would not update settings correctly.
|
||||||
|
0.21: Update boot.min.js.
|
||||||
|
|
|
||||||
|
|
@ -105,7 +105,7 @@ function handleStepGoalNotification() {
|
||||||
if (!settings.stepGoalNotificationDate || settings.stepGoalNotificationDate < now) { // notification not yet shown today?
|
if (!settings.stepGoalNotificationDate || settings.stepGoalNotificationDate < now) { // notification not yet shown today?
|
||||||
Bangle.buzz(200, 0.5);
|
Bangle.buzz(200, 0.5);
|
||||||
require("notify").show({
|
require("notify").show({
|
||||||
title : /*LANG*/ settings.stepGoal + " steps",
|
title : settings.stepGoal + /*LANG*/ " steps",
|
||||||
body : /*LANG*/ "You reached your step goal!",
|
body : /*LANG*/ "You reached your step goal!",
|
||||||
icon : atob("DAyBABmD6BaBMAsA8BCBCBCBCA8AAA==")
|
icon : atob("DAyBABmD6BaBMAsA8BCBCBCBCA8AAA==")
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
function l(){var a=require("Storage").readJSON("health.json",1)||{},d=Bangle.getHealthStatus("day").steps;a.stepGoalNotification&&0<a.stepGoal&&d>=a.stepGoal&&(d=(new Date(Date.now())).toISOString().split("T")[0],!a.stepGoalNotificationDate||a.stepGoalNotificationDate<d)&&(Bangle.buzz(200,.5),require("notify").show({title:"8000 steps",body:"You reached your step goal!",icon:atob("DAyBABmD6BaBMAsA8BCBCBCBCA8AAA==")}),a.stepGoalNotificationDate=d,require("Storage").writeJSON("health.json",
|
function l(){var a=require("Storage").readJSON("health.json",1)||{},d=Bangle.getHealthStatus("day").steps;a.stepGoalNotification&&0<a.stepGoal&&d>=a.stepGoal&&(d=(new Date(Date.now())).toISOString().split("T")[0],!a.stepGoalNotificationDate||a.stepGoalNotificationDate<d)&&(Bangle.buzz(200,.5),require("notify").show({title:a.stepGoal+" steps",body:"You reached your step goal!",icon:atob("DAyBABmD6BaBMAsA8BCBCBCBCA8AAA==")}),a.stepGoalNotificationDate=d,require("Storage").writeJSON("health.json",
|
||||||
a))}(function(){var a=0|(require("Storage").readJSON("health.json",1)||{}).hrm;if(1==a||2==a){var d=function(){Bangle.setHRMPower(1,"health");setTimeout(function(){return Bangle.setHRMPower(0,"health")},6E4*a);if(1==a)for(var b=1;2>=b;b++)setTimeout(function(){Bangle.setHRMPower(1,"health");setTimeout(function(){Bangle.setHRMPower(0,"health")},2E5*b+6E4)},2E5*b)};Bangle.on("health",d);Bangle.on("HRM",function(b){80<b.confidence&&Bangle.setHRMPower(0,"health")});Bangle.getHealthStatus().bpmConfidence||
|
a))}(function(){var a=0|(require("Storage").readJSON("health.json",1)||{}).hrm;if(1==a||2==a){var d=function(){Bangle.setHRMPower(1,"health");setTimeout(function(){return Bangle.setHRMPower(0,"health")},6E4*a);if(1==a)for(var b=1;2>=b;b++)setTimeout(function(){Bangle.setHRMPower(1,"health");setTimeout(function(){Bangle.setHRMPower(0,"health")},2E5*b+6E4)},2E5*b)};Bangle.on("health",d);Bangle.on("HRM",function(b){80<b.confidence&&Bangle.setHRMPower(0,"health")});Bangle.getHealthStatus().bpmConfidence||
|
||||||
d()}else Bangle.setHRMPower(0!=a,"health")})();Bangle.on("health",function(a){function d(c){return String.fromCharCode(c.steps>>8,c.steps&255,c.bpm,Math.min(c.movement/8,255))}var b=new Date(Date.now()-59E4);a&&0<a.steps&&l();var f=function(c){return 145*(c.getDate()-1)+6*c.getHours()+(0|6*c.getMinutes()/60)}(b);b=function(c){return"health-"+c.getFullYear()+"-"+(c.getMonth()+1)+".raw"}(b);var g=require("Storage").read(b);if(g){var e=g.substr(8+4*f,4);if("\u00ff\u00ff\u00ff\u00ff"!=e){print("HEALTH ERR: Already written!");
|
d()}else Bangle.setHRMPower(0!=a,"health")})();Bangle.on("health",function(a){function d(c){return String.fromCharCode(c.steps>>8,c.steps&255,c.bpm,Math.min(c.movement/8,255))}var b=new Date(Date.now()-59E4);a&&0<a.steps&&l();var f=function(c){return 145*(c.getDate()-1)+6*c.getHours()+(0|6*c.getMinutes()/60)}(b);b=function(c){return"health-"+c.getFullYear()+"-"+(c.getMonth()+1)+".raw"}(b);var g=require("Storage").read(b);if(g){var e=g.substr(8+4*f,4);if("\u00ff\u00ff\u00ff\u00ff"!=e){print("HEALTH ERR: Already written!");
|
||||||
return}}else require("Storage").write(b,"HEALTH1\x00",0,17988);var h=8+4*f;require("Storage").write(b,d(a),h,17988);if(143==f%145)if(f=h+4,"\u00ff\u00ff\u00ff\u00ff"!=g.substr(f,4))print("HEALTH ERR: Daily summary already written!");else{a={steps:0,bpm:0,movement:0,movCnt:0,bpmCnt:0};for(var k=0;144>k;k++)e=g.substr(h,4),"\u00ff\u00ff\u00ff\u00ff"!=e&&(a.steps+=(e.charCodeAt(0)<<8)+e.charCodeAt(1),a.movement+=e.charCodeAt(2),a.movCnt++,e=e.charCodeAt(2),a.bpm+=e,e&&a.bpmCnt++),h-=4;a.bpmCnt&&(a.bpm/=
|
return}}else require("Storage").write(b,"HEALTH1\x00",0,17988);var h=8+4*f;require("Storage").write(b,d(a),h,17988);if(143==f%145)if(f=h+4,"\u00ff\u00ff\u00ff\u00ff"!=g.substr(f,4))print("HEALTH ERR: Daily summary already written!");else{a={steps:0,bpm:0,movement:0,movCnt:0,bpmCnt:0};for(var k=0;144>k;k++)e=g.substr(h,4),"\u00ff\u00ff\u00ff\u00ff"!=e&&(a.steps+=(e.charCodeAt(0)<<8)+e.charCodeAt(1),a.movement+=e.charCodeAt(2),a.movCnt++,e=e.charCodeAt(2),a.bpm+=e,e&&a.bpmCnt++),h-=4;a.bpmCnt&&(a.bpm/=
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
"id": "health",
|
"id": "health",
|
||||||
"name": "Health Tracking",
|
"name": "Health Tracking",
|
||||||
"shortName": "Health",
|
"shortName": "Health",
|
||||||
"version": "0.19",
|
"version": "0.21",
|
||||||
"description": "Logs health data and provides an app to view it",
|
"description": "Logs health data and provides an app to view it",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"tags": "tool,system,health",
|
"tags": "tool,system,health",
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,9 @@
|
||||||
stepGoalNotification: false
|
stepGoalNotification: false
|
||||||
}, require("Storage").readJSON("health.json", true) || {});
|
}, require("Storage").readJSON("health.json", true) || {});
|
||||||
|
|
||||||
|
function setSettings() {
|
||||||
|
require("Storage").writeJSON("health.json", settings);
|
||||||
|
}
|
||||||
E.showMenu({
|
E.showMenu({
|
||||||
"": { title: /*LANG*/"Health Tracking" },
|
"": { title: /*LANG*/"Health Tracking" },
|
||||||
|
|
||||||
|
|
@ -22,7 +25,7 @@
|
||||||
][v],
|
][v],
|
||||||
onchange: v => {
|
onchange: v => {
|
||||||
settings.hrm = v;
|
settings.hrm = v;
|
||||||
setSettings(settings);
|
setSettings();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -33,7 +36,7 @@
|
||||||
step: 250,
|
step: 250,
|
||||||
onchange: v => {
|
onchange: v => {
|
||||||
settings.stepGoal = v;
|
settings.stepGoal = v;
|
||||||
setSettings(settings);
|
setSettings();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
/*LANG*/"Step Goal Notification": {
|
/*LANG*/"Step Goal Notification": {
|
||||||
|
|
@ -45,8 +48,4 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function setSettings(settings) {
|
|
||||||
require("Storage").writeJSON("health.json", settings);
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -1 +1,2 @@
|
||||||
0.01: New app!
|
0.01: New app!
|
||||||
|
0.02: Fix music updates while app is already open
|
||||||
|
|
|
||||||
|
|
@ -85,9 +85,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
const setUI = function(options, cb) {
|
const setUI = function(options, cb) {
|
||||||
|
delete Bangle.uiRemove; // don't clear out things when switching UI within the app
|
||||||
options = Object.assign({remove: () => uiRemove()}, options);
|
options = Object.assign({remove: () => uiRemove()}, options);
|
||||||
Bangle.setUI(options, cb);
|
Bangle.setUI(options, cb);
|
||||||
Bangle.on("message", onMessage);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const remove = function(msg) {
|
const remove = function(msg) {
|
||||||
|
|
@ -1161,8 +1161,10 @@
|
||||||
idx = MESSAGES.findIndex(m => m.src && m.src.toLowerCase().startsWith("alarm"));
|
idx = MESSAGES.findIndex(m => m.src && m.src.toLowerCase().startsWith("alarm"));
|
||||||
if (idx>=0) alarm = MESSAGES.splice(idx, 1)[0];
|
if (idx>=0) alarm = MESSAGES.splice(idx, 1)[0];
|
||||||
};
|
};
|
||||||
if (MESSAGES!==undefined) { // only if loading MESSAGES worked
|
|
||||||
g.reset().clear();
|
// Internal setUI suppresses Bangle.uiRemove between internal screens, so we
|
||||||
|
// need to call setUI to run uiRemove from previous app when fast-loaded.
|
||||||
|
Bangle.setUI();
|
||||||
Bangle.loadWidgets();
|
Bangle.loadWidgets();
|
||||||
require("messages").toggleWidget(false);
|
require("messages").toggleWidget(false);
|
||||||
Bangle.drawWidgets();
|
Bangle.drawWidgets();
|
||||||
|
|
@ -1205,4 +1207,3 @@
|
||||||
["touch", "drag", "swipe"].forEach(l => Bangle.on(l, clearUnreadStuff));
|
["touch", "drag", "swipe"].forEach(l => Bangle.on(l, clearUnreadStuff));
|
||||||
(B2 ? [BTN1] : [BTN1, BTN2, BTN3]).forEach(b => watches.push(setWatch(clearUnreadStuff, b, false)));
|
(B2 ? [BTN1] : [BTN1, BTN2, BTN3]).forEach(b => watches.push(setWatch(clearUnreadStuff, b, false)));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"id": "messagelist",
|
"id": "messagelist",
|
||||||
"name": "Message List",
|
"name": "Message List",
|
||||||
"version": "0.01",
|
"version": "0.02",
|
||||||
"description": "Display notifications from iOS and Gadgetbridge/Android as a list",
|
"description": "Display notifications from iOS and Gadgetbridge/Android as a list",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"type": "app",
|
"type": "app",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
0.01: fork from miclock, Added compatib with b widgets, devices(dynamic x,y) and themes(dynamic colors)
|
||||||
|
0.02: Code refactored, change colors in real time
|
||||||
|
0.03: Hour point size can be modified on real time.
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
# Mix Digital & Analog Clock
|
||||||
|
A dual and simultaneous Analog and Digital Clock, also shows day, month and year.
|
||||||
|
Color are automatically set depending on the configured Theme or device, bunt also change on realtime through touching the right side.
|
||||||
|
|
||||||
|
Compatible with BangleJS1,BangleJS2,and EMSCRIPTENx emulators
|
||||||
|
|
||||||
|
## Pictures:
|
||||||
|
|
||||||
|
Bangle JS1
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Screenshot emulator BJS2
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Screenshot emulator BJS1
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
SS emulator -color change
|
||||||
|

|
||||||
|
|
||||||
|
SS emulator -color change
|
||||||
|

|
||||||
|
|
||||||
|
SS emulator -color change
|
||||||
|

|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Open and see
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
Compatibility with devices
|
||||||
|
Dynamic Colours and positions
|
||||||
|
Support for bottom widgets
|
||||||
|
|
||||||
|
|
||||||
|
## Controls
|
||||||
|
|
||||||
|
Exit : BTN2 (BJS1)
|
||||||
|
Exit/launcher : left area
|
||||||
|
Change Color : right area
|
||||||
|
Increase Hour Points : swipe right
|
||||||
|
Decrease Hour Points : swipe left
|
||||||
|
|
||||||
|
|
||||||
|
## Coming soon
|
||||||
|
A better color combination
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
This app is so basic that probably the easiest is to just edit the code ;)
|
||||||
|
|
||||||
|
Otherwise you can contact me [here](https://github.com/dapgo/my_espruino_smartwatch_things)
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
require("heatshrink").decompress(atob("mEw4X/AAN994JB8noH+cFqtVqALHr5IB+oWHKgX/DAwWCDA8BA4IvBB4NABYcH/4KBAAP/6ALDj4WCDAX0BYd/6tVq2VqtX/ouECgILCEgIwCgP9BYt/BYUHFwQLDr48CBZcfHQILEq5ICBZd/LgQLDqpUCBbYAEC4+a1WlBaYjLBZNaIwIBBEYwLNy2WC6KbBC4qnFC4oLDZYILFa4oLJfYYADfYcB/4LF/4LCKgLkCcQRSCJAX1BYdfIwQ8CEgn/HQQwDDAVfFwgABA4IAC+oKEgEFBYdQBYoYDCwwYCF4IWHAFgA="))
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"id": "mixdiganclock",
|
||||||
|
"name": "Mix Dig&Anal Clock",
|
||||||
|
"version": "0.03",
|
||||||
|
"description": "A dual Analog and Digital Clock, based in Mixed Clock, but with more compatibility, change of colors, thicker clock hands... ",
|
||||||
|
"icon": "mixdiganclock.png",
|
||||||
|
"type": "clock",
|
||||||
|
"tags": "clock",
|
||||||
|
"screenshots": [{"url":"pic_mixdigan_bjs1.jpg"}],
|
||||||
|
"supports": ["BANGLEJS","BANGLEJS"],
|
||||||
|
"readme": "README.md",
|
||||||
|
"allow_emulator": true,
|
||||||
|
"storage": [
|
||||||
|
{"name":"mixdiganclock.app.js","url":"mixdiganclock.app.js"},
|
||||||
|
{"name":"mixdiganclock.img","url":"app-icon.js","evaluate":true}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,230 @@
|
||||||
|
/*fork of miclock, dynamic x,y, colors on realtime,
|
||||||
|
compatible with BJS1, BJS2 and bottom widgets
|
||||||
|
*/
|
||||||
|
var locale = require("locale");
|
||||||
|
var v_mode_debug=0; //, 0=no, 1 min, 2 prone detail
|
||||||
|
var v_model=process.env.BOARD;
|
||||||
|
var LastDrawDay; // to notice a change and repaint static texts
|
||||||
|
//RGB565 0x White , black, 'Orange',blue,red, olive,...
|
||||||
|
var a_colors= [0xFFFF,0x0000, 0xFD20, 0x001F,0xF800,0x7be0,0x780F,0x07E0]; //new Array(0xFFFF
|
||||||
|
var Radius= []; //new Array();
|
||||||
|
var TxtPosition=[];
|
||||||
|
var v_bfont_size;
|
||||||
|
var v_vfont_size;
|
||||||
|
var v_color1;
|
||||||
|
var v_color2;
|
||||||
|
var v_color3;
|
||||||
|
var v_color_erase;
|
||||||
|
var v_count_col;
|
||||||
|
var rect = Bangle.appRect;
|
||||||
|
var v_center_x;
|
||||||
|
var v_center_y;
|
||||||
|
if (v_mode_debug>0) console.log("a_colors.length "+a_colors.length);
|
||||||
|
|
||||||
|
g.clear();
|
||||||
|
//show the exit button
|
||||||
|
//Bangle.setUI();
|
||||||
|
Bangle.setUI("clock"); //implies center button for launcher
|
||||||
|
/*{
|
||||||
|
mode : "custom",
|
||||||
|
back : Bangle.showLauncher
|
||||||
|
});*/
|
||||||
|
|
||||||
|
Bangle.loadWidgets();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function setVariables() {
|
||||||
|
// different values depending on loaded widgets or not, so after load widgets
|
||||||
|
rect = Bangle.appRect;
|
||||||
|
v_center_x = g.getWidth()/2;
|
||||||
|
v_center_y = g.getHeight()/2; //vertical middle
|
||||||
|
//if (v_mode_debug>1) console.log(v_model+" center x, y "+v_center_x+" , "+v_center_y+" Max y,y2"+rect.y+" ,"+rect.y2);
|
||||||
|
TxtPosition = {
|
||||||
|
"x1": 3, "x2": g.getWidth()-3,
|
||||||
|
"y1": rect.y+17, "y2": rect.y2-6,
|
||||||
|
"x_HH": g.getWidth()/2 ,"y_mm": v_center_y+32
|
||||||
|
};
|
||||||
|
|
||||||
|
//emuls EMSCRIPTEN,EMSCRIPTEN2
|
||||||
|
v_count_col=2; //1st=0 1st compatible color (dark/light theme)
|
||||||
|
v_color_erase=g.getBgColor();
|
||||||
|
if (v_model=='BANGLEJS'||v_model=='EMSCRIPTEN') {
|
||||||
|
Radius = { "center": 7, "hour": 50, "min": 70, "dots": 88,"circleH":6,"circleM":2 };
|
||||||
|
v_bfont_size=3;
|
||||||
|
v_vfont_size=35;
|
||||||
|
v_color1=2; // orange
|
||||||
|
v_color2=4;
|
||||||
|
v_color3=0; //white , for hands PEND replace hardcoded by logic
|
||||||
|
}else{
|
||||||
|
Radius = { "center": 5, "hour": 35, "min": 50, "dots": 60, "circleH":5,"circleM":2 };
|
||||||
|
v_bfont_size=2;
|
||||||
|
v_vfont_size=22;
|
||||||
|
v_color1=3; // blue
|
||||||
|
v_color2=1;
|
||||||
|
v_color3=1; //opposite to bg, for hands PEND replace hardcoded by logic
|
||||||
|
}
|
||||||
|
if (v_mode_debug>0) console.log("set vars for: "+v_model);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function rotatePoint(x, y, d) {
|
||||||
|
rad = -1 * d / 180 * Math.PI;
|
||||||
|
var sin = Math.sin(rad);
|
||||||
|
var cos = Math.cos(rad);
|
||||||
|
xn = ((v_center_x + x * cos - y * sin) + 0.5) | 0;
|
||||||
|
yn = ((v_center_y + x * sin - y * cos) + 0.5) | 0;
|
||||||
|
p = [xn, yn];
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
//no need to repaint
|
||||||
|
function drawStaticRing(v_colorparam){
|
||||||
|
// draw hour and minute dots
|
||||||
|
if (v_mode_debug>0) console.log("color: "+v_colorparam);
|
||||||
|
//g.setColor(a_colors[v_color1]);
|
||||||
|
g.setColor(v_colorparam);
|
||||||
|
|
||||||
|
for (i = 0; i < 60; i++) {
|
||||||
|
// ? 2 : 4;
|
||||||
|
radius = (i % 5) ? Radius.circleM : Radius.circleH;
|
||||||
|
point = rotatePoint(0, Radius.dots, i * 6);
|
||||||
|
//if (v_mode_debug>1) console.log("point"+point);
|
||||||
|
g.fillCircle(point[0], point[1], radius);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//no need to repaint every min
|
||||||
|
function drawDailyTxt(){
|
||||||
|
var date = new Date();
|
||||||
|
var isEn = locale.name.startsWith("en");
|
||||||
|
var dateArray = date.toString().split(" ");
|
||||||
|
LastDrawDay=locale.dow(date,true);
|
||||||
|
var hour = date.getHours();
|
||||||
|
|
||||||
|
if (v_mode_debug>1) {
|
||||||
|
console.log("full date "+date.toString());
|
||||||
|
console.log("locale time "+locale.time(date,true));
|
||||||
|
console.log("LastDrawDay "+LastDrawDay);
|
||||||
|
console.log("locale new day "+(locale.dow(date,true)));
|
||||||
|
}
|
||||||
|
g.setColor(a_colors[v_color2]);
|
||||||
|
//small size then bitmap
|
||||||
|
g.setFont("4x6", v_bfont_size); //6x8
|
||||||
|
g.setFontAlign(-1, 0);
|
||||||
|
g.drawString(locale.dow(date,true) + ' ',TxtPosition.x1 , TxtPosition.y1, true);
|
||||||
|
g.drawString(isEn?(' ' + dateArray[2]):locale.month(date,true), TxtPosition.x1, TxtPosition.y2, true);
|
||||||
|
g.setFontAlign(1, 0);
|
||||||
|
g.drawString(isEn?locale.month(date,true):(' ' + dateArray[2]), TxtPosition.x2, TxtPosition.y1, true);
|
||||||
|
g.drawString(dateArray[3], TxtPosition.x2, TxtPosition.y2, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function drawMixedClock() {
|
||||||
|
var date = new Date();
|
||||||
|
var dateArray = date.toString().split(" ");
|
||||||
|
//var isEn = locale.name.startsWith("en");
|
||||||
|
var point = [];
|
||||||
|
var minute = date.getMinutes();
|
||||||
|
var hour = date.getHours();
|
||||||
|
var radius;
|
||||||
|
//Call function only after a change of day
|
||||||
|
if (LastDrawDay!=locale.dow(date,true)) drawDailyTxt();
|
||||||
|
//ERASE previous hands
|
||||||
|
// erase last MINutes hand
|
||||||
|
g.setColor(v_color_erase);
|
||||||
|
point = rotatePoint(0, Radius.min, (minute - 1) * 6);
|
||||||
|
g.drawLine(v_center_x, v_center_y, point[0], point[1]);
|
||||||
|
//to increase thicknes
|
||||||
|
g.drawLine(v_center_x+1, v_center_y, point[0]+1, point[1]);
|
||||||
|
// erase last two HOUR hands ¿2?
|
||||||
|
g.setColor(v_color_erase);
|
||||||
|
p = rotatePoint(0, Radius.hour, hour % 12 * 30 + (minute - 2) / 2 | 0);
|
||||||
|
g.drawLine(v_center_x, v_center_y, p[0], p[1]);
|
||||||
|
//to increase thicknes
|
||||||
|
g.drawLine(v_center_x+1, v_center_y, p[0]+1, p[1]);
|
||||||
|
|
||||||
|
point = rotatePoint(0, Radius.hour, hour % 12 * 30 + (minute - 1) / 2 | 0);
|
||||||
|
g.drawLine(v_center_x, v_center_y, point[0], point[1]);
|
||||||
|
//to increase thicknes
|
||||||
|
g.drawLine(v_center_x+1, v_center_y, point[0]+1, point[1]);
|
||||||
|
|
||||||
|
// here time DIGITs are draw under hands
|
||||||
|
|
||||||
|
// draw new MINute hand
|
||||||
|
point = rotatePoint(0, Radius.min, minute * 6);
|
||||||
|
g.setColor(a_colors[v_color3]);
|
||||||
|
g.drawLine(v_center_x, v_center_y, point[0], point[1]);
|
||||||
|
//to increase thicknes
|
||||||
|
g.drawLine(v_center_x+1, v_center_y, point[0]+1, point[1]);
|
||||||
|
// draw new HOUR hand
|
||||||
|
point = rotatePoint(0, Radius.hour, hour % 12 * 30 + date.getMinutes() / 2 | 0);
|
||||||
|
g.setColor(a_colors[v_color3]);
|
||||||
|
g.drawLine(v_center_x, v_center_y, point[0], point[1]);
|
||||||
|
//to increase thicknes
|
||||||
|
g.drawLine(v_center_x+1, v_center_y, point[0]+1, point[1]);
|
||||||
|
|
||||||
|
// draw DIGITs of time above hands for better UX
|
||||||
|
//g.setFont("6x8", 3); 3 bigger size
|
||||||
|
g.setFontVector(v_vfont_size);
|
||||||
|
g.setColor(a_colors[v_color2]);
|
||||||
|
g.setFontAlign(0, 0);
|
||||||
|
//by default 24H, to use format config 12H 24H read from locale
|
||||||
|
g.drawString(dateArray[4].substr(0, 5), TxtPosition.x_HH, TxtPosition.y_mm, true);
|
||||||
|
// the central point requires redrawing because hands draw over it
|
||||||
|
g.setColor(a_colors[v_color1]);
|
||||||
|
g.fillCircle(v_center_x, v_center_y, Radius.center);
|
||||||
|
}
|
||||||
|
function UserInput(){
|
||||||
|
Bangle.on('touch', function(button){
|
||||||
|
switch(button){
|
||||||
|
case 1:
|
||||||
|
Bangle.showLauncher();
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
//testing to improve
|
||||||
|
if (v_mode_debug>0) console.log("v_count_col/total: "+v_count_col+"/"+a_colors.length);
|
||||||
|
if (v_count_col<a_colors.length){
|
||||||
|
v_color1=v_count_col;
|
||||||
|
v_color2=v_count_col;
|
||||||
|
v_color3=v_count_col;
|
||||||
|
v_count_col++; //next color
|
||||||
|
}
|
||||||
|
else setVariables(); //v_count_col=3; //reset to 1st common color
|
||||||
|
if (v_mode_debug>0) console.log("paint on color: "+v_count_col);
|
||||||
|
drawStaticRing(a_colors[v_color1]);
|
||||||
|
drawDailyTxt();
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
//console.log("Touch 3 aka 1+2 not for emul");//center 1+2
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Bangle.on('swipe', dir => {
|
||||||
|
if(dir == 1) {
|
||||||
|
drawStaticRing(v_color_erase);
|
||||||
|
if (Radius.circleH<13) Radius.circleH++;
|
||||||
|
if (v_mode_debug>0) console.log("radio: "+Radius.circleH);
|
||||||
|
drawStaticRing(a_colors[v_color1]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
drawStaticRing(v_color_erase);
|
||||||
|
if (Radius.circleH>1) Radius.circleH--;
|
||||||
|
if (v_mode_debug>0) console.log("radio: "+Radius.circleH);
|
||||||
|
drawStaticRing(a_colors[v_color1]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Bangle.on('lcdPower', function(on) {
|
||||||
|
if (on)
|
||||||
|
drawMixedClock();
|
||||||
|
});
|
||||||
|
|
||||||
|
setVariables();
|
||||||
|
Bangle.drawWidgets();
|
||||||
|
UserInput();
|
||||||
|
|
||||||
|
setInterval(drawMixedClock, 5E3);
|
||||||
|
drawStaticRing(a_colors[v_color1]);
|
||||||
|
drawDailyTxt(); //1st time
|
||||||
|
drawMixedClock();
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
{"id":"mixdiganclock","name":"Mix Dig&Anal","type":"clock","src":"mixdiganclock.app.js","icon":"mixdiganclock.img","version":"0.02","tags":"clock","files":"mixdiganclock.info,mixdiganclock.app.js,mixdiganclock.img"}
|
||||||
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 1.7 MiB |
|
After Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 4.2 KiB |
|
|
@ -0,0 +1,2 @@
|
||||||
|
0.01: New App!
|
||||||
|
0.02: Hide widgets instead of not loading them at all
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{ "id": "saclock",
|
{ "id": "saclock",
|
||||||
"name": "Simple analog clock",
|
"name": "Simple analog clock",
|
||||||
"shortName":"Analog clock",
|
"shortName":"Analog clock",
|
||||||
"version":"0.01",
|
"version":"0.02",
|
||||||
"description": "A very basic analog clock",
|
"description": "A very basic analog clock",
|
||||||
"screenshots": [{"url":"screenshot.png"}],
|
"screenshots": [{"url":"screenshot.png"}],
|
||||||
"icon": "icon.png",
|
"icon": "icon.png",
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
/*LANG*/"< Back": back,
|
/*LANG*/"< Back": back,
|
||||||
};
|
};
|
||||||
require("ClockFace_menu").addSettingsFile(menu, "saclock.settings.json", [
|
require("ClockFace_menu").addSettingsFile(menu, "saclock.settings.json", [
|
||||||
"loadWidgets"
|
"hideWidgets"
|
||||||
]);
|
]);
|
||||||
E.showMenu(menu);
|
E.showMenu(menu);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -19,3 +19,4 @@
|
||||||
0.16: Improve support for date timezone
|
0.16: Improve support for date timezone
|
||||||
0.17: Fix midnight in local timezone (alarms wouldn't always fire as expected in timezone != 0)
|
0.17: Fix midnight in local timezone (alarms wouldn't always fire as expected in timezone != 0)
|
||||||
0.18: Update clock_info to avoid a redraw
|
0.18: Update clock_info to avoid a redraw
|
||||||
|
0.19: Update clock_info to refresh periodically on active alarms/timers
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,52 @@
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the array [interval, switchTimeout]
|
||||||
|
* `interval` is the refresh rate (hourly or per minute)
|
||||||
|
* `switchTimeout` is the time before the refresh rate should change (or expiration)
|
||||||
|
*/
|
||||||
|
function getRefreshIntervals(a) {
|
||||||
|
const minute = 60 * 1000;
|
||||||
|
const halfhour = 30 * minute;
|
||||||
|
const hour = 2 * halfhour;
|
||||||
|
let msecs = alarm.getTimeToAlarm(a);
|
||||||
|
if(typeof msecs == "undefined" || msecs == 0)
|
||||||
|
return [];
|
||||||
|
if(msecs > hour) { //refresh every half an hour
|
||||||
|
let remain = (msecs+minute) % halfhour;
|
||||||
|
if(remain < 27 * minute && remain != 0) //first align period (some tolerance)
|
||||||
|
return [ halfhour, remain ];
|
||||||
|
return [ halfhour, msecs - hour ];
|
||||||
|
} else { //refresh every minute
|
||||||
|
//alarms just need the progress bar refreshed, no need every minute
|
||||||
|
if(!a.timer) return [];
|
||||||
|
return [ minute, msecs ];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function _doInterval(interval) {
|
||||||
|
return setTimeout(()=>{
|
||||||
|
this.emit("redraw");
|
||||||
|
this.interval = setInterval(()=>{
|
||||||
|
this.emit("redraw");
|
||||||
|
}, interval);
|
||||||
|
}, interval);
|
||||||
|
}
|
||||||
|
function _doSwitchTimeout(a, switchTimeout) {
|
||||||
|
return setTimeout(()=>{
|
||||||
|
this.emit("redraw");
|
||||||
|
clearInterval(this.interval);
|
||||||
|
this.interval = undefined;
|
||||||
|
var tmp = getRefreshIntervals(a);
|
||||||
|
var interval = tmp[0];
|
||||||
|
var switchTimeout = tmp[1];
|
||||||
|
if(!interval) return;
|
||||||
|
this.interval = _doInterval.call(this, interval);
|
||||||
|
this.switchTimeout = _doSwitchTimeout.call(this, a, switchTimeout);
|
||||||
|
}, switchTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
var img = iconAlarmOn;
|
var img = iconAlarmOn;
|
||||||
//get only alarms not created by other apps
|
//get only alarms not created by other apps
|
||||||
var alarmItems = {
|
var alarmItems = {
|
||||||
|
|
@ -63,8 +109,20 @@
|
||||||
hasRange: true,
|
hasRange: true,
|
||||||
get: () => ({ text: getAlarmText(a), img: getAlarmIcon(a),
|
get: () => ({ text: getAlarmText(a), img: getAlarmIcon(a),
|
||||||
v: getAlarmValue(a), min:0, max:getAlarmMax(a)}),
|
v: getAlarmValue(a), min:0, max:getAlarmMax(a)}),
|
||||||
show: function() {},
|
show: function() {
|
||||||
hide: function () {},
|
var tmp = getRefreshIntervals(a);
|
||||||
|
var interval = tmp[0];
|
||||||
|
var switchTimeout = tmp[1];
|
||||||
|
if(!interval) return;
|
||||||
|
this.interval = _doInterval.call(this, interval);
|
||||||
|
this.switchTimeout = _doSwitchTimeout.call(this, a, switchTimeout);
|
||||||
|
},
|
||||||
|
hide: function() {
|
||||||
|
clearInterval(this.interval);
|
||||||
|
clearTimeout(this.switchTimeout);
|
||||||
|
this.interval = undefined;
|
||||||
|
this.switchTimeout = undefined;
|
||||||
|
},
|
||||||
run: function() { }
|
run: function() { }
|
||||||
})),
|
})),
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"id": "sched",
|
"id": "sched",
|
||||||
"name": "Scheduler",
|
"name": "Scheduler",
|
||||||
"version": "0.18",
|
"version": "0.19",
|
||||||
"description": "Scheduling library for alarms and timers",
|
"description": "Scheduling library for alarms and timers",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"type": "scheduler",
|
"type": "scheduler",
|
||||||
|
|
|
||||||
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
|
@ -1 +1,2 @@
|
||||||
0.01: 1st version: saves values to csv
|
0.01: 1st version: saves values to csv
|
||||||
|
0.02: added HTML interface
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,13 @@ Screenshot BJS1
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
Screenshot data file content
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
|
||||||
|
After Width: | Height: | Size: 28 KiB |
|
|
@ -0,0 +1,67 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<link rel="stylesheet" href="../../css/spectre.min.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="data"></div>
|
||||||
|
<button class="btn btn-default" id="btnSave">Save</button>
|
||||||
|
<button class="btn btn-default" id="btnDelete">Delete</button>
|
||||||
|
<script src="../../core/lib/interface.js"></script>
|
||||||
|
<script>
|
||||||
|
var dataElement = document.getElementById("data");
|
||||||
|
var csvData = "";
|
||||||
|
|
||||||
|
function getData() {
|
||||||
|
// show loading window
|
||||||
|
Util.showModal("Loading...");
|
||||||
|
// get the data
|
||||||
|
dataElement.innerHTML = "";
|
||||||
|
Util.readStorageFile(`temphistory.csv`,data=>{
|
||||||
|
csvData = data.trim();
|
||||||
|
// remove window
|
||||||
|
Util.hideModal();
|
||||||
|
// If no data, report it and exit
|
||||||
|
if (data.length==0) {
|
||||||
|
dataElement.innerHTML = "<b>No data found</b>";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Otherwise parse the data and output it as a table
|
||||||
|
//<td>${(new Date(l[0]*1000)).toLocaleString()}</td>
|
||||||
|
dataElement.innerHTML = `<table>
|
||||||
|
<tr>
|
||||||
|
<th>Month</th>
|
||||||
|
<th>Day</th>
|
||||||
|
<th>Time HH:mm</th>
|
||||||
|
<th>temperature</th>
|
||||||
|
</tr>`+data.trim().split("\n").map(l=>{
|
||||||
|
l = l.split(";");
|
||||||
|
return `<tr>
|
||||||
|
<td>${l[0]}</td>
|
||||||
|
<td>${l[1]}</td>
|
||||||
|
<td>${l[2]}</td>
|
||||||
|
<td>${l[3]}</td>
|
||||||
|
</tr>`
|
||||||
|
}).join("\n")+"</table>";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// You can call a utility function to save the data
|
||||||
|
document.getElementById("btnSave").addEventListener("click", function() {
|
||||||
|
Util.saveCSV("temphistory.csv", csvData);
|
||||||
|
});
|
||||||
|
// Or you can also delete the file
|
||||||
|
document.getElementById("btnDelete").addEventListener("click", function() {
|
||||||
|
Util.showModal("Deleting...");
|
||||||
|
Util.eraseStorageFile("temphistory.csv", function() {
|
||||||
|
Util.hideModal();
|
||||||
|
getData();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
// Called when app starts
|
||||||
|
function onInit() {
|
||||||
|
getData();
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -1,12 +1,14 @@
|
||||||
{
|
{
|
||||||
"id": "tempmonitor",
|
"id": "tempmonitor",
|
||||||
"name": "Temperature monitor",
|
"name": "Temperature monitor",
|
||||||
"version": "0.01",
|
"version": "0.02",
|
||||||
"description": "Displays the current temperature and stores in a CSV file",
|
"description": "Displays the current temperature and stores in a CSV file",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"tags": "tool",
|
"tags": "tool",
|
||||||
|
"interface": "interface.html",
|
||||||
"supports": ["BANGLEJS", "BANGLEJS2"],
|
"supports": ["BANGLEJS", "BANGLEJS2"],
|
||||||
"screenshots": [{"url":"photo_banglejs1.jpg"}],
|
"readme": "README.md",
|
||||||
|
"screenshots": [{"url":"ss_emul_bjs2.png"}],
|
||||||
"allow_emulator": true,
|
"allow_emulator": true,
|
||||||
"storage": [
|
"storage": [
|
||||||
{"name":"tempmonitor.app.js","url":"tempmonitor.app.js"},
|
{"name":"tempmonitor.app.js","url":"tempmonitor.app.js"},
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.5 KiB |
|
|
@ -1,14 +1,14 @@
|
||||||
// Temperature monitor that saves a log of measures
|
// Temperature monitor that saves a log of measures
|
||||||
// Version 001 standalone for developer
|
// standalone ver for developer, to remove testing lines
|
||||||
// PEND
|
// delimiter ; (excel) or , (oldscool)
|
||||||
//test with small savefreq
|
{
|
||||||
var v_mode_debug=0; //, 0=no, 1 min, 2 prone detail
|
var v_mode_debug=0; //, 0=no, 1 min, 2 prone detail
|
||||||
//var required for drawing with dynamic screen
|
//var required for drawing with dynamic screen
|
||||||
var rect = Bangle.appRect;
|
var rect = Bangle.appRect;
|
||||||
var history = [];
|
var history = [];
|
||||||
var readFreq=5000; //ms //PEND add to settings
|
var readFreq=5000; //ms //PEND add to settings
|
||||||
var saveFreq=30000; //ms
|
var saveFreq=60000; //ms 1min
|
||||||
var v_saveToFile='Y'; //Y save //N
|
var v_saveToFile= new Boolean(true); //true save //false
|
||||||
//with upload file º is not displayed properly
|
//with upload file º is not displayed properly
|
||||||
//with upload RAM º is displayed
|
//with upload RAM º is displayed
|
||||||
var v_t_symbol="";//ºC
|
var v_t_symbol="";//ºC
|
||||||
|
|
@ -68,10 +68,10 @@ function saveToFile() {
|
||||||
var strlastSaveTime=new String();
|
var strlastSaveTime=new String();
|
||||||
strlastSaveTime=a.toISOString();
|
strlastSaveTime=a.toISOString();
|
||||||
//strlastSaveTime=strlastSaveTime.concat(a.getFullYear(),a.getMonth()+1,a.getDate(),a.getHours(),a.getMinutes());;
|
//strlastSaveTime=strlastSaveTime.concat(a.getFullYear(),a.getMonth()+1,a.getDate(),a.getHours(),a.getMinutes());;
|
||||||
if (v_mode_debug==1) console.log("saving="+strlastSaveTime+","+lastMeasure);
|
if (v_mode_debug==1) console.log("saving="+strlastSaveTime+";"+a.getHours()+":"+a.getMinutes()+";"+lastMeasure);
|
||||||
|
if (v_saveToFile==true){
|
||||||
if (v_saveToFile=='Y'){
|
//write(strlastSaveTime+";"+
|
||||||
require("Storage").open(filename,"a").write(strlastSaveTime+","+lastMeasure+"\n");
|
require("Storage").open(filename,"a").write((a.getMonth()+1)+";"+a.getDate()+";"+a.getHours()+":"+a.getMinutes()+";"+lastMeasure+"\n");
|
||||||
//(getTime()+",");
|
//(getTime()+",");
|
||||||
v_saved_entries=v_saved_entries+1;
|
v_saved_entries=v_saved_entries+1;
|
||||||
}
|
}
|
||||||
|
|
@ -127,7 +127,7 @@ setInterval(function() {
|
||||||
drawTemperature();
|
drawTemperature();
|
||||||
}, readFreq); //ms
|
}, readFreq); //ms
|
||||||
|
|
||||||
if (v_saveToFile=="Y") {
|
if (v_saveToFile==true) {
|
||||||
setInterval(function() {
|
setInterval(function() {
|
||||||
saveToFile();
|
saveToFile();
|
||||||
}, saveFreq); //ms
|
}, saveFreq); //ms
|
||||||
|
|
@ -135,3 +135,4 @@ if (v_saveToFile=="Y") {
|
||||||
setTimeout(ClearScreen, 3500);
|
setTimeout(ClearScreen, 3500);
|
||||||
setTimeout(drawGraph,4000);
|
setTimeout(drawGraph,4000);
|
||||||
setTimeout(drawTemperature,4500);
|
setTimeout(drawTemperature,4500);
|
||||||
|
}
|
||||||
|
|
@ -5,3 +5,5 @@
|
||||||
0.05: Add altitude display (only Bangle.js 2)
|
0.05: Add altitude display (only Bangle.js 2)
|
||||||
0.06: Add power related settings to control the HR and pressure(altitude) sensor from the watchface
|
0.06: Add power related settings to control the HR and pressure(altitude) sensor from the watchface
|
||||||
0.07: Use ClockFace module and rework the settings to be able to personnalize the order of the lines
|
0.07: Use ClockFace module and rework the settings to be able to personnalize the order of the lines
|
||||||
|
0.08: Hide widgets instead of not loading them at all
|
||||||
|
Use Clockface_menu for widgets and power saving settings
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,8 @@ const clock = new ClockFace({
|
||||||
this.unlock_precision = 1;
|
this.unlock_precision = 1;
|
||||||
if (this.HRMinConfidence === undefined) this.HRMinConfidence = 50;
|
if (this.HRMinConfidence === undefined) this.HRMinConfidence = 50;
|
||||||
if (this.PowerOnInterval === undefined) this.PowerOnInterval = 15;
|
if (this.PowerOnInterval === undefined) this.PowerOnInterval = 15;
|
||||||
if (this.powerSaving===undefined) this.powerSaving = true;
|
if (this.powerSave===undefined) this.powerSave = this.powerSaving; // migrate old setting
|
||||||
|
if (this.powerSave===undefined) this.powerSave = true;
|
||||||
["L2", "L3", "L4", "L5", "L6", "L7", "L8", "L9"].forEach(k => {
|
["L2", "L3", "L4", "L5", "L6", "L7", "L8", "L9"].forEach(k => {
|
||||||
if (this[k]===undefined){
|
if (this[k]===undefined){
|
||||||
if(k == "L2") this[k] = "Date";
|
if(k == "L2") this[k] = "Date";
|
||||||
|
|
@ -55,7 +56,7 @@ const clock = new ClockFace({
|
||||||
});
|
});
|
||||||
|
|
||||||
// set the services (HRM, pressure sensor, etc....)
|
// set the services (HRM, pressure sensor, etc....)
|
||||||
if(!this.powerSaving){
|
if(!this.powerSave){
|
||||||
turnOnServices();
|
turnOnServices();
|
||||||
} else{
|
} else{
|
||||||
setInterval(turnOnServices, this.PowerOnInterval*60000); // every PowerOnInterval min
|
setInterval(turnOnServices, this.PowerOnInterval*60000); // every PowerOnInterval min
|
||||||
|
|
@ -156,7 +157,7 @@ function turnOnServices(){
|
||||||
if(clock.showAltitude){
|
if(clock.showAltitude){
|
||||||
Bangle.setBarometerPower(true, "terminalclock");
|
Bangle.setBarometerPower(true, "terminalclock");
|
||||||
}
|
}
|
||||||
if(clock.powerSaving){
|
if(clock.powerSave){
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
turnOffServices();
|
turnOffServices();
|
||||||
}, 45000);
|
}, 45000);
|
||||||
|
|
@ -194,7 +195,7 @@ Clock related functions but not in the ClockFace module
|
||||||
---------------------------------------------------- */
|
---------------------------------------------------- */
|
||||||
|
|
||||||
function unlock(){
|
function unlock(){
|
||||||
if(clock.powerSaving){
|
if(clock.powerSave){
|
||||||
turnOnServices();
|
turnOnServices();
|
||||||
}
|
}
|
||||||
clock.precision = clock.unlock_precision;
|
clock.precision = clock.unlock_precision;
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
"name": "Terminal Clock",
|
"name": "Terminal Clock",
|
||||||
"shortName":"Terminal Clock",
|
"shortName":"Terminal Clock",
|
||||||
"description": "A terminal cli like clock displaying multiple sensor data",
|
"description": "A terminal cli like clock displaying multiple sensor data",
|
||||||
"version":"0.07",
|
"version":"0.08",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"type": "clock",
|
"type": "clock",
|
||||||
"tags": "clock",
|
"tags": "clock",
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,8 @@
|
||||||
var FILE = "terminalclock.json";
|
var FILE = "terminalclock.json";
|
||||||
// Load settings
|
// Load settings
|
||||||
var settings = Object.assign({
|
var settings = Object.assign({
|
||||||
// ClockFace lib
|
|
||||||
loadWidgets: true,
|
|
||||||
// TerminalClock specific
|
// TerminalClock specific
|
||||||
HRMinConfidence: 50,
|
HRMinConfidence: 50,
|
||||||
powerSaving: true,
|
|
||||||
PowerOnInterval: 15,
|
PowerOnInterval: 15,
|
||||||
L2: 'Date',
|
L2: 'Date',
|
||||||
L3: 'HR',
|
L3: 'HR',
|
||||||
|
|
@ -17,6 +14,18 @@
|
||||||
L8: 'Empty',
|
L8: 'Empty',
|
||||||
L9: 'Empty',
|
L9: 'Empty',
|
||||||
}, require('Storage').readJSON(FILE, true) || {});
|
}, require('Storage').readJSON(FILE, true) || {});
|
||||||
|
// ClockFace lib: migrate "don't load widgets" to "hide widgets"
|
||||||
|
if (!("hideWidgets" in settings)) {
|
||||||
|
if (("loadWidgets" in settings) && !settings.loadWidgets) settings.hideWidgets = 1;
|
||||||
|
else settings.hideWidgets = 0;
|
||||||
|
}
|
||||||
|
delete settings.loadWidgets;
|
||||||
|
// ClockFace lib: migrate `powerSaving` to `powerSave`
|
||||||
|
if (!("powerSave" in settings)) {
|
||||||
|
if ("powerSaving" in settings) settings.powerSave = settings.powerSaving;
|
||||||
|
else settings.powerSave = true;
|
||||||
|
}
|
||||||
|
delete settings.powerSaving;
|
||||||
|
|
||||||
function writeSettings() {
|
function writeSettings() {
|
||||||
require('Storage').writeJSON(FILE, settings);
|
require('Storage').writeJSON(FILE, settings);
|
||||||
|
|
@ -63,25 +72,16 @@
|
||||||
writeSettings();
|
writeSettings();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'Show widgets': {
|
|
||||||
value: settings.loadWidgets,
|
|
||||||
onchange: v => {
|
|
||||||
settings.loadWidgets = v;
|
|
||||||
writeSettings();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'Power saving': {
|
|
||||||
value: settings.powerSaving,
|
|
||||||
onchange: v => {
|
|
||||||
settings.powerSaving = v;
|
|
||||||
writeSettings();
|
|
||||||
setTimeout(function() {
|
|
||||||
E.showMenu(getMainMenu());
|
|
||||||
},0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
if(settings.powerSaving){
|
const save = (key, v) => {
|
||||||
|
settings[key] = v;
|
||||||
|
writeSettings();
|
||||||
|
};
|
||||||
|
require("ClockFace_menu").addItems(mainMenu, save, {
|
||||||
|
hideWidgets: settings.hideWidgets,
|
||||||
|
powerSave: settings.powerSave,
|
||||||
|
});
|
||||||
|
if(settings.powerSave){
|
||||||
mainMenu['Power on interval'] = {
|
mainMenu['Power on interval'] = {
|
||||||
value: settings.PowerOnInterval,
|
value: settings.PowerOnInterval,
|
||||||
min: 3, max: 60,
|
min: 3, max: 60,
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ WIDGETS["wdclk"]={area:"tl",width:Bangle.CLOCK?0:52/* g.stringWidth("00:00") */,
|
||||||
this.width = Bangle.CLOCK?0:52;
|
this.width = Bangle.CLOCK?0:52;
|
||||||
return setTimeout(Bangle.drawWidgets,1); // widget changed size - redraw
|
return setTimeout(Bangle.drawWidgets,1); // widget changed size - redraw
|
||||||
}
|
}
|
||||||
if (!this.width) return; // if size not right, return
|
if (!this.width) return; // if not visible, return
|
||||||
g.reset().setFontCustom(atob("AAAAAAAAAAIAAAQCAQAAAd0BgMBdwAAAAAAAdwAB0RiMRcAAAERiMRdwAcAQCAQdwAcERiMRBwAd0RiMRBwAAEAgEAdwAd0RiMRdwAcERiMRdwAFAAd0QiEQdwAdwRCIRBwAd0BgMBAAABwRCIRdwAd0RiMRAAAd0QiEQAAAAAAAAAA="), 32, atob("BgAAAAAAAAAAAAAAAAYCAAYGBgYGBgYGBgYCAAAAAAAABgYGBgYG"), 512+9);
|
g.reset().setFontCustom(atob("AAAAAAAAAAIAAAQCAQAAAd0BgMBdwAAAAAAAdwAB0RiMRcAAAERiMRdwAcAQCAQdwAcERiMRBwAd0RiMRBwAAEAgEAdwAd0RiMRdwAcERiMRdwAFAAd0QiEQdwAdwRCIRBwAd0BgMBAAABwRCIRdwAd0RiMRAAAd0QiEQAAAAAAAAAA="), 32, atob("BgAAAAAAAAAAAAAAAAYCAAYGBgYGBgYGBgYCAAAAAAAABgYGBgYG"), 512+9);
|
||||||
var time = require("locale").time(new Date(),1);
|
var time = require("locale").time(new Date(),1);
|
||||||
g.drawString(time, this.x, this.y+3, true); // 5 * 6*2 = 60
|
g.drawString(time, this.x, this.y+3, true); // 5 * 6*2 = 60
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,9 @@
|
||||||
# Digital clock widget (bottom widget area)
|
# Digital clock widget (bottom widget area)
|
||||||
This very basic widget clock allows to test the unfrequently used widget bottom area.
|
This very basic widget clock shows time inside apps that respect the bottom widget area, also allows to test this unfrequently used area.
|
||||||
|
|
||||||
|
Note that it will not be displayed when a clock app is been shown
|
||||||
|
|
||||||
|
Compatible with BangleJS1,BangleJS2,and EMSCRIPTENx emulators
|
||||||
|
|
||||||
forked from
|
forked from
|
||||||
https://github.com/espruino/BangleApps/tree/master/apps/widclk
|
https://github.com/espruino/BangleApps/tree/master/apps/widclk
|
||||||
|
|
@ -10,14 +14,17 @@ Example of usage
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
Screenshot emulator bangle.js2
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
Upload the widget file
|
Upload the widget file
|
||||||
Open an app that supports displaying widgets
|
Open an app (not a clock/watchface) that supports displaying widgets (included the bottom one)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -25,4 +32,4 @@ Open an app that supports displaying widgets
|
||||||
|
|
||||||
This app is so basic that probably the easiest is to just edit the code ;)
|
This app is so basic that probably the easiest is to just edit the code ;)
|
||||||
|
|
||||||
Otherwise you can contact me [here](https://github.com/dapgo)
|
Otherwise you can contact me [here](https://github.com/dapgo/my_espruino_smartwatch_things)
|
||||||
|
|
@ -3,11 +3,12 @@
|
||||||
"name": "Digital clock (Bottom) widget",
|
"name": "Digital clock (Bottom) widget",
|
||||||
"shortName": "Digital clock Bottom Widget",
|
"shortName": "Digital clock Bottom Widget",
|
||||||
"version": "0.05",
|
"version": "0.05",
|
||||||
"description": "Displays time in the bottom of the screen (may not be compatible with some apps)",
|
"description": "Displays time HH:mm in the bottom of the screen (may not be compatible with some apps)",
|
||||||
"icon": "widclkbttm.png",
|
"icon": "widclkbttm.png",
|
||||||
"type": "widget",
|
"type": "widget",
|
||||||
"tags": "widget",
|
"tags": "widget",
|
||||||
"supports": ["BANGLEJS","BANGLEJS2"],
|
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||||
|
"screenshots": [{"url":"ss_bjs1.png"}],
|
||||||
"readme": "README.md",
|
"readme": "README.md",
|
||||||
"storage": [
|
"storage": [
|
||||||
{"name":"widclkbttm.wid.js","url":"widclkbttm.wid.js"}
|
{"name":"widclkbttm.wid.js","url":"widclkbttm.wid.js"}
|
||||||
|
|
|
||||||
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
|
@ -3,7 +3,7 @@ WIDGETS["wdclkbttm"]={area:"br",width:Bangle.CLOCK?0:60,draw:function() {
|
||||||
this.width = Bangle.CLOCK?0:60;
|
this.width = Bangle.CLOCK?0:60;
|
||||||
return setTimeout(Bangle.drawWidgets,1); // widget changed size - redraw
|
return setTimeout(Bangle.drawWidgets,1); // widget changed size - redraw
|
||||||
}
|
}
|
||||||
if (!this.width) return; // if size not right, return
|
if (!this.width) return; // if not visible, return
|
||||||
g.reset().setFont("6x8", 2).setFontAlign(-1, 0);
|
g.reset().setFont("6x8", 2).setFontAlign(-1, 0);
|
||||||
var time = require("locale").time(new Date(),1);
|
var time = require("locale").time(new Date(),1);
|
||||||
g.drawString(time, this.x, this.y+11, true); // 5 * 6*2 = 60
|
g.drawString(time, this.x, this.y+11, true); // 5 * 6*2 = 60
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,3 @@
|
||||||
0.01: 1st ver, inspired in some code from widclkbttm (Digital clock bttom widget)
|
0.01: 1st ver, inspired in some code from widclkbttm (Digital clock bttom widget)
|
||||||
0.02: Correction, intervals, dynamic color and font size depending on device
|
0.02: Correction, intervals, dynamic color and font size depending on device
|
||||||
|
0.03: minor corrections, and color depending on theme
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,9 @@
|
||||||
A basic HW/performance monitor widget that shows on real time some technical info, such as free mem, free storage, trash mem, files, FW version. Also allows to test the unfrequently used widget bottom area.
|
A basic HW/performance monitor widget that shows on real time some technical info, such as free mem, free storage, trash mem, files, FW version. Also allows to test the unfrequently used widget bottom area.
|
||||||
|
|
||||||
Compatible with BangleJS1,BangleJS2,and EMSCRIPTENx emulators
|
Compatible with BangleJS1,BangleJS2,and EMSCRIPTENx emulators
|
||||||
|
Dynamic Color dependant on Theme color bg
|
||||||
|
|
||||||
forked from widclkbttm (Digital clock bttom widget)
|
forked from my widclkbttm (Digital clock bttom widget)
|
||||||
|
|
||||||
|
|
||||||
## Photo
|
## Photo
|
||||||
|
|
@ -13,6 +14,8 @@ Example of usage
|
||||||

|

|
||||||

|

|
||||||
|
|
||||||
|
Screenshot emulator
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,13 @@
|
||||||
"id": "widhwbttm",
|
"id": "widhwbttm",
|
||||||
"name": "HW stats (Bottom) widget",
|
"name": "HW stats (Bottom) widget",
|
||||||
"shortName": "Digital clock Bottom Widget",
|
"shortName": "Digital clock Bottom Widget",
|
||||||
"version": "0.02",
|
"version": "0.03",
|
||||||
"description": "Displays technical info and mem stats in the bottom of the screen (may not be compatible with some apps)",
|
"description": "Displays technical info, such as model, ver, temperatura or mem stats in the bottom of the screen (may not be compatible with some apps)",
|
||||||
"icon": "widhwbttm.png",
|
"icon": "widhwbttm.png",
|
||||||
"type": "widget",
|
"type": "widget",
|
||||||
"tags": "widget",
|
"tags": "widget",
|
||||||
"supports": ["BANGLEJS","BANGLEJS2"],
|
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||||
|
"screenshots": [{"url":"screenshot.png"}],
|
||||||
"readme": "README.md",
|
"readme": "README.md",
|
||||||
"storage": [
|
"storage": [
|
||||||
{"name":"widhwbttm.wid.js","url":"widhwbttm.wid.js"}
|
{"name":"widhwbttm.wid.js","url":"widhwbttm.wid.js"}
|
||||||
|
|
|
||||||
|
After Width: | Height: | Size: 981 B |
|
After Width: | Height: | Size: 787 B |
|
|
@ -1,57 +1,59 @@
|
||||||
(function() {
|
(function() {
|
||||||
let intervalRef = null;
|
let intervalRef = null;
|
||||||
var v_switch; // show stats
|
var v_count; // show stats
|
||||||
var v_str_hw=new String();
|
var v_str_hw=new String();
|
||||||
if (process.env.BOARD=='BANGLEJS'||process.env.BOARD=='EMSCRIPTEN') var v_font_size=16;
|
//if (process.env.BOARD=='BANGLEJS'||process.env.BOARD=='EMSCRIPTEN') var v_bfont_size=2;
|
||||||
else var v_font_size=14;
|
var v_bfont_size=2;
|
||||||
if (v_switch == null || v_switch == '') v_switch=0;
|
if (g.theme.dark==true) var v_color=0xFFFF; //white
|
||||||
function draw(){
|
else var v_color=0x0000; //black
|
||||||
if (Bangle.CLOCK) return;
|
if (v_count == null || v_count == '') v_count=0;
|
||||||
|
|
||||||
if (v_switch==0) {
|
function draw(){
|
||||||
// var v_hw=process.env.VERSION;
|
// if (Bangle.CLOCK) return; //to remove from a clock
|
||||||
v_str_hw="V "+process.env.VERSION.substr(0,6);
|
if (v_count==0) {
|
||||||
v_switch++;
|
v_str_hw=process.env.VERSION.substr(0,6);
|
||||||
} else if (v_switch==1) {
|
v_count++;
|
||||||
|
} else if (v_count==1) {
|
||||||
v_str_hw=process.env.BOARD.substr(0,3)+".."+process.env.BOARD.substr(process.env.BOARD.length-3,3);
|
v_str_hw=process.env.BOARD.substr(0,3)+".."+process.env.BOARD.substr(process.env.BOARD.length-3,3);
|
||||||
v_switch++;
|
v_count++;
|
||||||
}
|
} else if (v_count==2) {
|
||||||
else if (v_switch==2) {
|
|
||||||
v_str_hw="Bat "+E.getBattery()+"%";
|
v_str_hw="Bat "+E.getBattery()+"%";
|
||||||
v_switch++;
|
v_count++;
|
||||||
|
}
|
||||||
|
else if (v_count==3 && process.env.BOARD.substr(0,6)=='BANGLE') {
|
||||||
|
v_str_hw="Tmp "+E.getTemperature();
|
||||||
|
v_count++;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// text prefix has to be 4char
|
// text prefix has to be 4char
|
||||||
stor=require("Storage").getStats();
|
stor=require("Storage").getStats();
|
||||||
if (v_switch==3) {
|
if (v_count==4) {
|
||||||
v_str_hw="Fre "+process.memory().free;
|
v_str_hw="Fre "+process.memory().free;
|
||||||
//+"/"+process.memory().total;
|
//+"/"+process.memory().total;
|
||||||
v_switch++;
|
v_count++;
|
||||||
}
|
}
|
||||||
else if (v_switch==4) {
|
else if (v_count==5) {
|
||||||
v_str_hw="Sto "+stor.freeBytes;
|
v_str_hw="Sto "+stor.freeBytes;
|
||||||
v_switch++;
|
v_count++;
|
||||||
} else if (v_switch==5) {
|
} else if (v_count==6) {
|
||||||
v_str_hw="Tra "+stor.trashBytes;
|
v_str_hw="Tra "+stor.trashBytes;
|
||||||
v_switch++;
|
v_count++;
|
||||||
} else if (v_switch==6) {
|
} else if (v_count==7) {
|
||||||
v_str_hw="Fil "+stor.fileCount;
|
v_str_hw="Fil "+stor.fileCount;
|
||||||
v_switch=0;
|
v_count=0;
|
||||||
}
|
}
|
||||||
// 4 char are prefix
|
// 4 char are prefix
|
||||||
if (v_str_hw.length>7) {
|
if (v_str_hw.length>7) {
|
||||||
//replace 3 digits by k
|
//replace 3 digits by k
|
||||||
//substring betw x and y
|
|
||||||
v_str_hw=v_str_hw.substr(0,v_str_hw.length-3)+"k";
|
v_str_hw=v_str_hw.substr(0,v_str_hw.length-3)+"k";
|
||||||
}
|
}
|
||||||
} //else storage
|
} //end else storage
|
||||||
g.reset().setFontVector(v_font_size).setFontAlign(-1, 0);
|
g.reset().setColor(v_color).setFont("6x8",v_bfont_size).setFontAlign(-1, 0);
|
||||||
//clean a longer previous string, care with br widgets
|
//clean a longer previous string, care with br widgets
|
||||||
g.drawString(" ", this.x, this.y+11, true);
|
g.drawString(" ", this.x, this.y+11, true);
|
||||||
g.drawString(v_str_hw, this.x, this.y+11, true);
|
g.drawString(v_str_hw, this.x, this.y+11, true);
|
||||||
} //end draw
|
} //end draw
|
||||||
|
|
||||||
WIDGETS["wdhwbttm"]={area:"bl",width:60,draw:draw};
|
WIDGETS["wdhwbttm"]={area:"bl",width:100,draw:draw};
|
||||||
//{area:"bl",width:Bangle.CLOCK?0:60,draw:draw};
|
|
||||||
if (Bangle.isLCDOn) intervalRef = setInterval(()=>WIDGETS["wdhwbttm"].draw(), 10*1000);
|
if (Bangle.isLCDOn) intervalRef = setInterval(()=>WIDGETS["wdhwbttm"].draw(), 10*1000);
|
||||||
})()
|
})()
|
||||||
|
|
|
||||||
|
|
@ -41,17 +41,12 @@ function ClockFace(options) {
|
||||||
this[k] = settings[k];
|
this[k] = settings[k];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// these default to true
|
// showDate defaults to true
|
||||||
["showDate", "loadWidgets"].forEach(k => {
|
if (this.showDate===undefined) this.showDate = true;
|
||||||
if (this[k]===undefined) this[k] = true;
|
// if (old) setting was to not load widgets, default to hiding them
|
||||||
});
|
if (this.hideWidgets===undefined && this.loadWidgets===false) this.hideWidgets = 1;
|
||||||
|
|
||||||
let s = require("Storage").readJSON("setting.json",1)||{};
|
let s = require("Storage").readJSON("setting.json",1)||{};
|
||||||
if ((global.__FILE__===undefined || global.__FILE__===s.clock)
|
|
||||||
&& s.clockHasWidgets!==this.loadWidgets) {
|
|
||||||
// save whether we can Fast Load
|
|
||||||
s.clockHasWidgets = this.loadWidgets;
|
|
||||||
require("Storage").writeJSON("setting.json", s);
|
|
||||||
}
|
|
||||||
// use global 24/12-hour setting if not set by clock-settings
|
// use global 24/12-hour setting if not set by clock-settings
|
||||||
if (!('is12Hour' in this)) this.is12Hour = !!(s["12hour"]);
|
if (!('is12Hour' in this)) this.is12Hour = !!(s["12hour"]);
|
||||||
}
|
}
|
||||||
|
|
@ -92,7 +87,9 @@ ClockFace.prototype.start = function() {
|
||||||
.CLOCK is set by Bangle.setUI('clock') but we want to load widgets so we can check appRect and *then*
|
.CLOCK is set by Bangle.setUI('clock') but we want to load widgets so we can check appRect and *then*
|
||||||
call setUI. see #1864 */
|
call setUI. see #1864 */
|
||||||
Bangle.CLOCK = 1;
|
Bangle.CLOCK = 1;
|
||||||
if (this.loadWidgets) Bangle.loadWidgets();
|
Bangle.loadWidgets();
|
||||||
|
const widget_util = ["show", "hide", "swipeOn"][this.hideWidgets|0];
|
||||||
|
require("widget_utils")[widget_util]();
|
||||||
if (this.init) this.init.apply(this);
|
if (this.init) this.init.apply(this);
|
||||||
const uiRemove = this._remove ? () => this.remove() : undefined;
|
const uiRemove = this._remove ? () => this.remove() : undefined;
|
||||||
if (this._upDown) {
|
if (this._upDown) {
|
||||||
|
|
@ -133,6 +130,7 @@ ClockFace.prototype.resume = function() {
|
||||||
};
|
};
|
||||||
ClockFace.prototype.remove = function() {
|
ClockFace.prototype.remove = function() {
|
||||||
this._removed = true;
|
this._removed = true;
|
||||||
|
require("widget_utils").show();
|
||||||
if (this._timeout) clearTimeout(this._timeout);
|
if (this._timeout) clearTimeout(this._timeout);
|
||||||
Bangle.removeListener("lcdPower", this._onLcd);
|
Bangle.removeListener("lcdPower", this._onLcd);
|
||||||
if (this._remove) this._remove.apply(this);
|
if (this._remove) this._remove.apply(this);
|
||||||
|
|
|
||||||
|
|
@ -140,7 +140,7 @@ For example:
|
||||||
// now
|
// now
|
||||||
clock.showDate === false;
|
clock.showDate === false;
|
||||||
clock.foo === 123;
|
clock.foo === 123;
|
||||||
clock.loadWidgets === true; // default when not in settings file
|
clock.hideWidgets === 0; // default when not in settings file
|
||||||
clock.is12Hour === ??; // not in settings file: uses global setting
|
clock.is12Hour === ??; // not in settings file: uses global setting
|
||||||
clock.start();
|
clock.start();
|
||||||
|
|
||||||
|
|
@ -152,13 +152,14 @@ The following properties are automatically set on the clock:
|
||||||
* `is12Hour`: `true` if the "Time Format" setting is set to "12h", `false` for "24h".
|
* `is12Hour`: `true` if the "Time Format" setting is set to "12h", `false` for "24h".
|
||||||
* `paused`: `true` while the clock is paused. (You don't need to check this inside your `draw()` code)
|
* `paused`: `true` while the clock is paused. (You don't need to check this inside your `draw()` code)
|
||||||
* `showDate`: `true` (if not overridden through the settings file.)
|
* `showDate`: `true` (if not overridden through the settings file.)
|
||||||
* `loadWidgets`: `true` (if not overridden through the settings file.)
|
* `hideWidgets`: `0` (if not overridden through the settings file.)
|
||||||
If set to `false` before calling `start()`, the clock won't call `Bangle.loadWidgets();` for you.
|
If set to `1` before calling `start()`, the clock calls `require("widget_utils")hide();` for you.
|
||||||
Best is to add a setting for this, but if you never want to load widgets, you could do this:
|
(Bangle.js 2 only: `2` for swipe-down)
|
||||||
|
Best is to add a setting for this, but if you never want to show widgets, you could do this:
|
||||||
```js
|
```js
|
||||||
var ClockFace = require("ClockFace");
|
var ClockFace = require("ClockFace");
|
||||||
var clock = new ClockFace({draw: function(){/*...*/}});
|
var clock = new ClockFace({draw: function(){/*...*/}});
|
||||||
clock.loadWidgets = false; // prevent loading of widgets
|
clock.hideWidgets = 1; // hide widgets
|
||||||
clock.start();
|
clock.start();
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -200,7 +201,7 @@ let menu = {
|
||||||
};
|
};
|
||||||
require("ClockFace_menu").addItems(menu, save, {
|
require("ClockFace_menu").addItems(menu, save, {
|
||||||
showDate: settings.showDate,
|
showDate: settings.showDate,
|
||||||
loadWidgets: settings.loadWidgets,
|
hideWidgets: settings.hideWidgets,
|
||||||
});
|
});
|
||||||
E.showMenu(menu);
|
E.showMenu(menu);
|
||||||
|
|
||||||
|
|
@ -213,7 +214,7 @@ let menu = {
|
||||||
/*LANG*/"< Back": back,
|
/*LANG*/"< Back": back,
|
||||||
};
|
};
|
||||||
require("ClockFace_menu").addSettingsFile(menu, "<appid>.settings.json", [
|
require("ClockFace_menu").addSettingsFile(menu, "<appid>.settings.json", [
|
||||||
"showDate", "loadWidgets", "powerSave",
|
"showDate", "hideWidgets", "powerSave",
|
||||||
]);
|
]);
|
||||||
E.showMenu(menu);
|
E.showMenu(menu);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,13 +10,12 @@ exports.addItems = function(menu, callback, items) {
|
||||||
let value = items[key];
|
let value = items[key];
|
||||||
const label = {
|
const label = {
|
||||||
showDate:/*LANG*/"Show date",
|
showDate:/*LANG*/"Show date",
|
||||||
loadWidgets:/*LANG*/"Load widgets",
|
hideWidgets:/*LANG*/"Widgets",
|
||||||
powerSave:/*LANG*/"Power saving",
|
powerSave:/*LANG*/"Power saving",
|
||||||
}[key];
|
}[key];
|
||||||
switch(key) {
|
switch(key) {
|
||||||
// boolean options which default to true
|
// boolean options which default to true
|
||||||
case "showDate":
|
case "showDate":
|
||||||
case "loadWidgets":
|
|
||||||
if (value===undefined) value = true;
|
if (value===undefined) value = true;
|
||||||
// fall through
|
// fall through
|
||||||
case "powerSave":
|
case "powerSave":
|
||||||
|
|
@ -25,6 +24,17 @@ exports.addItems = function(menu, callback, items) {
|
||||||
value: !!value,
|
value: !!value,
|
||||||
onchange: v => callback(key, v),
|
onchange: v => callback(key, v),
|
||||||
};
|
};
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "hideWidgets":
|
||||||
|
let options = [/*LANG*/"Show",/*LANG*/"Hide"];
|
||||||
|
if (process.env.HWVERSION===2) options.push(/*LANG*/"Swipe");
|
||||||
|
menu[label] = {
|
||||||
|
value: value|0,
|
||||||
|
min: 0, max: options.length-1,
|
||||||
|
format: v => options[v|0],
|
||||||
|
onchange: v => callback(key, v),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
@ -39,6 +49,12 @@ exports.addItems = function(menu, callback, items) {
|
||||||
exports.addSettingsFile = function(menu, settingsFile, items) {
|
exports.addSettingsFile = function(menu, settingsFile, items) {
|
||||||
let s = require("Storage").readJSON(settingsFile, true) || {};
|
let s = require("Storage").readJSON(settingsFile, true) || {};
|
||||||
|
|
||||||
|
// migrate "don't load widgets" to "hide widgets"
|
||||||
|
if (!("hideWidgets" in s) && ("loadWidgets" in s) && !s.loadWidgets) {
|
||||||
|
s.hideWidgets = 1;
|
||||||
|
}
|
||||||
|
delete s.loadWidgets;
|
||||||
|
|
||||||
function save(key, value) {
|
function save(key, value) {
|
||||||
s[key] = value;
|
s[key] = value;
|
||||||
require("Storage").writeJSON(settingsFile, s);
|
require("Storage").writeJSON(settingsFile, s);
|
||||||
|
|
|
||||||
|
|
@ -267,7 +267,7 @@ Layout.prototype.layout = function (l) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
cb[l.type](l);
|
if (cb[l.type]) cb[l.type](l);
|
||||||
};
|
};
|
||||||
Layout.prototype.debug = function(l,c) {
|
Layout.prototype.debug = function(l,c) {
|
||||||
if (!l) l = this._l;
|
if (!l) l = this._l;
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
function p(d,h){function b(e){"ram";e.id&&(a[e.id]=e);e.type||(e.type="");e.c&&e.c.forEach(b)}this._l=this.l=d;this.options=h||{};this.lazy=this.options.lazy||!1;this.physBtns=1;let f;if(2!=process.env.HWVERSION){this.physBtns=3;f=[];function e(l){"ram";"btn"==l.type&&f.push(l);l.c&&l.c.forEach(e)}e(d);f.length&&(this.physBtns=0,this.buttons=f,this.selectedButton=-1)}if(this.options.btns)if(d=this.options.btns,this.physBtns>=d.length){this.b=d;let e=Math.floor(Bangle.appRect.h/this.physBtns);
|
function p(d,h){function b(e){"ram";e.id&&(a[e.id]=e);e.type||(e.type="");e.c&&e.c.forEach(b)}this._l=this.l=d;this.options=h||{};this.lazy=this.options.lazy||!1;this.physBtns=1;let f;if(2!=process.env.HWVERSION){this.physBtns=3;f=[];function e(l){"ram";"btn"==l.type&&f.push(l);l.c&&l.c.forEach(e)}e(d);f.length&&(this.physBtns=0,this.buttons=f,this.selectedButton=-1)}if(this.options.btns)if(d=this.options.btns,this.physBtns>=d.length){this.b=d;let e=Math.floor(Bangle.appRect.h/
|
||||||
for(2<this.physBtns&&1==d.length&&d.unshift({label:""});this.physBtns>d.length;)d.push({label:""});this._l.width=g.getWidth()-8;this._l={type:"h",filly:1,c:[this._l,{type:"v",pad:1,filly:1,c:d.map(l=>(l.type="txt",l.font="6x8",l.height=e,l.r=1,l))}]}}else this._l.width=g.getWidth()-32,this._l={type:"h",c:[this._l,{type:"v",c:d.map(e=>(e.type="btn",e.filly=1,e.width=32,e.r=1,e))}]},f&&f.push.apply(f,this._l.c[1].c);this.setUI();var a=this;b(this._l);this.updateNeeded=!0}function t(d,h,b,f,a){var e=
|
this.physBtns);for(2<this.physBtns&&1==d.length&&d.unshift({label:""});this.physBtns>d.length;)d.push({label:""});this._l.width=g.getWidth()-8;this._l={type:"h",filly:1,c:[this._l,{type:"v",pad:1,filly:1,c:d.map(l=>(l.type="txt",l.font="6x8",l.height=e,l.r=1,l))}]}}else this._l.width=g.getWidth()-32,this._l={type:"h",c:[this._l,{type:"v",c:d.map(e=>(e.type="btn",e.filly=1,e.width=32,e.r=1,e))}]},f&&f.push.apply(f,this._l.c[1].c);this.setUI();var a=this;b(this._l);this.updateNeeded=!0}function t(d,
|
||||||
null==d.bgCol?a:g.toColor(d.bgCol);if(e!=a||"txt"==d.type||"btn"==d.type||"img"==d.type||"custom"==d.type){var l=d.c;delete d.c;var k="H"+E.CRC32(E.toJS(d));l&&(d.c=l);delete h[k]||((f[k]=[d.x,d.y,d.x+d.w-1,d.y+d.h-1]).bg=null==a?g.theme.bg:a,b&&(b.push(d),b=null))}if(d.c)for(var c of d.c)t(c,h,b,f,e)}p.prototype.setUI=function(){Bangle.setUI();let d;this.buttons&&(Bangle.setUI({mode:"updown",back:this.options.back,remove:this.options.remove},h=>{var b=this.selectedButton,f=this.buttons.length;if(void 0===
|
h,b,f,a){var e=null==d.bgCol?a:g.toColor(d.bgCol);if(e!=a||"txt"==d.type||"btn"==d.type||"img"==d.type||"custom"==d.type){var l=d.c;delete d.c;var k="H"+E.CRC32(E.toJS(d));l&&(d.c=l);delete h[k]||((f[k]=[d.x,d.y,d.x+d.w-1,d.y+d.h-1]).bg=null==a?g.theme.bg:a,b&&(b.push(d),b=null))}if(d.c)for(var c of d.c)t(c,h,b,f,e)}p.prototype.setUI=function(){Bangle.setUI();let d;this.buttons&&(Bangle.setUI({mode:"updown",back:this.options.back,remove:this.options.remove},h=>{var b=this.selectedButton,f=this.buttons.length;
|
||||||
h&&this.buttons[b])return this.buttons[b].cb();this.buttons[b]&&(delete this.buttons[b].selected,this.render(this.buttons[b]));b=(b+f+h)%f;this.buttons[b]&&(this.buttons[b].selected=1,this.render(this.buttons[b]));this.selectedButton=b}),d=!0);!this.options.back&&!this.options.remove||d||Bangle.setUI({mode:"custom",back:this.options.back,remove:this.options.remove});if(this.b){function h(b,f){.75<f.time-f.lastTime&&this.b[b].cbl?this.b[b].cbl(f):this.b[b].cb&&this.b[b].cb(f)}Bangle.btnWatches&&Bangle.btnWatches.forEach(clearWatch);
|
if(void 0===h&&this.buttons[b])return this.buttons[b].cb();this.buttons[b]&&(delete this.buttons[b].selected,this.render(this.buttons[b]));b=(b+f+h)%f;this.buttons[b]&&(this.buttons[b].selected=1,this.render(this.buttons[b]));this.selectedButton=b}),d=!0);!this.options.back&&!this.options.remove||d||Bangle.setUI({mode:"custom",back:this.options.back,remove:this.options.remove});if(this.b){function h(b,f){.75<f.time-f.lastTime&&this.b[b].cbl?this.b[b].cbl(f):this.b[b].cb&&this.b[b].cb(f)}Bangle.btnWatches&&
|
||||||
Bangle.btnWatches=[];this.b[0]&&Bangle.btnWatches.push(setWatch(h.bind(this,0),BTN1,{repeat:!0,edge:-1}));this.b[1]&&Bangle.btnWatches.push(setWatch(h.bind(this,1),BTN2,{repeat:!0,edge:-1}));this.b[2]&&Bangle.btnWatches.push(setWatch(h.bind(this,2),BTN3,{repeat:!0,edge:-1}))}if(2==process.env.HWVERSION){function h(b,f){b.cb&&f.x>=b.x&&f.y>=b.y&&f.x<=b.x+b.w&&f.y<=b.y+b.h&&(2==f.type&&b.cbl?b.cbl(f):b.cb&&b.cb(f));b.c&&b.c.forEach(a=>h(a,f))}Bangle.touchHandler=(b,f)=>h(this._l,f);Bangle.on("touch",
|
Bangle.btnWatches.forEach(clearWatch);Bangle.btnWatches=[];this.b[0]&&Bangle.btnWatches.push(setWatch(h.bind(this,0),BTN1,{repeat:!0,edge:-1}));this.b[1]&&Bangle.btnWatches.push(setWatch(h.bind(this,1),BTN2,{repeat:!0,edge:-1}));this.b[2]&&Bangle.btnWatches.push(setWatch(h.bind(this,2),BTN3,{repeat:!0,edge:-1}))}if(2==process.env.HWVERSION){function h(b,f){b.cb&&f.x>=b.x&&f.y>=b.y&&f.x<=b.x+b.w&&f.y<=b.y+b.h&&(2==f.type&&b.cbl?b.cbl(f):b.cb&&b.cb(f));b.c&&b.c.forEach(a=>h(a,f))}Bangle.touchHandler=
|
||||||
Bangle.touchHandler)}};p.prototype.render=function(d){function h(c){"ram";b.reset();void 0!==c.col&&b.setColor(c.col);void 0!==c.bgCol&&b.setBgColor(c.bgCol).clearRect(c.x,c.y,c.x+c.w-1,c.y+c.h-1);f[c.type](c)}d||(d=this._l);this.updateNeeded&&this.update();var b=g,f={"":function(){},txt:function(c){"ram";if(c.wrap){var m=b.setFont(c.font).setFontAlign(0,-1).wrapString(c.label,c.w),n=c.y+(c.h-b.getFontHeight()*m.length>>1);b.drawString(m.join("\n"),c.x+(c.w>>1),n)}else b.setFont(c.font).setFontAlign(0,
|
(b,f)=>h(this._l,f);Bangle.on("touch",Bangle.touchHandler)}};p.prototype.render=function(d){function h(c){"ram";b.reset();void 0!==c.col&&b.setColor(c.col);void 0!==c.bgCol&&b.setBgColor(c.bgCol).clearRect(c.x,c.y,c.x+c.w-1,c.y+c.h-1);f[c.type](c)}d||(d=this._l);this.updateNeeded&&this.update();var b=g,f={"":function(){},txt:function(c){"ram";if(c.wrap){var m=b.setFont(c.font).setFontAlign(0,-1).wrapString(c.label,c.w),n=c.y+(c.h-b.getFontHeight()*m.length>>1);b.drawString(m.join("\n"),c.x+(c.w>>
|
||||||
0,c.r).drawString(c.label,c.x+(c.w>>1),c.y+(c.h>>1))},btn:function(c){"ram";var m=c.x+(0|c.pad),n=c.y+(0|c.pad),q=c.w-(c.pad<<1),r=c.h-(c.pad<<1);m=[m,n+4,m+4,n,m+q-5,n,m+q-1,n+4,m+q-1,n+r-5,m+q-5,n+r-1,m+4,n+r-1,m,n+r-5,m,n+4];n=c.selected?b.theme.bgH:b.theme.bg2;b.setColor(n).fillPoly(m).setColor(c.selected?b.theme.fgH:b.theme.fg2).drawPoly(m);void 0!==c.col&&b.setColor(c.col);c.src?b.setBgColor(n).drawImage("function"==typeof c.src?c.src():c.src,c.x+c.w/2,c.y+c.h/2,{scale:c.scale||void 0,rotate:.5*
|
1),n)}else b.setFont(c.font).setFontAlign(0,0,c.r).drawString(c.label,c.x+(c.w>>1),c.y+(c.h>>1))},btn:function(c){"ram";var m=c.x+(0|c.pad),n=c.y+(0|c.pad),q=c.w-(c.pad<<1),r=c.h-(c.pad<<1);m=[m,n+4,m+4,n,m+q-5,n,m+q-1,n+4,m+q-1,n+r-5,m+q-5,n+r-1,m+4,n+r-1,m,n+r-5,m,n+4];n=c.selected?b.theme.bgH:b.theme.bg2;b.setColor(n).fillPoly(m).setColor(c.selected?b.theme.fgH:b.theme.fg2).drawPoly(m);void 0!==c.col&&b.setColor(c.col);c.src?b.setBgColor(n).drawImage("function"==typeof c.src?c.src():c.src,c.x+
|
||||||
Math.PI*(c.r||0)}):b.setFont(c.font||"6x8:2").setFontAlign(0,0,c.r).drawString(c.label,c.x+c.w/2,c.y+c.h/2)},img:function(c){"ram";b.drawImage("function"==typeof c.src?c.src():c.src,c.x+c.w/2,c.y+c.h/2,{scale:c.scale||void 0,rotate:.5*Math.PI*(c.r||0)})},custom:function(c){"ram";c.render(c)},h:function(c){"ram";c.c.forEach(h)},v:function(c){"ram";c.c.forEach(h)}};if(this.lazy){this.rects||(this.rects={});var a=this.rects.clone(),e=[];t(d,a,e,this.rects,null);for(var l in a)delete this.rects[l];d=
|
c.w/2,c.y+c.h/2,{scale:c.scale||void 0,rotate:.5*Math.PI*(c.r||0)}):b.setFont(c.font||"6x8:2").setFontAlign(0,0,c.r).drawString(c.label,c.x+c.w/2,c.y+c.h/2)},img:function(c){"ram";b.drawImage("function"==typeof c.src?c.src():c.src,c.x+c.w/2,c.y+c.h/2,{scale:c.scale||void 0,rotate:.5*Math.PI*(c.r||0)})},custom:function(c){"ram";c.render(c)},h:function(c){"ram";c.c.forEach(h)},v:function(c){"ram";c.c.forEach(h)}};if(this.lazy){this.rects||(this.rects={});var a=this.rects.clone(),e=[];t(d,a,e,this.rects,
|
||||||
Object.keys(a).map(c=>a[c]).reverse();for(var k of d)b.setBgColor(k.bg).clearRect.apply(g,k);e.forEach(h)}else h(d)};p.prototype.forgetLazyState=function(){this.rects={}};p.prototype.layout=function(d){var h={h:function(b){"ram";var f=b.x+(0|b.pad),a=0,e=b.c&&b.c.reduce((k,c)=>k+(0|c.fillx),0);e||(f+=b.w-b._w>>1,e=1);var l=f;b.c.forEach(k=>{k.x=0|l;f+=k._w;a+=0|k.fillx;l=f+Math.floor(a*(b.w-b._w)/e);k.w=0|l-k.x;k.h=0|(k.filly?b.h-(b.pad<<1):k._h);k.y=0|b.y+(0|b.pad)+((1+(0|k.valign))*(b.h-(b.pad<<
|
null);for(var l in a)delete this.rects[l];d=Object.keys(a).map(c=>a[c]).reverse();for(var k of d)b.setBgColor(k.bg).clearRect.apply(g,k);e.forEach(h)}else h(d)};p.prototype.forgetLazyState=function(){this.rects={}};p.prototype.layout=function(d){var h={h:function(b){"ram";var f=b.x+(0|b.pad),a=0,e=b.c&&b.c.reduce((k,c)=>k+(0|c.fillx),0);e||(f+=b.w-b._w>>1,e=1);var l=f;b.c.forEach(k=>{k.x=0|l;f+=k._w;a+=0|k.fillx;l=f+Math.floor(a*(b.w-b._w)/e);k.w=0|l-k.x;k.h=0|(k.filly?b.h-(b.pad<<1):k._h);k.y=0|
|
||||||
1)-k.h)>>1);if(k.c)h[k.type](k)})},v:function(b){"ram";var f=b.y+(0|b.pad),a=0,e=b.c&&b.c.reduce((k,c)=>k+(0|c.filly),0);e||(f+=b.h-b._h>>1,e=1);var l=f;b.c.forEach(k=>{k.y=0|l;f+=k._h;a+=0|k.filly;l=f+Math.floor(a*(b.h-b._h)/e);k.h=0|l-k.y;k.w=0|(k.fillx?b.w-(b.pad<<1):k._w);k.x=0|b.x+(0|b.pad)+((1+(0|k.halign))*(b.w-(b.pad<<1)-k.w)>>1);if(k.c)h[k.type](k)})}};h[d.type](d)};p.prototype.debug=function(d,h){d||(d=this._l);h=h||1;g.setColor(h&1,h&2,h&4).drawRect(d.x+h-1,d.y+h-1,d.x+d.w-h,d.y+d.h-h);
|
b.y+(0|b.pad)+((1+(0|k.valign))*(b.h-(b.pad<<1)-k.h)>>1);if(k.c)h[k.type](k)})},v:function(b){"ram";var f=b.y+(0|b.pad),a=0,e=b.c&&b.c.reduce((k,c)=>k+(0|c.filly),0);e||(f+=b.h-b._h>>1,e=1);var l=f;b.c.forEach(k=>{k.y=0|l;f+=k._h;a+=0|k.filly;l=f+Math.floor(a*(b.h-b._h)/e);k.h=0|l-k.y;k.w=0|(k.fillx?b.w-(b.pad<<1):k._w);k.x=0|b.x+(0|b.pad)+((1+(0|k.halign))*(b.w-(b.pad<<1)-k.w)>>1);if(k.c)h[k.type](k)})}};if(h[d.type])h[d.type](d)};p.prototype.debug=function(d,h){d||(d=this._l);h=h||1;g.setColor(h&
|
||||||
d.pad&&g.drawRect(d.x+d.pad-1,d.y+d.pad-1,d.x+d.w-d.pad,d.y+d.h-d.pad);h++;d.c&&d.c.forEach(b=>this.debug(b,h))};p.prototype.update=function(){function d(a){"ram";b[a.type](a);if(a.r&1){var e=a._w;a._w=a._h;a._h=e}a._w=Math.max(a._w+(a.pad<<1),0|a.width);a._h=Math.max(a._h+(a.pad<<1),0|a.height)}delete this.updateNeeded;var h=g,b={txt:function(a){"ram";a.font.endsWith("%")&&(a.font="Vector"+Math.round(h.getHeight()*a.font.slice(0,-1)/100));if(a.wrap)a._h=a._w=0;else{var e=g.setFont(a.font).stringMetrics(a.label);
|
1,h&2,h&4).drawRect(d.x+h-1,d.y+h-1,d.x+d.w-h,d.y+d.h-h);d.pad&&g.drawRect(d.x+d.pad-1,d.y+d.pad-1,d.x+d.w-d.pad,d.y+d.h-d.pad);h++;d.c&&d.c.forEach(b=>this.debug(b,h))};p.prototype.update=function(){function d(a){"ram";b[a.type](a);if(a.r&1){var e=a._w;a._w=a._h;a._h=e}a._w=Math.max(a._w+(a.pad<<1),0|a.width);a._h=Math.max(a._h+(a.pad<<1),0|a.height)}delete this.updateNeeded;var h=g,b={txt:function(a){"ram";a.font.endsWith("%")&&(a.font="Vector"+Math.round(h.getHeight()*a.font.slice(0,-1)/100));
|
||||||
a._w=e.width;a._h=e.height}},btn:function(a){"ram";a.font&&a.font.endsWith("%")&&(a.font="Vector"+Math.round(h.getHeight()*a.font.slice(0,-1)/100));var e=a.src?h.imageMetrics("function"==typeof a.src?a.src():a.src):h.setFont(a.font||"6x8:2").stringMetrics(a.label);a._h=16+e.height;a._w=20+e.width},img:function(a){"ram";var e=h.imageMetrics("function"==typeof a.src?a.src():a.src),l=a.scale||1;a._w=e.width*l;a._h=e.height*l},"":function(a){"ram";a._w=0;a._h=0},custom:function(a){"ram";a._w=0;a._h=0},
|
if(a.wrap)a._h=a._w=0;else{var e=g.setFont(a.font).stringMetrics(a.label);a._w=e.width;a._h=e.height}},btn:function(a){"ram";a.font&&a.font.endsWith("%")&&(a.font="Vector"+Math.round(h.getHeight()*a.font.slice(0,-1)/100));var e=a.src?h.imageMetrics("function"==typeof a.src?a.src():a.src):h.setFont(a.font||"6x8:2").stringMetrics(a.label);a._h=16+e.height;a._w=20+e.width},img:function(a){"ram";var e=h.imageMetrics("function"==typeof a.src?a.src():a.src),l=a.scale||1;a._w=e.width*l;a._h=e.height*l},
|
||||||
h:function(a){"ram";a.c.forEach(d);a._h=a.c.reduce((e,l)=>Math.max(e,l._h),0);a._w=a.c.reduce((e,l)=>e+l._w,0);null==a.fillx&&a.c.some(e=>e.fillx)&&(a.fillx=1);null==a.filly&&a.c.some(e=>e.filly)&&(a.filly=1)},v:function(a){"ram";a.c.forEach(d);a._h=a.c.reduce((e,l)=>e+l._h,0);a._w=a.c.reduce((e,l)=>Math.max(e,l._w),0);null==a.fillx&&a.c.some(e=>e.fillx)&&(a.fillx=1);null==a.filly&&a.c.some(e=>e.filly)&&(a.filly=1)}},f=this._l;d(f);delete b;f.fillx||f.filly?(f.w=Bangle.appRect.w,f.h=Bangle.appRect.h,
|
"":function(a){"ram";a._w=0;a._h=0},custom:function(a){"ram";a._w=0;a._h=0},h:function(a){"ram";a.c.forEach(d);a._h=a.c.reduce((e,l)=>Math.max(e,l._h),0);a._w=a.c.reduce((e,l)=>e+l._w,0);null==a.fillx&&a.c.some(e=>e.fillx)&&(a.fillx=1);null==a.filly&&a.c.some(e=>e.filly)&&(a.filly=1)},v:function(a){"ram";a.c.forEach(d);a._h=a.c.reduce((e,l)=>e+l._h,0);a._w=a.c.reduce((e,l)=>Math.max(e,l._w),0);null==a.fillx&&a.c.some(e=>e.fillx)&&(a.fillx=1);null==a.filly&&a.c.some(e=>e.filly)&&(a.filly=1)}},f=this._l;
|
||||||
f.x=Bangle.appRect.x,f.y=Bangle.appRect.y):(f.w=f._w,f.h=f._h,f.x=Bangle.appRect.w-f.w>>1,f.y=Bangle.appRect.y+(Bangle.appRect.h-f.h>>1));this.layout(f)};p.prototype.clear=function(d){d||(d=this._l);g.reset();void 0!==d.bgCol&&g.setBgColor(d.bgCol);g.clearRect(d.x,d.y,d.x+d.w-1,d.y+d.h-1)};exports=p
|
d(f);delete b;f.fillx||f.filly?(f.w=Bangle.appRect.w,f.h=Bangle.appRect.h,f.x=Bangle.appRect.x,f.y=Bangle.appRect.y):(f.w=f._w,f.h=f._h,f.x=Bangle.appRect.w-f.w>>1,f.y=Bangle.appRect.y+(Bangle.appRect.h-f.h>>1));this.layout(f)};p.prototype.clear=function(d){d||(d=this._l);g.reset();void 0!==d.bgCol&&g.setBgColor(d.bgCol);g.clearRect(d.x,d.y,d.x+d.w-1,d.y+d.h-1)};exports=p
|
||||||
|
|
@ -299,6 +299,23 @@ exports.addInteractive = function(menu, options) {
|
||||||
options.redraw = function() {
|
options.redraw = function() {
|
||||||
drawItem(menu[options.menuA].items[options.menuB]);
|
drawItem(menu[options.menuA].items[options.menuB]);
|
||||||
};
|
};
|
||||||
|
options.setItem = function (menuA, menuB) {
|
||||||
|
if (!menu[menuA] || !menu[menuA].items[menuB] || (options.menuA == menuA && options.menuB == menuB)) {
|
||||||
|
// menuA or menuB did not exist or did not change
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const oldMenuItem = menu[options.menuA].items[options.menuB];
|
||||||
|
if (oldMenuItem) {
|
||||||
|
menuHideItem(oldMenuItem);
|
||||||
|
oldMenuItem.removeAllListeners("draw");
|
||||||
|
}
|
||||||
|
options.menuA = menuA;
|
||||||
|
options.menuB = menuB;
|
||||||
|
menuShowItem(menu[options.menuA].items[options.menuB]);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return options;
|
return options;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -987,9 +987,9 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"json5": {
|
"json5": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
|
||||||
"integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
|
"integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"minimist": "^1.2.0"
|
"minimist": "^1.2.0"
|
||||||
|
|
|
||||||