mirror of https://github.com/espruino/BangleApps
Remove settings for what is displayed and instead allow circles to be changed by swiping
parent
7cc1627653
commit
416d5d0fff
|
@ -33,3 +33,4 @@
|
|||
0.17: Load circles from clkinfo
|
||||
0.18: Improved clkinfo handling and using it for the weather circle
|
||||
0.19: Remove old code and fixing clkinfo handling (fix HRM and other items that change)
|
||||
Remove settings for what is displayed and instead allow circles to be changed by swiping
|
||||
|
|
|
@ -5,6 +5,7 @@ A clock with three or four circles for different data at the bottom in a probabl
|
|||
By default the time, date and day of week is shown.
|
||||
|
||||
It can show the following information (this can be configured):
|
||||
|
||||
* Steps
|
||||
* Steps distance
|
||||
* Heart rate (automatically updates when screen is on and unlocked)
|
||||
|
@ -14,15 +15,24 @@ It can show the following information (this can be configured):
|
|||
* Temperature inside circle
|
||||
* Condition as icon below circle
|
||||
* Big weather icon next to clock
|
||||
* Time and progress until next sunrise or sunset (requires [my location app](https://banglejs.com/apps/#mylocation))
|
||||
* Temperature, air pressure or altitude from internal pressure sensor
|
||||
* Altitude from internal pressure sensor
|
||||
* Active alarms (if `Alarm` app installed)
|
||||
* Sunrise or sunset (if `Sunrise Clockinfo` app installed)
|
||||
|
||||
To change what is shown:
|
||||
|
||||
The color of each circle can be configured. The following colors are available:
|
||||
* Unlock the watch
|
||||
* Tap on the circle to change (a border is drawn around it)
|
||||
* Swipe up/down to change the guage within the given group
|
||||
* Swipe left/right to change the group (eg. between standard Bangle.js and Alarms/etc)
|
||||
|
||||
Data is provided by ['Clock Info'](http://www.espruino.com/Bangle.js+Clock+Info)
|
||||
so any apps that implement this feature can add extra information to be displayed.
|
||||
|
||||
The color of each circle can be configured from `Settings -> Apps -> Circles Clock`. The following colors are available:
|
||||
* Basic colors (red, green, blue, yellow, magenta, cyan, black, white)
|
||||
* Color depending on value (green -> red, red -> green)
|
||||
|
||||
|
||||
## Screenshots
|
||||

|
||||

|
||||
|
@ -38,5 +48,5 @@ The color of each circle can be configured. The following colors are available:
|
|||
Marco ([myxor](https://github.com/myxor))
|
||||
|
||||
## Icons
|
||||
Most of the icons are taken from [materialdesignicons](https://materialdesignicons.com) under Apache License 2.0 except the big weather icons which are from
|
||||
Most of the icons are taken from [materialdesignicons](https://materialdesignicons.com) under Apache License 2.0 except the big weather icons which are from
|
||||
[icons8](https://icons8.com/icon/set/weather/small--static--black)
|
||||
|
|
|
@ -41,11 +41,6 @@ let now = Math.round(new Date().getTime() / 1000);
|
|||
// layout values:
|
||||
let colorFg = g.theme.dark ? '#fff' : '#000';
|
||||
let colorBg = g.theme.dark ? '#000' : '#fff';
|
||||
let colorGrey = '#808080';
|
||||
let colorRed = '#ff0000';
|
||||
let colorGreen = '#008000';
|
||||
let colorBlue = '#0000ff';
|
||||
let colorYellow = '#ffff00';
|
||||
let widgetOffset = showWidgets ? 24 : 0;
|
||||
let dowOffset = circleCount == 3 ? 20 : 22; // dow offset relative to date
|
||||
let h = g.getHeight() - widgetOffset;
|
||||
|
@ -53,7 +48,7 @@ let w = g.getWidth();
|
|||
let hOffset = (circleCount == 3 ? 34 : 30) - widgetOffset;
|
||||
let h1 = Math.round(1 * h / 5 - hOffset);
|
||||
let h2 = Math.round(3 * h / 5 - hOffset);
|
||||
let h3 = Math.round(8 * h / 8 - hOffset - 3); // circle y position
|
||||
let h3 = Math.round(8 * h / 8 - hOffset - 3); // circle middle y position
|
||||
|
||||
/*
|
||||
* circle x positions
|
||||
|
@ -76,28 +71,17 @@ let circlePosX = [
|
|||
];
|
||||
|
||||
let radiusOuter = circleCount == 3 ? 25 : 20;
|
||||
let radiusBorder = radiusOuter+3; // absolute border of circles
|
||||
let radiusInner = circleCount == 3 ? 20 : 15;
|
||||
let circleFontSmall = circleCount == 3 ? "Vector:14" : "Vector:10";
|
||||
let circleFont = circleCount == 3 ? "Vector:15" : "Vector:11";
|
||||
let circleFontBig = circleCount == 3 ? "Vector:16" : "Vector:12";
|
||||
let iconOffset = circleCount == 3 ? 6 : 8;
|
||||
let defaultCircleTypes = ["Bangle/Steps", "Bangle/HRM", "Bangle/Battery", "weather"];
|
||||
|
||||
let circleInfoNum = [
|
||||
0, // circle1
|
||||
0, // circle2
|
||||
0, // circle3
|
||||
0, // circle4
|
||||
];
|
||||
let circleItemNum = [
|
||||
0, // circle1
|
||||
1, // circle2
|
||||
2, // circle3
|
||||
3, // circle4
|
||||
];
|
||||
|
||||
function draw() {
|
||||
g.reset().clearRect(Bangle.appRect);
|
||||
let R = Bangle.appRect;
|
||||
g.reset().clearRect(R.x,R.y, R.x2, h3-(radiusBorder+1));
|
||||
|
||||
g.setColor(colorBg);
|
||||
g.fillRect(0, widgetOffset, w, h2 + 22);
|
||||
|
@ -139,16 +123,13 @@ function draw() {
|
|||
if (icon) g.drawImage(icon, w - 48, h1, {scale:0.75});
|
||||
}
|
||||
|
||||
// FIXME do we really need to redraw circles every time?
|
||||
for (var i=1;i<=circleCount;i++)
|
||||
drawCircle(i);
|
||||
|
||||
queueDraw();
|
||||
}
|
||||
|
||||
function getCircleColor(index) {
|
||||
let color = settings["circle" + index + "color"];
|
||||
if (color && color != "") return color;
|
||||
return g.theme.fg;
|
||||
}
|
||||
|
||||
function getGradientColor(color, percent) {
|
||||
|
@ -176,7 +157,7 @@ function getCircleIconColor(index, color, percent) {
|
|||
if (colorizeIcon) {
|
||||
return getGradientColor(color, percent);
|
||||
} else {
|
||||
return "";
|
||||
return g.theme.fg;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -189,23 +170,15 @@ function drawEmpty(img, w, color) {
|
|||
.drawImage(img, w - iconOffset, h3 + radiusOuter - iconOffset, {scale: 16/24});
|
||||
}
|
||||
|
||||
function drawCircle(index) {
|
||||
var info = menu[circleInfoNum[index-1]];
|
||||
var type = settings['circle'+index];
|
||||
function drawCircle(index, item, data) {
|
||||
var w = circlePosX[index-1];
|
||||
drawCircleBackground(w);
|
||||
const color = getCircleColor(index);
|
||||
var item = info && info.items[circleItemNum[index-1]];
|
||||
if(!info || !item) {
|
||||
drawEmpty(info? info.img : null, w, color);
|
||||
return;
|
||||
}
|
||||
var data=item.get();
|
||||
//drawEmpty(info? info.img : null, w, color);
|
||||
var img = data.img;
|
||||
var percent = 1; //fill up if no range
|
||||
var txt = ""+data.text;
|
||||
if (txt.endsWith(" bpm")) txt=txt.slice(0,-4); // hack for heart rate - remove the 'bpm' text
|
||||
if(!img) img = info.img;
|
||||
if(item.hasRange) percent = (data.v-data.min) / (data.max-data.min);
|
||||
if(data.short) txt = data.short;
|
||||
drawGauge(w, h3, percent, color);
|
||||
|
@ -293,12 +266,11 @@ function formatSeconds(s) {
|
|||
* Draws the background and the grey circle
|
||||
*/
|
||||
function drawCircleBackground(w) {
|
||||
g.clearRect(w - radiusOuter - 3, h3 - radiusOuter - 3, w + radiusOuter + 3, h3 + radiusOuter + 3);
|
||||
// Draw rectangle background:
|
||||
g.setColor(colorBg);
|
||||
g.fillRect(w - radiusOuter - 3, h3 - radiusOuter - 3, w + radiusOuter + 3, h3 + radiusOuter + 3);
|
||||
g.fillRect(w - radiusBorder, h3 - radiusBorder, w + radiusBorder, g.getHeight()-1);
|
||||
// Draw grey background circle:
|
||||
g.setColor(colorGrey);
|
||||
g.setColor('#808080'); // grey
|
||||
g.fillCircle(w, h3, radiusOuter);
|
||||
}
|
||||
|
||||
|
@ -310,10 +282,6 @@ function drawInnerCircleAndTriangle(w) {
|
|||
g.fillPoly([w, h3, w - 15, h3 + radiusOuter + 5, w + 15, h3 + radiusOuter + 5]);
|
||||
}
|
||||
|
||||
function radians(a) {
|
||||
return a * Math.PI / 180;
|
||||
}
|
||||
|
||||
/*
|
||||
* This draws the actual gauge consisting out of lots of little filled circles
|
||||
*/
|
||||
|
@ -332,10 +300,12 @@ function drawGauge(cx, cy, percent, color) {
|
|||
color = getGradientColor(color, percent);
|
||||
g.setColor(color);
|
||||
|
||||
// FIXME: this one loop takes 0.25 sec EACH TIME the function is called
|
||||
for (let i = startRotation; i > endRotation - size; i -= size) {
|
||||
x = cx + radius * Math.sin(radians(i));
|
||||
y = cy + radius * Math.cos(radians(i));
|
||||
g.fillCircle(x, y, size);
|
||||
let r = i * Math.PI / 180; // radians
|
||||
g.fillCircle(
|
||||
cx + radius * Math.sin(r),
|
||||
cy + radius * Math.cos(r), size);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -354,35 +324,7 @@ function getWeather() {
|
|||
return jsonWeather && jsonWeather.weather ? jsonWeather.weather : undefined;
|
||||
}
|
||||
|
||||
|
||||
var menu = clock_info.load();
|
||||
for(var i=1; i<5; i++) {
|
||||
var circleType = settings['circle'+i];
|
||||
if(circleType.includes("/")) {
|
||||
let parts = circleType.split("/");
|
||||
let infoName = parts[0], itemName = parts[1];
|
||||
let infoNum = menu.findIndex(e=>e.name==infoName);
|
||||
if (infoNum<0) infoNum=0; // not found!
|
||||
let itemNum = 0; //get first if dynamic
|
||||
if(!menu[infoNum].dynamic)
|
||||
itemNum = menu[infoNum].items.findIndex(it=>it.name==itemName);
|
||||
if (itemNum<0) itemNum=0;
|
||||
circleInfoNum[i-1] = infoNum;
|
||||
circleItemNum[i-1] = itemNum;
|
||||
let menuItem = menu[infoNum].items[itemNum];
|
||||
if (menuItem) {
|
||||
(function(i){
|
||||
menuItem.on('redraw', function() {
|
||||
drawCircle(i);
|
||||
});
|
||||
})(i);
|
||||
menuItem.show();
|
||||
}
|
||||
} else { // empty?
|
||||
circleInfoNum[i-1] = -1;
|
||||
circleItemNum[i-1] = -1;
|
||||
}
|
||||
}
|
||||
g.clear(1); // clear the whole screen
|
||||
|
||||
Bangle.setUI({
|
||||
mode : "clock",
|
||||
|
@ -393,12 +335,29 @@ Bangle.setUI({
|
|||
// Called to unload all of the clock app
|
||||
if (drawTimeout) clearTimeout(drawTimeout);
|
||||
drawTimeout = undefined;
|
||||
// must call clkinfo.hide here for any showing clkinfo
|
||||
for(var i=1;i<=circleCount; i++)
|
||||
clockInfoMenu[i].remove();
|
||||
delete Graphics.prototype.setFontRobotoRegular50NumericOnly;
|
||||
delete Graphics.prototype.setFontRobotoRegular21;
|
||||
}*/
|
||||
});
|
||||
|
||||
let clockInfoDraw = (itm, info, options) => {
|
||||
//print("Draw",itm.name,options);
|
||||
drawCircle(options.circlePosition, itm, info);
|
||||
if (options.focus) g.reset().drawRect(options.x, options.y, options.x+options.w-2, options.y+options.h-1)
|
||||
};
|
||||
let clockInfoItems = require("clock_info").load();
|
||||
let clockInfoMenu = [];
|
||||
for(var i=0;i<circleCount; i++) {
|
||||
let w = circlePosX[i];
|
||||
let y = h3-radiusBorder;
|
||||
clockInfoMenu[i] = require("clock_info").addInteractive(clockInfoItems, {
|
||||
x:w-radiusBorder, y:y, w:radiusBorder*2, h:g.getHeight()-(y+1),
|
||||
draw : clockInfoDraw, circlePosition : i+1
|
||||
});
|
||||
}
|
||||
|
||||
Bangle.loadWidgets();
|
||||
if (!showWidgets) require("widget_utils").hide();
|
||||
else Bangle.drawWidgets();
|
||||
|
|
|
@ -3,10 +3,6 @@
|
|||
"showWidgets": false,
|
||||
"weatherCircleData": "humidity",
|
||||
"circleCount": 3,
|
||||
"circle1": "Bangle/HRM",
|
||||
"circle2": "Bangle/Steps",
|
||||
"circle3": "Bangle/Battery",
|
||||
"circle4": "weather",
|
||||
"circle1color": "green-red",
|
||||
"circle2color": "#0000ff",
|
||||
"circle3color": "red-green",
|
||||
|
|
|
@ -12,21 +12,6 @@
|
|||
storage.write(SETTINGS_FILE, settings);
|
||||
}
|
||||
|
||||
var valuesCircleTypes = ["empty"];
|
||||
var namesCircleTypes = ["empty"];
|
||||
clock_info.load().forEach(e=>{
|
||||
if(e.dynamic) {
|
||||
valuesCircleTypes = valuesCircleTypes.concat([e.name+"/"]);
|
||||
namesCircleTypes = namesCircleTypes.concat([e.name]);
|
||||
} else {
|
||||
let values = e.items.map(i=>e.name+"/"+i.name);
|
||||
let names = e.name=="Bangle" ? e.items.map(i=>i.name) : values;
|
||||
valuesCircleTypes = valuesCircleTypes.concat(values);
|
||||
namesCircleTypes = namesCircleTypes.concat(names);
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
const valuesColors = ["", "#ff0000", "#00ff00", "#0000ff", "#ffff00", "#ff00ff",
|
||||
"#00ffff", "#fff", "#000", "green-red", "red-green", "fg"];
|
||||
const namesColors = ["default", "red", "green", "blue", "yellow", "magenta",
|
||||
|
@ -103,12 +88,6 @@
|
|||
const menu = {
|
||||
'': { 'title': /*LANG*/'Circle ' + circleId },
|
||||
/*LANG*/'< Back': ()=>showMainMenu(),
|
||||
/*LANG*/'data': {
|
||||
value: valuesCircleTypes.indexOf(settings[circleName]),
|
||||
min: 0, max: valuesCircleTypes.length - 1,
|
||||
format: v => namesCircleTypes[v],
|
||||
onchange: x => save(circleName, valuesCircleTypes[x]),
|
||||
},
|
||||
/*LANG*/'color': {
|
||||
value: valuesColors.indexOf(settings[colorKey]) || 0,
|
||||
min: 0, max: valuesColors.length - 1,
|
||||
|
|
Loading…
Reference in New Issue