diff --git a/apps/8ball/8ball.png b/apps/8ball/8ball.png new file mode 100644 index 000000000..72344261a Binary files /dev/null and b/apps/8ball/8ball.png differ diff --git a/apps/8ball/ChangeLog b/apps/8ball/ChangeLog new file mode 100644 index 000000000..3bcffb19b --- /dev/null +++ b/apps/8ball/ChangeLog @@ -0,0 +1 @@ +0.01: New App! diff --git a/apps/8ball/app-icon.js b/apps/8ball/app-icon.js new file mode 100644 index 000000000..399dbef21 --- /dev/null +++ b/apps/8ball/app-icon.js @@ -0,0 +1 @@ +atob("MDCBAAAAAAAAAAAAAAAAAAAAH/AAAAAAf/4AAAAB4AeAAAAHgAHgAAAOAABwAAAcAAA4AAA4AMAcAABwAMAOAABgA/AGAADAAeADAAHAAMADgAGAAAABgAGAAAABgAMAAAAAwAMBAAAAwAMDAAAAwAMHwAAAwAMHwAAAwAMDAACAwAMBAADAwAMAAAPgwAMAAAPgwAMAAADAwAGAAACBgAGAAAABgAHAAAADgADAAAADAADgAAAHAAB////+AAB////+AABgAAAGAABgAAAGAABgAAAGAADAAAADAADAAAADAADAAAADAAGAAAABgAGAAAABgAH/////gAP/////wAYAAAAAYAYAAAAAYAf/////4AP/////wAAAAAAAAAAAAAAAAA==") diff --git a/apps/8ball/app.js b/apps/8ball/app.js new file mode 100644 index 000000000..8a3ee427e --- /dev/null +++ b/apps/8ball/app.js @@ -0,0 +1,92 @@ +var keyboard = "textinput"; +var Name = ""; +Bangle.setLCDTimeout(0); +var menuOpen = 1; +var answers = new Array("no", "yes","WHAT????","What do you think", "That was a bad question", "YES!!!", "NOOOOO!!", "nope","100%","yup","why should I answer that?","think for yourself","ask again later, I'm busy", "what Was that horrible question","how dare you?","you wanted to hear yes? okay, yes", "Don't get angry when I say no","you are 100% wrong","totally, for sure","hmmm... I'll ponder it and get back to you later","wow, you really have a lot of questions", "NOPE","is the sky blue, hmmm...","I don't have time to answer","How many more questions before you change my name?","theres this thing called wikipedia","hmm... I don't seem to be able to reach the internet right now","if you phrase it like that, yes","Huh, never thought so hard in my life","The winds of time say no"); +var consonants = new Array("b","c","d","f","g","h","j","k","l","m","n","p","q","r","s","t","v","w","x","y","z"); +var vowels = new Array("a","e","i","o","u"); +try {keyboard = require(keyboard);} catch(e) {keyboard = null;} +function generateName() +{ + Name = ""; + var nameLength = Math.round(Math.random()*5); + for(var i = 0; i < nameLength; i++){ + var cosonant = consonants[Math.round(Math.random()*consonants.length/2)]; + var vowel = vowels[Math.round(Math.random()*vowels.length/2)]; + Name = Name + cosonant + vowel; + if(Name == "") + { + generateName(); + } + } +} +generateName(); +function menu() +{ + g.clear(); + E.showMenu(); + menuOpen = 1; + E.showMenu({ + "" : { title : Name }, + "< Back" : () => menu(), + "Start" : () => { + E.showMenu(); + g.clear(); + menuOpen = 0; + Drawtext("ask " + Name + " a yes or no question"); + }, + "regenerate name" : () => { + menu(); + generateName(); + }, + "show answers" : () => { + var menu = new Array([]); + for(var i = 0; i < answers.length; i++){ + menu.push({title : answers[i]}); + } + E.showMenu(menu); + + + }, + + "Add answer" : () => { + E.showMenu(); + keyboard.input({}).then(result => {if(result != ""){answers.push(result);} menu();}); + }, + "Edit name" : () => { + E.showMenu(); + keyboard.input({}).then(result => {if(result != ""){Name = result;} menu();}); + + }, + "Exit" : () => load(), + }); +} +menu(); + + var answer; +function Drawtext(text) +{ + g.clear(); + g.setFont("Vector", 20); + g.drawString(g.wrapString(text, g.getWidth(), -20).join("\n")); +} +function WriteAnswer() +{ + if (menuOpen == 0) + { + var randomnumber = Math.round(Math.random()*answers.length); + answer = answers[randomnumber]; + Drawtext(answer); + setTimeout(function() { + Drawtext("ask " + Name + " a yes or no question"); +}, 3000); + + } + +} +setWatch(function() { + menu(); + +}, (process.env.HWVERSION==2) ? BTN1 : BTN2, {repeat:true, edge:"falling"}); + + Bangle.on('touch', function(button, xy) { WriteAnswer(); }); diff --git a/apps/8ball/metadata.json b/apps/8ball/metadata.json new file mode 100644 index 000000000..da387d3d6 --- /dev/null +++ b/apps/8ball/metadata.json @@ -0,0 +1,19 @@ +{ "id": "8ball", + "name": "Magic 8 ball", + "shortName":"8ball", + "icon": "8ball.png", + "version":"0.01", + "screenshots": [ + {"url":"screenshot.png"}, + {"url":"screenshot-1.png"}, + {"url":"screenshot-2.png"} + ], + "allow_emulator": true, + "description": "A very sarcastic magic 8ball", + "tags": "game", + "supports": ["BANGLEJS2"], + "storage": [ + {"name":"8ball.app.js","url":"app.js"}, + {"name":"8ball.img","url":"app-icon.js","evaluate":true} + ] +} diff --git a/apps/8ball/screenshot-1.png b/apps/8ball/screenshot-1.png new file mode 100644 index 000000000..edf1a4695 Binary files /dev/null and b/apps/8ball/screenshot-1.png differ diff --git a/apps/8ball/screenshot-2.png b/apps/8ball/screenshot-2.png new file mode 100644 index 000000000..c5c607089 Binary files /dev/null and b/apps/8ball/screenshot-2.png differ diff --git a/apps/8ball/screenshot.png b/apps/8ball/screenshot.png new file mode 100644 index 000000000..f1f888cf3 Binary files /dev/null and b/apps/8ball/screenshot.png differ diff --git a/apps/blc/ChangeLog b/apps/blc/ChangeLog new file mode 100644 index 000000000..4860c24a6 --- /dev/null +++ b/apps/blc/ChangeLog @@ -0,0 +1 @@ +0.10: New app introduced to the app loader! diff --git a/apps/blc/README.md b/apps/blc/README.md new file mode 100644 index 000000000..a3581cdc7 --- /dev/null +++ b/apps/blc/README.md @@ -0,0 +1,13 @@ +# Binary LED Clock + +A binary watch with LEDs, showing time and date. + +From top to bottom the watch face shows four rows of leds: + +* hours (red leds) +* minutes (green leds) +* day (yellow leds, top row) +* month (yellow leds, bottom row) + +As usual, luminous leds represent a logical one, dark leds a logcal '0'. +Widgets aren't affected and are shown as normal. diff --git a/apps/blc/blc-icon.js b/apps/blc/blc-icon.js new file mode 100644 index 000000000..a8d30baee --- /dev/null +++ b/apps/blc/blc-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEw4n/AAIHBqut8FPgH4sspk1T885/feoMI74TB1Fc51Dmfg28gKmMCrNSAgMlyo5BgV7uQIKgEhiMRkECAYMSgErolLBBIXBqIKBqEFAYMVgF0olEuAIIC4ORBQOQhIDBjMA2gOB2AIIF7JfXR67X0lvdHwQII7vSa4/TmYKBBBEtmc9a40NmYKBBBIbBmfQa4oOEBBAXFF65fXR64A/AG8IvN4AgOG62ABAuHy4IGgEHiMXAgNu91gBAtxiNwBAsAhMRjIEB73ucIIIEyMRyAIFF7BfXAH6/IttoKxRoIgEG93mQxSYIgEN93tWxTIIF7BfXAH4AGw93u/A44IDhl8vQRFBogXB0ECuGoBAcKxRxBC53Hhlyk8ggVyuQGBvlwhgNBk98BAN6I4UgC4N4BwWgAwWsC4fAk4IB0AvBAgIQBBwUIkQOBAwQXCJIIEBI4UAkQXE48sAwgXJF40mgAvDvRtCC4pfEC4WCPYJdBDYNyC4wAX")) diff --git a/apps/blc/blc-icon.png b/apps/blc/blc-icon.png new file mode 100644 index 000000000..8bbf6ae71 Binary files /dev/null and b/apps/blc/blc-icon.png differ diff --git a/apps/blc/blc.js b/apps/blc/blc.js new file mode 100644 index 000000000..8a0f93d70 --- /dev/null +++ b/apps/blc/blc.js @@ -0,0 +1,136 @@ +//Binary LED Clock (BLC) by aeMKai + +{ // must be inside our own scope here so that when we are unloaded everything disappears + // we also define functions using 'let fn = function() {..}' for the same reason. function decls are global + let drawTimeout; + + // Actually draw the watch face + let draw = function() + { + // Bangle.js2 -> 176x176 + var x_rgt = g.getWidth(); + var y_bot = g.getHeight(); + //var x_cntr = x_rgt / 2; + var y_cntr = y_bot / 18*7; // not to high because of widget-field (1/3 is to high) + g.reset().clearRect(Bangle.appRect); // clear whole background (w/o widgets) + + let white = [1,1,1]; + let red = [1,0,0]; + let green = [0,1,0]; + //let blue = [0,0,1]; + let yellow = [1,1,0]; + //let magenta = [1,0,1]; + //let cyan = [0,1,1]; + let black = [0,0,0]; + let bord_col = white; + let col_off = black; + + var col = new Array(red, green, yellow, yellow); // [R,G,B] + + let pot_2 = [1, 2, 4, 8, 16, 32]; // array with powers of two, because power-op (**) + // doesn't work -> maybe also faster + + + var nr_lines = 4; // 4 rows: hour (hr), minute (min), day (day), month (mon) + + // Arrays: [hr, min, day, mon] + //No of Bits: 5 6 5 4 + let msbits = [4, 5, 4, 3]; // MSB = No bits - 1 + let rad = [12, 12, 8, 8]; // radiuses for each row + var x_dist = 28; + let y_dist = [0, 30, 60, 85]; // y-position from y_centr for each row from top + // don't calc. automatic as for x, because of different spaces + var x_offs_rgt = 16; // distance from right border (layout) + + // Date-Time-Array: 4x6 Bit + //var idx_hr = 0; + //var idx_min = 1; + //var idx_day = 2; + //var idx_mon = 3; + var dt_bit_arr = [[0, 0, 0, 0, 0, 0],[0, 0, 0, 0, 0, 0],[0, 0, 0, 0, 0, 0],[0, 0, 0, 0, 0, 0]]; + + var date_time = new Date(); + var hr = date_time.getHours(); // 0..23 + var min = date_time.getMinutes(); // 0..59 + var day = date_time.getDate(); // 1..31 + var mon = date_time.getMonth() + 1; // GetMonth() -> 0..11 + + let dt_array = [hr, min, day, mon]; + + +//////////////////////////////////////// +// compute bit-pattern from time/date and draw leds +//////////////////////////////////////// + var line_cnt = 0; + var cnt = 0; + var bit_cnt = 0; + + while (line_cnt < nr_lines) + { + + //////////////////////////////////////// + // compute bit-pattern + bit_cnt = msbits[line_cnt]; + + while (bit_cnt >= 0) + { + if (dt_array[line_cnt] >= pot_2[bit_cnt]) + { + dt_array[line_cnt] -= pot_2[bit_cnt]; + dt_bit_arr[line_cnt][bit_cnt] = 1; + } + else + { + dt_bit_arr[line_cnt][bit_cnt] = 0; + } + bit_cnt--; + } + + //////////////////////////////////////// + // draw leds (first white border for black screen, then led itself) + cnt = 0; + + while (cnt <= msbits[line_cnt]) + { + g.setColor(bord_col[0], bord_col[1], bord_col[2]); + g.drawCircle(x_rgt-x_offs_rgt-cnt*x_dist, y_cntr-20+y_dist[line_cnt], rad[line_cnt]); + + if (dt_bit_arr[line_cnt][cnt] == 1) + { + g.setColor(col[line_cnt][0], col[line_cnt][1], col[line_cnt][2]); + } + else + { + g.setColor(col_off[0], col_off[1], col_off[2]); + } + g.fillCircle(x_rgt-x_offs_rgt-cnt*x_dist, y_cntr-20+y_dist[line_cnt], rad[line_cnt]-1); + cnt++; + } + line_cnt++; + } + + // queue next draw + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function() + { + drawTimeout = undefined; + draw(); + }, 60000 - (Date.now() % 60000)); + }; + + // Show launcher when middle button pressed + Bangle.setUI( + { + mode : "clock", + remove : function() + { + // Called to unload all of the clock app + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = undefined; + } + }); + // Load widgets + Bangle.loadWidgets(); + draw(); + setTimeout(Bangle.drawWidgets,0); +} diff --git a/apps/blc/metadata.json b/apps/blc/metadata.json new file mode 100644 index 000000000..174926ebc --- /dev/null +++ b/apps/blc/metadata.json @@ -0,0 +1,17 @@ +{ + "id":"blc", + "name":"Binary LED Clock", + "version": "0.10", + "description": "Binary LED Clock with date", + "icon":"blc-icon.png", + "screenshots": [{"url":"screenshot_blc.bmp"}], + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS2"], + "allow_emulator": true, + "readme": "README.md", + "storage": [ + {"name":"blc.app.js","url":"blc.js"}, + {"name":"blc.img","url":"blc-icon.js","evaluate":true} + ] +} diff --git a/apps/blc/screenshot_blc.bmp b/apps/blc/screenshot_blc.bmp new file mode 100644 index 000000000..50b8539bb Binary files /dev/null and b/apps/blc/screenshot_blc.bmp differ diff --git a/apps/boxclk/ChangeLog b/apps/boxclk/ChangeLog index cc73fbc08..b78eba44c 100644 --- a/apps/boxclk/ChangeLog +++ b/apps/boxclk/ChangeLog @@ -3,3 +3,4 @@ 0.03: Allows showing the month in short or long format by setting `"shortMonth"` to true or false 0.04: Improves touchscreen drag handling for background apps such as Pattern Launcher 0.05: Fixes step count not resetting after a new day starts +0.06 Added clockbackground app functionality diff --git a/apps/boxclk/app.js b/apps/boxclk/app.js index 12c69e789..548062349 100644 --- a/apps/boxclk/app.js +++ b/apps/boxclk/app.js @@ -5,11 +5,11 @@ * --------------------------------------------------------------- */ + let background = require("clockbg"); let storage = require("Storage"); let locale = require("locale"); let widgets = require("widget_utils"); let date = new Date(); - let bgImage; let configNumber = (storage.readJSON("boxclk.json", 1) || {}).selectedConfig || 0; let fileName = 'boxclk' + (configNumber > 0 ? `-${configNumber}` : '') + '.json'; // Add a condition to check if the file exists, if it does not, default to 'boxclk.json' @@ -71,14 +71,6 @@ * --------------------------------------------------------------- */ - for (let key in boxesConfig) { - if (key === 'bg' && boxesConfig[key].img) { - bgImage = storage.read(boxesConfig[key].img); - } else if (key !== 'selectedConfig') { - boxes[key] = Object.assign({}, boxesConfig[key]); - } - } - let boxKeys = Object.keys(boxes); boxKeys.forEach((key) => { @@ -224,9 +216,7 @@ return function(boxes) { date = new Date(); g.clear(); - if (bgImage) { - g.drawImage(bgImage, 0, 0); - } + background.fillRect(Bangle.appRect); if (boxes.time) { boxes.time.string = modString(boxes.time, locale.time(date, isBool(boxes.time.short, true) ? 1 : 0)); updatePerMinute = isBool(boxes.time.short, true); @@ -412,4 +402,4 @@ widgets.swipeOn(); modSetColor(); setup(); -} \ No newline at end of file +} diff --git a/apps/boxclk/boxclk.space.img b/apps/boxclk/boxclk.space.img deleted file mode 100644 index 1708b5c24..000000000 Binary files a/apps/boxclk/boxclk.space.img and /dev/null differ diff --git a/apps/boxclk/metadata.json b/apps/boxclk/metadata.json index dd81ac436..79b4c3019 100644 --- a/apps/boxclk/metadata.json +++ b/apps/boxclk/metadata.json @@ -4,6 +4,7 @@ "version": "0.05", "description": "A customizable clock with configurable text boxes that can be positioned to show your favorite background", "icon": "app.png", + "dependencies" : { "clockbg":"module" }, "screenshots": [ {"url":"screenshot.png"}, {"url":"screenshot-1.png"}, diff --git a/apps/dedreckon/ChangeLog b/apps/dedreckon/ChangeLog new file mode 100644 index 000000000..263d4078d --- /dev/null +++ b/apps/dedreckon/ChangeLog @@ -0,0 +1 @@ +0.01: attempt to import diff --git a/apps/dedreckon/README.md b/apps/dedreckon/README.md new file mode 100644 index 000000000..706c7f191 --- /dev/null +++ b/apps/dedreckon/README.md @@ -0,0 +1,20 @@ +# Ded Reckon + +Dead Reckoning using compass and step counter. + +This allows logging track using "dead reckoning" -- that's logging +angles from compass and distances from step counter. You need to mark +turns, and point watch to direction of the turn. Simultaneously, it +tries to log positions using GPS. You can use it to calibrate your +step length by comparing GPS and step counter data. It can also get +pretty accurate recording of track walked in right circumstances. + +Tap bottom part of the screen to select display (text or map for +now). Point watch to new direction, then tap top left part of screen +to indicate a turn. + +Map shows blue line for track from dead reckonging, and green line for +track from GPS. + +You probably want magnav installed (and calibrated) for useful +results, as it provides library with better compass. \ No newline at end of file diff --git a/apps/dedreckon/app-icon.js b/apps/dedreckon/app-icon.js new file mode 100644 index 000000000..39b72f00b --- /dev/null +++ b/apps/dedreckon/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwhHXAH4A/AH4A/AFsAFtoADF1wwqF4wwhEI5goGGIjFYN4wFF1KbHGUolIMc4lGSdIwJd9DstAH7FrBywwgad4veDwojJBIIvcFwIACGBYICGDYvEGBYvdFwqyLL8i+LF7oxFRxgveGAQ0EF5IwfMY4vpL5AFLAEYv/F8owoE44vrAY4vmAQIEEF85dGGE0AE4gvoFwpmHd0oINAH4A/AH4AvA")) diff --git a/apps/dedreckon/app.png b/apps/dedreckon/app.png new file mode 100644 index 000000000..db3fcfb88 Binary files /dev/null and b/apps/dedreckon/app.png differ diff --git a/apps/dedreckon/dedreckon.app.js b/apps/dedreckon/dedreckon.app.js new file mode 100644 index 000000000..449bf9c1b --- /dev/null +++ b/apps/dedreckon/dedreckon.app.js @@ -0,0 +1,442 @@ +/* Ded Reckon */ +/* eslint-disable no-unused-vars */ + +/* fmt library v0.1.3 */ +let fmt = { + icon_alt : "\0\x08\x1a\1\x00\x00\x00\x20\x30\x78\x7C\xFE\xFF\x00\xC3\xE7\xFF\xDB\xC3\xC3\xC3\xC3\x00\x00\x00\x00\x00\x00\x00\x00", + icon_m : "\0\x08\x1a\1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xC3\xE7\xFF\xDB\xC3\xC3\xC3\xC3\x00\x00\x00\x00\x00\x00\x00\x00", + icon_km : "\0\x08\x1a\1\xC3\xC6\xCC\xD8\xF0\xD8\xCC\xC6\xC3\x00\xC3\xE7\xFF\xDB\xC3\xC3\xC3\xC3\x00\x00\x00\x00\x00\x00\x00\x00", + icon_kph : "\0\x08\x1a\1\xC3\xC6\xCC\xD8\xF0\xD8\xCC\xC6\xC3\x00\xC3\xE7\xFF\xDB\xC3\xC3\xC3\xC3\x00\xFF\x00\xC3\xC3\xFF\xC3\xC3", + icon_c : "\0\x08\x1a\1\x00\x00\x60\x90\x90\x60\x00\x7F\xFF\xC0\xC0\xC0\xC0\xC0\xFF\x7F\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + + /* 0 .. DD.ddddd + 1 .. DD MM.mmm' + 2 .. DD MM'ss" + */ + geo_mode : 1, + + init: function() {}, + fmtDist: function(km) { + if (km >= 1.0) return km.toFixed(1) + this.icon_km; + return (km*1000).toFixed(0) + this.icon_m; + }, + fmtSteps: function(n) { return this.fmtDist(0.001 * 0.719 * n); }, + fmtAlt: function(m) { return m.toFixed(0) + this.icon_alt; }, + draw_dot : 1, + add0: function(i) { + if (i > 9) { + return ""+i; + } else { + return "0"+i; + } + }, + fmtTOD: function(now) { + this.draw_dot = !this.draw_dot; + let dot = ":"; + if (!this.draw_dot) + dot = "."; + return now.getHours() + dot + this.add0(now.getMinutes()); + }, + fmtNow: function() { return this.fmtTOD(new Date()); }, + fmtTimeDiff: function(d) { + if (d < 180) + return ""+d.toFixed(0); + d = d/60; + return ""+d.toFixed(0)+"m"; + }, + fmtAngle: function(x) { + switch (this.geo_mode) { + case 0: + return "" + x; + case 1: { + let d = Math.floor(x); + let m = x - d; + m = m*60; + return "" + d + " " + m.toFixed(3) + "'"; + } + case 2: { + let d = Math.floor(x); + let m = x - d; + m = m*60; + let mf = Math.floor(m); + let s = m - mf; + s = s*60; + return "" + d + " " + mf + "'" + s.toFixed(0) + '"'; + } + } + return "bad mode?"; + }, + fmtPos: function(pos) { + let x = pos.lat; + let c = "N"; + if (x<0) { + c = "S"; + x = -x; + } + let s = c+this.fmtAngle(x) + "\n"; + c = "E"; + if (x<0) { + c = "W"; + x = -x; + } + return s + c + this.fmtAngle(x); + }, + fmtFix: function(fix, t) { + if (fix && fix.fix && fix.lat) { + return this.fmtSpeed(fix.speed) + " " + + this.fmtAlt(fix.alt); + } else { + return "N/FIX " + this.fmtTimeDiff(t); + } + }, + fmtSpeed: function(kph) { + return kph.toFixed(1) + this.icon_kph; + }, +}; + +/* gps library v0.1.1 */ +let gps = { + emulator: -1, + init: function(x) { + this.emulator = (process.env.BOARD=="EMSCRIPTEN" + || process.env.BOARD=="EMSCRIPTEN2")?1:0; + }, + state: {}, + on_gps: function(f) { + let fix = this.getGPSFix(); + f(fix); + + /* + "lat": number, // Latitude in degrees + "lon": number, // Longitude in degrees + "alt": number, // altitude in M + "speed": number, // Speed in kph + "course": number, // Course in degrees + "time": Date, // Current Time (or undefined if not known) + "satellites": 7, // Number of satellites + "fix": 1 // NMEA Fix state - 0 is no fix + "hdop": number, // Horizontal Dilution of Precision + */ + this.state.timeout = setTimeout(this.on_gps, 1000, f); + }, + off_gps: function() { + clearTimeout(this.state.timeout); + }, + getGPSFix: function() { + if (!this.emulator) + return Bangle.getGPSFix(); + let fix = {}; + fix.fix = 1; + fix.lat = 50; + fix.lon = 14-(getTime()-this.gps_start) / 1000; /* Go West! */ + fix.alt = 200; + fix.speed = 5; + fix.course = 30; + fix.time = Date(); + fix.satellites = 5; + fix.hdop = 12; + return fix; + }, + gps_start : -1, + start_gps: function() { + Bangle.setGPSPower(1, "libgps"); + this.gps_start = getTime(); + }, + stop_gps: function() { + Bangle.setGPSPower(0, "libgps"); + }, +}; + +/* ui library 0.1 */ +let ui = { + display: 0, + numScreens: 2, + drawMsg: function(msg) { + g.reset().setFont("Vector", 35) + .setColor(1,1,1) + .fillRect(0, this.wi, 176, 176) + .setColor(0,0,0) + .drawString(msg, 5, 30); + }, + drawBusy: function() { + this.drawMsg("\n.oO busy"); + }, + nextScreen: function() { + print("nextS"); + this.display = this.display + 1; + if (this.display == this.numScreens) + this.display = 0; + this.drawBusy(); + }, + prevScreen: function() { + print("prevS"); + this.display = this.display - 1; + if (this.display < 0) + this.display = this.numScreens - 1; + this.drawBusy(); +}, + onSwipe: function(dir) { + this.nextScreen(); +}, + h: 176, + w: 176, + wi: 32, + last_b: 0, + touchHandler: function(d) { + let x = Math.floor(d.x); + let y = Math.floor(d.y); + + if (d.b != 1 || this.last_b != 0) { + this.last_b = d.b; + return; + } + + print("touch", x, y, this.h, this.w); + + /* + if ((xthis.h/2) && (ythis.w/2)) { + print("prev"); + this.prevScreen(); + } + if ((x>this.h/2) && (y>this.w/2)) { + print("next"); + this.nextScreen(); + } + }, + init: function() { + } +}; + +var last_steps = Bangle.getStepCount(), last_time = getTime(), speed = 0, step_phase = 0; + +var mpstep = 0.719 * 1.15; + +function updateSteps() { + if (step_phase ++ > 9) { + step_phase =0; + let steps = Bangle.getStepCount(); + let time = getTime(); + + speed = 3.6 * mpstep * ((steps-last_steps) / (time-last_time)); + last_steps = steps; + last_time = time; + } + return "" + fmt.fmtSpeed(speed) + " " + step_phase + "\n" + fmt.fmtDist(log_dist/1000) + " " + fmt.fmtDist(log_last/1000); +} + +/* compensated compass */ +var CALIBDATA = require("Storage").readJSON("magnav.json",1)||null; +const tiltfixread = require("magnav").tiltfixread; +var heading; + + +var cancel_gps = false; + +function drawStats() { + let fix = gps.getGPSFix(); + + let msg = fmt.fmtFix(fix, getTime() - gps.gps_start); + + msg += "\n" + fmt.fmtDist(gps_dist/1000) + " " + fmt.fmtDist(gps_last/1000) + "\n" + updateSteps(); + let c = Bangle.getCompass(); + if (c) msg += "\n" + c.heading.toFixed(0) + "/" + heading.toFixed(0) + "deg " + log.length + "\n"; + + g.reset().clear().setFont("Vector", 31) + .setColor(1,1,1) + .fillRect(0, 24, 176, 100) + .setColor(0,0,0) + .drawString(msg, 3, 25); +} + +function updateGps() { + if (cancel_gps) + return; + heading = tiltfixread(CALIBDATA.offset,CALIBDATA.scale); + if (ui.display == 0) { + setTimeout(updateGps, 1000); + drawLog(); + drawStats(); + } + if (ui.display == 1) { + setTimeout(updateGps, 1000); + drawLog(); + } +} + +function stopGps() { + cancel_gps=true; + gps.stop_gps(); +} + +var log = [], log_dist = 0, gps_dist = 0; +var log_last = 0, gps_last = 0; + +function logEntry() { + let e = {}; + e.time = getTime(); + e.fix = gps.getGPSFix(); + e.steps = Bangle.getStepCount(); + if (0) { + let c = Bangle.getCompass(); + if (c) + e.dir = c.heading; + else + e.dir = -1; + } else { + e.dir = heading; + } + return e; +} + +function onTurn() { + let e = logEntry(); + log.push(e); +} + +function radians(a) { return a*Math.PI/180; } +function degrees(a) { return a*180/Math.PI; } +// distance between 2 lat and lons, in meters, Mean Earth Radius = 6371km +// https://www.movable-type.co.uk/scripts/latlong.html +// (Equirectangular approximation) +function calcDistance(a,b) { + var x = radians(b.lon-a.lon) * Math.cos(radians((a.lat+b.lat)/2)); + var y = radians(b.lat-a.lat); + return Math.sqrt(x*x + y*y) * 6371000; +} + +var dn, de; +function initConv(fix) { + let n = { lat: fix.lat+1, lon: fix.lon }; + let e = { lat: fix.lat, lon: fix.lon+1 }; + + dn = calcDistance(fix, n); + de = calcDistance(fix, e); + print("conversion is ", dn, 108000, de, 50000); +} +function toM(start, fix) { + return { x: (fix.lon - start.lon) * de, y: (fix.lat - start.lat) * dn }; +} +var mpp = 4; +function toPix(q) { + let p = { x: q.x, y: q.y }; + p.x /= mpp; /* 10 m / pix */ + p.y /= -mpp; + p.x += 85; + p.y += 85; + return p; +} + +function drawLog() { + let here = logEntry(); + if (!here.fix.lat) { + here.fix.lat = 50; + here.fix.lon = 14; + } + initConv(here.fix); + log.push(here); + let l = log; + log_dist = 0; + log_last = -1; + gps_last = -1; + + g.reset().clear(); + g.setColor(0, 0, 1); + let last = { x: 0, y: 0 }; + for (let i = l.length - 2; i >= 0; i--) { + let next = {}; + let m = (l[i+1].steps - l[i].steps) * mpstep; + let dir = radians(180 + l[i].dir); + next.x = last.x + m * Math.sin(dir); + next.y = last.y + m * Math.cos(dir); + print(dir, m, last, next); + let lp = toPix(last); + let np = toPix(next); + g.drawLine(lp.x, lp.y, np.x, np.y); + g.drawCircle(np.x, np.y, 3); + last = next; + if (log_last == -1) + log_last = m; + log_dist += m; + } + g.setColor(0, 1, 0); + last = { x: 0, y: 0 }; + gps_dist = 0; + for (let i = l.length - 2; i >= 0; i--) { + let fix = l[i].fix; + if (fix.fix && fix.lat) { + let next = toM(here.fix, fix); + let lp = toPix(last); + let np = toPix(next); + let d = Math.sqrt((next.x-last.x)*(next.x-last.x)+(next.y-last.y)*(next.y-last.y)); + if (gps_last == -1) + gps_last = d; + gps_dist += d; + g.drawLine(lp.x, lp.y, np.x, np.y); + g.drawCircle(np.x, np.y, 3); + last = next; + } + } + log.pop(); +} + +function testPaint() { + let pos = gps.getGPSFix(); + log = []; + let e = { fix: pos, steps: 100, dir: 0 }; + log.push(e); + e = { fix: pos, steps: 200, dir: 90 }; + log.push(e); + e = { fix: pos, steps: 300, dir: 0 }; + log.push(e); + print(log, log.length, log[0], log[1]); + drawLog(); +} + +function touchHandler(d) { + let x = Math.floor(d.x); + let y = Math.floor(d.y); + + if (d.b != 1 || ui.last_b != 0) { + ui.last_b = d.b; + return; + } + + + if ((xui.h/2) && (y ui.onSwipe(s), + clock : 0 +}); + +if (0) + testPaint(); +if (1) { + g.reset(); + updateGps(); +} diff --git a/apps/dedreckon/metadata.json b/apps/dedreckon/metadata.json new file mode 100644 index 000000000..79bf8868e --- /dev/null +++ b/apps/dedreckon/metadata.json @@ -0,0 +1,13 @@ +{ "id": "dedreckon", + "name": "Ded Reckon", + "version": "0.01", + "description": "Dead Reckoning using compass and step counter", + "icon": "app.png", + "readme": "README.md", + "supports" : ["BANGLEJS2"], + "tags": "outdoors", + "storage": [ + {"name":"dedreckon.app.js","url":"dedreckon.app.js"}, + {"name":"dedreckon.img","url":"app-icon.js","evaluate":true} + ] +} diff --git a/apps/drained/ChangeLog b/apps/drained/ChangeLog index 65c93e70f..3767ad71e 100644 --- a/apps/drained/ChangeLog +++ b/apps/drained/ChangeLog @@ -4,3 +4,4 @@ Also avoid polluting global scope. 0.04: Enhance menu: enable bluetooth, visit settings & visit recovery 0.05: Enhance menu: permit toggling bluetooth +0.06: Display clock in green when charging, with "charging" text diff --git a/apps/drained/app.js b/apps/drained/app.js index c74affea3..deafe7d68 100644 --- a/apps/drained/app.js +++ b/apps/drained/app.js @@ -37,14 +37,19 @@ var draw = function () { require("locale").dow(date, 0).toUpperCase(); var x2 = x + 6; var y2 = y + 66; + var charging = Bangle.isCharging(); g.reset() .clearRect(Bangle.appRect) .setFont("Vector", 55) .setFontAlign(0, 0) + .setColor(charging ? "#0f0" : g.theme.fg) .drawString(timeStr, x, y) .setFont("Vector", 24) - .drawString(dateStr, x2, y2) - .drawString("".concat(E.getBattery(), "%"), x2, y2 + 48); + .drawString(dateStr, x2, y2); + if (charging) + g.drawString("charging: ".concat(E.getBattery(), "%"), x2, y2 + 48); + else + g.drawString("".concat(E.getBattery(), "%"), x2, y2 + 48); if (nextDraw) clearTimeout(nextDraw); nextDraw = setTimeout(function () { @@ -96,8 +101,10 @@ function drainedRestore() { load(); } var checkCharge = function () { - if (E.getBattery() < restore) + if (E.getBattery() < restore) { + draw(); return; + } drainedRestore(); }; if (Bangle.isCharging()) diff --git a/apps/drained/app.ts b/apps/drained/app.ts index de6114f99..a779a8660 100644 --- a/apps/drained/app.ts +++ b/apps/drained/app.ts @@ -54,15 +54,21 @@ const draw = () => { require("locale").dow(date, 0).toUpperCase(); const x2 = x + 6; const y2 = y + 66; + const charging = Bangle.isCharging(); g.reset() .clearRect(Bangle.appRect) .setFont("Vector", 55) .setFontAlign(0, 0) + .setColor(charging ? "#0f0" : g.theme.fg) .drawString(timeStr, x, y) .setFont("Vector", 24) - .drawString(dateStr, x2, y2) - .drawString(`${E.getBattery()}%`, x2, y2 + 48); + .drawString(dateStr, x2, y2); + + if(charging) + g.drawString(`charging: ${E.getBattery()}%`, x2, y2 + 48); + else + g.drawString(`${E.getBattery()}%`, x2, y2 + 48); if(nextDraw) clearTimeout(nextDraw); nextDraw = setTimeout(() => { @@ -125,7 +131,10 @@ function drainedRestore() { // "public", to allow users to call } const checkCharge = () => { - if(E.getBattery() < restore) return; + if(E.getBattery() < restore) { + draw(); + return; + } drainedRestore(); }; diff --git a/apps/drained/metadata.json b/apps/drained/metadata.json index 115289d09..a5389a91b 100644 --- a/apps/drained/metadata.json +++ b/apps/drained/metadata.json @@ -1,7 +1,7 @@ { "id": "drained", "name": "Drained", - "version": "0.05", + "version": "0.06", "description": "Switches to displaying a simple clock when the battery percentage is low, and disables some peripherals", "readme": "README.md", "icon": "icon.png", diff --git a/apps/ffcniftyapp/ChangeLog b/apps/ffcniftyapp/ChangeLog index 30dcec467..ef797827e 100644 --- a/apps/ffcniftyapp/ChangeLog +++ b/apps/ffcniftyapp/ChangeLog @@ -1,3 +1,4 @@ 0.01: New Clock Nifty A ++ >> adding more information on the right side of the clock +0.02: Fix weather icon for languages other than English diff --git a/apps/ffcniftyapp/app.js b/apps/ffcniftyapp/app.js index 840dd72ff..5ca48c2f1 100644 --- a/apps/ffcniftyapp/app.js +++ b/apps/ffcniftyapp/app.js @@ -1,5 +1,5 @@ const w = require("weather"); -//const locale = require("locale"); +const locale = require("locale"); // Weather icons from https://icons8.com/icon/set/weather/color function getSun() { @@ -67,6 +67,33 @@ function chooseIcon(condition) { return getPartSun; } else return getErr; } + +/* +* Choose weather icon to display based on weather conditition code +* https://openweathermap.org/weather-conditions#Weather-Condition-Codes-2 +*/ +function chooseIconByCode(code) { + const codeGroup = Math.round(code / 100); + switch (codeGroup) { + case 2: return getStorm; + case 3: return getRain; + case 5: + switch (code) { + case 511: return getSnow; + default: return getRain; + } + case 6: return getSnow; + case 7: return getPartSun; + case 8: + switch (code) { + case 800: return getSun; + case 804: return getCloud; + default: return getPartSun; + } + default: return getCloud; + } +} + /*function condenseWeather(condition) { condition = condition.toLowerCase(); if (condition.includes("thunderstorm") || @@ -143,8 +170,17 @@ const clock = new ClockFace({ //let cWea =(curr === "no data" ? "no data" : curr.txt); let cTemp= (curr === "no data" ? 273 : curr.temp); // const temp = locale.temp(curr.temp - 273.15).match(/^(\D*\d*)(.*)$/); - let w_icon = chooseIcon(curr.txt === undefined ? "no data" : curr.txt ); - //let w_icon = chooseIcon(curr.txt); + + let w_icon = getErr; + if (locale.name === "en" || locale.name === "en_GB" || locale.name === "en_US") { + w_icon = chooseIcon(curr.txt === undefined ? "no data" : curr.txt); + } else { + // cannot use condition string to determine icon if language is not English; use weather code instead + const code = curr.code || -1; + if (code > 0) { + w_icon = chooseIconByCode(curr.code); + } + } g.setFontAlign(1, 0).setFont("Vector", 90 * this.scale); g.drawString(format(hour), this.centerTimeScaleX, this.center.y - 31 * this.scale); diff --git a/apps/ffcniftyapp/metadata.json b/apps/ffcniftyapp/metadata.json index bbe8e7e69..6f368160b 100644 --- a/apps/ffcniftyapp/metadata.json +++ b/apps/ffcniftyapp/metadata.json @@ -1,7 +1,7 @@ { "id": "ffcniftyapp", "name": "Nifty-A Clock ++", - "version": "0.01", + "version": "0.02", "description": "A nifty clock with time and date and more", "dependencies": {"weather":"app"}, "icon": "app.png", diff --git a/apps/fwupdate/custom.html b/apps/fwupdate/custom.html index 6c47cf3f2..606e59d89 100644 --- a/apps/fwupdate/custom.html +++ b/apps/fwupdate/custom.html @@ -106,6 +106,7 @@ function onInit(device) { else if (crcs[0] == 3816337552) version = "2v21"; else if (crcs[0] == 3329616485) version = "2v22"; else if (crcs[0] == 1569433504) version = "2v23"; + else if (crcs[0] == 680675961) version = "2v24"; else { // for other versions all 7 pages are used, check those var crc = crcs[1]; if (crc==1339551013) { version = "2v10.219"; ok = false; } diff --git a/apps/gipy/ChangeLog b/apps/gipy/ChangeLog index 6e72fee81..b0445c161 100644 --- a/apps/gipy/ChangeLog +++ b/apps/gipy/ChangeLog @@ -138,4 +138,6 @@ 0.25: Minor code improvements -0.26: Support for large paths (grid sizes > 65k) +0.26: Add option to plot openstmap if installed + +0.27: Support for large paths (grid sizes > 65k) diff --git a/apps/gipy/app.js b/apps/gipy/app.js index 566975a3e..659e12d98 100644 --- a/apps/gipy/app.js +++ b/apps/gipy/app.js @@ -666,11 +666,11 @@ class Status { towards = next_point; } let diff = towards.minus(this.projected_point); - direction = Math.atan2(diff.lat, diff.lon); + const direction = Math.atan2(diff.lat, diff.lon); let full_angle = direction - this.angle; - c = this.projected_point.coordinates( + const c = this.projected_point.coordinates( this.displayed_position, this.adjusted_cos_direction, this.adjusted_sin_direction, @@ -1400,7 +1400,7 @@ function ask_options(fn) { g.flip(); function options_select(b, xy) { - end = false; + let end = false; if (xy.y < height / 2 - 10) { g.setColor(0, 0, 0).fillRect(10, 10, width - 10, height / 2 - 10); g.setColor(1, 1, 1).setFont("Vector:30").setFontAlign(0,0).drawString("Forward", width/2, height/4); @@ -1480,6 +1480,98 @@ function start_gipy(path, maps, interests, heights) { } }, }; + try { + // plot openstmap option if installed + const osm = require("openstmap"); + menu[/*LANG*/"Plot OpenStMap"] = function() { + E.showMenu(); // remove menu + + // compute min/max coordinates + const fix = Bangle.getGPSFix(); + let minLat = fix.lat ? fix.lat : 90; + let maxLat = fix.lat ? fix.lat : -90; + let minLong = fix.lon ? fix.lon : 180; + let maxLong = fix.lon ? fix.lon : -180; + for(let i=0; imaxLat) maxLat=point.lat; if(point.latmaxLong) maxLong=point.lon; if(point.lon scaleY ? scaleX : scaleY)*1.1); // add 10% margin + osm.lat = (minLat+maxLat)/2.0; + osm.lon = (minLong+maxLong)/2.0; + + const drawOpenStmap = () => { + g.clearRect(Bangle.appRect); + osm.draw(); + + // draw track + g.setColor("#f09"); + for(let i=0; i { // back handling + g.clearRect(0, 0, g.getWidth(), g.getHeight()); + E.showMenu(menu); + }, + drag: (ev) => { // zoom, move + if (ev.b) { + osm.scroll(ev.dx, ev.dy); + if (!startDrag) { + startDrag = getTime(); + } + } else { + if (getTime() - startDrag < 0.2) { + // tap + if (ev.y > g.getHeight() / 2) { + osm.scale *= 2; + } else { + osm.scale /= 2; + } + } + startDrag = 0; + drawOpenStmap(); + } + }, + }); + }; + } catch (ex) { + // openstmap not available. + } E.showMenu(menu); }, BTN1, diff --git a/apps/iconbits/ChangeLog b/apps/iconbits/ChangeLog index 263d4078d..10f5d311c 100644 --- a/apps/iconbits/ChangeLog +++ b/apps/iconbits/ChangeLog @@ -1 +1,2 @@ 0.01: attempt to import +0.02: implement colors and lines diff --git a/apps/iconbits/README.md b/apps/iconbits/README.md index c5c524ab0..90bc0f5a3 100644 --- a/apps/iconbits/README.md +++ b/apps/iconbits/README.md @@ -3,5 +3,18 @@ Bitmap editor suitable for creating icons and fonts for BangleJS2. You'll want to run a copy of this in simulator, and another one on -watch to view the results. Draw using the provided tools, then press -the button, and you'll get result on the console. +watch to view the results. + +Draw using the provided tools, then press the button, and you'll get +result on the console; you can also use "dump();" on command +line. show_icon() takes same parameter as is used in app-icon.js +files, you can just copy&paste it to get an icon. By using +"for_screen();" command, then taking a screenshot, you can easily +generate app.png file. + +It is also possible to load existing icon into editor, using +"load_icon("");" command. At the end of iconbits.app.js file there are +more utility functions. + + + diff --git a/apps/iconbits/app.png b/apps/iconbits/app.png index 7a3ee2e90..d4e822ac7 100644 Binary files a/apps/iconbits/app.png and b/apps/iconbits/app.png differ diff --git a/apps/iconbits/iconbits.app.js b/apps/iconbits/iconbits.app.js index 625070dd5..5fc10423c 100644 --- a/apps/iconbits/iconbits.app.js +++ b/apps/iconbits/iconbits.app.js @@ -10,14 +10,16 @@ let kule = [0, 0, 0]; // R, G, B var font_height = 22, font_width = 8; var zoom_x = 64, zoom_y = 24, zoom_f = 6; + var color = true; let oldLock = false; let sg = null; + const top_bar = 20; function clear(m) { sg.setColor(1,1,1).fillRect(0,0, font_width, font_height); } - function setup(m) { + function __setup(m) { mode = m; switch (m) { case 'font': @@ -37,19 +39,32 @@ zoom_f = 2; break; } + } + function setup(m) { + __setup(m); sg = Graphics.createArrayBuffer(font_width, font_height, 8, {}); clear(); } + function icon_big() { + zoom_x = 16; + zoom_y = 25; + zoom_f = 3; + } + + function icon_small() { + __setup("icon"); + } + function updateLock() { if (oldLock) { return; } g.setColor('#fff'); g.fillRect(0, 0, g.getWidth(), 20); - g.setFont('6x8', 2); + g.setFont('Vector', 22); g.setColor('#000'); - g.drawString('PLEASE UNLOCK', 10, 2); + g.drawString('PLEASE\nUNLOCK', 10, 2); oldLock = true; } Bangle.on("lock", function() { @@ -60,17 +75,20 @@ Bangle.on("lock", function() { drawUtil(); } }); - function nextColor () { + function nextColor() { kule[0] = Math.random(); kule[1] = Math.random(); kule[2] = Math.random(); } - function selectColor (x) { - let c; + function selectColor(x) { + if (color) { + let i = Math.floor((x - 32) / 4); + kule = toColor(i); + return; + } + let c = 255; if (x < g.getWidth()/2) { c = 0; - } else { - c = 255; } kule[0] = c; kule[1] = c; @@ -79,8 +97,8 @@ Bangle.on("lock", function() { function nextPen () { switch (pen) { case 'circle': pen = 'pixel'; break; - case 'pixel': pen = 'crayon'; break; - case 'crayon': pen = 'square'; break; + case 'pixel': pen = 'line'; break; + case 'line': pen = 'square'; break; case 'square': pen = 'circle'; break; default: pen = 'pixel'; break; } @@ -89,8 +107,8 @@ Bangle.on("lock", function() { discard = setTimeout(function () { oldX = -1; oldY = -1; console.log('timeout'); discard = null; }, 500); } - var oldX = -1; - var oldY = -1; + var oldX = -1, oldY = -1; + var line_from = null; function drawBrushIcon () { const w = g.getWidth(); @@ -110,13 +128,17 @@ Bangle.on("lock", function() { g.drawLine(w - 14, 6, w - 10, 12); g.drawLine(w - 6, 6, w - 10, 12); break; + case 'line': + g.drawLine(w - 5, 5, w - 15, 15); + break; } } - function drawArea () { + function drawArea() { g.clear(); if (mode == "draw") return; + const w = g.getWidth; g.setColor(0, 0, 0.5); g.fillRect(0, 0, g.getWidth(), g.getHeight()); g.setColor(1, 1, 1); @@ -129,13 +151,28 @@ Bangle.on("lock", function() { update(); } - function drawUtil () { + function toColor(i) { + let r = [0, 0, 0]; + r[0] = (i % 3) / 2; + i = Math.floor(i / 3); + r[1] = (i % 3) / 2; + i = Math.floor(i / 3); + r[2] = (i % 3) / 2; + return r; + } + + function drawUtil() { if (Bangle.isLocked()) { updateLock(); } // titlebar g.setColor(kule[0], kule[1], kule[2]); - g.fillRect(0, 0, g.getWidth(), 20); + g.fillRect(0, 0, g.getWidth(), top_bar); + for (let i = 0; i < 3*3*3; i++) { + let r = toColor(i); + g.setColor(r[0], r[1], r[2]); + g.fillRect(32+4*i, 12, 32+4*i+3, top_bar); + } // clear button g.setColor('#000'); // black g.fillCircle(10, 10, 8, 8); @@ -149,7 +186,7 @@ Bangle.on("lock", function() { drawBrushIcon(); } - function transform (p) { + function transform(p) { if (p.x < zoom_x || p.y < zoom_y) return p; p.x = ((p.x - zoom_x) / zoom_f); @@ -159,8 +196,12 @@ Bangle.on("lock", function() { return p; } - function __draw (g, from, to) { + function __draw(g, from, to) { + let XS = (to.x - from.x) / 32; + let YS = (to.y - from.y) / 32; + switch (pen) { + case 'line': case 'pixel': g.drawLine(from.x, from.y, to.x, to.y); break; @@ -170,27 +211,25 @@ Bangle.on("lock", function() { g.drawLine(from.x + 2, from.y + 2, to.x, to.y + 2); break; case 'circle': - var XS = (to.x - from.x) / 32; - var YS = (to.y - from.y) / 32; for (let i = 0; i < 32; i++) { - g.fillCircle(from.x + (i * XS), from.y + (i * YS), 4, 4); + g.fillCircle(from.x + (i * XS), from.y + (i * YS), 2, 2); } break; case 'square': - var XS = (to.x - from.x) / 32; - var YS = (to.y - from.y) / 32; for (let i = 0; i < 32; i++) { const posX = from.x + (i * XS); const posY = from.y + (i * YS); - g.fillRect(posX - 10, posY - 10, posX + 10, posY + 10); + g.fillRect(posX - 4, posY - 4, posX + 4, posY + 4); } break; + default: + print("Unkown pen ", pen); } - } function update() { - g.drawImage(sg, 0, 64, {}); + if (zoom_f < 3) + g.drawImage(sg, 4, 64, {}); g.drawImage(sg, zoom_x, zoom_y, { scale: zoom_f }); } @@ -227,7 +266,7 @@ Bangle.on("lock", function() { }, 100); // tap and hold the clear button - if (tap.x < 32 && tap.y < 32) { + if (tap.x < 32 && tap.y < top_bar) { if (tap.b === 1) { if (tapTimer === null) { tapTimer = setTimeout(function () { @@ -244,7 +283,7 @@ Bangle.on("lock", function() { } return; } - if (tap.x > g.getWidth() - 32 && tap.y < 32) { + if (tap.x > g.getWidth() - 32 && tap.y < top_bar) { if (tap.b === 1) { if (tapTimer === null) { tapTimer = setTimeout(function () { @@ -264,7 +303,7 @@ Bangle.on("lock", function() { } drawUtil(); return; - } else if (tap.y < 32) { + } else if (tap.y < top_bar) { if (mode == "draw") nextColor(); else @@ -272,20 +311,31 @@ Bangle.on("lock", function() { drawUtil(); return; } - oldX = to.x; - oldY = to.y; sg.setColor(kule[0], kule[1], kule[2]); g.setColor(kule[0], kule[1], kule[2]); + oldX = to.x; + oldY = to.y; - do_draw(from, to); + if (pen != "line") { + do_draw(from, to); + } else { + if (tap.b == 1) { + print(line_from); + if (!line_from) { + line_from = to; + } else { + do_draw(line_from, to); + line_from = null; + } + } + } drawUtil(); } - function on_btn(n) { + +function dump(n) { function f(i) { return "\\x" + i.toString(16).padStart(2, '0'); } - print("on_btn", n); - print(g.getPixel(0, 0)); let s = f(0) + f(font_width) + f(font_height) + f(1); // 0..black, 65535..white for (let y = 0; y < font_height; y++) { @@ -296,41 +346,55 @@ Bangle.on("lock", function() { } s += f(v); } - print("Manual bitmap\n"); - print('ft("' + s + '");'); - if (1) { - s = ""; - var im = sg.asImage("string"); - for (var v of im) { - //print("val", v, typeof v); - s += f(v); - } - //print("wh", im, typeof im, im[0], typeof im[0]); - //print("Image:", im.length, s); - print('fi("'+btoa(im)+'");'); - } - - + if (mode == "font") + print('show_font("' + s + '");'); + var im = sg.asImage("string"); + //print('show_unc_icon("'+btoa(im)+'");'); + print('show_icon("'+btoa(require('heatshrink').compress(im))+'");'); } - setup("icon"); - drawArea(); - Bangle.setUI({ +setup("icon"); +drawArea(); +Bangle.setUI({ "mode": "custom", "drag": on_drag, - "btn": on_btn, - }); - drawUtil(); + "btn": dump, +}); +drawUtil(); - -function ft(icon) { +function show_font(icon) { g.reset().clear(); g.setFont("Vector", 26).drawString("Hellord" + icon, 0, 0); } -function fi(icon) { +function show_bin_icon(icon) { g.reset().clear(); - g.drawImage(atob(icon), 40, 40); + g.drawImage(icon, 40, 40); +} + +function show_unc_icon(icon) { + show_bin_icon(atob(icon)); +} + +function show_icon(icon) { + let unc = require("heatshrink").decompress(atob(icon)); + show_bin_icon(unc); +} + +function load_bin_icon(i) { + sg.reset().clear(); + sg.drawImage(i, 0, 0); + drawArea(); +} + +function load_icon(icon) { + let unc = require("heatshrink").decompress(atob(icon)); + load_bin_icon(unc); +} + +function for_screen() { + g.reset().clear(); + icon_big(); + update(); } -//ft(icon_10 + "23.1" + icon_hpa); diff --git a/apps/iconbits/metadata.json b/apps/iconbits/metadata.json index b98a43953..edb4b4d6a 100644 --- a/apps/iconbits/metadata.json +++ b/apps/iconbits/metadata.json @@ -1,6 +1,6 @@ { "id": "iconbits", "name": "Icon bits", - "version": "0.01", + "version": "0.02", "description": "Bitmap editor suitable for creating icons", "icon": "app.png", "readme": "README.md", diff --git a/apps/lato/ChangeLog b/apps/lato/ChangeLog index 686f3b707..814b06b31 100644 --- a/apps/lato/ChangeLog +++ b/apps/lato/ChangeLog @@ -1,3 +1,4 @@ 0.01: first release 0.02: Use clock_info module as an app -0.03: clock_info now uses app name to maintain settings specifically for this clock face \ No newline at end of file +0.03: clock_info now uses app name to maintain settings specifically for this clock face +0.04: add optional date display, and a settings page to configure it \ No newline at end of file diff --git a/apps/lato/README.md b/apps/lato/README.md index 556ee6fbc..1dc571509 100644 --- a/apps/lato/README.md +++ b/apps/lato/README.md @@ -5,6 +5,7 @@ A simple clock with the Lato font, with fast load and clock_info ![](screenshot1.png) ![](screenshot2.png) ![](screenshot3.png) +![](screenshot4.png) This clock is a Lato version of Simplest++. Simplest++ provided the smallest example of a clock that supports 'fast load' and 'clock @@ -25,6 +26,8 @@ Pastel Clock. * Settings are saved automatically and reloaded along with the clock. +* Date display can be enabled and disabled, along with format choice in the app settings + ## About Clock Info's * The clock info modules enable all clocks to add the display of information to the clock face. @@ -52,3 +55,5 @@ Pastel Clock. Written by: [Hugh Barney](https://github.com/hughbarney) For support and discussion please post in the [Bangle JS Forum](http://forum.espruino.com/microcosms/1424/) + +Date functionality added by [Septolum](https://github.com/Septolum) diff --git a/apps/lato/app.js b/apps/lato/app.js index 88e723a78..369cba17f 100644 --- a/apps/lato/app.js +++ b/apps/lato/app.js @@ -38,6 +38,11 @@ Graphics.prototype.setFontLatoSmall = function(scale) { // must be inside our own scope here so that when we are unloaded everything disappears // we also define functions using 'let fn = function() {..}' for the same reason. function decls are global + let settings = Object.assign({ + dateDisplay: false, + dateFormat: 0, + }, require("Storage").readJSON("lato.json", true) || {}); + let draw = function() { var date = new Date(); var timeStr = require("locale").time(date,1); @@ -53,6 +58,25 @@ Graphics.prototype.setFontLatoSmall = function(scale) { g.setFontAlign(0, 0); g.setColor(g.theme.fg); g.drawString(timeStr, w/2, h/2); + + if (settings.dateDisplay) { + switch (settings.dateFormat) { + case 1: + var dateStr = require("locale").date(date,1); + break; + + case 2: + var dateStr = require("locale").date(date); + break; + + default: + var dateStr = require("locale").dow(date,1) + ', ' + date.getDate() + ' ' + require("locale").month(date,1); + break; + } + g.setFontVector(16); + g.drawString(dateStr, w/2, h/4 -4); + } + clockInfoMenu.redraw(); // clock_info_support // schedule a draw for the next minute diff --git a/apps/lato/metadata.json b/apps/lato/metadata.json index 406413790..baeb5d3ea 100644 --- a/apps/lato/metadata.json +++ b/apps/lato/metadata.json @@ -1,7 +1,7 @@ { "id": "lato", "name": "Lato", - "version": "0.03", + "version": "0.04", "description": "A Lato Font clock with fast load and clock_info", "readme": "README.md", "icon": "app.png", @@ -12,6 +12,10 @@ "dependencies" : { "clock_info":"module" }, "storage": [ {"name":"lato.app.js","url":"app.js"}, - {"name":"lato.img","url":"icon.js","evaluate":true} + {"name":"lato.img","url":"icon.js","evaluate":true}, + {"name":"lato.settings.js","url":"settings.js"} + ], + "data": [ + {"name":"lato.json"} ] } diff --git a/apps/lato/screenshot4.png b/apps/lato/screenshot4.png new file mode 100644 index 000000000..5fc70fb18 Binary files /dev/null and b/apps/lato/screenshot4.png differ diff --git a/apps/lato/settings.js b/apps/lato/settings.js new file mode 100644 index 000000000..ff74ed47c --- /dev/null +++ b/apps/lato/settings.js @@ -0,0 +1,24 @@ +(function(back) { + let settings = require('Storage').readJSON('lato.json',1)||{}; + if (typeof settings.dateDisplay !== "boolean") settings.dateDisplay = false; // default value + if (typeof settings.dateFormat !== "number") settings.dateFormat = 0; // default value + function save(key, value) { + settings[key] = value; + require('Storage').write('lato.json', settings); + } + const appMenu = { + '': {'title': 'Lato'}, + '< Back': back, + 'Display Date?': { + value: settings.dateDisplay, + onchange: (v) => {save('dateDisplay', v)} + }, + "Date Format": { + value: settings.dateFormat, + min: 0, max: 2, + format: v => ["DoW, dd MMM","Locale Short","Locale Long"][v], + onchange: (v) => {save('dateFormat', v)} + } + }; + E.showMenu(appMenu) + }) \ No newline at end of file diff --git a/apps/lint_exemptions.js b/apps/lint_exemptions.js index e5a2170bd..b3503de72 100644 --- a/apps/lint_exemptions.js +++ b/apps/lint_exemptions.js @@ -196,12 +196,6 @@ module.exports = { "no-undef" ] }, - "apps/sixths/sixths.app.js": { - "hash": "2a4676828bdf78df052df402de34e6f1abd1c847ebe0d193fc789cd6e9dd0e5c", - "rules": [ - "no-undef" - ] - }, "apps/scribble/app.js": { "hash": "6d13abd27bab8009a6bdabe1df2df394bc14aac20c68f67e8f8b085fa6b427cd", "rules": [ @@ -1021,12 +1015,6 @@ module.exports = { "no-undef" ] }, - "apps/gipy/app.js": { - "hash": "41f342e8ef6f2a87b3aea19b75ee45cfdfeff723b94281049e3ae0ec89cddba5", - "rules": [ - "no-undef" - ] - }, "apps/geissclk/precompute.js": { "hash": "2317812a9e348e7883e93a4be9e294ad7accd4dc3f0e31ee00343e2412030f98", "rules": [ @@ -1249,12 +1237,6 @@ module.exports = { "no-undef" ] }, - "apps/accelrec/app.js": { - "hash": "b5369a60afc8f360f0b33f71080eb3f5d09a1bf3703acfcf07cd80dd19f1997d", - "rules": [ - "no-undef" - ] - }, "apps/BLEcontroller/app-joy.js": { "hash": "e4f34bb1bc11b52c3d7a1c537a140b0e23ccef82694dcd602cb517a8ba342898", "rules": [ diff --git a/apps/locale/locale.html b/apps/locale/locale.html index 8ec818aae..b198b1c4b 100644 --- a/apps/locale/locale.html +++ b/apps/locale/locale.html @@ -1,10 +1,12 @@ - + + @@ -15,18 +17,20 @@
- + +

- + +
+

-

Then click

- +