From bcc30cadae9fea049ab5fb715d08576b353921d7 Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Wed, 27 Apr 2022 20:28:42 +0100 Subject: [PATCH 01/34] First commit for this app --- apps/timersimple/ChangeLog | 1 + apps/timersimple/Readme.md | 10 ++ apps/timersimple/icons8-time-span-48.png | Bin 0 -> 1933 bytes apps/timersimple/metadata.json | 18 +++ apps/timersimple/timersimple.app.js | 191 +++++++++++++++++++++++ apps/timersimple/timersimple.icon.js | 1 + 6 files changed, 221 insertions(+) create mode 100644 apps/timersimple/ChangeLog create mode 100644 apps/timersimple/Readme.md create mode 100644 apps/timersimple/icons8-time-span-48.png create mode 100644 apps/timersimple/metadata.json create mode 100644 apps/timersimple/timersimple.app.js create mode 100644 apps/timersimple/timersimple.icon.js diff --git a/apps/timersimple/ChangeLog b/apps/timersimple/ChangeLog new file mode 100644 index 000000000..7b83706bf --- /dev/null +++ b/apps/timersimple/ChangeLog @@ -0,0 +1 @@ +0.01: First release diff --git a/apps/timersimple/Readme.md b/apps/timersimple/Readme.md new file mode 100644 index 000000000..e940ba0ab --- /dev/null +++ b/apps/timersimple/Readme.md @@ -0,0 +1,10 @@ +# Simple Timer + +Does one thing well. Set a time in hours, minutes and seconds, and alerts you when time is up. Opening the app while the timer is running (or just leaving the app open) shows how much time is left on the timer. This is the part I felt was missing from the Alarms and Timer app. + +Drag or tap on the up and down buttons over the hour, minute or second to set the time. + +![](timersimple-scr1.png) +![](timersimple-scr2.png) + +Written by: [Sir Indy](https://github.com/sir-indy) For support and discussion please post in the [Bangle JS Forum](http://forum.espruino.com/microcosms/1424/) \ No newline at end of file diff --git a/apps/timersimple/icons8-time-span-48.png b/apps/timersimple/icons8-time-span-48.png new file mode 100644 index 0000000000000000000000000000000000000000..9a9dfb6abd1801997481d40bd41e475afe845f1a GIT binary patch literal 1933 zcmV;82Xgp{P)}f;`d3 z{4|bF%roc{(>PYg>)2T4uNQwW0+8Ygn zw6{|X*_#deBv!4>$$!2UDtwRtR+g1(ggqUDi`B3w1D||bZ8oxLjVqIK^H_${Y^z~l z4qgh>@{lV8OUG!WT9`-!KJBimUYE47XSH$tg5tx3jsS-xFyB^uwzDMC;IL=l!y5-< z9+954uQIM*AISi#lMCP$CvkuJ4u)O*aEx9--^e9+r0Ecf=!uc#t|RYnvWwyLAC`go z?%yS^GUR=enP|!kU-~Re#w|gd=<}d^s2vxspT^kKkXqR19O8=wOG^ls-(f)m?_4{g zFW`RgpNxbx8DS|_K+V7$d{n|$jx%WMJqbznDr)IjZYFiFu&+^B5r751fyc1Hwpj5C zfh8P%XxfioJo9HP)2AqE$&bX?v9}lML({h39gzCC-!JN^E^y&m@Z=oN4bkCgbVMQwY= z*zAbfFN;ZmOl8~{`+A-uz>|e9nCd!CJ0_IvRcAnwn3n+P0ASKRj=tMAtW3&7f<7H2 zI>#qXY|Z(Z@>SCLAit>AHpqY=2n+~H{kd(AmO#hGAuWClRwX@&1bsTFOrxvX4>~Ru zJ95hcI0}>%e^MOu#snGg6E*WLM0JofT47ge>o>5KdAF#$Bv=7xfvTbZp6TV6R*5nj$K=3XG9ERMqDlz z>g(%q>((vJb~&kmV-sNE8K6L}e|dR=DX3#Y2rL#0Y&IL3o12lJpO1k7CtiQ`D4u(! z6ixMQkfp%o_x}C+sH>~PzJ2?UnVE?L2M(a2p+VC?#n0qV=B z!M~vA;xz{W0ES^;u~^XA*$J!F3bWaakvk(Ot9l%zZ?1#gZigs}U>F8lw{AsMRTZvX zyM_}dPH6V4=Yz&xrX-?rBbfukFeoi8MM+5s($muc3Q(Csuh*lxx*EmB#aOW-=&3FV zY6d0&%kx24*)GTc-?{xVK<8gx zuQY?JL+Ac4BDK&x)CR9K<4+B+o!jinc50_lnSj*$a~H0khL1+~tfK{=Ea80rX$4E_ z)l!kF_W_obYXHn=1IDI?@Rj3CbX98LOGhKdrvnxo4+X7JYpZHN*wZmcfm(mAt@k9H z<2}(+83NAn9-Qkt6~Iy8gGx)gY62^OsT7&SwJ%$GR z8<6CH6YUreIpm!qk|9-Y~btXXO?+BBgadZuyMRxK!B*jK2-{l-V))ssgCmz0~7A7~9{puZA!bcD6>M4aR)Z`rw@fW8YLWV&yWxJwCsS^1Op#z=x9{zFq~ zY5UkGlC_kO_W*bzjaPw(0`GD>zcy0wz!HD*mA4dTF~Ca{v=ksKBa5a^fU#20noyfm zIEc<~RzYCIg7cdI6#g&uVFr+e@9x)=00sf{fxt#&($02nvq$4M>q9)m_Z|NQLRok` Trm{7g00000NkvXXu0mjfz&ofF literal 0 HcmV?d00001 diff --git a/apps/timersimple/metadata.json b/apps/timersimple/metadata.json new file mode 100644 index 000000000..5d0e5d5e4 --- /dev/null +++ b/apps/timersimple/metadata.json @@ -0,0 +1,18 @@ +{ + "id":"timersimple", + "name":"Timer Simple", + "shortName": "Timer Simple", + "version": "0.01", + "description": "Sets a single timer, and tells you how long left.", + "readme": "README.md", + "icon":"icons8-time-span-48.png", + "screenshots": [{"url":"timersimple-scr1.png"},{"url":"timersimple-scr2.png"}], + "tags": "tool,alarm,timer", + "supports": ["BANGLEJS2"], + "dependencies": {"scheduler":"type"}, + "allow_emulator": true, + "storage": [ + {"name":"timersimple.app.js","url":"timersimple.app.js"}, + {"name":"timersimple.img","url":"timersimple.icon.js","evaluate":true} + ] + } \ No newline at end of file diff --git a/apps/timersimple/timersimple.app.js b/apps/timersimple/timersimple.app.js new file mode 100644 index 000000000..ddc6bb4c1 --- /dev/null +++ b/apps/timersimple/timersimple.app.js @@ -0,0 +1,191 @@ +Modules.addCached("Layout",function(){function Layout(d,b){function e(a){a.id&&(h[a.id]=a),a.type||(a.type=''),a.c&&a.c.forEach(e)}this._l=this.l=d,this.physBtns=process.env.HWVERSION==2?1:3,b=b||{},this.lazy=b.lazy||!1;var c,f;if(Bangle.setUI(),process.env.HWVERSION!=2){c=[];function a(b){b.type=='btn'&&c.push(b),b.c&&b.c.forEach(a)}a(d),c.length&&(this.physBtns=0,this.buttons=c,this.selectedButton=-1,Bangle.setUI({mode:'updown',back:b.back},c=>{var a=this.selectedButton,b=this.buttons.length;if(c===undefined&&this.buttons[a])return this.buttons[a].cb();this.buttons[a]&&(delete this.buttons[a].selected,this.render(this.buttons[a])),a=(a+b+c)%b,this.buttons[a]&&(this.buttons[a].selected=1,this.render(this.buttons[a])),this.selectedButton=a}),f=!0)}if(b.back&&!f&&Bangle.setUI({mode:'custom',back:b.back}),b.btns){var a=b.btns;if(this.b=a,this.physBtns>=a.length){function b(a,b){b.time-b.lastTime>.75&&this.b[a].cbl?this.b[a].cbl(b):this.b[a].cb&&this.b[a].cb(b)}let c=Math.floor(Bangle.appRect.h/this.physBtns);Bangle.btnWatches&&Bangle.btnWatches.forEach(clearWatch),Bangle.btnWatches=[],this.physBtns>2&&a.length==1&&a.unshift({label:''});while(this.physBtns>a.length)a.push({label:''});a[0]&&Bangle.btnWatches.push(setWatch(b.bind(this,0),BTN1,{repeat:!0,edge:-1})),a[1]&&Bangle.btnWatches.push(setWatch(b.bind(this,1),BTN2,{repeat:!0,edge:-1})),a[2]&&Bangle.btnWatches.push(setWatch(b.bind(this,2),BTN3,{repeat:!0,edge:-1})),this._l.width=g.getWidth()-8,this._l={type:'h',filly:1,c:[this._l,{type:'v',pad:1,filly:1,c:a.map(a=>(a.type='txt',a.font='6x8',a.height=c,a.r=1,a))}]}}else this._l.width=g.getWidth()-32,this._l={type:'h',c:[this._l,{type:'v',c:a.map(a=>(a.type='btn',a.filly=1,a.width=32,a.r=1,a))}]},c&&c.push.apply(c,this._l.c[1].c)}if(process.env.HWVERSION==2){function a(b,c){b.cb&&c.x>=b.x&&c.y>=b.y&&c.x<=b.x+b.w&&c.y<=b.y+b.h&&(c.type==2&&b.cbl?b.cbl(c):b.cb&&b.cb(c)),b.c&&b.c.forEach(b=>a(b,c))}Bangle.touchHandler=(c,b)=>a(this._l,b),Bangle.on('touch',Bangle.touchHandler)}var h=this;e(this._l),this.updateNeeded=!0}function prepareLazyRender(a,h,b,i,c){var d=a.bgCol==null?c:g.toColor(a.bgCol);if(d!=c||a.type=='txt'||a.type=='btn'||a.type=='img'||a.type=='custom'){var e=a.c;delete a.c;var f='H'+E.CRC32(E.toJS(a));if(e&&(a.c=e),!delete h[f]){var j=i[f]=[a.x,a.y,a.x+a.w-1,a.y+a.h-1];j.bg=c==null?g.theme.bg:c,b&&(b.push(a),b=null)}}if(a.c)for(var k of a.c)prepareLazyRender(k,h,b,i,d)}Layout.prototype.remove=function(a){Bangle.btnWatches&&(Bangle.btnWatches.forEach(clearWatch),delete Bangle.btnWatches),Bangle.touchHandler&&(Bangle.removeListener('touch',Bangle.touchHandler),delete Bangle.touchHandler)},Layout.prototype.render=function(b){function c(a){"ram";g.reset(),a.col!==undefined&&g.setColor(a.col),a.bgCol!==undefined&&g.setBgColor(a.bgCol).clearRect(a.x,a.y,a.x+a.w-1,a.y+a.h-1),f[a.type](a)}b||(b=this._l),this.updateNeeded&&this.update();var f={'':function(){},txt:function(a){if(a.wrap){g.setFont(a.font).setFontAlign(0,-1);var b=g.wrapString(a.label,a.w),c=a.y+(a.h-g.getFontHeight()*b.length>>1);b.forEach((b,d)=>g.drawString(b,a.x+(a.w>>1),c+g.getFontHeight()*d))}else g.setFont(a.font).setFontAlign(0,0,a.r).drawString(a.label,a.x+(a.w>>1),a.y+(a.h>>1))},btn:function(a){var b=a.x+(0|a.pad),c=a.y+(0|a.pad),d=a.w-(a.pad<<1),e=a.h-(a.pad<<1),f=[b,c+4,b+4,c,b+d-5,c,b+d-1,c+4,b+d-1,c+e-5,b+d-5,c+e-1,b+4,c+e-1,b,c+e-5,b,c+4],h=a.selected?g.theme.bgH:g.theme.bg2;g.setColor(h).fillPoly(f).setColor(a.selected?g.theme.fgH:g.theme.fg2).drawPoly(f),a.col!==undefined&&g.setColor(a.col),a.src?g.setBgColor(h).drawImage('f'==(typeof a.src)[0]?a.src():a.src,a.x+10+(0|a.pad),a.y+8+(0|a.pad)):g.setFont('6x8',2).setFontAlign(0,0,a.r).drawString(a.label,a.x+a.w/2,a.y+a.h/2)},img:function(a){g.drawImage('f'==(typeof a.src)[0]?a.src():a.src,a.x+(0|a.pad),a.y+(0|a.pad),a.scale?{scale:a.scale}:undefined)},custom:function(a){a.render(a)},h:function(a){a.c.forEach(c)},v:function(a){a.c.forEach(c)}};if(this.lazy){this.rects||(this.rects={});var a=this.rects.clone(),d=[];prepareLazyRender(b,a,d,this.rects,null);for(var h in a)delete this.rects[h];var i=Object.keys(a).map(b=>a[b]).reverse();for(var e of i)g.setBgColor(e.bg).clearRect.apply(g,e);d.forEach(c)}else c(b)},Layout.prototype.forgetLazyState=function(){this.rects={}},Layout.prototype.layout=function(a){switch(a.type){case'h':{var b=a.x+(0|a.pad),h=0,d=a.c&&a.c.reduce((a,b)=>a+(0|b.fillx),0);d||(b+=a.w-a._w>>1,d=1);var e=b;a.c.forEach(c=>{c.x=0|e,b+=c._w,h+=0|c.fillx,e=b+Math.floor(h*(a.w-a._w)/d),c.w=0|e-c.x,c.h=0|(c.filly?a.h-(a.pad<<1):c._h),c.y=0|a.y+(0|a.pad)+((1+(0|c.valign))*(a.h-(a.pad<<1)-c.h)>>1),c.c&&this.layout(c)});break}case'v':{var c=a.y+(0|a.pad),i=0,f=a.c&&a.c.reduce((a,b)=>a+(0|b.filly),0);f||(c+=a.h-a._h>>1,f=1);var g=c;a.c.forEach(b=>{b.y=0|g,c+=b._h,i+=0|b.filly,g=c+Math.floor(i*(a.h-a._h)/f),b.h=0|g-b.y,b.w=0|(b.fillx?a.w-(a.pad<<1):b._w),b.x=0|a.x+(0|a.pad)+((1+(0|b.halign))*(a.w-(a.pad<<1)-b.w)>>1),b.c&&this.layout(b)});break}}},Layout.prototype.debug=function(a,b){a||(a=this._l),b=b||1,g.setColor(b&1,b&2,b&4).drawRect(a.x+b-1,a.y+b-1,a.x+a.w-b,a.y+a.h-b),a.pad&&g.drawRect(a.x+a.pad-1,a.y+a.pad-1,a.x+a.w-a.pad,a.y+a.h-a.pad),b++,a.c&&a.c.forEach(a=>this.debug(a,b))},Layout.prototype.update=function(){function b(a){"ram";if(c[a.type](a),a.r&1){var b=a._w;a._w=a._h,a._h=b}a._w=0|Math.max(a._w+(a.pad<<1),0|a.width),a._h=0|Math.max(a._h+(a.pad<<1),0|a.height)}delete this.updateNeeded;var c={txt:function(a){if(a.font.endsWith('%')&&(a.font='Vector'+Math.round(g.getHeight()*a.font.slice(0,-1)/100)),a.wrap)a._h=a._w=0;else{var b=g.setFont(a.font).stringMetrics(a.label);a._w=b.width,a._h=b.height}},btn:function(a){var b=a.src?g.imageMetrics('f'==(typeof a.src)[0]?a.src():a.src):g.setFont('6x8',2).stringMetrics(a.label);a._h=16+b.height,a._w=20+b.width},img:function(a){var b=g.imageMetrics('f'==(typeof a.src)[0]?a.src():a.src),c=a.scale||1;a._w=b.width*c,a._h=b.height*c},'':function(a){a._w=0,a._h=0},custom:function(a){a._w=0,a._h=0},h:function(a){a.c.forEach(b),a._h=a.c.reduce((a,b)=>Math.max(a,b._h),0),a._w=a.c.reduce((a,b)=>a+b._w,0),a.fillx==null&&a.c.some(a=>a.fillx)&&(a.fillx=1),a.filly==null&&a.c.some(a=>a.filly)&&(a.filly=1)},v:function(a){a.c.forEach(b),a._h=a.c.reduce((a,b)=>a+b._h,0),a._w=a.c.reduce((a,b)=>Math.max(a,b._w),0),a.fillx==null&&a.c.some(a=>a.fillx)&&(a.fillx=1),a.filly==null&&a.c.some(a=>a.filly)&&(a.filly=1)}},a=this._l;b(a),a.fillx||a.filly?(a.w=Bangle.appRect.w,a.h=Bangle.appRect.h,a.x=Bangle.appRect.x,a.y=Bangle.appRect.y):(a.w=a._w,a.h=a._h,a.x=Bangle.appRect.w-a.w>>1,a.y=Bangle.appRect.y+(Bangle.appRect.h-a.h>>1)),this.layout(a)},Layout.prototype.clear=function(a){a||(a=this._l),g.reset(),a.bgCol!==undefined&&g.setBgColor(a.bgCol),g.clearRect(a.x,a.y,a.x+a.w-1,a.y+a.h-1)},exports=Layout}); + +const secondsToTime = (s) => new Object({h:Math.floor((s/3600) % 24), m:Math.floor((s/60) % 60), s:Math.floor(s % 60)}); +const clamp = (num, min, max) => Math.min(Math.max(num, min), max); +function formatTime(s) { + var t = secondsToTime(s); + if (t.h) { + return t.h + ':' + ("0" + t.m).substr(-2) + ':' + ("0" + t.s).substr(-2); + } else { + return t.m + ':' + ("0" + t.s).substr(-2); + } +} + +Bangle.loadWidgets(); +Bangle.drawWidgets(); + +var Layout = require("Layout"); +var seconds = 5 * 60; +var drawTimeout; +var timerLayout; +var timePickerLayout; +var imgArrowDown = Graphics.createImage(` +xxx xxx +xxx xxx + xxx xxx + xxx xxx + xxxxx + xxxxx + xxx + xxx + x +`); +var imgArrowUp = Graphics.createImage(` + x + xxx + xxx + xxxxx + xxxxx + xxx xxx + xxx xxx +xxx xxx +xxx xxx +`); + +function onDrag(event) { + var scale = 1; + if (event.x < timePickerLayout.hours.w) { + scale = 3600; + } else if (event.x > timePickerLayout.mins.x && event.x < timePickerLayout.secs.x) { + scale = 60; + } + seconds -= Math.round(event.dy/5) * scale; + updateTimePicker(); +} + +function onTouch(button, xy) { + var touchMidpoint = timePickerLayout.hours.y + timePickerLayout.hours.h/2; + var diff = 0; + if (xy.y > 24 && xy.y < touchMidpoint - 10) { + diff = 1; + } else if (xy.y > touchMidpoint + 10 && xy.y < timePickerLayout.btnStart.y) { + diff = -1; + } else if (xy.y > timePickerLayout.btnStart.y) { + runTimer(); + return; + } + if (xy.x < timePickerLayout.hours.w) { + diff *= 3600; + } else if (xy.x > timePickerLayout.mins.x && xy.x < timePickerLayout.secs.x) { + diff *= 60; + } + seconds += diff; + updateTimePicker(); +} + +function updateTimePicker() { + seconds = clamp(seconds, 0, 24 * 3600 - 1); + var set_time = secondsToTime(seconds); + updateLayoutField(timePickerLayout, 'hours', set_time.h); + updateLayoutField(timePickerLayout, 'mins', set_time.m); + updateLayoutField(timePickerLayout, 'secs', set_time.s); +} + +function updateLayoutField(layout, field, value) { + layout.clear(layout[field]); + layout[field].label = value; + layout.render(layout[field]); +} + +function updateTimer() { + var timeToNext = require("sched").getTimeToAlarm(require("sched").getAlarm("simpletimer")); + var d = new Date(); + updateLayoutField(timerLayout, 'timer', formatTime(timeToNext / 1000)); + updateLayoutField(timerLayout, 'time', require("locale").time(d,1)); + queueDraw(1000); +} + +function queueDraw(millisecs) { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function() { + drawTimeout = undefined; + updateTimer(); + }, millisecs - (Date.now() % millisecs)); +} + +function timerStop() { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = undefined; + seconds = require("sched").getTimeToAlarm(require("sched").getAlarm("simpletimer")) / 1000; + require("sched").setAlarm("simpletimer", undefined); + require("sched").reload(); + runTimePicker(); +} + +var timePickerLayoutCode = { + type:"v", c: [ + {type:undefined, height:2}, + //{type:"txt", font:"15%", label:"TIMER", id:"title"}, + {type:"h", c: [ + {type:"v", c: [ + {type:"txt", font:"6x8", label:/*LANG*/"Hours", col:g.theme.fg2}, + {type:"img", pad:8, src:imgArrowUp, col:g.theme.fg2}, + {type:"txt", font:"20%", label:"0", id:"hours", filly:1, fillx:1}, + {type:"img", pad:8, src:imgArrowDown, col:g.theme.fg2} + ]}, + {type:"v", c: [ + {type:"txt", font:"6x8", label:/*LANG*/"Minutes", col:g.theme.fg2}, + {type:"img", pad:8, src:imgArrowUp, col:g.theme.fg2}, + {type:"txt", font:"20%", label:"0", id:"mins", filly:1, fillx:1}, + {type:"img", pad:8, src:imgArrowDown, col:g.theme.fg2} + ]}, + {type:"v", c: [ + {type:"txt", font:"6x8", label:/*LANG*/"Seconds", col:g.theme.fg2}, + {type:"img", pad:8, src:imgArrowUp, col:g.theme.fg2}, + {type:"txt", font:"20%", label:"0", id:"secs", filly:1, fillx:1}, + {type:"img", pad:8, src:imgArrowDown, col:g.theme.fg2} + ]}, + ]}, + {type:"btn", font:"12x20", label:"Start", id:"btnStart", fillx:1 } + ], filly:1 +}; + +var timerLayoutCode = { + type:"v", c: [ + {type:undefined, height:8}, + {type:"txt", font:"6x8", label:/*LANG*/"Timer", id:"title", col:g.theme.fg2}, + {type:"txt", font:"22%", label:"0:00", id:"timer", fillx:1, filly:1 }, + {type:"h", c: [ + {type:"txt", font:"6x8", pad:8, label:/*LANG*/"Time Now:", halign:-1, col:g.theme.fg2}, + {type:"txt", font:"6x8", label:"00:00", id:"time", halign:1, col:g.theme.fg2}, + ]}, + {type:"btn", font:"12x20", label:"Stop", cb: l=>timerStop(), fillx:1 } + ], filly:1 +}; + +function runTimePicker() { + g.clearRect(Bangle.appRect); + timePickerLayout = new Layout(timePickerLayoutCode); + Bangle.setUI({ + mode : "custom", + touch : function(n,e) {onTouch(n,e);}, + drag : function(e) {onDrag(e);}, + btn : function(n) {runTimer();}, + }); + timePickerLayout.render(); + updateTimePicker(); +} + +function runTimer() { + require("sched").setAlarm("simpletimer", { + //msg : "Mr Flibble is very angry!", + vibrate : ".-.-", + hidden: true, + timer : seconds * 1000 + }); + require("sched").reload(); + g.clearRect(Bangle.appRect); + timerLayout = new Layout(timerLayoutCode); + timerLayout.render(); + updateTimer(); +} + +var timeToNext = require("sched").getTimeToAlarm(require("sched").getAlarm("simpletimer")); +if (timeToNext != undefined) { + g.clearRect(Bangle.appRect); + timerLayout = new Layout(timerLayoutCode); + timerLayout.render(); + updateTimer(); +} else { + runTimePicker(); +} diff --git a/apps/timersimple/timersimple.icon.js b/apps/timersimple/timersimple.icon.js new file mode 100644 index 000000000..cd40303a0 --- /dev/null +++ b/apps/timersimple/timersimple.icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwcBkmSpIC/ARf//9JkQRMCAIRBAwIRKv4RFpARIz4QCCIdJiREJAAgJCCI0nCI3+BgOJCIs/CI3/9MkyJoIAAxuGp4RJ8gRQ/mSogRDu4RJNwKSEqXfCJPSCImSrYRJ+SkEyVfCJP6CIo1B4wRHUgIREA4MAj4SHCIeUCIP//EAt4RHkQRF//ggIDB+EHCJf/wEAAAQRM/0CoAmCCJf/4VDI5pcCNwoRKNZ4RMUIQRLYowAIYozpRrYRJ+QREqVLCJPSpGSCIdJv5GIyQREpVJfA///mSogRDpNJloRH8mSBwQRDku/CIwMBCIspkmXCAvpkmRCIslAYKkETwMkxIRFkmkyVLNwYJCBwgCDAwyeEAQqSBAwiMEAQwGFBxACDygDBkQOKAX4CD")) \ No newline at end of file From ed71d95f651dc86450875b5120f3ae0941d3cce1 Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Wed, 27 Apr 2022 20:44:06 +0100 Subject: [PATCH 02/34] Added screenshots --- apps/timersimple/timersimple-scr1.png | Bin 0 -> 3232 bytes apps/timersimple/timersimple-scr2.png | Bin 0 -> 3017 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/timersimple/timersimple-scr1.png create mode 100644 apps/timersimple/timersimple-scr2.png diff --git a/apps/timersimple/timersimple-scr1.png b/apps/timersimple/timersimple-scr1.png new file mode 100644 index 0000000000000000000000000000000000000000..5556f8ecc0f2b0c0e343e144f53b2a90741e55c3 GIT binary patch literal 3232 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 literal 0 HcmV?d00001 From 8cef58b110b8132b606265f109b2017698521ce6 Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Wed, 27 Apr 2022 20:45:30 +0100 Subject: [PATCH 03/34] Rename Readme to README --- apps/timersimple/{Readme.md => README.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename apps/timersimple/{Readme.md => README.md} (100%) diff --git a/apps/timersimple/Readme.md b/apps/timersimple/README.md similarity index 100% rename from apps/timersimple/Readme.md rename to apps/timersimple/README.md From bb0aa17d4a11a09dff40c090de9d263741942596 Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Thu, 28 Apr 2022 12:08:06 +0100 Subject: [PATCH 04/34] Changes after feedback Feedback in forum here: http://forum.espruino.com/conversations/375342 --- apps/timersimple/timersimple.app.js | 53 ++++++++++++++--------------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/apps/timersimple/timersimple.app.js b/apps/timersimple/timersimple.app.js index ddc6bb4c1..8bbe66e83 100644 --- a/apps/timersimple/timersimple.app.js +++ b/apps/timersimple/timersimple.app.js @@ -1,5 +1,3 @@ -Modules.addCached("Layout",function(){function Layout(d,b){function e(a){a.id&&(h[a.id]=a),a.type||(a.type=''),a.c&&a.c.forEach(e)}this._l=this.l=d,this.physBtns=process.env.HWVERSION==2?1:3,b=b||{},this.lazy=b.lazy||!1;var c,f;if(Bangle.setUI(),process.env.HWVERSION!=2){c=[];function a(b){b.type=='btn'&&c.push(b),b.c&&b.c.forEach(a)}a(d),c.length&&(this.physBtns=0,this.buttons=c,this.selectedButton=-1,Bangle.setUI({mode:'updown',back:b.back},c=>{var a=this.selectedButton,b=this.buttons.length;if(c===undefined&&this.buttons[a])return this.buttons[a].cb();this.buttons[a]&&(delete this.buttons[a].selected,this.render(this.buttons[a])),a=(a+b+c)%b,this.buttons[a]&&(this.buttons[a].selected=1,this.render(this.buttons[a])),this.selectedButton=a}),f=!0)}if(b.back&&!f&&Bangle.setUI({mode:'custom',back:b.back}),b.btns){var a=b.btns;if(this.b=a,this.physBtns>=a.length){function b(a,b){b.time-b.lastTime>.75&&this.b[a].cbl?this.b[a].cbl(b):this.b[a].cb&&this.b[a].cb(b)}let c=Math.floor(Bangle.appRect.h/this.physBtns);Bangle.btnWatches&&Bangle.btnWatches.forEach(clearWatch),Bangle.btnWatches=[],this.physBtns>2&&a.length==1&&a.unshift({label:''});while(this.physBtns>a.length)a.push({label:''});a[0]&&Bangle.btnWatches.push(setWatch(b.bind(this,0),BTN1,{repeat:!0,edge:-1})),a[1]&&Bangle.btnWatches.push(setWatch(b.bind(this,1),BTN2,{repeat:!0,edge:-1})),a[2]&&Bangle.btnWatches.push(setWatch(b.bind(this,2),BTN3,{repeat:!0,edge:-1})),this._l.width=g.getWidth()-8,this._l={type:'h',filly:1,c:[this._l,{type:'v',pad:1,filly:1,c:a.map(a=>(a.type='txt',a.font='6x8',a.height=c,a.r=1,a))}]}}else this._l.width=g.getWidth()-32,this._l={type:'h',c:[this._l,{type:'v',c:a.map(a=>(a.type='btn',a.filly=1,a.width=32,a.r=1,a))}]},c&&c.push.apply(c,this._l.c[1].c)}if(process.env.HWVERSION==2){function a(b,c){b.cb&&c.x>=b.x&&c.y>=b.y&&c.x<=b.x+b.w&&c.y<=b.y+b.h&&(c.type==2&&b.cbl?b.cbl(c):b.cb&&b.cb(c)),b.c&&b.c.forEach(b=>a(b,c))}Bangle.touchHandler=(c,b)=>a(this._l,b),Bangle.on('touch',Bangle.touchHandler)}var h=this;e(this._l),this.updateNeeded=!0}function prepareLazyRender(a,h,b,i,c){var d=a.bgCol==null?c:g.toColor(a.bgCol);if(d!=c||a.type=='txt'||a.type=='btn'||a.type=='img'||a.type=='custom'){var e=a.c;delete a.c;var f='H'+E.CRC32(E.toJS(a));if(e&&(a.c=e),!delete h[f]){var j=i[f]=[a.x,a.y,a.x+a.w-1,a.y+a.h-1];j.bg=c==null?g.theme.bg:c,b&&(b.push(a),b=null)}}if(a.c)for(var k of a.c)prepareLazyRender(k,h,b,i,d)}Layout.prototype.remove=function(a){Bangle.btnWatches&&(Bangle.btnWatches.forEach(clearWatch),delete Bangle.btnWatches),Bangle.touchHandler&&(Bangle.removeListener('touch',Bangle.touchHandler),delete Bangle.touchHandler)},Layout.prototype.render=function(b){function c(a){"ram";g.reset(),a.col!==undefined&&g.setColor(a.col),a.bgCol!==undefined&&g.setBgColor(a.bgCol).clearRect(a.x,a.y,a.x+a.w-1,a.y+a.h-1),f[a.type](a)}b||(b=this._l),this.updateNeeded&&this.update();var f={'':function(){},txt:function(a){if(a.wrap){g.setFont(a.font).setFontAlign(0,-1);var b=g.wrapString(a.label,a.w),c=a.y+(a.h-g.getFontHeight()*b.length>>1);b.forEach((b,d)=>g.drawString(b,a.x+(a.w>>1),c+g.getFontHeight()*d))}else g.setFont(a.font).setFontAlign(0,0,a.r).drawString(a.label,a.x+(a.w>>1),a.y+(a.h>>1))},btn:function(a){var b=a.x+(0|a.pad),c=a.y+(0|a.pad),d=a.w-(a.pad<<1),e=a.h-(a.pad<<1),f=[b,c+4,b+4,c,b+d-5,c,b+d-1,c+4,b+d-1,c+e-5,b+d-5,c+e-1,b+4,c+e-1,b,c+e-5,b,c+4],h=a.selected?g.theme.bgH:g.theme.bg2;g.setColor(h).fillPoly(f).setColor(a.selected?g.theme.fgH:g.theme.fg2).drawPoly(f),a.col!==undefined&&g.setColor(a.col),a.src?g.setBgColor(h).drawImage('f'==(typeof a.src)[0]?a.src():a.src,a.x+10+(0|a.pad),a.y+8+(0|a.pad)):g.setFont('6x8',2).setFontAlign(0,0,a.r).drawString(a.label,a.x+a.w/2,a.y+a.h/2)},img:function(a){g.drawImage('f'==(typeof a.src)[0]?a.src():a.src,a.x+(0|a.pad),a.y+(0|a.pad),a.scale?{scale:a.scale}:undefined)},custom:function(a){a.render(a)},h:function(a){a.c.forEach(c)},v:function(a){a.c.forEach(c)}};if(this.lazy){this.rects||(this.rects={});var a=this.rects.clone(),d=[];prepareLazyRender(b,a,d,this.rects,null);for(var h in a)delete this.rects[h];var i=Object.keys(a).map(b=>a[b]).reverse();for(var e of i)g.setBgColor(e.bg).clearRect.apply(g,e);d.forEach(c)}else c(b)},Layout.prototype.forgetLazyState=function(){this.rects={}},Layout.prototype.layout=function(a){switch(a.type){case'h':{var b=a.x+(0|a.pad),h=0,d=a.c&&a.c.reduce((a,b)=>a+(0|b.fillx),0);d||(b+=a.w-a._w>>1,d=1);var e=b;a.c.forEach(c=>{c.x=0|e,b+=c._w,h+=0|c.fillx,e=b+Math.floor(h*(a.w-a._w)/d),c.w=0|e-c.x,c.h=0|(c.filly?a.h-(a.pad<<1):c._h),c.y=0|a.y+(0|a.pad)+((1+(0|c.valign))*(a.h-(a.pad<<1)-c.h)>>1),c.c&&this.layout(c)});break}case'v':{var c=a.y+(0|a.pad),i=0,f=a.c&&a.c.reduce((a,b)=>a+(0|b.filly),0);f||(c+=a.h-a._h>>1,f=1);var g=c;a.c.forEach(b=>{b.y=0|g,c+=b._h,i+=0|b.filly,g=c+Math.floor(i*(a.h-a._h)/f),b.h=0|g-b.y,b.w=0|(b.fillx?a.w-(a.pad<<1):b._w),b.x=0|a.x+(0|a.pad)+((1+(0|b.halign))*(a.w-(a.pad<<1)-b.w)>>1),b.c&&this.layout(b)});break}}},Layout.prototype.debug=function(a,b){a||(a=this._l),b=b||1,g.setColor(b&1,b&2,b&4).drawRect(a.x+b-1,a.y+b-1,a.x+a.w-b,a.y+a.h-b),a.pad&&g.drawRect(a.x+a.pad-1,a.y+a.pad-1,a.x+a.w-a.pad,a.y+a.h-a.pad),b++,a.c&&a.c.forEach(a=>this.debug(a,b))},Layout.prototype.update=function(){function b(a){"ram";if(c[a.type](a),a.r&1){var b=a._w;a._w=a._h,a._h=b}a._w=0|Math.max(a._w+(a.pad<<1),0|a.width),a._h=0|Math.max(a._h+(a.pad<<1),0|a.height)}delete this.updateNeeded;var c={txt:function(a){if(a.font.endsWith('%')&&(a.font='Vector'+Math.round(g.getHeight()*a.font.slice(0,-1)/100)),a.wrap)a._h=a._w=0;else{var b=g.setFont(a.font).stringMetrics(a.label);a._w=b.width,a._h=b.height}},btn:function(a){var b=a.src?g.imageMetrics('f'==(typeof a.src)[0]?a.src():a.src):g.setFont('6x8',2).stringMetrics(a.label);a._h=16+b.height,a._w=20+b.width},img:function(a){var b=g.imageMetrics('f'==(typeof a.src)[0]?a.src():a.src),c=a.scale||1;a._w=b.width*c,a._h=b.height*c},'':function(a){a._w=0,a._h=0},custom:function(a){a._w=0,a._h=0},h:function(a){a.c.forEach(b),a._h=a.c.reduce((a,b)=>Math.max(a,b._h),0),a._w=a.c.reduce((a,b)=>a+b._w,0),a.fillx==null&&a.c.some(a=>a.fillx)&&(a.fillx=1),a.filly==null&&a.c.some(a=>a.filly)&&(a.filly=1)},v:function(a){a.c.forEach(b),a._h=a.c.reduce((a,b)=>a+b._h,0),a._w=a.c.reduce((a,b)=>Math.max(a,b._w),0),a.fillx==null&&a.c.some(a=>a.fillx)&&(a.fillx=1),a.filly==null&&a.c.some(a=>a.filly)&&(a.filly=1)}},a=this._l;b(a),a.fillx||a.filly?(a.w=Bangle.appRect.w,a.h=Bangle.appRect.h,a.x=Bangle.appRect.x,a.y=Bangle.appRect.y):(a.w=a._w,a.h=a._h,a.x=Bangle.appRect.w-a.w>>1,a.y=Bangle.appRect.y+(Bangle.appRect.h-a.h>>1)),this.layout(a)},Layout.prototype.clear=function(a){a||(a=this._l),g.reset(),a.bgCol!==undefined&&g.setBgColor(a.bgCol),g.clearRect(a.x,a.y,a.x+a.w-1,a.y+a.h-1)},exports=Layout}); - const secondsToTime = (s) => new Object({h:Math.floor((s/3600) % 24), m:Math.floor((s/60) % 60), s:Math.floor(s % 60)}); const clamp = (num, min, max) => Math.min(Math.max(num, min), max); function formatTime(s) { @@ -10,12 +8,13 @@ function formatTime(s) { return t.m + ':' + ("0" + t.s).substr(-2); } } +const timerID = "simpletimer"; Bangle.loadWidgets(); Bangle.drawWidgets(); var Layout = require("Layout"); -var seconds = 5 * 60; +var seconds = 5 * 60; // Default to 5 minutes var drawTimeout; var timerLayout; var timePickerLayout; @@ -42,15 +41,17 @@ xxx xxx xxx xxx `); +const imgPause = atob("GBiBAP+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B/w=="); +const imgPlay = atob("GBiBAIAAAOAAAPgAAP4AAP+AAP/gAP/4AP/+AP//gP//4P//+P///v///v//+P//4P//gP/+AP/4AP/gAP+AAP4AAPgAAOAAAIAAAA=="); + function onDrag(event) { - var scale = 1; + var diff = -Math.round(event.dy/5); if (event.x < timePickerLayout.hours.w) { - scale = 3600; + diff *= 3600; } else if (event.x > timePickerLayout.mins.x && event.x < timePickerLayout.secs.x) { - scale = 60; + diff *= 60; } - seconds -= Math.round(event.dy/5) * scale; - updateTimePicker(); + updateTimePicker(diff); } function onTouch(button, xy) { @@ -69,12 +70,11 @@ function onTouch(button, xy) { } else if (xy.x > timePickerLayout.mins.x && xy.x < timePickerLayout.secs.x) { diff *= 60; } - seconds += diff; - updateTimePicker(); + updateTimePicker(diff); } -function updateTimePicker() { - seconds = clamp(seconds, 0, 24 * 3600 - 1); +function updateTimePicker(diff) { + seconds = clamp(seconds + (diff || 0), 0, 24 * 3600 - 1); var set_time = secondsToTime(seconds); updateLayoutField(timePickerLayout, 'hours', set_time.h); updateLayoutField(timePickerLayout, 'mins', set_time.m); @@ -88,10 +88,10 @@ function updateLayoutField(layout, field, value) { } function updateTimer() { - var timeToNext = require("sched").getTimeToAlarm(require("sched").getAlarm("simpletimer")); - var d = new Date(); + var timeToNext = require("sched").getTimeToAlarm(require("sched").getAlarm(timerID)); updateLayoutField(timerLayout, 'timer', formatTime(timeToNext / 1000)); - updateLayoutField(timerLayout, 'time', require("locale").time(d,1)); + //var d = new Date(); + //updateLayoutField(timerLayout, 'time', require("locale").time(d,1)); queueDraw(1000); } @@ -106,8 +106,8 @@ function queueDraw(millisecs) { function timerStop() { if (drawTimeout) clearTimeout(drawTimeout); drawTimeout = undefined; - seconds = require("sched").getTimeToAlarm(require("sched").getAlarm("simpletimer")) / 1000; - require("sched").setAlarm("simpletimer", undefined); + seconds = require("sched").getTimeToAlarm(require("sched").getAlarm(timerID)) / 1000; + require("sched").setAlarm(timerID, undefined); require("sched").reload(); runTimePicker(); } @@ -136,20 +136,20 @@ var timePickerLayoutCode = { {type:"img", pad:8, src:imgArrowDown, col:g.theme.fg2} ]}, ]}, - {type:"btn", font:"12x20", label:"Start", id:"btnStart", fillx:1 } + {type:"btn", src:imgPlay, id:"btnStart", fillx:1 } ], filly:1 }; var timerLayoutCode = { type:"v", c: [ {type:undefined, height:8}, - {type:"txt", font:"6x8", label:/*LANG*/"Timer", id:"title", col:g.theme.fg2}, + //{type:"txt", font:"6x8", label:/*LANG*/"Timer", id:"title", col:g.theme.fg2}, {type:"txt", font:"22%", label:"0:00", id:"timer", fillx:1, filly:1 }, - {type:"h", c: [ - {type:"txt", font:"6x8", pad:8, label:/*LANG*/"Time Now:", halign:-1, col:g.theme.fg2}, - {type:"txt", font:"6x8", label:"00:00", id:"time", halign:1, col:g.theme.fg2}, - ]}, - {type:"btn", font:"12x20", label:"Stop", cb: l=>timerStop(), fillx:1 } + //{type:"h", c: [ + // {type:"txt", font:"6x8", pad:8, label:/*LANG*/"Time Now:", halign:-1, col:g.theme.fg2}, + // {type:"txt", font:"6x8", label:"00:00", id:"time", halign:1, col:g.theme.fg2}, + //]}, + {type:"btn", src:imgPause, cb: l=>timerStop(), fillx:1 } ], filly:1 }; @@ -167,8 +167,7 @@ function runTimePicker() { } function runTimer() { - require("sched").setAlarm("simpletimer", { - //msg : "Mr Flibble is very angry!", + require("sched").setAlarm(timerID, { vibrate : ".-.-", hidden: true, timer : seconds * 1000 @@ -180,7 +179,7 @@ function runTimer() { updateTimer(); } -var timeToNext = require("sched").getTimeToAlarm(require("sched").getAlarm("simpletimer")); +var timeToNext = require("sched").getTimeToAlarm(require("sched").getAlarm(timerID)); if (timeToNext != undefined) { g.clearRect(Bangle.appRect); timerLayout = new Layout(timerLayoutCode); From 7f2af3c892862f79d47c54384d94d41491de285c Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Fri, 29 Apr 2022 09:55:31 +0100 Subject: [PATCH 05/34] Update Layout.js --- modules/Layout.js | 71 ++++++++++++++++++----------------------------- 1 file changed, 27 insertions(+), 44 deletions(-) diff --git a/modules/Layout.js b/modules/Layout.js index 0bfbc28ad..8784e1a8d 100644 --- a/modules/Layout.js +++ b/modules/Layout.js @@ -1,18 +1,13 @@ /* Copyright (c) 2022 Bangle.js contributors. See the file LICENSE for copying permission. */ /* - Take a look at README.md for hints on developing with this library. - Usage: - ``` var Layout = require("Layout"); var layout = new Layout( layoutObject, options ) layout.render(optionalObject); ``` - For example: - ``` var Layout = require("Layout"); var layout = new Layout( { @@ -24,10 +19,7 @@ var layout = new Layout( { g.clear(); layout.render(); ``` - - layoutObject has: - * A `type` field of: * `undefined` - blank, can be used for padding * `"txt"` - a text label, with value `label` and `r` for text rotation. 'font' is required @@ -51,34 +43,25 @@ layoutObject has: * A `fillx` int to choose if the object should fill available space in x. 0=no, 1=yes, 2=2x more space * A `filly` int to choose if the object should fill available space in y. 0=no, 1=yes, 2=2x more space * `width` and `height` fields to optionally specify minimum size - options is an object containing: - * `lazy` - a boolean specifying whether to enable automatic lazy rendering * `btns` - array of objects containing: * `label` - the text on the button * `cb` - a callback function * `cbl` - a callback function for long presses * `back` - a callback function, passed as `back` into Bangle.setUI - If automatic lazy rendering is enabled, calls to `layout.render()` will attempt to automatically determine what objects have changed or moved, clear their previous locations, and re-render just those objects. - Once `layout.update()` is called, the following fields are added to each object: - * `x` and `y` for the top left position * `w` and `h` for the width and height * `_w` and `_h` for the **minimum** width and height - - Other functions: - * `layout.update()` - update positions of everything if contents have changed * `layout.debug(obj)` - draw outlines for objects on screen * `layout.clear(obj)` - clear the given object (you can also just specify `bgCol` to clear before each render) * `layout.forgetLazyState()` - if lazy rendering is enabled, makes the next call to `render()` perform a full re-render - */ @@ -138,15 +121,15 @@ function Layout(layout, options) { } // enough physical buttons let btnHeight = Math.floor(Bangle.appRect.h / this.physBtns); - if (Bangle.btnWatch) Bangle.btnWatch.forEach(clearWatch); - Bangle.btnWatch = []; + if (Bangle.btnWatches) Bangle.btnWatches.forEach(clearWatch); + Bangle.btnWatches = []; if (this.physBtns > 2 && buttons.length==1) buttons.unshift({label:""}); // pad so if we have a button in the middle while (this.physBtns > buttons.length) buttons.push({label:""}); - if (buttons[0]) Bangle.btnWatch.push(setWatch(pressHandler.bind(this,0), BTN1, {repeat:true,edge:-1})); - if (buttons[1]) Bangle.btnWatch.push(setWatch(pressHandler.bind(this,1), BTN2, {repeat:true,edge:-1})); - if (buttons[2]) Bangle.btnWatch.push(setWatch(pressHandler.bind(this,2), BTN3, {repeat:true,edge:-1})); + if (buttons[0]) Bangle.btnWatches.push(setWatch(pressHandler.bind(this,0), BTN1, {repeat:true,edge:-1})); + if (buttons[1]) Bangle.btnWatches.push(setWatch(pressHandler.bind(this,1), BTN2, {repeat:true,edge:-1})); + if (buttons[2]) Bangle.btnWatches.push(setWatch(pressHandler.bind(this,2), BTN3, {repeat:true,edge:-1})); this._l.width = g.getWidth()-8; // text width this._l = {type:"h", filly:1, c: [ this._l, @@ -190,9 +173,9 @@ function Layout(layout, options) { } Layout.prototype.remove = function (l) { - if (Bangle.btnWatch) { - Bangle.btnWatch.forEach(clearWatch); - delete Bangle.btnWatch; + if (Bangle.btnWatches) { + Bangle.btnWatches.forEach(clearWatch); + delete Bangle.btnWatches; } if (Bangle.touchHandler) { Bangle.removeListener("touch",Bangle.touchHandler); @@ -237,34 +220,34 @@ Layout.prototype.render = function (l) { "":function(){}, "txt":function(l){ if (l.wrap) { - g.setFont(l.font).setFontAlign(0,-1); + g.setFont(l.font, l.scale||1).setFontAlign(0,-1); var lines = g.wrapString(l.label, l.w); var y = l.y+((l.h-g.getFontHeight()*lines.length)>>1); // TODO: on 2v11 we can just render in a single drawString call lines.forEach((line, i) => g.drawString(line, l.x+(l.w>>1), y+g.getFontHeight()*i)); } else { - g.setFont(l.font).setFontAlign(0,0,l.r).drawString(l.label, l.x+(l.w>>1), l.y+(l.h>>1)); + g.setFont(l.font, l.scale||1).setFontAlign(0,0,l.r).drawString(l.label, l.x+(l.w>>1), l.y+(l.h>>1)); } }, "btn":function(l){ var x = l.x+(0|l.pad), y = l.y+(0|l.pad), w = l.w-(l.pad<<1), h = l.h-(l.pad<<1); - var poly = [ - x,y+4, - x+4,y, - x+w-5,y, - x+w-1,y+4, - x+w-1,y+h-5, - x+w-5,y+h-1, - x+4,y+h-1, - x,y+h-5, - x,y+4 - ], bg = l.selected?g.theme.bgH:g.theme.bg2; - g.setColor(bg).fillPoly(poly).setColor(l.selected ? g.theme.fgH : g.theme.fg2).drawPoly(poly); + var bg = l.selected?g.theme.bgH:g.theme.bg2; + g.setColor(bg).fillRect(x, y, x+w, y+h, 4).setColor(l.selected ? g.theme.fgH : g.theme.fg2).drawRect(x, y, x+w, y+h, 4); if (l.col!==undefined) g.setColor(l.col); - if (l.src) g.setBgColor(bg).drawImage("function"==typeof l.src?l.src():l.src, l.x + 10 + (0|l.pad), l.y + 8 + (0|l.pad)); - else g.setFont("6x8",2).setFontAlign(0,0,l.r).drawString(l.label,l.x+l.w/2,l.y+l.h/2); + if (l.src) g.setBgColor(bg).drawImage( + "function"==typeof l.src?l.src():l.src, + l.x + l.w/2 + (0|l.pad), + l.y + l.h/2 + (0|l.pad), + {scale: l.scale ? l.scale : undefined, rotate: Math.PI*0.5*(l.r ? l.r : 0)} + ); + else g.setFont(l.font||"6x8", l.scale||2).setFontAlign(0,0,l.r).drawString(l.label,l.x+l.w/2,l.y+l.h/2); }, "img":function(l){ - g.drawImage("function"==typeof l.src?l.src():l.src, l.x + (0|l.pad), l.y + (0|l.pad), l.scale?{scale:l.scale}:undefined); + g.drawImage( + "function"==typeof l.src?l.src():l.src, + l.x + l.w/2 + (0|l.pad), + l.y + l.h/2 + (0|l.pad), + {scale: l.scale ? l.scale : undefined, rotate: Math.PI*0.5*(l.r ? l.r : 0)} + ); }, "custom":function(l){ l.render(l); },"h":function(l) { l.c.forEach(render); }, @@ -361,11 +344,11 @@ Layout.prototype.update = function() { if (l.wrap) { l._h = l._w = 0; } else { - var m = g.setFont(l.font).stringMetrics(l.label); + var m = g.setFont(l.font, l.scale||1).stringMetrics(l.label); l._w = m.width; l._h = m.height; } }, "btn": function(l) { - var m = l.src?g.imageMetrics("function"==typeof l.src?l.src():l.src):g.setFont("6x8",2).stringMetrics(l.label); + var m = l.src?g.imageMetrics("function"==typeof l.src?l.src():l.src):g.setFont(l.font||"6x8", l.scale||2).stringMetrics(l.label); l._h = 16 + m.height; l._w = 20 + m.width; }, "img": function(l) { From 826bc2973857a01e9f0288d4359768dfad2691dc Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Fri, 29 Apr 2022 10:16:42 +0100 Subject: [PATCH 06/34] Update Layout.js --- modules/Layout.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/modules/Layout.js b/modules/Layout.js index 8784e1a8d..39aab9dc8 100644 --- a/modules/Layout.js +++ b/modules/Layout.js @@ -22,17 +22,19 @@ layout.render(); layoutObject has: * A `type` field of: * `undefined` - blank, can be used for padding - * `"txt"` - a text label, with value `label` and `r` for text rotation. 'font' is required + * `"txt"` - a text label, with value `label`. 'font' is required * `"btn"` - a button, with value `label` and callback `cb` optional `src` specifies an image (like img) in which case label is ignored + Default font is `6x8`, scale 2. This can be overridden with the `font` or `scale` fields. * `"img"` - an image where `src` is an image, or a function which is called to return an image to draw. - optional `scale` specifies if image should be scaled up or not * `"custom"` - a custom block where `render(layoutObj)` is called to render * `"h"` - Horizontal layout, `c` is an array of more `layoutObject` * `"v"` - Vertical layout, `c` is an array of more `layoutObject` * A `id` field. If specified the object is added with this name to the returned `layout` object, so can be referenced as `layout.foo` * A `font` field, eg `6x8` or `30%` to use a percentage of screen height +* A `scale` field, eg `2` to set scale of an image or text +* A `r` field to set rotation of text or images. * A `wrap` field to enable line wrapping. Requires some combination of `width`/`height` and `fillx`/`filly` to be set. Not compatible with text rotation. * A `col` field, eg `#f00` for red @@ -232,20 +234,20 @@ Layout.prototype.render = function (l) { var x = l.x+(0|l.pad), y = l.y+(0|l.pad), w = l.w-(l.pad<<1), h = l.h-(l.pad<<1); var bg = l.selected?g.theme.bgH:g.theme.bg2; - g.setColor(bg).fillRect(x, y, x+w, y+h, 4).setColor(l.selected ? g.theme.fgH : g.theme.fg2).drawRect(x, y, x+w, y+h, 4); + g.setColor(bg).fillRect({x:x,y:y,x2:x+w,y2:y+h,r:4}).setColor(l.selected ? g.theme.fgH : g.theme.fg2).drawRect({x:x,y:y,x2:x+w,y2:y+h,r:4}); if (l.col!==undefined) g.setColor(l.col); if (l.src) g.setBgColor(bg).drawImage( "function"==typeof l.src?l.src():l.src, - l.x + l.w/2 + (0|l.pad), - l.y + l.h/2 + (0|l.pad), + l.x + (l.w + (0|l.pad))/2, + l.y + (l.h + (0|l.pad))/2, {scale: l.scale ? l.scale : undefined, rotate: Math.PI*0.5*(l.r ? l.r : 0)} ); else g.setFont(l.font||"6x8", l.scale||2).setFontAlign(0,0,l.r).drawString(l.label,l.x+l.w/2,l.y+l.h/2); }, "img":function(l){ g.drawImage( "function"==typeof l.src?l.src():l.src, - l.x + l.w/2 + (0|l.pad), - l.y + l.h/2 + (0|l.pad), + l.x + (l.w + (0|l.pad))/2, + l.y + (l.h + (0|l.pad))/2, {scale: l.scale ? l.scale : undefined, rotate: Math.PI*0.5*(l.r ? l.r : 0)} ); }, "custom":function(l){ From 1e4486861a672f13f5accf405862f6df0654502d Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Fri, 29 Apr 2022 10:26:44 +0100 Subject: [PATCH 07/34] Update Layout.js --- modules/Layout.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/modules/Layout.js b/modules/Layout.js index 39aab9dc8..230d488be 100644 --- a/modules/Layout.js +++ b/modules/Layout.js @@ -233,8 +233,18 @@ Layout.prototype.render = function (l) { }, "btn":function(l){ var x = l.x+(0|l.pad), y = l.y+(0|l.pad), w = l.w-(l.pad<<1), h = l.h-(l.pad<<1); - var bg = l.selected?g.theme.bgH:g.theme.bg2; - g.setColor(bg).fillRect({x:x,y:y,x2:x+w,y2:y+h,r:4}).setColor(l.selected ? g.theme.fgH : g.theme.fg2).drawRect({x:x,y:y,x2:x+w,y2:y+h,r:4}); + var poly = [ + x,y+4, + x+4,y, + x+w-5,y, + x+w-1,y+4, + x+w-1,y+h-5, + x+w-5,y+h-1, + x+4,y+h-1, + x,y+h-5, + x,y+4 + ], bg = l.selected?g.theme.bgH:g.theme.bg2; + g.setColor(bg).fillPoly(poly).setColor(l.selected ? g.theme.fgH : g.theme.fg2).drawPoly(poly); if (l.col!==undefined) g.setColor(l.col); if (l.src) g.setBgColor(bg).drawImage( "function"==typeof l.src?l.src():l.src, From fc1bd36ec217c2857abff529da886c1c474f47d0 Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Fri, 29 Apr 2022 11:16:48 +0100 Subject: [PATCH 08/34] Update Layout.js --- modules/Layout.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/modules/Layout.js b/modules/Layout.js index 230d488be..7e5dd4b62 100644 --- a/modules/Layout.js +++ b/modules/Layout.js @@ -231,6 +231,8 @@ Layout.prototype.render = function (l) { g.setFont(l.font, l.scale||1).setFontAlign(0,0,l.r).drawString(l.label, l.x+(l.w>>1), l.y+(l.h>>1)); } }, "btn":function(l){ + if (l.font && l.font.endsWith("%")) + l.font = "Vector"+Math.round(g.getHeight()*l.font.slice(0,-1)/100); var x = l.x+(0|l.pad), y = l.y+(0|l.pad), w = l.w-(l.pad<<1), h = l.h-(l.pad<<1); var poly = [ @@ -248,16 +250,16 @@ Layout.prototype.render = function (l) { if (l.col!==undefined) g.setColor(l.col); if (l.src) g.setBgColor(bg).drawImage( "function"==typeof l.src?l.src():l.src, - l.x + (l.w + (0|l.pad))/2, - l.y + (l.h + (0|l.pad))/2, + l.x + l.w/2, + l.y + l.h/2, {scale: l.scale ? l.scale : undefined, rotate: Math.PI*0.5*(l.r ? l.r : 0)} ); else g.setFont(l.font||"6x8", l.scale||2).setFontAlign(0,0,l.r).drawString(l.label,l.x+l.w/2,l.y+l.h/2); }, "img":function(l){ g.drawImage( "function"==typeof l.src?l.src():l.src, - l.x + (l.w + (0|l.pad))/2, - l.y + (l.h + (0|l.pad))/2, + l.x + l.w/2, + l.y + l.h/2, {scale: l.scale ? l.scale : undefined, rotate: Math.PI*0.5*(l.r ? l.r : 0)} ); }, "custom":function(l){ @@ -360,6 +362,8 @@ Layout.prototype.update = function() { l._w = m.width; l._h = m.height; } }, "btn": function(l) { + if (l.font && l.font.endsWith("%")) + l.font = "Vector"+Math.round(g.getHeight()*l.font.slice(0,-1)/100); var m = l.src?g.imageMetrics("function"==typeof l.src?l.src():l.src):g.setFont(l.font||"6x8", l.scale||2).stringMetrics(l.label); l._h = 16 + m.height; l._w = 20 + m.width; @@ -413,5 +417,3 @@ Layout.prototype.clear = function(l) { if (l.bgCol!==undefined) g.setBgColor(l.bgCol); g.clearRect(l.x,l.y,l.x+l.w-1,l.y+l.h-1); }; - -exports = Layout; From c69fe8e2c4191cdffcca236a45fed3590dced07b Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Fri, 29 Apr 2022 11:17:27 +0100 Subject: [PATCH 09/34] Update timersimple.app.js --- apps/timersimple/timersimple.app.js | 41 +++++++++++------------------ 1 file changed, 16 insertions(+), 25 deletions(-) diff --git a/apps/timersimple/timersimple.app.js b/apps/timersimple/timersimple.app.js index 8bbe66e83..ef53c1e72 100644 --- a/apps/timersimple/timersimple.app.js +++ b/apps/timersimple/timersimple.app.js @@ -13,23 +13,12 @@ const timerID = "simpletimer"; Bangle.loadWidgets(); Bangle.drawWidgets(); -var Layout = require("Layout"); +//var Layout = require("Layout"); var seconds = 5 * 60; // Default to 5 minutes var drawTimeout; var timerLayout; var timePickerLayout; -var imgArrowDown = Graphics.createImage(` -xxx xxx -xxx xxx - xxx xxx - xxx xxx - xxxxx - xxxxx - xxx - xxx - x -`); -var imgArrowUp = Graphics.createImage(` +var imgArrow = Graphics.createImage(` x xxx xxx @@ -117,26 +106,27 @@ var timePickerLayoutCode = { {type:undefined, height:2}, //{type:"txt", font:"15%", label:"TIMER", id:"title"}, {type:"h", c: [ - {type:"v", c: [ + {type:"v", width:g.getWidth()/3, c: [ {type:"txt", font:"6x8", label:/*LANG*/"Hours", col:g.theme.fg2}, - {type:"img", pad:8, src:imgArrowUp, col:g.theme.fg2}, - {type:"txt", font:"20%", label:"0", id:"hours", filly:1, fillx:1}, - {type:"img", pad:8, src:imgArrowDown, col:g.theme.fg2} + {type:"img", pad:8, src:imgArrow, col:g.theme.fg2}, + {type:"txt", font:"20%", label:"00", id:"hours", filly:1, fillx:1}, + {type:"img", pad:8, src:imgArrow, col:g.theme.fg2, r:2} ]}, - {type:"v", c: [ + {type:"v", width:g.getWidth()/3, c: [ {type:"txt", font:"6x8", label:/*LANG*/"Minutes", col:g.theme.fg2}, - {type:"img", pad:8, src:imgArrowUp, col:g.theme.fg2}, - {type:"txt", font:"20%", label:"0", id:"mins", filly:1, fillx:1}, - {type:"img", pad:8, src:imgArrowDown, col:g.theme.fg2} + {type:"img", pad:8, src:imgArrow, col:g.theme.fg2}, + {type:"txt", font:"20%", label:"00", id:"mins", filly:1, fillx:1}, + {type:"img", pad:8, src:imgArrow, col:g.theme.fg2, r:2} ]}, - {type:"v", c: [ + {type:"v", width:g.getWidth()/3, c: [ {type:"txt", font:"6x8", label:/*LANG*/"Seconds", col:g.theme.fg2}, - {type:"img", pad:8, src:imgArrowUp, col:g.theme.fg2}, - {type:"txt", font:"20%", label:"0", id:"secs", filly:1, fillx:1}, - {type:"img", pad:8, src:imgArrowDown, col:g.theme.fg2} + {type:"img", pad:8, src:imgArrow, col:g.theme.fg2}, + {type:"txt", font:"20%", label:"00", id:"secs", filly:1, fillx:1}, + {type:"img", pad:8, src:imgArrow, col:g.theme.fg2, r:2} ]}, ]}, {type:"btn", src:imgPlay, id:"btnStart", fillx:1 } + //{type:"btn", label:'Start', font:"20%", id:"btnStart", fillx:0 } ], filly:1 }; @@ -164,6 +154,7 @@ function runTimePicker() { }); timePickerLayout.render(); updateTimePicker(); + //timePickerLayout.debug(); } function runTimer() { From b840a92f5ae7e75704813b6ab03ebf23236849cd Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Fri, 29 Apr 2022 11:20:26 +0100 Subject: [PATCH 10/34] Update timersimple.app.js --- apps/timersimple/timersimple.app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/timersimple/timersimple.app.js b/apps/timersimple/timersimple.app.js index ef53c1e72..cece0dd6b 100644 --- a/apps/timersimple/timersimple.app.js +++ b/apps/timersimple/timersimple.app.js @@ -13,7 +13,7 @@ const timerID = "simpletimer"; Bangle.loadWidgets(); Bangle.drawWidgets(); -//var Layout = require("Layout"); +var Layout = require("Layout"); var seconds = 5 * 60; // Default to 5 minutes var drawTimeout; var timerLayout; From f1149233050055e0a6e8376227ff4cb53659512b Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Fri, 29 Apr 2022 11:27:43 +0100 Subject: [PATCH 11/34] Update README.md --- apps/timersimple/README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/timersimple/README.md b/apps/timersimple/README.md index e940ba0ab..894a46e7a 100644 --- a/apps/timersimple/README.md +++ b/apps/timersimple/README.md @@ -1,5 +1,7 @@ # Simple Timer +TESTING - DO NOT INSTALL, MAY BE BROKEN + Does one thing well. Set a time in hours, minutes and seconds, and alerts you when time is up. Opening the app while the timer is running (or just leaving the app open) shows how much time is left on the timer. This is the part I felt was missing from the Alarms and Timer app. Drag or tap on the up and down buttons over the hour, minute or second to set the time. @@ -7,4 +9,4 @@ Drag or tap on the up and down buttons over the hour, minute or second to set th ![](timersimple-scr1.png) ![](timersimple-scr2.png) -Written by: [Sir Indy](https://github.com/sir-indy) For support and discussion please post in the [Bangle JS Forum](http://forum.espruino.com/microcosms/1424/) \ No newline at end of file +Written by: [Sir Indy](https://github.com/sir-indy) For support and discussion please post in the [Bangle JS Forum](http://forum.espruino.com/microcosms/1424/) From baa242e92bd245b703a9ddf9c2881fbeb15f1847 Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Fri, 29 Apr 2022 11:28:58 +0100 Subject: [PATCH 12/34] Update Layout.js --- modules/Layout.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/Layout.js b/modules/Layout.js index 7e5dd4b62..19553c0a5 100644 --- a/modules/Layout.js +++ b/modules/Layout.js @@ -417,3 +417,5 @@ Layout.prototype.clear = function(l) { if (l.bgCol!==undefined) g.setBgColor(l.bgCol); g.clearRect(l.x,l.y,l.x+l.w-1,l.y+l.h-1); }; + +exports = Layout; From f60d0f22a23bcb7a8ef37765ff46e16629aace97 Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Fri, 29 Apr 2022 12:33:42 +0100 Subject: [PATCH 13/34] Update timersimple.app.js --- apps/timersimple/timersimple.app.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/timersimple/timersimple.app.js b/apps/timersimple/timersimple.app.js index cece0dd6b..1c775b908 100644 --- a/apps/timersimple/timersimple.app.js +++ b/apps/timersimple/timersimple.app.js @@ -34,6 +34,7 @@ const imgPause = atob("GBiBAP+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B/ const imgPlay = atob("GBiBAIAAAOAAAPgAAP4AAP+AAP/gAP/4AP/+AP//gP//4P//+P///v///v//+P//4P//gP/+AP/4AP/gAP+AAP4AAPgAAOAAAIAAAA=="); function onDrag(event) { + Bangle.buzz(20, 0.3); var diff = -Math.round(event.dy/5); if (event.x < timePickerLayout.hours.w) { diff *= 3600; @@ -47,10 +48,13 @@ function onTouch(button, xy) { var touchMidpoint = timePickerLayout.hours.y + timePickerLayout.hours.h/2; var diff = 0; if (xy.y > 24 && xy.y < touchMidpoint - 10) { + Bangle.buzz(40, 0.3); diff = 1; } else if (xy.y > touchMidpoint + 10 && xy.y < timePickerLayout.btnStart.y) { + Bangle.buzz(40, 0.3); diff = -1; } else if (xy.y > timePickerLayout.btnStart.y) { + Bangle.buzz(40, 0.6); runTimer(); return; } From 2e8744ca22f42d699792a786e58eb3ed532caa94 Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Sun, 1 May 2022 18:02:15 +0100 Subject: [PATCH 14/34] Move changes to smpltmr --- apps/smpltmr/ChangeLog | 3 +- apps/smpltmr/README.md | 15 +- apps/smpltmr/app.js | 255 ++++++++++++++--------- apps/smpltmr/description.png | Bin 7771 -> 0 bytes apps/smpltmr/metadata.json | 4 +- apps/timersimple/ChangeLog | 1 - apps/timersimple/README.md | 12 -- apps/timersimple/icons8-time-span-48.png | Bin 1933 -> 0 bytes apps/timersimple/metadata.json | 18 -- apps/timersimple/timersimple-scr1.png | Bin 3232 -> 0 bytes apps/timersimple/timersimple-scr2.png | Bin 3017 -> 0 bytes apps/timersimple/timersimple.app.js | 185 ---------------- apps/timersimple/timersimple.icon.js | 1 - 13 files changed, 159 insertions(+), 335 deletions(-) delete mode 100644 apps/smpltmr/description.png delete mode 100644 apps/timersimple/ChangeLog delete mode 100644 apps/timersimple/README.md delete mode 100644 apps/timersimple/icons8-time-span-48.png delete mode 100644 apps/timersimple/metadata.json delete mode 100644 apps/timersimple/timersimple-scr1.png delete mode 100644 apps/timersimple/timersimple-scr2.png delete mode 100644 apps/timersimple/timersimple.app.js delete mode 100644 apps/timersimple/timersimple.icon.js diff --git a/apps/smpltmr/ChangeLog b/apps/smpltmr/ChangeLog index 07afedd21..bf128e2fb 100644 --- a/apps/smpltmr/ChangeLog +++ b/apps/smpltmr/ChangeLog @@ -1 +1,2 @@ -0.01: Release \ No newline at end of file +0.01: Release +0.02: Rewrite with new interface \ No newline at end of file diff --git a/apps/smpltmr/README.md b/apps/smpltmr/README.md index 1296166e2..2c6e6f9ab 100644 --- a/apps/smpltmr/README.md +++ b/apps/smpltmr/README.md @@ -1,21 +1,12 @@ # Simple Timer -A simple app to set a timer quickly. Simply tab on top/bottom/left/right -to select the minutes and tab in the middle of the screen to start/stop -the timer. Note that this timer depends on qalarm. - -# Overview -If you open the app, you can simply control the timer -by clicking on top, bottom, left or right of the screen. -If you tab at the middle of the screen, the timer is -started / stopped. - -![](description.png) +A simple app to set a timer quickly. Drag or tap on the up and down buttons over the hour, minute or second to set the time. +This app uses the `sched` library, which allows the timer to continue to run in the background when this app is closed. # Creator [David Peer](https://github.com/peerdavid) - +[Sir Indy](https://github.com/sir-indy) # Thanks to... Time icon created by CreativeCons - Flaticon \ No newline at end of file diff --git a/apps/smpltmr/app.js b/apps/smpltmr/app.js index eb01e27d0..5f893b054 100644 --- a/apps/smpltmr/app.js +++ b/apps/smpltmr/app.js @@ -1,124 +1,173 @@ -/* - * SIMPLE TIMER - * - * Creator: David Peer - * Date: 02/2022 - */ +const secondsToTime = (s) => new Object({h:Math.floor((s/3600) % 24), m:Math.floor((s/60) % 60), s:Math.floor(s % 60)}); +const clamp = (num, min, max) => Math.min(Math.max(num, min), max); +function formatTime(s) { + var t = secondsToTime(s); + if (t.h) { + return t.h + ':' + ("0" + t.m).substr(-2) + ':' + ("0" + t.s).substr(-2); + } else { + return t.m + ':' + ("0" + t.s).substr(-2); + } +} +const timerID = "simpletimer"; Bangle.loadWidgets(); +Bangle.drawWidgets(); +var Layout = require("Layout"); +var seconds = 5 * 60; // Default to 5 minutes +var drawTimeout; +var imgArrow = Graphics.createImage(` + x + xxx + xxx + xxxxx + xxxxx + xxx xxx + xxx xxx +xxx xxx +xxx xxx +`); -const alarm = require("sched"); +const imgPause = atob("GBiBAP+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B/w=="); +const imgPlay = atob("GBiBAIAAAOAAAPgAAP4AAP+AAP/gAP/4AP/+AP//gP//4P//+P///v///v//+P//4P//gP/+AP/4AP/gAP+AAP4AAPgAAOAAAIAAAA=="); -const TIMER_IDX = "smpltmr"; -const screenWidth = g.getWidth(); -const screenHeight = g.getHeight(); -const cx = parseInt(screenWidth/2); -const cy = parseInt(screenHeight/2)-12; -var minutes = 5; -var interval; //used for the 1 second interval timer - - -function isTimerEnabled(){ - var alarmObj = alarm.getAlarm(TIMER_IDX); - if(alarmObj===undefined || !alarmObj.on){ - return false; +function onDrag(event) { + Bangle.buzz(20, 0.3); + var diff = -Math.round(event.dy/5); + if (event.x < timePickerLayout.hours.w) { + diff *= 3600; + } else if (event.x > timePickerLayout.mins.x && event.x < timePickerLayout.secs.x) { + diff *= 60; } - - return true; + updateTimePicker(diff); } -function getTimerMin(){ - var alarmObj = alarm.getAlarm(TIMER_IDX); - return Math.round(alarm.getTimeToAlarm(alarmObj)/(60*1000)); -} - -function setTimer(minutes){ - alarm.setAlarm(TIMER_IDX, { - // msg : "Simple Timer", - timer : minutes*60*1000, - }); - alarm.reload(); -} - -function deleteTimer(){ - alarm.setAlarm(TIMER_IDX, undefined); - alarm.reload(); -} - -setWatch(_=>load(), BTN1); -function draw(){ - g.clear(1); - Bangle.drawWidgets(); - - if (interval) { - clearInterval(interval); +function onTouch(button, xy) { + var touchMidpoint = timePickerLayout.hours.y + timePickerLayout.hours.h/2; + var diff = 0; + if (xy.y > 24 && xy.y < touchMidpoint - 10) { + Bangle.buzz(40, 0.3); + diff = 1; + } else if (xy.y > touchMidpoint + 10 && xy.y < timePickerLayout.btnStart.y) { + Bangle.buzz(40, 0.3); + diff = -1; + } else if (xy.y > timePickerLayout.btnStart.y) { + Bangle.buzz(40, 0.6); + runTimer(); + return; } - interval = undefined; - - // Write time - g.setFontAlign(0, 0, 0); - g.setFont("Vector", 32).setFontAlign(0,-1); - - var started = isTimerEnabled(); - var text = minutes + " min."; - if(started){ - var min = getTimerMin(); - text = min + " min."; + if (xy.x < timePickerLayout.hours.w) { + diff *= 3600; + } else if (xy.x > timePickerLayout.mins.x && xy.x < timePickerLayout.secs.x) { + diff *= 60; } + updateTimePicker(diff); +} - var rectWidth = parseInt(g.stringWidth(text) / 2); - - if(started){ - interval = setInterval(draw, 1000); - g.setColor("#ff0000"); +function onButton() { + var timeToNext = require("sched").getTimeToAlarm(require("sched").getAlarm(timerID)); + g.clearRect(Bangle.appRect); + if (timeToNext != undefined) { + runTimer(); } else { - g.setColor(g.theme.fg); + runTimePicker(); } - g.fillRect(cx-rectWidth-5, cy-5, cx+rectWidth, cy+30); - - g.setColor(g.theme.bg); - g.drawString(text, cx, cy); } +function updateTimePicker(diff) { + seconds = clamp(seconds + (diff || 0), 0, 24 * 3600 - 1); + var set_time = secondsToTime(seconds); + updateLayoutField(timePickerLayout, 'hours', set_time.h); + updateLayoutField(timePickerLayout, 'mins', set_time.m); + updateLayoutField(timePickerLayout, 'secs', set_time.s); +} -Bangle.on('touch', function(btn, e){ - var left = parseInt(g.getWidth() * 0.25); - var right = g.getWidth() - left; - var upper = parseInt(g.getHeight() * 0.25); - var lower = g.getHeight() - upper; +function updateLayoutField(layout, field, value) { + layout.clear(layout[field]); + layout[field].label = value; + layout.render(layout[field]); +} - var isLeft = e.x < left; - var isRight = e.x > right; - var isUpper = e.y < upper; - var isLower = e.y > lower; - var isMiddle = !isLeft && !isRight && !isUpper && !isLower; - var started = isTimerEnabled(); +function updateTimer() { + var timeToNext = require("sched").getTimeToAlarm(require("sched").getAlarm(timerID)); + updateLayoutField(timerLayout, 'timer', formatTime(timeToNext / 1000)); + queueDraw(1000); +} - if(isRight && !started){ - minutes += 1; - Bangle.buzz(40, 0.3); - } else if(isLeft && !started){ - minutes -= 1; - Bangle.buzz(40, 0.3); - } else if(isUpper && !started){ - minutes += 5; - Bangle.buzz(40, 0.3); - } else if(isLower && !started){ - minutes -= 5; - Bangle.buzz(40, 0.3); - } else if(isMiddle) { - if(!started){ - setTimer(minutes); - } else { - deleteTimer(); - } - Bangle.buzz(80, 0.6); - } - minutes = Math.max(0, minutes); +function queueDraw(millisecs) { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function() { + drawTimeout = undefined; + updateTimer(); + }, millisecs - (Date.now() % millisecs)); +} - draw(); +function timerStop() { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = undefined; + seconds = require("sched").getTimeToAlarm(require("sched").getAlarm(timerID)) / 1000; + require("sched").setAlarm(timerID, undefined); + require("sched").reload(); + runTimePicker(); +} + +function runTimePicker() { + g.clearRect(Bangle.appRect); + Bangle.setUI({ + mode : "custom", + touch : function(n,e) {onTouch(n,e);}, + drag : function(e) {onDrag(e);}, + btn : function(n) {onButton();}, + }); + timePickerLayout.render(); + updateTimePicker(); + //timePickerLayout.debug(); +} + +function runTimer() { + require("sched").setAlarm(timerID, { + vibrate : ".-.-", + hidden: true, + timer : seconds * 1000 + }); + require("sched").reload(); + g.clearRect(Bangle.appRect); + timerLayout.render(); + updateTimer(); +} + +var timePickerLayout = new Layout({ + type:"v", c: [ + {type:undefined, height:2}, + {type:"h", c: [ + {type:"v", width:g.getWidth()/3, c: [ + {type:"txt", font:"6x8", label:/*LANG*/"Hours", col:g.theme.fg2}, + {type:"img", pad:8, src:imgArrow, col:g.theme.fg2}, + {type:"txt", font:"20%", label:"00", id:"hours", filly:1, fillx:1}, + {type:"img", pad:8, src:imgArrow, col:g.theme.fg2, r:2} + ]}, + {type:"v", width:g.getWidth()/3, c: [ + {type:"txt", font:"6x8", label:/*LANG*/"Minutes", col:g.theme.fg2}, + {type:"img", pad:8, src:imgArrow, col:g.theme.fg2}, + {type:"txt", font:"20%", label:"00", id:"mins", filly:1, fillx:1}, + {type:"img", pad:8, src:imgArrow, col:g.theme.fg2, r:2} + ]}, + {type:"v", width:g.getWidth()/3, c: [ + {type:"txt", font:"6x8", label:/*LANG*/"Seconds", col:g.theme.fg2}, + {type:"img", pad:8, src:imgArrow, col:g.theme.fg2}, + {type:"txt", font:"20%", label:"00", id:"secs", filly:1, fillx:1}, + {type:"img", pad:8, src:imgArrow, col:g.theme.fg2, r:2} + ]}, + ]}, + {type:"btn", src:imgPlay, id:"btnStart", fillx:1 } + ], filly:1 }); -g.reset(); -draw(); \ No newline at end of file +var timerLayout = new Layout({ + type:"v", c: [ + {type:"txt", font:"22%", label:"0:00", id:"timer", fillx:1, filly:1 }, + {type:"btn", src:imgPause, cb: l=>timerStop(), fillx:1 } + ], filly:1 +}); + +onButton(); \ No newline at end of file diff --git a/apps/smpltmr/description.png b/apps/smpltmr/description.png deleted file mode 100644 index 1286d1ab94e56658995ba8dabe08bfc7dea51bc6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7771 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 SWZ<+Iq^bmYRH|V9`ab}V`IlM% diff --git a/apps/smpltmr/metadata.json b/apps/smpltmr/metadata.json index 06bad962d..ee5c7ce9b 100644 --- a/apps/smpltmr/metadata.json +++ b/apps/smpltmr/metadata.json @@ -2,10 +2,10 @@ "id": "smpltmr", "name": "Simple Timer", "shortName": "Simple Timer", - "version": "0.01", + "version": "0.02", "description": "A very simple app to start a timer.", "icon": "app.png", - "tags": "tool", + "tags": "tool,alarm,timer", "dependencies": {"scheduler":"type"}, "supports": ["BANGLEJS2"], "screenshots": [{"url":"screenshot.png"}, {"url": "screenshot_2.png"}], diff --git a/apps/timersimple/ChangeLog b/apps/timersimple/ChangeLog deleted file mode 100644 index 7b83706bf..000000000 --- a/apps/timersimple/ChangeLog +++ /dev/null @@ -1 +0,0 @@ -0.01: First release diff --git a/apps/timersimple/README.md b/apps/timersimple/README.md deleted file mode 100644 index 894a46e7a..000000000 --- a/apps/timersimple/README.md +++ /dev/null @@ -1,12 +0,0 @@ -# Simple Timer - -TESTING - DO NOT INSTALL, MAY BE BROKEN - -Does one thing well. Set a time in hours, minutes and seconds, and alerts you when time is up. Opening the app while the timer is running (or just leaving the app open) shows how much time is left on the timer. This is the part I felt was missing from the Alarms and Timer app. - -Drag or tap on the up and down buttons over the hour, minute or second to set the time. - -![](timersimple-scr1.png) -![](timersimple-scr2.png) - -Written by: [Sir Indy](https://github.com/sir-indy) For support and discussion please post in the [Bangle JS Forum](http://forum.espruino.com/microcosms/1424/) diff --git a/apps/timersimple/icons8-time-span-48.png b/apps/timersimple/icons8-time-span-48.png deleted file mode 100644 index 9a9dfb6abd1801997481d40bd41e475afe845f1a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1933 zcmV;82Xgp{P)}f;`d3 z{4|bF%roc{(>PYg>)2T4uNQwW0+8Ygn zw6{|X*_#deBv!4>$$!2UDtwRtR+g1(ggqUDi`B3w1D||bZ8oxLjVqIK^H_${Y^z~l z4qgh>@{lV8OUG!WT9`-!KJBimUYE47XSH$tg5tx3jsS-xFyB^uwzDMC;IL=l!y5-< z9+954uQIM*AISi#lMCP$CvkuJ4u)O*aEx9--^e9+r0Ecf=!uc#t|RYnvWwyLAC`go z?%yS^GUR=enP|!kU-~Re#w|gd=<}d^s2vxspT^kKkXqR19O8=wOG^ls-(f)m?_4{g zFW`RgpNxbx8DS|_K+V7$d{n|$jx%WMJqbznDr)IjZYFiFu&+^B5r751fyc1Hwpj5C zfh8P%XxfioJo9HP)2AqE$&bX?v9}lML({h39gzCC-!JN^E^y&m@Z=oN4bkCgbVMQwY= z*zAbfFN;ZmOl8~{`+A-uz>|e9nCd!CJ0_IvRcAnwn3n+P0ASKRj=tMAtW3&7f<7H2 zI>#qXY|Z(Z@>SCLAit>AHpqY=2n+~H{kd(AmO#hGAuWClRwX@&1bsTFOrxvX4>~Ru zJ95hcI0}>%e^MOu#snGg6E*WLM0JofT47ge>o>5KdAF#$Bv=7xfvTbZp6TV6R*5nj$K=3XG9ERMqDlz z>g(%q>((vJb~&kmV-sNE8K6L}e|dR=DX3#Y2rL#0Y&IL3o12lJpO1k7CtiQ`D4u(! z6ixMQkfp%o_x}C+sH>~PzJ2?UnVE?L2M(a2p+VC?#n0qV=B z!M~vA;xz{W0ES^;u~^XA*$J!F3bWaakvk(Ot9l%zZ?1#gZigs}U>F8lw{AsMRTZvX zyM_}dPH6V4=Yz&xrX-?rBbfukFeoi8MM+5s($muc3Q(Csuh*lxx*EmB#aOW-=&3FV zY6d0&%kx24*)GTc-?{xVK<8gx zuQY?JL+Ac4BDK&x)CR9K<4+B+o!jinc50_lnSj*$a~H0khL1+~tfK{=Ea80rX$4E_ z)l!kF_W_obYXHn=1IDI?@Rj3CbX98LOGhKdrvnxo4+X7JYpZHN*wZmcfm(mAt@k9H z<2}(+83NAn9-Qkt6~Iy8gGx)gY62^OsT7&SwJ%$GR z8<6CH6YUreIpm!qk|9-Y~btXXO?+BBgadZuyMRxK!B*jK2-{l-V))ssgCmz0~7A7~9{puZA!bcD6>M4aR)Z`rw@fW8YLWV&yWxJwCsS^1Op#z=x9{zFq~ zY5UkGlC_kO_W*bzjaPw(0`GD>zcy0wz!HD*mA4dTF~Ca{v=ksKBa5a^fU#20noyfm zIEc<~RzYCIg7cdI6#g&uVFr+e@9x)=00sf{fxt#&($02nvq$4M>q9)m_Z|NQLRok` Trm{7g00000NkvXXu0mjfz&ofF diff --git a/apps/timersimple/metadata.json b/apps/timersimple/metadata.json deleted file mode 100644 index 5d0e5d5e4..000000000 --- a/apps/timersimple/metadata.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "id":"timersimple", - "name":"Timer Simple", - "shortName": "Timer Simple", - "version": "0.01", - "description": "Sets a single timer, and tells you how long left.", - "readme": "README.md", - "icon":"icons8-time-span-48.png", - "screenshots": [{"url":"timersimple-scr1.png"},{"url":"timersimple-scr2.png"}], - "tags": "tool,alarm,timer", - "supports": ["BANGLEJS2"], - "dependencies": {"scheduler":"type"}, - "allow_emulator": true, - "storage": [ - {"name":"timersimple.app.js","url":"timersimple.app.js"}, - {"name":"timersimple.img","url":"timersimple.icon.js","evaluate":true} - ] - } \ No newline at end of file diff --git a/apps/timersimple/timersimple-scr1.png b/apps/timersimple/timersimple-scr1.png deleted file mode 100644 index 5556f8ecc0f2b0c0e343e144f53b2a90741e55c3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3232 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 diff --git a/apps/timersimple/timersimple.app.js b/apps/timersimple/timersimple.app.js deleted file mode 100644 index 1c775b908..000000000 --- a/apps/timersimple/timersimple.app.js +++ /dev/null @@ -1,185 +0,0 @@ -const secondsToTime = (s) => new Object({h:Math.floor((s/3600) % 24), m:Math.floor((s/60) % 60), s:Math.floor(s % 60)}); -const clamp = (num, min, max) => Math.min(Math.max(num, min), max); -function formatTime(s) { - var t = secondsToTime(s); - if (t.h) { - return t.h + ':' + ("0" + t.m).substr(-2) + ':' + ("0" + t.s).substr(-2); - } else { - return t.m + ':' + ("0" + t.s).substr(-2); - } -} -const timerID = "simpletimer"; - -Bangle.loadWidgets(); -Bangle.drawWidgets(); - -var Layout = require("Layout"); -var seconds = 5 * 60; // Default to 5 minutes -var drawTimeout; -var timerLayout; -var timePickerLayout; -var imgArrow = Graphics.createImage(` - x - xxx - xxx - xxxxx - xxxxx - xxx xxx - xxx xxx -xxx xxx -xxx xxx -`); - -const imgPause = atob("GBiBAP+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B/w=="); -const imgPlay = atob("GBiBAIAAAOAAAPgAAP4AAP+AAP/gAP/4AP/+AP//gP//4P//+P///v///v//+P//4P//gP/+AP/4AP/gAP+AAP4AAPgAAOAAAIAAAA=="); - -function onDrag(event) { - Bangle.buzz(20, 0.3); - var diff = -Math.round(event.dy/5); - if (event.x < timePickerLayout.hours.w) { - diff *= 3600; - } else if (event.x > timePickerLayout.mins.x && event.x < timePickerLayout.secs.x) { - diff *= 60; - } - updateTimePicker(diff); -} - -function onTouch(button, xy) { - var touchMidpoint = timePickerLayout.hours.y + timePickerLayout.hours.h/2; - var diff = 0; - if (xy.y > 24 && xy.y < touchMidpoint - 10) { - Bangle.buzz(40, 0.3); - diff = 1; - } else if (xy.y > touchMidpoint + 10 && xy.y < timePickerLayout.btnStart.y) { - Bangle.buzz(40, 0.3); - diff = -1; - } else if (xy.y > timePickerLayout.btnStart.y) { - Bangle.buzz(40, 0.6); - runTimer(); - return; - } - if (xy.x < timePickerLayout.hours.w) { - diff *= 3600; - } else if (xy.x > timePickerLayout.mins.x && xy.x < timePickerLayout.secs.x) { - diff *= 60; - } - updateTimePicker(diff); -} - -function updateTimePicker(diff) { - seconds = clamp(seconds + (diff || 0), 0, 24 * 3600 - 1); - var set_time = secondsToTime(seconds); - updateLayoutField(timePickerLayout, 'hours', set_time.h); - updateLayoutField(timePickerLayout, 'mins', set_time.m); - updateLayoutField(timePickerLayout, 'secs', set_time.s); -} - -function updateLayoutField(layout, field, value) { - layout.clear(layout[field]); - layout[field].label = value; - layout.render(layout[field]); -} - -function updateTimer() { - var timeToNext = require("sched").getTimeToAlarm(require("sched").getAlarm(timerID)); - updateLayoutField(timerLayout, 'timer', formatTime(timeToNext / 1000)); - //var d = new Date(); - //updateLayoutField(timerLayout, 'time', require("locale").time(d,1)); - queueDraw(1000); -} - -function queueDraw(millisecs) { - if (drawTimeout) clearTimeout(drawTimeout); - drawTimeout = setTimeout(function() { - drawTimeout = undefined; - updateTimer(); - }, millisecs - (Date.now() % millisecs)); -} - -function timerStop() { - if (drawTimeout) clearTimeout(drawTimeout); - drawTimeout = undefined; - seconds = require("sched").getTimeToAlarm(require("sched").getAlarm(timerID)) / 1000; - require("sched").setAlarm(timerID, undefined); - require("sched").reload(); - runTimePicker(); -} - -var timePickerLayoutCode = { - type:"v", c: [ - {type:undefined, height:2}, - //{type:"txt", font:"15%", label:"TIMER", id:"title"}, - {type:"h", c: [ - {type:"v", width:g.getWidth()/3, c: [ - {type:"txt", font:"6x8", label:/*LANG*/"Hours", col:g.theme.fg2}, - {type:"img", pad:8, src:imgArrow, col:g.theme.fg2}, - {type:"txt", font:"20%", label:"00", id:"hours", filly:1, fillx:1}, - {type:"img", pad:8, src:imgArrow, col:g.theme.fg2, r:2} - ]}, - {type:"v", width:g.getWidth()/3, c: [ - {type:"txt", font:"6x8", label:/*LANG*/"Minutes", col:g.theme.fg2}, - {type:"img", pad:8, src:imgArrow, col:g.theme.fg2}, - {type:"txt", font:"20%", label:"00", id:"mins", filly:1, fillx:1}, - {type:"img", pad:8, src:imgArrow, col:g.theme.fg2, r:2} - ]}, - {type:"v", width:g.getWidth()/3, c: [ - {type:"txt", font:"6x8", label:/*LANG*/"Seconds", col:g.theme.fg2}, - {type:"img", pad:8, src:imgArrow, col:g.theme.fg2}, - {type:"txt", font:"20%", label:"00", id:"secs", filly:1, fillx:1}, - {type:"img", pad:8, src:imgArrow, col:g.theme.fg2, r:2} - ]}, - ]}, - {type:"btn", src:imgPlay, id:"btnStart", fillx:1 } - //{type:"btn", label:'Start', font:"20%", id:"btnStart", fillx:0 } - ], filly:1 -}; - -var timerLayoutCode = { - type:"v", c: [ - {type:undefined, height:8}, - //{type:"txt", font:"6x8", label:/*LANG*/"Timer", id:"title", col:g.theme.fg2}, - {type:"txt", font:"22%", label:"0:00", id:"timer", fillx:1, filly:1 }, - //{type:"h", c: [ - // {type:"txt", font:"6x8", pad:8, label:/*LANG*/"Time Now:", halign:-1, col:g.theme.fg2}, - // {type:"txt", font:"6x8", label:"00:00", id:"time", halign:1, col:g.theme.fg2}, - //]}, - {type:"btn", src:imgPause, cb: l=>timerStop(), fillx:1 } - ], filly:1 -}; - -function runTimePicker() { - g.clearRect(Bangle.appRect); - timePickerLayout = new Layout(timePickerLayoutCode); - Bangle.setUI({ - mode : "custom", - touch : function(n,e) {onTouch(n,e);}, - drag : function(e) {onDrag(e);}, - btn : function(n) {runTimer();}, - }); - timePickerLayout.render(); - updateTimePicker(); - //timePickerLayout.debug(); -} - -function runTimer() { - require("sched").setAlarm(timerID, { - vibrate : ".-.-", - hidden: true, - timer : seconds * 1000 - }); - require("sched").reload(); - g.clearRect(Bangle.appRect); - timerLayout = new Layout(timerLayoutCode); - timerLayout.render(); - updateTimer(); -} - -var timeToNext = require("sched").getTimeToAlarm(require("sched").getAlarm(timerID)); -if (timeToNext != undefined) { - g.clearRect(Bangle.appRect); - timerLayout = new Layout(timerLayoutCode); - timerLayout.render(); - updateTimer(); -} else { - runTimePicker(); -} diff --git a/apps/timersimple/timersimple.icon.js b/apps/timersimple/timersimple.icon.js deleted file mode 100644 index cd40303a0..000000000 --- a/apps/timersimple/timersimple.icon.js +++ /dev/null @@ -1 +0,0 @@ -require("heatshrink").decompress(atob("mEwwcBkmSpIC/ARf//9JkQRMCAIRBAwIRKv4RFpARIz4QCCIdJiREJAAgJCCI0nCI3+BgOJCIs/CI3/9MkyJoIAAxuGp4RJ8gRQ/mSogRDu4RJNwKSEqXfCJPSCImSrYRJ+SkEyVfCJP6CIo1B4wRHUgIREA4MAj4SHCIeUCIP//EAt4RHkQRF//ggIDB+EHCJf/wEAAAQRM/0CoAmCCJf/4VDI5pcCNwoRKNZ4RMUIQRLYowAIYozpRrYRJ+QREqVLCJPSpGSCIdJv5GIyQREpVJfA///mSogRDpNJloRH8mSBwQRDku/CIwMBCIspkmXCAvpkmRCIslAYKkETwMkxIRFkmkyVLNwYJCBwgCDAwyeEAQqSBAwiMEAQwGFBxACDygDBkQOKAX4CD")) \ No newline at end of file From eca76d78ba51126342855cda72a486b68f05814d Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Sun, 1 May 2022 18:11:00 +0100 Subject: [PATCH 15/34] Update to button press --- apps/smpltmr/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/smpltmr/app.js b/apps/smpltmr/app.js index 5f893b054..25a11361b 100644 --- a/apps/smpltmr/app.js +++ b/apps/smpltmr/app.js @@ -53,7 +53,7 @@ function onTouch(button, xy) { diff = -1; } else if (xy.y > timePickerLayout.btnStart.y) { Bangle.buzz(40, 0.6); - runTimer(); + onButton(); return; } if (xy.x < timePickerLayout.hours.w) { From d42afd7f9e00efb9cad0de517075e918c099d1a0 Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Sun, 1 May 2022 18:20:59 +0100 Subject: [PATCH 16/34] Tweak to button --- apps/smpltmr/app.js | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/apps/smpltmr/app.js b/apps/smpltmr/app.js index 25a11361b..72cb3b387 100644 --- a/apps/smpltmr/app.js +++ b/apps/smpltmr/app.js @@ -68,9 +68,9 @@ function onButton() { var timeToNext = require("sched").getTimeToAlarm(require("sched").getAlarm(timerID)); g.clearRect(Bangle.appRect); if (timeToNext != undefined) { - runTimer(); + timerRun(); } else { - runTimePicker(); + timerStop(); } } @@ -102,15 +102,6 @@ function queueDraw(millisecs) { }, millisecs - (Date.now() % millisecs)); } -function timerStop() { - if (drawTimeout) clearTimeout(drawTimeout); - drawTimeout = undefined; - seconds = require("sched").getTimeToAlarm(require("sched").getAlarm(timerID)) / 1000; - require("sched").setAlarm(timerID, undefined); - require("sched").reload(); - runTimePicker(); -} - function runTimePicker() { g.clearRect(Bangle.appRect); Bangle.setUI({ @@ -124,7 +115,7 @@ function runTimePicker() { //timePickerLayout.debug(); } -function runTimer() { +function timerRun() { require("sched").setAlarm(timerID, { vibrate : ".-.-", hidden: true, @@ -136,6 +127,15 @@ function runTimer() { updateTimer(); } +function timerStop() { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = undefined; + seconds = require("sched").getTimeToAlarm(require("sched").getAlarm(timerID)) / 1000; + require("sched").setAlarm(timerID, undefined); + require("sched").reload(); + runTimePicker(); +} + var timePickerLayout = new Layout({ type:"v", c: [ {type:undefined, height:2}, From ea0d17afebceefdc5fb8402cc6935522f6e3e5d6 Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Sun, 1 May 2022 18:25:55 +0100 Subject: [PATCH 17/34] Fix start time --- apps/smpltmr/app.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/smpltmr/app.js b/apps/smpltmr/app.js index 72cb3b387..27cbe52c4 100644 --- a/apps/smpltmr/app.js +++ b/apps/smpltmr/app.js @@ -130,7 +130,10 @@ function timerRun() { function timerStop() { if (drawTimeout) clearTimeout(drawTimeout); drawTimeout = undefined; - seconds = require("sched").getTimeToAlarm(require("sched").getAlarm(timerID)) / 1000; + var timeToNext = require("sched").getTimeToAlarm(require("sched").getAlarm(timerID)); + if (timeToNext != undefined) { + seconds = timeToNext / 1000; + } require("sched").setAlarm(timerID, undefined); require("sched").reload(); runTimePicker(); From 4ee8b843bee607fa255b53b3c1f1d071d0ab00c6 Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Sun, 1 May 2022 18:38:49 +0100 Subject: [PATCH 18/34] Update to select running mode --- apps/smpltmr/app.js | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/apps/smpltmr/app.js b/apps/smpltmr/app.js index 27cbe52c4..7bee1ad20 100644 --- a/apps/smpltmr/app.js +++ b/apps/smpltmr/app.js @@ -16,6 +16,7 @@ Bangle.drawWidgets(); var Layout = require("Layout"); var seconds = 5 * 60; // Default to 5 minutes var drawTimeout; +var timerRunning = False; var imgArrow = Graphics.createImage(` x xxx @@ -32,7 +33,7 @@ const imgPause = atob("GBiBAP+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B/ const imgPlay = atob("GBiBAIAAAOAAAPgAAP4AAP+AAP/gAP/4AP/+AP//gP//4P//+P///v///v//+P//4P//gP/+AP/4AP/gAP+AAP4AAPgAAOAAAIAAAA=="); function onDrag(event) { - Bangle.buzz(20, 0.3); + Bangle.buzz(40, 0.3); var diff = -Math.round(event.dy/5); if (event.x < timePickerLayout.hours.w) { diff *= 3600; @@ -65,12 +66,11 @@ function onTouch(button, xy) { } function onButton() { - var timeToNext = require("sched").getTimeToAlarm(require("sched").getAlarm(timerID)); g.clearRect(Bangle.appRect); - if (timeToNext != undefined) { - timerRun(); - } else { + if (timerRunning) { timerStop(); + } else { + timerRun(); } } @@ -82,12 +82,6 @@ function updateTimePicker(diff) { updateLayoutField(timePickerLayout, 'secs', set_time.s); } -function updateLayoutField(layout, field, value) { - layout.clear(layout[field]); - layout[field].label = value; - layout.render(layout[field]); -} - function updateTimer() { var timeToNext = require("sched").getTimeToAlarm(require("sched").getAlarm(timerID)); updateLayoutField(timerLayout, 'timer', formatTime(timeToNext / 1000)); @@ -173,4 +167,13 @@ var timerLayout = new Layout({ ], filly:1 }); +function updateLayoutField(layout, field, value) { + layout.clear(layout[field]); + layout[field].label = value; + layout.render(layout[field]); +} + +if (require("sched").getTimeToAlarm(require("sched").getAlarm(timerID)) != undefined) { + timerRunning = True; +} onButton(); \ No newline at end of file From cebdf1453c7975e1ba1d124e0777a33f9492a878 Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Sun, 1 May 2022 18:45:52 +0100 Subject: [PATCH 19/34] True False to true false --- apps/smpltmr/app.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/smpltmr/app.js b/apps/smpltmr/app.js index 7bee1ad20..350c2f5d8 100644 --- a/apps/smpltmr/app.js +++ b/apps/smpltmr/app.js @@ -16,7 +16,7 @@ Bangle.drawWidgets(); var Layout = require("Layout"); var seconds = 5 * 60; // Default to 5 minutes var drawTimeout; -var timerRunning = False; +var timerRunning = false; var imgArrow = Graphics.createImage(` x xxx @@ -174,6 +174,6 @@ function updateLayoutField(layout, field, value) { } if (require("sched").getTimeToAlarm(require("sched").getAlarm(timerID)) != undefined) { - timerRunning = True; + timerRunning = true; } onButton(); \ No newline at end of file From bbb4a92383b65cecc75d7a6b6fd50e113431f2f8 Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Sun, 1 May 2022 20:58:10 +0100 Subject: [PATCH 20/34] Set timer running properly --- apps/smpltmr/app.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/smpltmr/app.js b/apps/smpltmr/app.js index 350c2f5d8..502891c6a 100644 --- a/apps/smpltmr/app.js +++ b/apps/smpltmr/app.js @@ -68,8 +68,10 @@ function onTouch(button, xy) { function onButton() { g.clearRect(Bangle.appRect); if (timerRunning) { + timerRunning = false; timerStop(); } else { + timerRunning = true; timerRun(); } } From 072ce2444db6e615bcd270da27ecc47e95c9095f Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Mon, 2 May 2022 10:59:07 +0100 Subject: [PATCH 21/34] Change timerRunning to a function, and other bits --- apps/smpltmr/app.js | 101 +++++++++++++++++++++++++------------------- 1 file changed, 58 insertions(+), 43 deletions(-) diff --git a/apps/smpltmr/app.js b/apps/smpltmr/app.js index 502891c6a..de02319fd 100644 --- a/apps/smpltmr/app.js +++ b/apps/smpltmr/app.js @@ -1,3 +1,17 @@ +/* + * SIMPLE TIMER + * + * Creator: David Peer + * Date: 02/2022 + * + * Modified: Sir Indy + * Date: 05/2022 + */ + +const Layout = require("Layout"); +const alarm = require("sched") +const TIMER_IDX = "smpltmr"; + const secondsToTime = (s) => new Object({h:Math.floor((s/3600) % 24), m:Math.floor((s/60) % 60), s:Math.floor(s % 60)}); const clamp = (num, min, max) => Math.min(Math.max(num, min), max); function formatTime(s) { @@ -8,16 +22,14 @@ function formatTime(s) { return t.m + ':' + ("0" + t.s).substr(-2); } } -const timerID = "simpletimer"; -Bangle.loadWidgets(); -Bangle.drawWidgets(); - -var Layout = require("Layout"); var seconds = 5 * 60; // Default to 5 minutes var drawTimeout; -var timerRunning = false; -var imgArrow = Graphics.createImage(` +//var timerRunning = false; +function timerRunning() { + return (alarm.getTimeToAlarm(alarm.getAlarm(TIMER_IDX)) != undefined) +} +const imgArrow = Graphics.createImage(` x xxx xxx @@ -33,23 +45,25 @@ const imgPause = atob("GBiBAP+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B/ const imgPlay = atob("GBiBAIAAAOAAAPgAAP4AAP+AAP/gAP/4AP/+AP//gP//4P//+P///v///v//+P//4P//gP/+AP/4AP/gAP+AAP4AAPgAAOAAAIAAAA=="); function onDrag(event) { - Bangle.buzz(40, 0.3); - var diff = -Math.round(event.dy/5); - if (event.x < timePickerLayout.hours.w) { - diff *= 3600; - } else if (event.x > timePickerLayout.mins.x && event.x < timePickerLayout.secs.x) { - diff *= 60; + if (timerRunning()) { + Bangle.buzz(40, 0.3); + var diff = -Math.round(event.dy/5); + if (event.x < timePickerLayout.hours.w) { + diff *= 3600; + } else if (event.x > timePickerLayout.mins.x && event.x < timePickerLayout.secs.x) { + diff *= 60; + } + updateTimePicker(diff); } - updateTimePicker(diff); } function onTouch(button, xy) { var touchMidpoint = timePickerLayout.hours.y + timePickerLayout.hours.h/2; var diff = 0; - if (xy.y > 24 && xy.y < touchMidpoint - 10) { + if (timerRunning() && xy.y > 24 && xy.y < touchMidpoint - 10) { Bangle.buzz(40, 0.3); diff = 1; - } else if (xy.y > touchMidpoint + 10 && xy.y < timePickerLayout.btnStart.y) { + } else if (timerRunning() && xy.y > touchMidpoint + 10 && xy.y < timePickerLayout.btnStart.y) { Bangle.buzz(40, 0.3); diff = -1; } else if (xy.y > timePickerLayout.btnStart.y) { @@ -67,11 +81,9 @@ function onTouch(button, xy) { function onButton() { g.clearRect(Bangle.appRect); - if (timerRunning) { - timerRunning = false; + if (timerRunning()) { timerStop(); } else { - timerRunning = true; timerRun(); } } @@ -85,7 +97,7 @@ function updateTimePicker(diff) { } function updateTimer() { - var timeToNext = require("sched").getTimeToAlarm(require("sched").getAlarm(timerID)); + var timeToNext = alarm.getTimeToAlarm(alarm.getAlarm(TIMER_IDX)); updateLayoutField(timerLayout, 'timer', formatTime(timeToNext / 1000)); queueDraw(1000); } @@ -98,26 +110,13 @@ function queueDraw(millisecs) { }, millisecs - (Date.now() % millisecs)); } -function runTimePicker() { - g.clearRect(Bangle.appRect); - Bangle.setUI({ - mode : "custom", - touch : function(n,e) {onTouch(n,e);}, - drag : function(e) {onDrag(e);}, - btn : function(n) {onButton();}, - }); - timePickerLayout.render(); - updateTimePicker(); - //timePickerLayout.debug(); -} - function timerRun() { - require("sched").setAlarm(timerID, { + alarm.setAlarm(TIMER_IDX, { vibrate : ".-.-", hidden: true, timer : seconds * 1000 }); - require("sched").reload(); + alarm.reload(); g.clearRect(Bangle.appRect); timerLayout.render(); updateTimer(); @@ -126,13 +125,15 @@ function timerRun() { function timerStop() { if (drawTimeout) clearTimeout(drawTimeout); drawTimeout = undefined; - var timeToNext = require("sched").getTimeToAlarm(require("sched").getAlarm(timerID)); + var timeToNext = alarm.getTimeToAlarm(alarm.getAlarm(TIMER_IDX)); if (timeToNext != undefined) { seconds = timeToNext / 1000; } - require("sched").setAlarm(timerID, undefined); - require("sched").reload(); - runTimePicker(); + alarm.setAlarm(TIMER_IDX, undefined); + alarm.reload(); + g.clearRect(Bangle.appRect); + timePickerLayout.render(); + updateTimePicker(); } var timePickerLayout = new Layout({ @@ -175,7 +176,21 @@ function updateLayoutField(layout, field, value) { layout.render(layout[field]); } -if (require("sched").getTimeToAlarm(require("sched").getAlarm(timerID)) != undefined) { - timerRunning = true; -} -onButton(); \ No newline at end of file +Bangle.loadWidgets(); +Bangle.drawWidgets(); + +Bangle.setUI({ + mode : "custom", + touch : function(n,e) {onTouch(n,e);}, + drag : function(e) {onDrag(e);}, + btn : function(n) {onButton();}, +}); + +g.clearRect(Bangle.appRect); +if (timerRunning()) { + timerLayout.render(); + updateTimer(); +} else { + timePickerLayout.render(); + updateTimePicker(); +} \ No newline at end of file From d49980291c646f707b3acfd46b49efdd1ae886c8 Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Mon, 2 May 2022 11:14:35 +0100 Subject: [PATCH 22/34] correct onTouch if timerRunning --- apps/smpltmr/app.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/smpltmr/app.js b/apps/smpltmr/app.js index de02319fd..2904fd6a1 100644 --- a/apps/smpltmr/app.js +++ b/apps/smpltmr/app.js @@ -45,7 +45,7 @@ const imgPause = atob("GBiBAP+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B/ const imgPlay = atob("GBiBAIAAAOAAAPgAAP4AAP+AAP/gAP/4AP/+AP//gP//4P//+P///v///v//+P//4P//gP/+AP/4AP/gAP+AAP4AAPgAAOAAAIAAAA=="); function onDrag(event) { - if (timerRunning()) { + if (!timerRunning()) { Bangle.buzz(40, 0.3); var diff = -Math.round(event.dy/5); if (event.x < timePickerLayout.hours.w) { @@ -84,7 +84,9 @@ function onButton() { if (timerRunning()) { timerStop(); } else { - timerRun(); + if (seconds > 0) { + timerRun(); + } } } From ba0a1be37395f396c3ba44599ea6fe60fdf37a8d Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Mon, 2 May 2022 11:32:57 +0100 Subject: [PATCH 23/34] Tweak Readme.md --- apps/smpltmr/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/smpltmr/README.md b/apps/smpltmr/README.md index 2c6e6f9ab..310332955 100644 --- a/apps/smpltmr/README.md +++ b/apps/smpltmr/README.md @@ -4,8 +4,9 @@ A simple app to set a timer quickly. Drag or tap on the up and down buttons over This app uses the `sched` library, which allows the timer to continue to run in the background when this app is closed. -# Creator +# Creators [David Peer](https://github.com/peerdavid) + [Sir Indy](https://github.com/sir-indy) # Thanks to... From a95af8225b1ef4aedb93a6ea033f7b93c8a3fdd1 Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Mon, 2 May 2022 12:30:07 +0100 Subject: [PATCH 24/34] Added screenshots --- apps/smpltmr/screenshot.png | Bin 1845 -> 0 bytes apps/smpltmr/screenshot_1.png | Bin 0 -> 2940 bytes apps/smpltmr/screenshot_2.png | Bin 1950 -> 2496 bytes apps/smpltmr/screenshot_3.png | Bin 0 -> 2715 bytes apps/smpltmr/screenshot_4.png | Bin 0 -> 2994 bytes 5 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 apps/smpltmr/screenshot.png create mode 100644 apps/smpltmr/screenshot_1.png create mode 100644 apps/smpltmr/screenshot_3.png create mode 100644 apps/smpltmr/screenshot_4.png diff --git a/apps/smpltmr/screenshot.png b/apps/smpltmr/screenshot.png deleted file mode 100644 index eff94475c73638521c0dc59ff9ec55182f609d2b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1845 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 literal 0 HcmV?d00001 diff --git a/apps/smpltmr/screenshot_2.png b/apps/smpltmr/screenshot_2.png index 7b5dc9a3df7dc091d1dfe6d8dd3aa29c51351127..fb0145f17dde8dd27f1f443d7b4ac722657c6a88 100644 GIT binary patch literal 2496 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 literal 0 HcmV?d00001 diff --git a/apps/smpltmr/screenshot_4.png b/apps/smpltmr/screenshot_4.png new file mode 100644 index 0000000000000000000000000000000000000000..c0f984378e178638882b93c8c3d2b8a1f70aa475 GIT binary patch literal 2994 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 Date: Mon, 2 May 2022 12:30:18 +0100 Subject: [PATCH 25/34] updated readme --- apps/smpltmr/README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/apps/smpltmr/README.md b/apps/smpltmr/README.md index 310332955..eeb48d338 100644 --- a/apps/smpltmr/README.md +++ b/apps/smpltmr/README.md @@ -4,6 +4,11 @@ A simple app to set a timer quickly. Drag or tap on the up and down buttons over This app uses the `sched` library, which allows the timer to continue to run in the background when this app is closed. +![](screenshot_1.png) +![](screenshot_2.png) +![](screenshot_3.png) +![](screenshot_4.png) + # Creators [David Peer](https://github.com/peerdavid) From 51807e2b9ae988b7130f79ff5dc08150c4b09a6e Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Mon, 2 May 2022 12:31:57 +0100 Subject: [PATCH 26/34] Update onTouch to work properly --- apps/smpltmr/app.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/apps/smpltmr/app.js b/apps/smpltmr/app.js index 2904fd6a1..63aeafa91 100644 --- a/apps/smpltmr/app.js +++ b/apps/smpltmr/app.js @@ -60,14 +60,12 @@ function onDrag(event) { function onTouch(button, xy) { var touchMidpoint = timePickerLayout.hours.y + timePickerLayout.hours.h/2; var diff = 0; - if (timerRunning() && xy.y > 24 && xy.y < touchMidpoint - 10) { - Bangle.buzz(40, 0.3); + Bangle.buzz(40, 0.3); + if (!timerRunning() && xy.y > 24 && xy.y < touchMidpoint - 10) { diff = 1; - } else if (timerRunning() && xy.y > touchMidpoint + 10 && xy.y < timePickerLayout.btnStart.y) { - Bangle.buzz(40, 0.3); + } else if (!timerRunning() && xy.y > touchMidpoint + 10 && xy.y < timePickerLayout.btnStart.y) { diff = -1; } else if (xy.y > timePickerLayout.btnStart.y) { - Bangle.buzz(40, 0.6); onButton(); return; } From c5e1adc7a2384c9839a98007885a23a80989b284 Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Mon, 2 May 2022 12:33:22 +0100 Subject: [PATCH 27/34] Add screenshots to metadata.json --- apps/smpltmr/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/smpltmr/metadata.json b/apps/smpltmr/metadata.json index ee5c7ce9b..cb1ef6eab 100644 --- a/apps/smpltmr/metadata.json +++ b/apps/smpltmr/metadata.json @@ -8,7 +8,7 @@ "tags": "tool,alarm,timer", "dependencies": {"scheduler":"type"}, "supports": ["BANGLEJS2"], - "screenshots": [{"url":"screenshot.png"}, {"url": "screenshot_2.png"}], + "screenshots": [{"url":"screenshot_1.png"}, {"url": "screenshot_2.png"}, {"url": "screenshot_3.png"}, {"url": "screenshot_4.png"}], "readme": "README.md", "storage": [ {"name":"smpltmr.app.js","url":"app.js"}, From cf060cfe3e655b49f4f9fd6406d80ffe62d99a1a Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Tue, 3 May 2022 09:12:28 +0100 Subject: [PATCH 28/34] Update app.js --- apps/smpltmr/app.js | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/apps/smpltmr/app.js b/apps/smpltmr/app.js index 63aeafa91..b474b8454 100644 --- a/apps/smpltmr/app.js +++ b/apps/smpltmr/app.js @@ -29,18 +29,7 @@ var drawTimeout; function timerRunning() { return (alarm.getTimeToAlarm(alarm.getAlarm(TIMER_IDX)) != undefined) } -const imgArrow = Graphics.createImage(` - x - xxx - xxx - xxxxx - xxxxx - xxx xxx - xxx xxx -xxx xxx -xxx xxx -`); - +const imgArrow = atob("CQmBAAgOBwfD47ndx+OA"); const imgPause = atob("GBiBAP+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B//+B/w=="); const imgPlay = atob("GBiBAIAAAOAAAPgAAP4AAP+AAP/gAP/4AP/+AP//gP//4P//+P///v///v//+P//4P//gP/+AP/4AP/gAP+AAP4AAPgAAOAAAIAAAA=="); @@ -193,4 +182,4 @@ if (timerRunning()) { } else { timePickerLayout.render(); updateTimePicker(); -} \ No newline at end of file +} From 0a93ea7c00af5c65892bc129d4d5807caab80526 Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Tue, 3 May 2022 10:06:10 +0100 Subject: [PATCH 29/34] Update Layout.js Remove text scale option, as scale can be set in font, as per #1699 --- modules/Layout.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/modules/Layout.js b/modules/Layout.js index 19553c0a5..f2ebc418a 100644 --- a/modules/Layout.js +++ b/modules/Layout.js @@ -32,9 +32,9 @@ layoutObject has: * `"v"` - Vertical layout, `c` is an array of more `layoutObject` * A `id` field. If specified the object is added with this name to the returned `layout` object, so can be referenced as `layout.foo` -* A `font` field, eg `6x8` or `30%` to use a percentage of screen height -* A `scale` field, eg `2` to set scale of an image or text -* A `r` field to set rotation of text or images. +* A `font` field, eg `6x8` or `30%` to use a percentage of screen height. Set scale with :, e.g. `6x8:2`. +* A `scale` field, eg `2` to set scale of an image +* A `r` field to set rotation of text or images (0: 0°, 1: 90°, 2: 180°, 3: 270°). * A `wrap` field to enable line wrapping. Requires some combination of `width`/`height` and `fillx`/`filly` to be set. Not compatible with text rotation. * A `col` field, eg `#f00` for red @@ -222,13 +222,13 @@ Layout.prototype.render = function (l) { "":function(){}, "txt":function(l){ if (l.wrap) { - g.setFont(l.font, l.scale||1).setFontAlign(0,-1); + g.setFont(l.font).setFontAlign(0,-1); var lines = g.wrapString(l.label, l.w); var y = l.y+((l.h-g.getFontHeight()*lines.length)>>1); // TODO: on 2v11 we can just render in a single drawString call lines.forEach((line, i) => g.drawString(line, l.x+(l.w>>1), y+g.getFontHeight()*i)); } else { - g.setFont(l.font, l.scale||1).setFontAlign(0,0,l.r).drawString(l.label, l.x+(l.w>>1), l.y+(l.h>>1)); + g.setFont(l.font).setFontAlign(0,0,l.r).drawString(l.label, l.x+(l.w>>1), l.y+(l.h>>1)); } }, "btn":function(l){ if (l.font && l.font.endsWith("%")) @@ -252,15 +252,15 @@ Layout.prototype.render = function (l) { "function"==typeof l.src?l.src():l.src, l.x + l.w/2, l.y + l.h/2, - {scale: l.scale ? l.scale : undefined, rotate: Math.PI*0.5*(l.r ? l.r : 0)} + {scale: l.scale||undefined, rotate: Math.PI*0.5*(l.r||0)} ); - else g.setFont(l.font||"6x8", l.scale||2).setFontAlign(0,0,l.r).drawString(l.label,l.x+l.w/2,l.y+l.h/2); + else g.setFont(l.font||"6x8:2").setFontAlign(0,0,l.r).drawString(l.label,l.x+l.w/2,l.y+l.h/2); }, "img":function(l){ g.drawImage( "function"==typeof l.src?l.src():l.src, l.x + l.w/2, l.y + l.h/2, - {scale: l.scale ? l.scale : undefined, rotate: Math.PI*0.5*(l.r ? l.r : 0)} + {scale: l.scale||undefined, rotate: Math.PI*0.5*(l.r||0)} ); }, "custom":function(l){ l.render(l); @@ -358,13 +358,13 @@ Layout.prototype.update = function() { if (l.wrap) { l._h = l._w = 0; } else { - var m = g.setFont(l.font, l.scale||1).stringMetrics(l.label); + var m = g.setFont(l.font).stringMetrics(l.label); l._w = m.width; l._h = m.height; } }, "btn": function(l) { if (l.font && l.font.endsWith("%")) l.font = "Vector"+Math.round(g.getHeight()*l.font.slice(0,-1)/100); - var m = l.src?g.imageMetrics("function"==typeof l.src?l.src():l.src):g.setFont(l.font||"6x8", l.scale||2).stringMetrics(l.label); + var m = l.src?g.imageMetrics("function"==typeof l.src?l.src():l.src):g.setFont(l.font||"6x8:2").stringMetrics(l.label); l._h = 16 + m.height; l._w = 20 + m.width; }, "img": function(l) { From fd5e0bf45c925c54576e601705e245d88afeffe1 Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Tue, 3 May 2022 12:30:50 +0100 Subject: [PATCH 30/34] Update app.js Fix onTouch while timerRunning. Previously briefly showed timer picker numbers. --- apps/smpltmr/app.js | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/apps/smpltmr/app.js b/apps/smpltmr/app.js index b474b8454..37d508359 100644 --- a/apps/smpltmr/app.js +++ b/apps/smpltmr/app.js @@ -50,20 +50,24 @@ function onTouch(button, xy) { var touchMidpoint = timePickerLayout.hours.y + timePickerLayout.hours.h/2; var diff = 0; Bangle.buzz(40, 0.3); - if (!timerRunning() && xy.y > 24 && xy.y < touchMidpoint - 10) { - diff = 1; - } else if (!timerRunning() && xy.y > touchMidpoint + 10 && xy.y < timePickerLayout.btnStart.y) { - diff = -1; - } else if (xy.y > timePickerLayout.btnStart.y) { + if (xy.y > timePickerLayout.btnStart.y) { onButton(); return; } - if (xy.x < timePickerLayout.hours.w) { - diff *= 3600; - } else if (xy.x > timePickerLayout.mins.x && xy.x < timePickerLayout.secs.x) { - diff *= 60; + if (!timerRunning()) { + if (&& xy.y > 24 && xy.y < touchMidpoint - 10) { + diff = 1; + } else if (&& xy.y > touchMidpoint + 10 && xy.y < timePickerLayout.btnStart.y) { + diff = -1; + } + if (xy.x < timePickerLayout.hours.w) { + diff *= 3600; + } else if (xy.x > timePickerLayout.mins.x && xy.x < timePickerLayout.secs.x) { + diff *= 60; + } + updateTimePicker(diff); } - updateTimePicker(diff); + } function onButton() { From aad0a48a88d9456249b9b109a0ee4230b02675df Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Tue, 3 May 2022 12:33:12 +0100 Subject: [PATCH 31/34] Update app.js Whoops --- apps/smpltmr/app.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/smpltmr/app.js b/apps/smpltmr/app.js index 37d508359..1583663ba 100644 --- a/apps/smpltmr/app.js +++ b/apps/smpltmr/app.js @@ -55,9 +55,9 @@ function onTouch(button, xy) { return; } if (!timerRunning()) { - if (&& xy.y > 24 && xy.y < touchMidpoint - 10) { + if (xy.y > 24 && xy.y < touchMidpoint - 10) { diff = 1; - } else if (&& xy.y > touchMidpoint + 10 && xy.y < timePickerLayout.btnStart.y) { + } else if (xy.y > touchMidpoint + 10 && xy.y < timePickerLayout.btnStart.y) { diff = -1; } if (xy.x < timePickerLayout.hours.w) { From 7d5aa89c2194a03e78b7144e2f9047393e73e25f Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Tue, 3 May 2022 12:54:34 +0100 Subject: [PATCH 32/34] Update app.js Fix layout button uninitialised if timer already running. --- apps/smpltmr/app.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/apps/smpltmr/app.js b/apps/smpltmr/app.js index 1583663ba..b7511724a 100644 --- a/apps/smpltmr/app.js +++ b/apps/smpltmr/app.js @@ -47,14 +47,15 @@ function onDrag(event) { } function onTouch(button, xy) { - var touchMidpoint = timePickerLayout.hours.y + timePickerLayout.hours.h/2; - var diff = 0; - Bangle.buzz(40, 0.3); - if (xy.y > timePickerLayout.btnStart.y) { + if (xy.y > (timePickerLayout.btnStart.y||timerLayout.btnStart.y)) { + Bangle.buzz(40, 0.3); onButton(); return; } if (!timerRunning()) { + var touchMidpoint = timePickerLayout.hours.y + timePickerLayout.hours.h/2; + var diff = 0; + Bangle.buzz(40, 0.3); if (xy.y > 24 && xy.y < touchMidpoint - 10) { diff = 1; } else if (xy.y > touchMidpoint + 10 && xy.y < timePickerLayout.btnStart.y) { @@ -159,7 +160,7 @@ var timePickerLayout = new Layout({ var timerLayout = new Layout({ type:"v", c: [ {type:"txt", font:"22%", label:"0:00", id:"timer", fillx:1, filly:1 }, - {type:"btn", src:imgPause, cb: l=>timerStop(), fillx:1 } + {type:"btn", src:imgPause, id:"btnStart", cb: l=>timerStop(), fillx:1 } ], filly:1 }); From c94b8be6292b55d1ec5351fbfa42b391658de2f6 Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Wed, 4 May 2022 10:18:48 +0100 Subject: [PATCH 33/34] Update Layout.js Removed as per https://github.com/espruino/BangleApps/pull/1788#discussion_r863924717 --- modules/Layout.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/modules/Layout.js b/modules/Layout.js index f2ebc418a..c978c611b 100644 --- a/modules/Layout.js +++ b/modules/Layout.js @@ -231,8 +231,6 @@ Layout.prototype.render = function (l) { g.setFont(l.font).setFontAlign(0,0,l.r).drawString(l.label, l.x+(l.w>>1), l.y+(l.h>>1)); } }, "btn":function(l){ - if (l.font && l.font.endsWith("%")) - l.font = "Vector"+Math.round(g.getHeight()*l.font.slice(0,-1)/100); var x = l.x+(0|l.pad), y = l.y+(0|l.pad), w = l.w-(l.pad<<1), h = l.h-(l.pad<<1); var poly = [ From ffcba2a8fe0a9a4cdd2d5870fb81ae8fc0329b1f Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Wed, 4 May 2022 10:19:59 +0100 Subject: [PATCH 34/34] Update app.js Tweak colours --- apps/smpltmr/app.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/apps/smpltmr/app.js b/apps/smpltmr/app.js index b7511724a..4e95d3a30 100644 --- a/apps/smpltmr/app.js +++ b/apps/smpltmr/app.js @@ -135,22 +135,22 @@ var timePickerLayout = new Layout({ {type:undefined, height:2}, {type:"h", c: [ {type:"v", width:g.getWidth()/3, c: [ - {type:"txt", font:"6x8", label:/*LANG*/"Hours", col:g.theme.fg2}, - {type:"img", pad:8, src:imgArrow, col:g.theme.fg2}, + {type:"txt", font:"6x8", label:/*LANG*/"Hours"}, + {type:"img", pad:8, src:imgArrow}, {type:"txt", font:"20%", label:"00", id:"hours", filly:1, fillx:1}, - {type:"img", pad:8, src:imgArrow, col:g.theme.fg2, r:2} + {type:"img", pad:8, src:imgArrow, r:2} ]}, {type:"v", width:g.getWidth()/3, c: [ - {type:"txt", font:"6x8", label:/*LANG*/"Minutes", col:g.theme.fg2}, - {type:"img", pad:8, src:imgArrow, col:g.theme.fg2}, + {type:"txt", font:"6x8", label:/*LANG*/"Minutes"}, + {type:"img", pad:8, src:imgArrow}, {type:"txt", font:"20%", label:"00", id:"mins", filly:1, fillx:1}, - {type:"img", pad:8, src:imgArrow, col:g.theme.fg2, r:2} + {type:"img", pad:8, src:imgArrow, r:2} ]}, {type:"v", width:g.getWidth()/3, c: [ - {type:"txt", font:"6x8", label:/*LANG*/"Seconds", col:g.theme.fg2}, - {type:"img", pad:8, src:imgArrow, col:g.theme.fg2}, + {type:"txt", font:"6x8", label:/*LANG*/"Seconds"}, + {type:"img", pad:8, src:imgArrow}, {type:"txt", font:"20%", label:"00", id:"secs", filly:1, fillx:1}, - {type:"img", pad:8, src:imgArrow, col:g.theme.fg2, r:2} + {type:"img", pad:8, src:imgArrow, r:2} ]}, ]}, {type:"btn", src:imgPlay, id:"btnStart", fillx:1 }