diff --git a/apps.json b/apps.json index fad1e9c6e..f6175e160 100644 --- a/apps.json +++ b/apps.json @@ -57,7 +57,7 @@ { "id": "messages", "name": "Messages", - "version": "0.09", + "version": "0.10", "description": "App to display notifications from iOS and Gadgetbridge", "icon": "app.png", "type": "app", @@ -146,7 +146,7 @@ { "id": "setting", "name": "Settings", - "version": "0.34", + "version": "0.35", "description": "A menu for setting up Bangle.js", "icon": "settings.png", "tags": "tool,system", @@ -263,16 +263,17 @@ "id": "mywelcome", "name": "Customised Welcome", "shortName": "My Welcome", - "version": "0.12", + "version": "0.13", "description": "Appears at first boot and explains how to use Bangle.js. Like 'Welcome', but can be customised with a greeting", "icon": "app.png", "tags": "start,welcome", - "supports": ["BANGLEJS"], + "supports": ["BANGLEJS","BANGLEJS2"], "custom": "custom.html", "screenshots": [{"url":"bangle1-customized-welcome-screenshot.png"}], "storage": [ {"name":"mywelcome.boot.js","url":"boot.js"}, - {"name":"mywelcome.app.js","url":"app.js"}, + {"name":"mywelcome.app.js","url":"app-bangle1.js","supports": ["BANGLEJS"]}, + {"name":"mywelcome.app.js","url":"app-bangle2.js","supports": ["BANGLEJS2"]}, {"name":"mywelcome.settings.js","url":"settings.js"}, {"name":"mywelcome.img","url":"app-icon.js","evaluate":true} ], @@ -1955,11 +1956,12 @@ "id": "openstmap", "name": "OpenStreetMap", "shortName": "OpenStMap", - "version": "0.10", - "description": "[BETA] Loads map tiles from OpenStreetMap onto your Bangle.js and displays a map of where you are", + "version": "0.11", + "description": "Loads map tiles from OpenStreetMap onto your Bangle.js and displays a map of where you are. Once installed this also adds map functionality to `GPS Recorder` and `Recorder` apps", "icon": "app.png", - "tags": "outdoors,gps", + "tags": "outdoors,gps,osm", "supports": ["BANGLEJS","BANGLEJS2"], + "screenshots": [{"url":"screenshot.png"}], "custom": "custom.html", "customConnect": true, "storage": [ @@ -1989,11 +1991,12 @@ "id": "chronowid", "name": "Chrono Widget", "shortName": "Chrono Widget", - "version": "0.03", + "version": "0.04", "description": "Chronometer (timer) which runs as widget.", "icon": "app.png", "tags": "tool,widget", "supports": ["BANGLEJS","BANGLEJS2"], + "screenshots": [{"url":"screenshot.png"}], "readme": "README.md", "storage": [ {"name":"chronowid.wid.js","url":"widget.js"}, @@ -4643,23 +4646,6 @@ {"name":"a_speech_timer.img","url":"app-icon.js","evaluate":true} ] }, - { - "id": "sensible", - "name": "SensiBLE", - "shortName": "SensiBLE", - "version": "0.02", - "description": "Collect, display and advertise real-time sensor data.", - "icon": "sensible.png", - "type": "app", - "tags": "tool,sensors", - "supports" : [ "BANGLEJS2" ], - "allow_emulator": true, - "readme": "README.md", - "storage": [ - { "name": "sensible.app.js", "url": "sensible.js" }, - { "name": "sensible.img", "url": "sensible-icon.js", "evaluate": true } - ] - }, { "id": "mylocation", "name": "My Location", "shortName":"My Location", @@ -4735,7 +4721,7 @@ { "id": "weatherClock", "name": "Weather Clock", - "version": "0.01", + "version": "0.02", "description": "A clock which displays current weather conditions (requires Gadgetbridge and Weather apps).", "icon": "app.png", "screenshots": [{"url":"screens/screen1.png"}], diff --git a/apps/chronowid/ChangeLog b/apps/chronowid/ChangeLog index e173467a1..ded543397 100644 --- a/apps/chronowid/ChangeLog +++ b/apps/chronowid/ChangeLog @@ -1,3 +1,5 @@ 0.01: New widget and app! 0.02: Setting to reset values, timer buzzes at 00:00 and not later (see readme) -0.03: Display only minutes:seconds when less than 1 hour left \ No newline at end of file +0.03: Display only minutes:seconds when less than 1 hour left +0.04: Change to 7 segment font, move to top widget bar + Better auto-update behaviour, less RAM used diff --git a/apps/chronowid/README.md b/apps/chronowid/README.md index ec1d5dd46..6e0aba681 100644 --- a/apps/chronowid/README.md +++ b/apps/chronowid/README.md @@ -5,14 +5,13 @@ The advantage is, that you can still see your normal watchface and other widgets The widget is always active, but only shown when the timer is on. Hours, minutes, seconds and timer status can be set with an app. -When there is less than one seconds left on the timer it buzzes. +When there is less than one second left on the timer it buzzes. The widget has been tested on Bangle 1 and Bangle 2 ## Screenshots -![](chrono_with_wave.jpg) -![](chrono_with_pastel.jpg) +![](screenshot.png) ## Features @@ -28,15 +27,15 @@ There are no settings section in the settings app, timer can be set using an app * Hours: Set the hours for the timer * Minutes: Set the minutes for the timer * Seconds: Set the seconds for the timer -* Timer on: Starts the timer and displays the widget when set to 'On'. You have to leave the app to load the widget which starts the timer. The widget is always there, but only visible when timer is on. +* Timer on: Starts the timer and displays the widget when set to 'On'. You have to leave the app to load the widget which starts the timer. The widget is always there, but only visible when timer is on. ## Releases -* Offifical app loader: https://github.com/espruino/BangleApps/tree/master/apps/chronowid (https://banglejs.com/apps/) +* Official app loader: https://github.com/espruino/BangleApps/tree/master/apps/chronowid (https://banglejs.com/apps/) * Forked app loader: https://github.com/Purple-Tentacle/BangleApps/tree/master/apps/chronowid (https://purple-tentacle.github.io/BangleApps/index.html#) * Development: https://github.com/Purple-Tentacle/BangleAppsDev/tree/master/apps/chronowid ## Requests -If you have any feature requests, please write here: http://forum.espruino.com/conversations/345972/ \ No newline at end of file +If you have any feature requests, please write here: http://forum.espruino.com/conversations/345972/ diff --git a/apps/chronowid/app.js b/apps/chronowid/app.js index 0cacdee23..f38105e34 100644 --- a/apps/chronowid/app.js +++ b/apps/chronowid/app.js @@ -3,7 +3,6 @@ Bangle.loadWidgets(); Bangle.drawWidgets(); const storage = require('Storage'); -const boolFormat = v => v ? "On" : "Off"; let settingsChronowid; function updateSettings() { @@ -12,6 +11,7 @@ function updateSettings() { now.getHours() + settingsChronowid.hours, now.getMinutes() + settingsChronowid.minutes, now.getSeconds() + settingsChronowid.seconds); settingsChronowid.goal = goal.getTime(); storage.writeJSON('chronowid.json', settingsChronowid); + if (WIDGETS["chronowid"]) WIDGETS["chronowid"].reload(); } function resetSettings() { @@ -44,6 +44,7 @@ function showMenu() { timerMenu.started.value = settingsChronowid.started; } }, + '< Back' : ()=>{load();}, 'Reset values': function() { settingsChronowid.hours = 0; settingsChronowid.minutes = 0; @@ -84,15 +85,15 @@ function showMenu() { }, 'Timer on': { value: settingsChronowid.started, - format: boolFormat, + format: v => v ? "On" : "Off", onchange: v => { settingsChronowid.started = v; updateSettings(); } }, }; - timerMenu['-Exit-'] = ()=>{load();}; + return E.showMenu(timerMenu); } -showMenu(); \ No newline at end of file +showMenu(); diff --git a/apps/chronowid/chrono_with_pastel.jpg b/apps/chronowid/chrono_with_pastel.jpg deleted file mode 100644 index 2f5993e79..000000000 Binary files a/apps/chronowid/chrono_with_pastel.jpg and /dev/null differ diff --git a/apps/chronowid/chrono_with_wave.jpg b/apps/chronowid/chrono_with_wave.jpg deleted file mode 100644 index 5f35bd28b..000000000 Binary files a/apps/chronowid/chrono_with_wave.jpg and /dev/null differ diff --git a/apps/chronowid/screenshot.png b/apps/chronowid/screenshot.png new file mode 100644 index 000000000..f94eece94 Binary files /dev/null and b/apps/chronowid/screenshot.png differ diff --git a/apps/chronowid/widget.js b/apps/chronowid/widget.js index f0e785efd..2d1c78941 100644 --- a/apps/chronowid/widget.js +++ b/apps/chronowid/widget.js @@ -1,93 +1,79 @@ (() => { - const storage = require('Storage'); - settingsChronowid = storage.readJSON("chronowid.json",1)||{}; //read settingsChronowid from file - var height = 23; - var width = 58; + var settingsChronowid; var interval = 0; //used for the 1 second interval timer - var now = new Date(); + var diff; - var time = 0; - var diff = settingsChronowid.goal - now; - //Convert ms to time function getTime(t) { var milliseconds = parseInt((t % 1000) / 100), seconds = Math.floor((t / 1000) % 60), minutes = Math.floor((t / (1000 * 60)) % 60), hours = Math.floor((t / (1000 * 60 * 60)) % 24); - - hours = (hours < 10) ? "0" + hours : hours; - minutes = (minutes < 10) ? "0" + minutes : minutes; - seconds = (seconds < 10) ? "0" + seconds : seconds; - - return hours + ":" + minutes + ":" + seconds; + return hours.toString().padStart(2,0) + ":" + minutes.toString().padStart(2,0) + ":" + seconds.toString().padStart(2,0); } - function printDebug() { - print ("Nowtime: " + getTime(now)); - print ("Now: " + now); + /*function printDebug() { print ("Goaltime: " + getTime(settingsChronowid.goal)); print ("Goal: " + settingsChronowid.goal); print("Difftime: " + getTime(diff)); print("Diff: " + diff); print ("Started: " + settingsChronowid.started); print ("----"); - } + }*/ //counts down, calculates and displays function countDown() { - now = new Date(); + var now = new Date(); diff = settingsChronowid.goal - now; //calculate difference - WIDGETS["chronowid"].draw(); - //time is up + // time is up if (settingsChronowid.started && diff < 1000) { Bangle.buzz(1500); //write timer off to file settingsChronowid.started = false; - storage.writeJSON('chronowid.json', settingsChronowid); + require('Storage').writeJSON('chronowid.json', settingsChronowid); clearInterval(interval); //stop interval + interval = undefined; } - //printDebug(); + // calculates width and redraws accordingly + WIDGETS["chronowid"].redraw(); } - // draw your widget - function draw() { - if (!settingsChronowid.started) { - width = 0; - return; //do not draw anything if timer is not started - } - g.reset(); - if (diff >= 0) { - if (diff < 3600000) { //less than 1 hour left - width = 58; - g.clearRect(this.x,this.y,this.x+width,this.y+height); - g.setFont("6x8", 2); - g.drawString(getTime(diff).substring(3), this.x+1, this.y+5); //remove hour part 00:00:00 -> 00:00 - } - if (diff >= 3600000) { //one hour or more left - width = 48; - g.clearRect(this.x,this.y,this.x+width,this.y+height); - g.setFont("6x8", 1); - g.drawString(getTime(diff), this.x+1, this.y+((height/2)-4)); //display hour 00:00:00 - } - } - // not needed anymoe, because we check if diff < 1000 now, so 00:00 is displayed. - // else { - // width = 58; - // g.clearRect(this.x,this.y,this.x+width,this.y+height); - // g.setFont("6x8", 2); - // g.drawString("END", this.x+15, this.y+5); - // } - } - - if (settingsChronowid.started) interval = setInterval(countDown, 1000); //start countdown each second - // add the widget - WIDGETS["chronowid"]={area:"bl",width:width,draw:draw,reload:function() { - reload(); - Bangle.drawWidgets(); // relayout all widgets + WIDGETS["chronowid"]={area:"tl",width:0,draw:function() { + if (!this.width) return; + g.reset().setFontAlign(0,0).clearRect(this.x,this.y,this.x+this.width,this.y+23); + //g.drawRect(this.x,this.y,this.x+this.width-1, this.y+23); + var scale; + var timeStr; + if (diff < 3600000) { //less than 1 hour left + width = 58; + scale = 2; + timeStr = getTime(diff).substring(3); // remove hour part 00:00:00 -> 00:00 + } else { //one hour or more left + width = 48; + scale = 1; + timeStr = getTime(diff); //display hour 00:00:00 but small + } + // Font5x9Numeric7Seg - just build this in as it's tiny + g.setFontCustom(atob("AAAAAAAAAAIAAAQCAQAAAd0BgMBdwAAAAAAAdwAB0RiMRcAAAERiMRdwAcAQCAQdwAcERiMRBwAd0RiMRBwAAEAgEAdwAd0RiMRdwAcERiMRdwAFAAd0QiEQdwAdwRCIRBwAd0BgMBAAABwRCIRdwAd0RiMRAAAd0QiEQAAAAAAAAAA="), 32, atob("BgAAAAAAAAAAAAAAAAYCAAYGBgYGBgYGBgYCAAAAAAAABgYGBgYG"), 9 + (scale<<8)); + g.drawString(timeStr, this.x+this.width/2, this.y+12); + }, redraw:function() { + var last = this.width; + if (!settingsChronowid.started) this.width = 0; + else this.width = (diff < 3600000) ? 58 : 48; + if (last != this.width) Bangle.drawWidgets(); + else this.draw(); + }, reload:function() { + settingsChronowid = require('Storage').readJSON("chronowid.json",1)||{}; + if (interval) clearInterval(interval); + interval = undefined; + // start countdown each second + if (settingsChronowid.started) interval = setInterval(countDown, 1000); + // reset everything + countDown(); }}; //printDebug(); - countDown(); -})(); \ No newline at end of file + // set width correctly, start countdown each second + WIDGETS["chronowid"].reload(); +})(); diff --git a/apps/messages/ChangeLog b/apps/messages/ChangeLog index 84c5b7551..269a2cf62 100644 --- a/apps/messages/ChangeLog +++ b/apps/messages/ChangeLog @@ -8,6 +8,8 @@ Back now marks a message as read Clicking top-left opens a menu which allows you to delete a message or mark unread 0.07: Added settings menu with option to choose vibrate pattern and frequency (fix #909) -0.08: Fix rendering of long messages (fix #969) +0.08: Fix rendering of long messages (fix #969) buzz on new message (fix #999) -0.09: Respect the 'new' attribute if it was set from iOS integrations \ No newline at end of file +0.09: Message now disappears after 60s if no action taken and clock loads (fix 922) + Fix phone icon (#1014) +0.10: Respect the 'new' attribute if it was set from iOS integrations \ No newline at end of file diff --git a/apps/messages/README.md b/apps/messages/README.md index c243ec06a..e9aa128d1 100644 --- a/apps/messages/README.md +++ b/apps/messages/README.md @@ -8,9 +8,17 @@ and responded to. It is a replacement for the old `notify`/`gadgetbridge` apps. -## Usage +## Settings + +You can change settings by going to the global `Settings` app, then `App Settings` +and `Messages`: + +* `Vibrate` - This is the pattern of buzzes that should be made when a new message is received +* `Repeat` - How often should buzzes repeat - the default of 4 means the Bangle will buzz every 4 seconds +* `Unread Timer` - when a new message is received we go into the Messages app. +If there is no user input for this amount of time then the app will exit and return +to the clock where `MESSAGES` will be shown in the Widget bar. -... ## Requests diff --git a/apps/messages/app.js b/apps/messages/app.js index 38968ced5..c609acb4b 100644 --- a/apps/messages/app.js +++ b/apps/messages/app.js @@ -42,7 +42,12 @@ try { }; } - +/** this is a timeout if the app has started and is showing a single message +but the user hasn't seen it (eg no user input) - in which case +we should start a timeout for settings.unreadTimeout to return +to the clock. */ +var unreadTimeout; +/// List of all our messages var MESSAGES = require("Storage").readJSON("messages.json",1)||[]; if (!Array.isArray(MESSAGES)) MESSAGES=[]; var onMessagesModified = function(msg) { @@ -171,8 +176,14 @@ function showMessageSettings(msg) { function showMessage(msgid) { var msg = MESSAGES.find(m=>m.id==msgid); if (!msg) return checkMessages(); // go home if no message found - if (msg.src=="Maps") return showMapMessage(msg); - if (msg.id=="music") return showMusicMessage(msg); + if (msg.src=="Maps") { + cancelReloadTimeout(); // don't auto-reload to clock now + return showMapMessage(msg); + } + if (msg.id=="music") { + cancelReloadTimeout(); // don't auto-reload to clock now + return showMusicMessage(msg); + } // Normal text message display var title=msg.title, titleFont = fontLarge, lines; if (title) { @@ -186,14 +197,15 @@ function showMessage(msgid) { } var buttons = [ {type:"btn", src:getBackImage(), cb:()=>{ - msg.new = false; // read mail - saveMessages(); + msg.new = false; saveMessages(); // read mail + cancelReloadTimeout(); // don't auto-reload to clock now checkMessages({clockIfNoMsg:1,clockIfAllRead:0,showMsgIfUnread:1}); }} // back ]; if (msg.positive) { buttons.push({type:"btn", src:getPosImage(), cb:()=>{ msg.new = false; saveMessages(); + cancelReloadTimeout(); // don't auto-reload to clock now Bangle.messageResponse(msg,true); checkMessages({clockIfNoMsg:1,clockIfAllRead:1,showMsgIfUnread:1}); }}); @@ -202,6 +214,7 @@ function showMessage(msgid) { buttons.push({type:"btn", src:getNegImage(), cb:()=>{ console.log("Response"); msg.new = false; saveMessages(); + cancelReloadTimeout(); // don't auto-reload to clock now Bangle.messageResponse(msg,false); checkMessages({clockIfNoMsg:1,clockIfAllRead:1,showMsgIfUnread:1}); }}); @@ -210,7 +223,10 @@ function showMessage(msgid) { var body = (lines.length>4) ? lines.slice(0,4).join("\n")+"..." : lines.join("\n"); layout = new Layout({ type:"v", c: [ {type:"h", fillx:1, bgCol:colBg, c: [ - { type:"btn", src:getMessageImage(msg), cb:()=>showMessageSettings(msg) }, + { type:"btn", src:getMessageImage(msg), cb:()=>{ + cancelReloadTimeout(); // don't auto-reload to clock now + showMessageSettings(msg); + }}, { type:"v", fillx:1, c: [ {type:"txt", font:fontSmall, label:msg.src||"Message", bgCol:colBg, fillx:1, pad:2, halign:1 }, title?{type:"txt", font:titleFont, label:title, bgCol:colBg, fillx:1, pad:2 }:{}, @@ -249,7 +265,8 @@ function checkMessages(options) { // no new messages - go to clock? if (options.clockIfAllRead && newMessages.length==0) return load(); - + // we don't have to time out of this screen... + cancelReloadTimeout(); // Otherwise show a menu E.showScroller({ h : 48, @@ -291,9 +308,23 @@ function checkMessages(options) { }); } +function cancelReloadTimeout() { + if (!unreadTimeout) return; + clearTimeout(unreadTimeout); + unreadTimeout = undefined; +} + + g.clear(); Bangle.loadWidgets(); Bangle.drawWidgets(); setTimeout(() => { + var unreadTimeoutSecs = (require('Storage').readJSON("messages.settings.json", true) || {}).unreadTimeout; + if (unreadTimeoutSecs===undefined) unreadTimeoutSecs=60; + if (unreadTimeoutSecs) + unreadTimeout = setTimeout(function() { + print("Message not seen - reloading"); + load(); + }, unreadTimeoutSecs*1000); checkMessages({clockIfNoMsg:0,clockIfAllRead:0,showMsgIfUnread:1}); },10); // if checkMessages wants to 'load', do that diff --git a/apps/messages/lib.js b/apps/messages/lib.js index 586a82b67..63f55dd03 100644 --- a/apps/messages/lib.js +++ b/apps/messages/lib.js @@ -1,10 +1,10 @@ +/* Push a new message onto messages queue, event is: + {t:"add",id:int, src,title,subject,body,sender,tel, important:bool, new:bool} + {t:"add",id:int, id:"music", state, artist, track, etc} // add new + {t:"remove-",id:int} // remove + {t:"modify",id:int, title:string} // modified +*/ exports.pushMessage = function(event) { - /* event is: - {t:"add",id:int, src,title,subject,body,sender,tel, important:bool, new:bool} // add new - {t:"add",id:int, id:"music", state, artist, track, etc} // add new - {t:"remove-",id:int} // remove - {t:"modify",id:int, title:string} // modified - */ var messages, inApp = "undefined"!=typeof MESSAGES; if (inApp) messages = MESSAGES; // we're in an app that has already loaded messages @@ -51,6 +51,7 @@ exports.pushMessage = function(event) { WIDGETS.messages.show(); }, 500); } +/// Remove all messages exports.clearAll = function(event) { var messages, inApp = "undefined"!=typeof MESSAGES; if (inApp) { diff --git a/apps/messages/settings.js b/apps/messages/settings.js index ef6266cf6..fd8ce8f39 100644 --- a/apps/messages/settings.js +++ b/apps/messages/settings.js @@ -3,6 +3,7 @@ let settings = require('Storage').readJSON("messages.settings.json", true) || {}; if (settings.vibrate===undefined) settings.vibrate="."; if (settings.repeat===undefined) settings.repeat=4; + if (settings.unreadTimeout===undefined) settings.unreadTimeout=60; return settings; } function updateSetting(setting, value) { @@ -30,6 +31,12 @@ format: v => v+"s", onchange: v => updateSetting("repeat", v) }, + 'Unread timer': { + value: settings().unreadTimeout, + min: 0, max: 240, step : 10, + format: v => v?v+"s":"Off", + onchange: v => updateSetting("unreadTimeout", v) + }, }; E.showMenu(mainmenu); }) diff --git a/apps/messages/widget.js b/apps/messages/widget.js index 3a22b40fd..245a303fc 100644 --- a/apps/messages/widget.js +++ b/apps/messages/widget.js @@ -1,4 +1,3 @@ - WIDGETS["messages"]={area:"tl",width:0,draw:function() { if (!this.width) return; var c = (Date.now()-this.t)/1000; @@ -13,9 +12,10 @@ WIDGETS["messages"]={area:"tl",width:0,draw:function() { WIDGETS["messages"].buzz(); // buzz every 4 seconds } setTimeout(()=>WIDGETS["messages"].draw(), 1000); -},show:function() { +},show:function(quiet) { WIDGETS["messages"].t=Date.now(); // first time WIDGETS["messages"].l=Date.now()-10000; // last buzz + if (quiet) WIDGETS["messages"].t -= 500000; // if quiet, set last time in the past so there is no buzzing WIDGETS["messages"].width=64; Bangle.drawWidgets(); Bangle.setLCDPower(1);// turns screen on @@ -34,3 +34,10 @@ WIDGETS["messages"]={area:"tl",width:0,draw:function() { } b(); }}; +/* We might have returned here if we were in the Messages app for a +message but then the watch was never viewed. In that case we don't +want to buzz but should still show that there are unread messages. */ +if (global.MESSAGES===undefined) (function() { + var messages = require("Storage").readJSON("messages.json",1)||[]; + if (messages.some(m=>m.new)) WIDGETS["messages"].show(true); +})(); diff --git a/apps/mywelcome/ChangeLog b/apps/mywelcome/ChangeLog index b012da933..f2b54e42c 100644 --- a/apps/mywelcome/ChangeLog +++ b/apps/mywelcome/ChangeLog @@ -14,3 +14,4 @@ 0.10: Add birthday style 0.11: Skip double buffering, use 240x240 size 0.12: Fix swipe direction (#800) +0.13: Bangle.js 2 support diff --git a/apps/mywelcome/app.js b/apps/mywelcome/app-bangle1.js similarity index 100% rename from apps/mywelcome/app.js rename to apps/mywelcome/app-bangle1.js diff --git a/apps/mywelcome/app-bangle2.js b/apps/mywelcome/app-bangle2.js new file mode 100644 index 000000000..aeee6918d --- /dev/null +++ b/apps/mywelcome/app-bangle2.js @@ -0,0 +1,254 @@ +// exec each function from seq one after the other +function animate(seq,period) { + var c = g.getColor(); + var i = setInterval(function() { + if (seq.length) { + var f = seq.shift(); + g.setColor(c); + if (f) f(); + } else clearInterval(i); + },period); +} + +// Fade in to FG color with angled lines +function fade(col, callback) { + var n = 0; + function f() {"ram" + g.setColor(col); + for (var i=n;i<240;i+=10) g.drawLine(i,0,0,i).drawLine(i,240,240,i); + g.flip(); + n++; + if (n<10) setTimeout(f,0); + else callback(); + } + f(); +} + + +var SCENE_COUNT=11; +function getScene(n) { + if (n==0) return function() { + console.log("Start app"); + g.clear(1); + eval(require("Storage").read("mywelcome.custom.js")); + } + if (n==1) return function() { + g.reset().setBgColor(0).clearRect(0,0,176,176); + g.setFont("6x15"); + var n=0; + var l = Bangle.getLogo(); + var im = g.imageMetrics(l); + var i = setInterval(function() { + n+=0.1; + g.setColor(n,n,n); + g.drawImage(l,(176-im.width)/2,(176-im.height)/2); + if (n>=1) { + clearInterval(i); + setTimeout(()=>g.drawString("Open",44,104), 500); + setTimeout(()=>g.drawString("Hackable",44,116), 1000); + setTimeout(()=>g.drawString("Smart Watch",44,128), 1500); + } + },50); + }; + if (n==2) return function() { + var img = require("heatshrink").decompress(atob("ptR4n/j/4gH+8H5wl+jOukVVoHZ8dt/n//n37OtgH9sHhwHp4H5xmkGiH72MRje/LL/7iIAEE7sPEgoAC+AlagIlIiMQErPxDwUYxAABwIHCj8N7nOl3uEqa6BEggnFjfM5nCkUil3gEq5KDAAQmC6QmBE4JxSEhIABiQmB8QmSXoQlCYRMdEwIlCAAIlNhYlOiO85nNEyMPEoZwIAAcsYIYmPXoYlMiKaFExX/u9VEqLBBOYrCH+czmtVqJyDEpiaCOYsgSYszmc3qtTEqMR7hzG8AlGmd1OQglOOY6aEgYlCmmZoJMCTBrnD6SaIEoU/zOUuolSjbnBJgqaCEoU5zOXX4RyQYBBzCS4X5zNDqqZCJiERJg5zBEoVJEoM1JgYlQjhMHc4JLEmZMEEp6ZIJgPzS4WTmZMVTILmFYAK+BmglCmd1JgUYJiPNEorABEIOZygDBm5MCiJMQlhMH8ByBXwIlBJgUxJiMd5nOTIzlBTAK+BAANVq4jPAAS/HJgJyCTATAEACC/B4S/IJgIlCYAgAPiS/Kn5yEYANTEyPc5niOQxMB/LlCOapyJJgbpBYAZzROQK/Gl0ATIWfEoZzBc6IlB6SYGgBJBJgpzSlhyH8EAh5MBTIjnCuIlOjjlHTAJzC/LmDTSSYIEoTABOYIlETSKYHXwIABOYM0yYmETSCYHEobnDOYqaBExu8TAwlEc4U5EoiaCmK+NTAolFEwX0TQzBMXwXiEpTBCAAomNEoS+EEo4mIYIImKEoS+EEpDoBEyUbEo3gEo4mJdAImIJY4lJEycdEoPOOBYmPuIlE+HcJYhKKTZ1fhYkB2EAhnNcYMuEhomMr8A3YABEoJyB5gjOAAYmHm9VgELEoJMBEoXAEyXzE45YBJgXwEqx1I+ByDOYJyVJw5yCgEB3cQGgJMWJwQnCu6/CgFBigDB13S/glVAAf1qomCglEoADB1QDBADEPEoNVqEAolEgEKolKErJMDYAJMD0lE0AmaEoNaAgJMCFIYAahV/IgIiDOTgABNYJMEOToiCIoJMCOTzfCN4RMBOTxsDJIRyfIwZMBKQZzfJgRyfOYZMBOUBzCJgNKOT5zDJgLoCADxKBOAIABOT6aCAARyfOYRyjOYRyjOYlKEsBzEEsBzEOUJzDOUIABOUiaDOURzCOUZzCEscKCiY")); + var im = g.imageMetrics(img); + g.reset(); + g.setBgColor("#ff00ff"); + var y = 176, speed = 5; + function balloon(callback) { + y-=speed; + var x = (176-im.width)/2; + g.drawImage(img,x,y); + g.clearRect(x,y+81,x+77,y+81+speed); + if (y>30) setTimeout(balloon,0,callback); + else callback(); + } + fade("#ff00ff", function() { + balloon(function() { + g.setColor(-1).setFont("6x15:2").setFontAlign(0,0); + g.drawString("Welcome.",88,130); + }); + }); + setTimeout(function() { + var n=0; + var i = setInterval(function() { + n+=4; + g.scroll(0,-4); + if (n>150) + clearInterval(i); + },20); + },3500); + + }; + if (n==3) return function() { + g.reset(); + g.setBgColor("#ffff00").setColor(0).clear(); + g.setFont("12x20").setFontAlign(0,0); + var x = 70, y = 25, h=25; + animate([ + ()=>g.drawString("Your",x,y+=h), + ()=>g.drawString("Bangle.js",x,y+=h), + ()=>g.drawString("has one",x,y+=h), + ()=>g.drawString("button",x,y+=h), + ()=>{g.setFont("12x20:2").setFontAlign(0,0,1).drawString("HERE!",150,88);} + ],200); + }; + if (n==4) return function() { + g.reset(); + g.setBgColor("#00ffff").setColor(0).clear(); + g.setFontAlign(0,0).setFont("6x15:2"); + g.drawString("Press",88,40).setFontAlign(0,-1); + g.setFont("12x20"); + g.drawString("To wake the\nscreen up, or to\nselect", 88,60); + }; + if (n==5) return function() { + g.reset(); + g.setBgColor("#00ffff").setColor(0).clear(); + g.setFontAlign(0,0).setFont("6x15:2"); + g.drawString("Long Press",88,40).setFontAlign(0,-1); + g.setFont("12x20"); + g.drawString("To go back to\nthe clock", 88,60); + }; + if (n==6) return function() { + g.reset(); + g.setBgColor("#ff0000").setColor(0).clear(); + g.setFontAlign(0,0).setFont("12x20"); + g.drawString("If Bangle.js ever\nstops, hold the\nbutton for\nten seconds.\n\nBangle.js will\nthen reboot.", 88,78); + }; + if (n==7) return function() { + g.reset(); + g.setBgColor("#0000ff").setColor(-1).clear(); + g.setFont("12x20").setFontAlign(0,0); + var x = 88, y = -20, h=60; + animate([ + ()=>{g.drawString("Bangle.js has a\nfull touchscreen",x,y+=h);}, + 0,0, + ()=>{g.drawString("Drag up and down\nto scroll and\ntap to select",x,y+=h);}, + ],300); + }; + if (n==8) return function() { + g.reset(); + g.setBgColor("#00ff00").setColor(0).clear(); + g.setFont("12x20").setFontAlign(0,0); + var x = 88, y = -35, h=80; + animate([ + ()=>{g.drawString("Bangle.js comes\nwith a few\napps installed",x,y+=h);}, + 0,0, + ()=>{g.drawString("To add more, visit\nbanglejs.com/apps",x,y+=h);}, + ],400); + }; + if (n==9) return function() { + g.reset(); + g.setBgColor("#ff0000").setColor(0).clear(); + g.setFont("12x20").setFontAlign(0,0); + var x = 88; + g.drawString("You can also make\nyour own apps!",x,30); + g.drawString("Check out\nbanglejs.com",x,130); + + var rx = 0, ry = 0; + // draw a cube + function draw() { + // rotate + rx += 0.1; + ry += 0.11; + var rcx=Math.cos(rx), + rsx=Math.sin(rx), + rcy=Math.cos(ry), + rsy=Math.sin(ry); + // Project 3D coordinates into 2D + function p(x,y,z) { + var t; + t = x*rcy + z*rsy; + z = z*rcy - x*rsy; + x=t; + t = y*rcx + z*rsx; + z = z*rcx - y*rsx; + y=t; + z += 4; + return [88 + 60*x/z, 78+ 60*y/z]; + } + + var a; + // draw a series of lines to make up our cube + var s = 30; + g.clearRect(88-s,78-s,88+s,78+s); + a = p(-1,-1,-1); g.moveTo(a[0],a[1]); + a = p(1,-1,-1); g.lineTo(a[0],a[1]); + a = p(1,1,-1); g.lineTo(a[0],a[1]); + a = p(-1,1,-1); g.lineTo(a[0],a[1]); + a = p(-1,-1,-1); g.lineTo(a[0],a[1]); + a = p(-1,-1,1); g.moveTo(a[0],a[1]); + a = p(1,-1,1); g.lineTo(a[0],a[1]); + a = p(1,1,1); g.lineTo(a[0],a[1]); + a = p(-1,1,1); g.lineTo(a[0],a[1]); + a = p(-1,-1,1); g.lineTo(a[0],a[1]); + a = p(-1,-1,-1); g.moveTo(a[0],a[1]); + a = p(-1,-1,1); g.lineTo(a[0],a[1]); + a = p(1,-1,-1); g.moveTo(a[0],a[1]); + a = p(1,-1,1); g.lineTo(a[0],a[1]); + a = p(1,1,-1); g.moveTo(a[0],a[1]); + a = p(1,1,1); g.lineTo(a[0],a[1]); + a = p(-1,1,-1); g.moveTo(a[0],a[1]); + a = p(-1,1,1); g.lineTo(a[0],a[1]); + } + + setInterval(draw,50); + }; + if (n==10) return function() { + g.reset(); + g.setBgColor("#ffffff");g.clear(); + g.setFontAlign(0,0); + g.setFont("12x20"); + + var x = 88, y = 10, h=21; + animate([ + ()=>g.drawString("That's it!",x,y+=h), + ()=>{g.drawString("Press",x,y+=h*2); + g.drawString("the button",x,y+=h); + g.drawString("to start",x,y+=h); + g.drawString("Bangle.js",x,y+=h);} + ],400); + } +} + +var sceneNumber = 0; + +function move(dir) { + if (dir>0 && sceneNumber+1 == SCENE_COUNT) return; // at the end + sceneNumber = (sceneNumber+dir)%SCENE_COUNT; + if (sceneNumber<0) sceneNumber=0; + clearInterval(); + getScene(sceneNumber)(); + if (sceneNumber>1) { + var l = SCENE_COUNT; + for (var i=0;i move(dir)); +setWatch(()=>{ + if (sceneNumber == SCENE_COUNT-1) + load(); + else + move(1); +}, BTN1, {repeat:true}); + +Bangle.setLCDTimeout(0); +Bangle.setLocked(0); +Bangle.setLCDPower(1); +move(0); diff --git a/apps/mywelcome/custom.html b/apps/mywelcome/custom.html index c4c721765..340f178e8 100644 --- a/apps/mywelcome/custom.html +++ b/apps/mywelcome/custom.html @@ -28,13 +28,15 @@ function getApp() { var line3 = document.getElementById("line3").value; var line4 = document.getElementById("line4").value; var style = document.getElementById("style").value; + // build the app's text using a templated String if (style=="Birthday") return `(function() { var ib = require("heatshrink").decompress(atob("jk0ggGDhOZAAWQCYwMEBxAMFAAIaHyc/+c5DgwMC/84Dg4aCBgwcDBoOf+Y4GBoQEBn4zCI44DBDQ4NEyf4BpgoIBoefxINMBhApEBrQAKBrrrGWpANZHBT7FBpYqIFAYcJBggNOFQwoFDgwMHBwoMIBwYMKBrkykANLmcwBu0zBrMDBv4AFN5gA/ADY")); var ir = require("heatshrink").decompress(atob("jk0ggGDhvdAAXQCYwMEBxAMFAAIaH6c/+c9DgwMC/8zDg4aC/4YCHIwNB7/zHAwNCAgM/DQwqDAYIaHBonT/oNMFBAND74NNBhApEBrQAKBrrrGWpANZHBT7FBpYqIFAYcJBgkA5oMF7gNFFQwoFDgwMHHIoMIAAPM5gMKBrk0oANLmcwBu0zBrMDBv4AFN5gA/ADYA=")); var ig = require("heatshrink").decompress(atob("jk0ggGDg93AAVwCYwMEBxAMFAAIaHuc/+c3DgwMC/8yDg4aC/4YCHIwNBv/zHAwNCAgM/DQwqDAYIaHBolz+4NMFBANDv8nBpgMIFIgNaABQNddYy1IBrI4KfYoNLFRAoDDhIMEgHnBgt+BooqGFAoqGBg4OFBhAODBhQNcmUgBpczmAN2mYNZgYN/AApvMAH4Ab")); var igift = require("heatshrink").decompress(atob("q1QxH+ADOi0QbZ5nMHDQAbKgIACKa4ACKnJWVKghW0KgxWTKgxWyKhBWRKhBWwKhRWPKhRWuKhhWNKhhWtKpxWKKhys8KxBU8Ky5U+KypU/KyhU/KyhU/KynGKn5WTKn5WUKmHCADpJJE7uYABZUfKuuYKv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/AAv+Kv5VT/wADyIAaKpIlbABZSEKv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/ADNtKv6rdKzZVwKhAABy5V/Khw")); - var W=240,H=240; + var W=g.getWidth(),H=g.getHeight(); + var titleFont = g.getFonts().includes("12x20") ? "12x20" : "6x8:2"; var blns = []; function updateFlake(f) { f.im = [ir,ig,ib][Math.round(Math.random()*100)%3]; @@ -60,7 +62,7 @@ var ig = require("heatshrink").decompress(atob("jk0ggGDg93AAVwCYwMEBxAMFAAIaHuc/ }); var x = W/2, y = H/2; g.drawImage(igift,x-43,y-80); - g.setFont("6x8",2).setFontAlign(0,0); + g.setFont(titleFont).setFontAlign(0,0); g.drawString(${JSON.stringify(line1)},x,y+=20); g.drawString(${JSON.stringify(line2)},x,y+=20); g.setFont("6x8"); @@ -68,7 +70,7 @@ var ig = require("heatshrink").decompress(atob("jk0ggGDg93AAVwCYwMEBxAMFAAIaHuc/ g.drawString(${JSON.stringify(line4)},x,y+=10); g.flip(); } - g.clear(); + g.clear(1).setBgColor(0).setColor(-1).clearRect(0,0,W,H); setInterval(draw,50); })()`; // if (style=="Christmas") @@ -76,6 +78,7 @@ var ig = require("heatshrink").decompress(atob("jk0ggGDg93AAVwCYwMEBxAMFAAIaHuc/ var isnow = require("heatshrink").decompress(atob("jEagQWTgfAAocf+gFDh4FDiARBggVB3AFBl3Agf8jfkn/AgX/v/9/+Agfv/2//YrBgfwh4wCgfghYFJCIYdFFIw1EIIpNFL44FFOIoAP")); var itree = require("heatshrink").decompress(atob("mtWxH+ADHHDTI0aGuXH5vNGmhqvTYIzBGtoxF6fTG4g4oGgQyBAAZssGoI0Ga1g1FGdo01ZgIAEGmHHNoLSuAAN/rdb0YFBGlgCBGYIABA4YArGYY1CGn4znAAM6GeVd5PQ5Iyurc/vQ0oGZFAn+d4XC3d5GddiGYIEBy+7zoEBGlFhoEcsQ9GT08+oFk1mkGdaVBMgNArnJ6/KzswGs/J6GlrlbqtbvPC5PCy8wGohniMIPJvIpCqmX3e7vI0BqhqlMIY0DqhtBqoEBa0xgBMIIoEqoABGQwzfsIhBv4qHABM50vQGjg1CGaN66DoBGt1ioGd5LoBGjo1PGYNhvLoCa7wnBqgvGA4YzCAgN5GUAsCqoDBmAHCAYU/wPQ0oSDGcBiDqkwAYcxoFd5PX6GdGjrIIqtUAAc3jk5vPC4fCy5pef5I2BTQMcnAHBy+7y95T0oADnFk1ekBpI2aGRUin7NGAA9hsIzVsIgHTAKZBZoPJ5LNDGhBpXGolcwOsrtcA4TNB3bNDGb/+sVin9AoGe6HX5InEvN/TkP+5XQwM/sRsBzqWB4QuKGjvC6HQ4QdDvKWBZYMwmAuHmFUCYNbqibX3fD5O7qolEZQQ0FBwgKDqgJBGiphEDwNUEgJbBFIQqCAgYOCB4IzCnE6GyhYFGoQnDABYzGAAQ1UAAo2NBoQSBnOB0t/Gjo2EABIPCoGe6HX4QzTGRIAEqtVF4QEBBQc4oE4y/J5PCvIxeABk/oADBvO73eXTyAyZMwM/Awd5vIOFGslAr2Av4PLNcU/jmA6HX5I1KasFcn8dTIOd5PJ4SZGGiNhAAIyNn0ckU+ZYe7AAJpJEYJnNGZk+n9kw9cBAcwGoN5aZg1JJJQABm8/oEjoDKC5ALCrUwqh/NrvQ6HDGp04n9doEdoE/sQJBZQZhCqgABGZk6zw0K/1dnVAoNAFwOlCYL1FubJBy4GCGh1AnOX4XC3YzHFYOeCgdV5PQ5OdD4rKBqqYNGYlbv+X3edGY3CGgKMDAAO7JAJgDAClcr2BEYgADaIZ0DL4uXGbDuB6HX5I1GsP+sNhOgWXIhBmWd4Od5PK4TwFGIJoBAYI2BAD0/jlcQoO7AAJaEGQQADGr0/sjNEvOdAoZmDGgw2ZsVAkeAZpQACGZI2VsU/kVGn1bZoPJZogpGGhA4GfRYwBoGC1mlBQbNFFoo0JNxAGCEod/wM6oFAn9iv/J6/Kzo1Ey9/MZQAKCg4GCFgTDEvPCSwI0BC5I0RN4ocEYYPQ5OdHgeXSwTFKGaJyKFYPC3f+MIdbpzFLAD4zB/1OqtbqtOGgYArGAIADGl9UAAI0wGQN5GoQ0vvIABGoI0uGYQABqo0zNOg0uaQY0/GllOGn40//w=")); var W=g.getWidth(),H=g.getHeight(); + var titleFont = g.getFonts().includes("12x20") ? "12x20" : "6x8:2"; var flakes = []; for (var i=0;i<10;i++) { var f = { @@ -97,7 +100,7 @@ var ig = require("heatshrink").decompress(atob("jk0ggGDg93AAVwCYwMEBxAMFAAIaHuc/ }); var x = W/2, y = H/2; g.drawImage(itree,x-27,y-80); - g.setFont("6x8",2).setFontAlign(0,0); + g.setFont(titleFont).setFontAlign(0,0); g.drawString(${JSON.stringify(line1)},x,y+=20); g.drawString(${JSON.stringify(line2)},x,y+=20); g.setFont("6x8"); @@ -105,7 +108,7 @@ var ig = require("heatshrink").decompress(atob("jk0ggGDg93AAVwCYwMEBxAMFAAIaHuc/ g.drawString(${JSON.stringify(line4)},x,y+=10); g.flip(); } - g.clear(); + g.clear(1).setBgColor(0).setColor(-1).clearRect(0,0,W,H); setInterval(draw,50); })(); `; diff --git a/apps/openstmap/ChangeLog b/apps/openstmap/ChangeLog index 69c34ed4e..6cb9d061e 100644 --- a/apps/openstmap/ChangeLog +++ b/apps/openstmap/ChangeLog @@ -8,3 +8,5 @@ 0.08: Update for drag event refactor 0.09: Use current theme cols when drawing GPS info 0.10: Improve scale factor calculation to fix scaling issues (#984) +0.11: Add slight offset to OSM data to align it properly (fix #984) + Fix alignment of satellite info text diff --git a/apps/openstmap/app.js b/apps/openstmap/app.js index c33acd8ad..62597ca20 100644 --- a/apps/openstmap/app.js +++ b/apps/openstmap/app.js @@ -25,11 +25,11 @@ function drawMarker() { var fix; Bangle.on('GPS',function(f) { fix=f; - g.reset().clearRect(0,y1,240,y1+8).setFont("6x8").setFontAlign(0,0); + g.reset().clearRect(0,y1,g.getWidth()-1,y1+8).setFont("6x8").setFontAlign(0,0); var txt = fix.satellites+" satellites"; if (!fix.fix) txt += " - NO FIX"; - g.drawString(txt,120,y1 + 4); + g.drawString(txt,g.getWidth()/2,y1 + 4); drawMarker(); }); Bangle.setGPSPower(1, "app"); diff --git a/apps/openstmap/custom.html b/apps/openstmap/custom.html index eeb148f54..56dea1188 100644 --- a/apps/openstmap/custom.html +++ b/apps/openstmap/custom.html @@ -132,8 +132,10 @@ TODO: var zoom = map.getZoom(); var centerlatlon = map.getBounds().getCenter(); var center = map.project(centerlatlon, zoom).divideBy(OSMTILESIZE); - var ox = Math.round((center.x - Math.floor(center.x)) * OSMTILESIZE); - var oy = Math.round((center.y - Math.floor(center.y)) * OSMTILESIZE); + // Reason for 16px adjustment below not 100% known, but it seems to + // align everything perfectly: https://github.com/espruino/BangleApps/issues/984 + var ox = Math.round((center.x - Math.floor(center.x)) * OSMTILESIZE) + 16; + var oy = Math.round((center.y - Math.floor(center.y)) * OSMTILESIZE) + 16; center = center.floor(); // make sure we're in the middle of a tile // JS version of Bangle.js's projection function bproject(lat, lon) { @@ -155,8 +157,15 @@ TODO: var bd = bproject(pd.lat, pd.lng) var scale = bc.distanceTo(bd); - var tileGetters = []; + // test + /*var p = bproject(centerlatlon.lat, centerlatlon.lng); + var q = bproject(mylat, mylon); + var testPt = { + x : (q.x-p.x)/scale + (MAPSIZE/2), + y : (MAPSIZE/2) - (q.y-p.y)/scale + };*/ + var tileGetters = []; // Render everything to a canvas... var canvas = document.getElementById("maptiles"); canvas.style.display=""; @@ -173,6 +182,11 @@ TODO: tileGetters.push(new Promise(function(resolve,reject) { img.onload = function(){ ctx.drawImage(img,i*OSMTILESIZE - ox, j*OSMTILESIZE - oy); + /*if (testPt) { + ctx.fillStyle="green"; + ctx.fillRect(testPt.x-1, testPt.y-5, 3,10); + ctx.fillRect(testPt.x-5, testPt.y-1, 10,3); + }*/ resolve(); }; })); diff --git a/apps/openstmap/screenshot.png b/apps/openstmap/screenshot.png new file mode 100644 index 000000000..2895b562e Binary files /dev/null and b/apps/openstmap/screenshot.png differ diff --git a/apps/setting/ChangeLog b/apps/setting/ChangeLog index d840654fe..b393dda00 100644 --- a/apps/setting/ChangeLog +++ b/apps/setting/ChangeLog @@ -37,3 +37,4 @@ 0.32: Fix 'beep' menu on Bangle.js 2 0.33: Really fix 'beep' menu on Bangle.js 2 this time 0.34: Remove Quiet Mode LCD settings: now handled by Quiet Mode Schedule app +0.35: Change App/Widget settings to 'App Settings' so it fits on Bangle screen diff --git a/apps/setting/settings.js b/apps/setting/settings.js index 9432d0a38..e00c15462 100644 --- a/apps/setting/settings.js +++ b/apps/setting/settings.js @@ -96,7 +96,7 @@ function showMainMenu() { '': { 'title': 'Settings' }, '< Back': ()=>load(), 'Make Connectable': ()=>makeConnectable(), - 'App/Widget Settings': ()=>showAppSettingsMenu(), + 'App Settings': ()=>showAppSettingsMenu(), 'BLE': ()=>showBLEMenu(), 'Debug Info': { value: settings.log, diff --git a/apps/weatherClock/ChangeLog b/apps/weatherClock/ChangeLog index 2286a7f70..f4a63e976 100644 --- a/apps/weatherClock/ChangeLog +++ b/apps/weatherClock/ChangeLog @@ -1 +1,2 @@ -0.01: New App! \ No newline at end of file +0.01: New App! +0.02: Minor layout format tweak so it uses less memory and draws ok on Bangle.js 1 (#1012) diff --git a/apps/weatherClock/app.js b/apps/weatherClock/app.js index 0a3d390f2..46cc38312 100644 --- a/apps/weatherClock/app.js +++ b/apps/weatherClock/app.js @@ -69,22 +69,20 @@ var clockLayout = new Layout( { {type:"txt", font:"10%", label:"01/01/1970", id:"date" } ] }, - {type: "v", fillx: 1, c: [ - {type: "h", valign : 1, fillx:1, c: [ - {type: "img", filly: 1, id: "weatherIcon", src: sunIcon}, - {type: "v", fillx:1, c: [ - {type: "h", c: [ - {type: "txt", font: "10%", id: "temp", label: "000"}, - {type: "txt", font: "10%", id: "tempUnit", label: "°C"}, - ]}, - {type: "h", c: [ - {type: "txt", font: "10%", id: "wind", label: "00"}, - {type: "txt", font: "10%", id: "windUnit", label: "km/h"}, - ]} - ] - }, - ]}, - ]}] + {type: "h", valign : 1, fillx:1, c: [ + {type: "img", filly: 1, id: "weatherIcon", src: sunIcon}, + {type: "v", fillx:1, c: [ + {type: "h", c: [ + {type: "txt", font: "10%", id: "temp", label: "000"}, + {type: "txt", font: "10%", id: "tempUnit", label: "°C"}, + ]}, + {type: "h", c: [ + {type: "txt", font: "10%", id: "wind", label: "00"}, + {type: "txt", font: "10%", id: "windUnit", label: "km/h"}, + ]} + ] + }, + ]}] }); // timeout used to update every minute @@ -133,4 +131,4 @@ Bangle.setUI("clock"); // Show launcher when middle button pressed Bangle.loadWidgets(); Bangle.drawWidgets(); clockLayout.render(); -draw(); \ No newline at end of file +draw(); diff --git a/apps/welcome/app-bangle2.js b/apps/welcome/app-bangle2.js index 93d1c5657..41d051148 100644 --- a/apps/welcome/app-bangle2.js +++ b/apps/welcome/app-bangle2.js @@ -244,5 +244,6 @@ setWatch(()=>{ }, BTN1, {repeat:true}); Bangle.setLCDTimeout(0); +Bangle.setLocked(0); Bangle.setLCDPower(1); move(0);