diff --git a/apps.json b/apps.json index 89f06b52e..0e30c045f 100644 --- a/apps.json +++ b/apps.json @@ -219,8 +219,8 @@ { "id": "slidingtext", "name": "Sliding Clock", "icon": "slidingtext.png", - "version":"0.02", - "description": "Inspired by the Pebble sliding clock, old times are scrolled off the screen and new times on. You are also able to change language on the fly so you can see the time written in other languages using button 1. Currently only English, French and Japanese are supported", + "version":"0.05", + "description": "Inspired by the Pebble sliding clock, old times are scrolled off the screen and new times on. You are also able to change language on the fly so you can see the time written in other languages using button 1. Currently English, French, Japanese, Spanish and German are supported", "tags": "clock", "type":"clock", "allow_emulator":true, @@ -232,8 +232,10 @@ {"name":"slidingtext.locale.en.js","url":"slidingtext.locale.en.js"}, {"name":"slidingtext.locale.en2.js","url":"slidingtext.locale.en2.js"}, {"name":"slidingtext.utils.en.js","url":"slidingtext.utils.en.js"}, + {"name":"slidingtext.locale.es.js","url":"slidingtext.locale.es.js"}, {"name":"slidingtext.locale.fr.js","url":"slidingtext.locale.fr.js"}, {"name":"slidingtext.locale.jp.js","url":"slidingtext.locale.jp.js"}, + {"name":"slidingtext.locale.de.js","url":"slidingtext.locale.de.js"}, {"name":"slidingtext.dtfmt.js","url":"slidingtext.dtfmt.js"} ] }, @@ -459,7 +461,7 @@ { "id": "heart", "name": "Heart Rate Recorder", "icon": "app.png", - "version":"0.04", + "version":"0.05", "interface": "interface.html", "description": "Application that allows you to record your heart rate. Can run in background", "tags": "tool,health,widget", @@ -3042,7 +3044,7 @@ "name": "Gadgetbridge Music Controls", "shortName":"Music Controls", "icon": "icon.png", - "version":"0.02", + "version":"0.03", "description": "Control the music on your Gadgetbridge-connected phone", "tags": "tools,bluetooth,gadgetbridge,music", "type":"app", diff --git a/apps/gbmusic/ChangeLog b/apps/gbmusic/ChangeLog index 4fa99c934..0afcae268 100644 --- a/apps/gbmusic/ChangeLog +++ b/apps/gbmusic/ChangeLog @@ -1,2 +1,3 @@ 0.01: Initial version -0.02: Increase text brightness, improve controls, (try to) reduce memory usage \ No newline at end of file +0.02: Increase text brightness, improve controls, (try to) reduce memory usage +0.03: Only auto-start if active app is a clock, auto close after 1 hour of inactivity diff --git a/apps/gbmusic/app.js b/apps/gbmusic/app.js index 7cfbb574a..ee50c1c17 100644 --- a/apps/gbmusic/app.js +++ b/apps/gbmusic/app.js @@ -11,7 +11,8 @@ let info = { n: 0, c: 0, }; -const TOUT = 300000; // auto close timeout: 5 minutes (in ms) +const POUT = 300000; // auto close timeout when paused: 5 minutes (in ms) +const IOUT = 3600000; // auto close timeout for inactivity: 1 hour (in ms) /////////////////////// // Self-repeating timeouts @@ -44,7 +45,7 @@ function brightness() { if (!fade) { return 1; } - return Math.max(0, 1-((Date.now()-fade)/TOUT)); + return Math.max(0, 1-((Date.now()-fade)/POUT)); } // Scroll long track names @@ -396,26 +397,50 @@ function musicInfo(e) { if (Bangle.isLCDOn()) { drawMusic(); } + if (tIxt) { + clearTimeout(tIxt); + tIxt = null; + } + if (auto && stat==="play") { + // if inactive for double song duration (or an hour if unknown), load the clock + // i.e. phone finished playing without bothering to notify the watch + tIxt = setTimeout(load, (info.dur*2000) || IOUT); + } } -let tXit; +let tPxt, tIxt; function musicState(e) { stat = e.state; // if paused for five minutes, load the clock // (but timeout resets if we get new info, even while paused) - if (tXit) { - clearTimeout(tXit); + if (tPxt) { + clearTimeout(tPxt); + tPxt = null; + } + if (tIxt) { + clearTimeout(tIxt); + tIxt = null; } - tXit = null; fade = null; delete info.track_color; - if (stat!=="play" && auto) { - if (stat==="stop") { // never actually happens with my phone :-( - load(); - } else { // also quit when paused for a long time - tXit = setTimeout(load, TOUT); - fade = Date.now(); - fadeOut(); + if (auto) { // auto opened -> auto close + switch(stat) { + case "stop": // never actually happens with my phone :-( + load(); + break; + case "play": + // if inactive for double song duration (or an hour if unknown), load the clock + // i.e. phone finished playing without bothering to notify the watch + tIxt = setTimeout(load, (info.dur*2000) || IOUT); + break; + case "pause": + default: + // quit when paused for a long time + // also fade out track info while waiting for this + tPxt = setTimeout(load, POUT); + fade = Date.now(); + fadeOut(); + break; } } if (Bangle.isLCDOn()) { @@ -538,7 +563,7 @@ function startLCDWatch() { ///////////////////// // check for saved music stat (by widget) to load g.clear(); -global.gbmusic_active = true; // we don't need our widget +global.gbmusic_active = true; // we don't need our widget (needed for <2.09 devices) Bangle.loadWidgets(); Bangle.drawWidgets(); delete (global.gbmusic_active); diff --git a/apps/gbmusic/widget.js b/apps/gbmusic/widget.js index 1a55490b5..86bda99a1 100644 --- a/apps/gbmusic/widget.js +++ b/apps/gbmusic/widget.js @@ -1,38 +1,44 @@ (() => { if (global.gbmusic_active || !(require("Storage").readJSON("gbmusic.json", 1) || {}).autoStart) { - return + return; + } + if (typeof __FILE__ === 'string') { // only exists since 2v09 + const info = require("Storage").readJSON(__FILE__.split(".")[0]+".info", 1) || false; + if (info && info.type!=="clock") { // info can have no type (but then it isn't a clock) + return; + } } - let state, info + let state, info; function checkMusic() { if (state!=="play" || !info) { - return + return; } // playing music: launch music app require("Storage").writeJSON("gbmusic.load.json", { state: state, info: info, - }) - load("gbmusic.app.js") + }); + load("gbmusic.app.js"); } - const _GB = global.GB + const _GB = global.GB; global.GB = (event) => { // we eat music events! switch(event.t) { case "musicinfo": - info = event - delete(info.t) - checkMusic() - break + info = event; + delete (info.t); + checkMusic(); + break; case "musicstate": - state = event.state - checkMusic() - break + state = event.state; + checkMusic(); + break; default: if (_GB) { - setTimeout(_GB, 0, event) + setTimeout(_GB, 0, event); } } - } -})() + }; +})(); diff --git a/apps/heart/ChangeLog b/apps/heart/ChangeLog index 4751f0d10..083ecec85 100644 --- a/apps/heart/ChangeLog +++ b/apps/heart/ChangeLog @@ -3,3 +3,11 @@ Clean up recordings on app removal 0.03: added graphing feature of 164 latest measurements 0.04: Fix memory usage when viewing HRM traces +0.05: Add loading screen for viewRecord + List average, minimum & maximum measurement in viewRecord + Disable recording only when current recording file is erased + Fix timezone offset + Draw chart based on height and width of display instead of hard-coded limits + Reduce memory usage by ~30% + Generate scale based on defined minimum and maximum measurement + Added background line on 50% to ease estimation of drawn values diff --git a/apps/heart/app.js b/apps/heart/app.js index 75edf8c4e..77a1c2106 100644 --- a/apps/heart/app.js +++ b/apps/heart/app.js @@ -1,25 +1,17 @@ -const GraphXZero = 40; -const GraphYZero = 200; -const GraphY100 = 80; +E.setFlags({pretokenise:1}); -const GraphMarkerOffset = 5; -const MaxValueCount = 164; -const GraphXMax = GraphXZero + MaxValueCount; +function log(msg) { + console.log("heart: " + msg + "; mem used: " + process.memory().usage / process.memory().blocksize); + return; +} + +log("start"); Bangle.loadWidgets(); Bangle.drawWidgets(); var settings = require("Storage").readJSON("heart.json",1)||{}; -var globalSettings = require('Storage').readJSON('setting.json', true) || {timezone: 0}; -require('DateExt').locale({ - str: "0D.0M. 0h:0m", - offset: [ - globalSettings.timezone * 60, - globalSettings.timezone * 60 - ] -}); - function getFileNbr(n) { return ".heart"+n.toString(36); } @@ -28,6 +20,7 @@ function updateSettings() { require("Storage").write("heart.json", settings); if (WIDGETS["heart"]) WIDGETS["heart"].reload(); + return; } function showMainMenu() { @@ -52,214 +45,232 @@ function showMainMenu() { updateSettings(); } }, - 'View Records': ()=>{viewRecords()}, - 'Graph Records': ()=>{graphRecords()}, + 'View Records': ()=>{createRecordMenu(viewRecord.bind());}, + 'Graph Records': ()=>{createRecordMenu(graphRecord.bind());}, '< Back': ()=>{load();} }; return E.showMenu(mainMenu); } -function viewRecords() { +// Date().as().str cannot be used as it always returns UTC time +function getDateString(timestamp) { + var date = new Date(timestamp); + var day = date.getDate() < 10 ? "0" + date.getDate().toString() : date.getDate().toString(); + var month = date.getMonth() < 10 ? "0" + date.getMonth().toString() : date.getMonth().toString(); + return day + "." + month + "." + date.getFullYear(); +} + +// Date().as().str cannot be used as it always returns UTC time +function getTimeString(timestamp) { + var date = new Date(timestamp); + var hour = date.getHours() < 10 ? '0' + date.getHours().toString() : date.getHours().toString(); + var minute = date.getMinutes() < 10 ? '0' + date.getMinutes().toString() : date.getMinutes().toString(); + return hour + ':' + minute; +} + +function createRecordMenu(func) { const menu = { '': { 'title': 'Heart Records' } }; var found = false; for (var n=0;n<36;n++) { - var f = require("Storage").open(getFileNbr(n),"r"); - if (f.readLine()!==undefined) { - menu["Record "+n] = viewRecord.bind(null,n); + var line = require("Storage").open(getFileNbr(n),"r").readLine(); + if (line!==undefined) { + menu["#" + n + " " + getDateString(line.split(",")[0]*1000) + " " + getTimeString(line.split(",")[0]*1000)] = func.bind(null, n); found = true; } } if (!found) menu["No Records Found"] = function(){}; - menu['< Back'] = ()=>{showMainMenu()}; + menu['< Back'] = ()=>{showMainMenu();}; return E.showMenu(menu); } function viewRecord(n) { + E.showMenu({'': 'Heart Record '+n}); + E.showMessage( + "Loading Data ...\n\nMay take a while,\nwill vibrate\nwhen done.", + 'Heart Record '+n + ); const menu = { '': { 'title': 'Heart Record '+n } }; - var heartCount = 0; var heartTime; var f = require("Storage").open(getFileNbr(n),"r"); var l = f.readLine(); - if (l!==undefined) { - var c = l.split(","); - heartTime = new Date(c[0]*1000); - } + // using arrays for memory optimization + var limits = Uint8Array(2); + // using arrays for memory optimization + var avg = Uint32Array(2); + // minimum + limits[0] = 2000; + // maximum + limits[1] = 0; + // count + avg[0] = 0; + // average sum + avg[1] = 0; + var count = 0; + var value = 0; + if (l!==undefined) + heartTime = new Date(l.split(",")[0]*1000); + log("parsing records"); while (l!==undefined) { - heartCount++; - // TODO: min/max/average of heart rate? + count++; + if (parseInt(l.split(',')[2]) >= 70) { + avg[0]++; + value = parseInt(l.split(',')[1]); + if (value < limits[0]) { + limits[0] = value; + } else if (value > limits[1]) { + limits[1] = value; + } + avg[1] += value; + } l = f.readLine(); } + l = undefined; + value = undefined; + log("finished parsing"); if (heartTime) menu[" "+heartTime.toString().substr(4,17)] = function(){}; - menu[heartCount+" records"] = function(){}; - // TODO: option to draw it? Just scan through, project using min/max - menu['Erase'] = function() { + menu[count + " records"] = function(){}; + menu["Min: " + limits[0]] = function(){}; + menu["Max: " + limits[1]] = function(){}; + menu["Avg: " + Math.round(avg[1] / avg[0])] = function(){}; + menu["Erase"] = function() { E.showPrompt("Delete Record?").then(function(v) { if (v) { - settings.isRecording = false; - updateSettings(); - var f = require("Storage").open(getFileNbr(n),"r"); - f.erase(); - viewRecords(); + if (n == settings.fileNbr) { + settings.isRecording = false; + updateSettings(); + } + require("Storage").open(getFileNbr(n),"r").erase(); + E.showMenu(); + createRecordMenu(viewRecord.bind()); } else - viewRecord(n); + return viewRecord(n); }); }; - menu['< Back'] = ()=>{viewRecords()}; - print(menu); + menu['< Back'] = ()=>{createRecordMenu(viewRecord.bind());}; + Bangle.buzz(200, 0.3); return E.showMenu(menu); } -function graphRecords() { - const menu = { - '': { 'title': 'Heart Records' } - }; - var found = false; - for (var n=0;n<36;n++) { - var f = require("Storage").open(getFileNbr(n),"r"); - var line = f.readLine(); - if (line!==undefined) { - menu["#"+n+" "+Date(line.split(",")[0]*1000).as().str] = graphRecord.bind(null,n); - found = true; - } - } - if (!found) - menu["No Records Found"] = function(){}; - menu['< Back'] = ()=>{showMainMenu()}; - return E.showMenu(menu); -} - -// based on batchart -function renderHomeIcon() { - //Home for Btn2 - g.setColor(1, 1, 1); - g.drawLine(220, 118, 227, 110); - g.drawLine(227, 110, 234, 118); - - g.drawPoly([222,117,222,125,232,125,232,117], false); - g.drawRect(226,120,229,125); -} - -function renderChart() { - // Left Y axis (Battery) - g.setColor(1, 1, 0); - g.drawLine(GraphXZero, GraphYZero + GraphMarkerOffset, GraphXZero, GraphY100); - - g.setFontAlign(1, -1, 0); - g.drawString("150", 35, GraphY100 - GraphMarkerOffset); - g.drawLine(GraphXZero - GraphMarkerOffset, GraphY100, GraphXZero, GraphY100); - - g.drawString("125", 35, GraphYZero - 110 - GraphMarkerOffset); - g.drawLine(GraphXZero - GraphMarkerOffset, 150, GraphXZero, 150); - - g.drawString("100", 35, GraphYZero - 100 - GraphMarkerOffset); - g.drawLine(GraphXZero - GraphMarkerOffset, 150, GraphXZero, 150); - - g.drawString("90", 35, GraphYZero - 90 - GraphMarkerOffset); - g.drawLine(GraphXZero - GraphMarkerOffset, 150, GraphXZero, 150); - - g.drawString("80", 35, GraphYZero - 70 - GraphMarkerOffset); - g.drawLine(GraphXZero - GraphMarkerOffset, 150, GraphXZero, 150); - - g.drawString("70", 35, GraphYZero - 50 - GraphMarkerOffset); - g.drawLine(GraphXZero - GraphMarkerOffset, 150, GraphXZero, 150); - - g.drawString("60", 35, GraphYZero - 30 - GraphMarkerOffset); - g.drawLine(GraphXZero - GraphMarkerOffset, 150, GraphXZero, 150); - - g.drawString("50", 35, GraphYZero - 20 - GraphMarkerOffset); - g.drawLine(GraphXZero - GraphMarkerOffset, 150, GraphXZero, 150); - - g.drawString("40", 35, GraphYZero - 10 - GraphMarkerOffset); - g.drawLine(GraphXZero - GraphMarkerOffset, 150, GraphXZero, 150); - - g.drawString("30", 35, GraphYZero - GraphMarkerOffset); - - g.setColor(1, 1, 1); - g.drawLine(GraphXZero - GraphMarkerOffset, GraphYZero, GraphXMax + GraphMarkerOffset, GraphYZero); - - console.log("Finished drawing chart"); -} - -// as drawing starts at 30 HRM decreasing measrure by 30 -// recalculate for range 110-150 as only 20 pixels are available -function getY(measure) { - positionY = GraphYZero - measure + 30; - if (100 < measure < 150) { - positionY = GraphYZero - ( 100 + Math.round((measure - 100)/2) ) + 30; - g.setColor(1, 0, 0); - } else if (60 < measrure < 100) { - positionY = GraphYZero - ( 30 + Math.round((measure - 30)/2) ) + 30; - g.setColor(0, 1, 0); - } - if (positionY > GraphYZero) { - positionY = GraphYZero; - g.setColor(1, 0, 0); - } - if (positionY < GraphY100) { - positionY = GraphY100; - g.setColor(1, 0, 0); - } - return positionY; -} - function stop() { E.showMenu(); load(); } function graphRecord(n) { - E.showMenu({'': 'Heart Record '+n}); + var headline = "Heart Record " + n; + E.showMenu({'': headline}); E.showMessage( "Loading Data ...\n\nMay take a while,\nwill vibrate\nwhen done.", - 'Heart Record '+n + headline ); - g.setFont("Vector", 10); - var lastPixel; + const MinMeasurement = 30; + const MaxMeasurement = 150; + const GraphXLabel = 35; + const GraphXZero = 40; + const GraphY100 = 60; + const GraphMarkerOffset = 5; + // calculate number of pixels based on display width + const MaxValueCount = g.getWidth() - GraphXZero - ( g.getWidth() - 220 ) - GraphMarkerOffset; + // calculate Y axis "0" pixel + const GraphYZero = g.getHeight() - g.setFont("Vector", 10).getFontHeight() - GraphMarkerOffset * 2; + // calculate X axis max drawable pixel + const GraphXMax = GraphXZero + MaxValueCount; + // calculate space between labels of scale + const LabelOffset = (GraphYZero - GraphY100) / (MaxMeasurement - MinMeasurement); + var lineCount = 0; - var positionX = GraphXZero; - var positionY = GraphYZero; var startLine = 1; - var tempCount = 0; var f = require("Storage").open(getFileNbr(n),"r"); var line = f.readLine(); - var times = Array(2); - console.log("Counting lines"); + + log("Counting lines"); + while (line !== undefined) { lineCount++; line = f.readLine(); } - console.log(`Line count: ${lineCount}`); - if (lineCount > MaxValueCount) { + + log(`lineCount: ${lineCount}`); + if (lineCount > MaxValueCount) startLine = lineCount - MaxValueCount; - } - console.log(`start: ${startLine}`); + f = undefined; + line = undefined; + lineCount = undefined; + log(`startLine: ${startLine}`); f = require("Storage").open(getFileNbr(n),"r"); line = f.readLine(); + + var times = Uint32Array(2); + var tempCount = 0; + var positionX = GraphXZero; + var positionY = GraphYZero; + var measure; + while (line !== undefined) { currentLine = line; line = f.readLine(); tempCount++; if (tempCount == startLine) { - g.clear(); - Bangle.loadWidgets(); - Bangle.drawWidgets(); - renderHomeIcon(); - renderChart(); + // generating rgaph in loop when reaching startLine to keep loading + // message on screen until graph can be drawn + g.clear(). + // Home for Btn2 + setColor(1, 1, 1). + drawLine(220, 118, 227, 110). + drawLine(227, 110, 234, 118). + drawPoly([222,117,222,125,232,125,232,117], false). + drawRect(226,120,229,125). + + // headline + setFontAlign(0, -1, 0). + setFont("6x8", 2). + drawString(headline, g.getWidth()/2 - headline.length/2, GraphY100 - g.getFontHeight() - GraphMarkerOffset). + + // Chart + setColor(1, 1, 0). + // horizontal bottom line + drawLine(GraphXZero, GraphYZero + GraphMarkerOffset, GraphXZero, GraphY100). + // vertical left line + drawLine(GraphXZero - GraphMarkerOffset, GraphYZero, GraphXMax + GraphMarkerOffset, GraphYZero). + // scale indicator line for 100% + drawLine(GraphXZero - GraphMarkerOffset, GraphY100, GraphXZero, GraphY100). + // scale indicator line for 50% + drawLine(GraphXZero - GraphMarkerOffset, GraphY100 + (GraphYZero - GraphY100)/2, GraphXZero, GraphY100 + (GraphYZero - GraphY100)/2). + // background line for 50% + setColor(1, 1, 1). + drawLine(GraphXZero + 1, GraphY100 + (GraphYZero - GraphY100)/2, GraphXMax, GraphY100 + (GraphYZero - GraphY100)/2). + setFontAlign(1, -1, 0). + setFont("Vector", 10); + + // scale text + for (var i = MaxMeasurement; i >= MinMeasurement; i-=10) { + g.drawString(i, GraphXLabel, GraphY100 + LabelOffset * ( MaxMeasurement - i ) - GraphMarkerOffset); + } + + log("Finished drawing chart"); } else if (tempCount > startLine) { positionX++; if (parseInt(currentLine.split(",")[2]) >= 70) { - g.setColor(1, 1, 1); + g.setColor(1, 0.3, 0.3); oldPositionY = positionY; - positionY = getY(parseInt(currentLine.split(",")[1])); - if (times[0] === undefined) { + measure = parseInt(currentLine.split(",")[1]); + positionY = GraphYZero - measure + MinMeasurement; + if (positionY > GraphYZero) { + positionY = GraphYZero; + } + if (positionY < GraphY100) { + positionY = GraphY100; + } + + if (times[0] === 0) { times[0] = parseInt(currentLine.split(",")[0]); } if (tempCount == startLine + 1) { @@ -270,26 +281,30 @@ function graphRecord(n) { } } } - g.flip(); } - g.setColor(1, 1, 0); - g.setFont("Vector", 10); - console.log('start: ' + times[0]); - console.log('end: ' + times[1]); - if (times[0] !== undefined) { - g.setFontAlign(-1, -1, 0); - var startdate = new Date(times[0]*1000); - g.drawString(startdate.local().as("0h:0m").str, 15, GraphYZero + 12); + g.setColor(1, 1, 0).setFont("Vector", 10); + log('startTime: ' + times[0]); + log('endTime: ' + times[1]); + + if (times[0] !== 0) { + g.setFontAlign(-1, -1, 0). + drawString(getTimeString(times[0]*1000), 15, GraphYZero + 12); } - if (times[1] !== undefined) { - g.setFontAlign(1, -1, 0); - var enddate = new Date(times[1]*1000); - g.drawString(enddate.local().as().str, GraphXMax, GraphYZero + 12); + + if (times[1] !== 0) { + var dateStr = getDateString(times[1]*1000); + g.setFontAlign(-1, -1, 0). + drawString(dateStr, GraphXMax/2 - dateStr.length/2 - GraphMarkerOffset, GraphYZero + 12). + setFontAlign(1, -1, 0). + drawString(getTimeString(times[1]*1000), GraphXMax, GraphYZero + 12); } - console.log("Finished rendering data"); + + log("Finished rendering data"); Bangle.buzz(200, 0.3); + g.flip(); setWatch(stop, BTN2, {edge:"falling", debounce:50, repeat:false}); + return; } showMainMenu(); diff --git a/apps/locale/locales.js b/apps/locale/locales.js index bad920b44..34f259498 100644 --- a/apps/locale/locales.js +++ b/apps/locale/locales.js @@ -549,7 +549,26 @@ var locales = { abday: "ned.,pon.,tor.,sre.,čet.,pet.,sob.", day: "nedelja,ponedeljek,torek,sreda,četrtek,petek,sobota", trans: { yes: "da", Yes: "Da", no: "ne", No: "Ne", ok: "ok", on: "Vklj.", off: "Izklj.", "< Back": "< Nazaj" } - }/*, + }, + "pt_PT": { + lang: "pt_PT", + decimal_point: ",", + thousands_sep: " ", + currency_symbol: "€", + int_curr_symbol: "EUR", + speed: "kmh", + distance: { 0: "m", 1: "km" }, + temperature: "°C", + ampm: { 0: "am", 1: "pm" }, + timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" }, + datePattern: { 0: "%d %b %Y", 1: "%d/%m/%y" }, + abmonth: "Jan,Fev,Mar,Abr,Mai,Jun,Jul,Ago,Set,Out,Nov,Dez", + month: "Janeiro,Fevereiro,Março,Abril,Maio,Junho,Julho,Agosto,Setembro,Outubro,Novembro,Dezembro", + abday: "Dom,Seg,Ter,Qua,Qui,Sex,Sab", + day: "Domingo,Segunda-feira,Terça-feira,Quarta-feira,Quinta-feira,Sexta-feira,Sábado", + trans: { yes: "sim", Yes: "Sim", no: "não", No: "Não", ok: "ok", on: "on", off: "off" } + }, +/*, "he_IL": { // This won't work until we get a font - see https://github.com/espruino/BangleApps/issues/399 codePage : "ISO8859-8", lang: "he_IL", diff --git a/apps/slidingtext/ChangeLog b/apps/slidingtext/ChangeLog index 01e6b06c3..932134ab1 100644 --- a/apps/slidingtext/ChangeLog +++ b/apps/slidingtext/ChangeLog @@ -1,2 +1,5 @@ 0.01: Initial Release 0.02: Color Themes, Smoother scrolling +0.03: Added Spanish Language +0.04: Added German Language +0.05: BUGFIX: pedometer widget interfered with the clock Font Alignment diff --git a/apps/slidingtext/README.md b/apps/slidingtext/README.md index cc802638a..d2d2fb5b6 100644 --- a/apps/slidingtext/README.md +++ b/apps/slidingtext/README.md @@ -13,6 +13,8 @@ Use Button 1 (the top right button) to change the language | English | English (Traditional) | French | Japanese (Romanji) | | ---- | ---- | ---- | ---- | |  |  |  | | +| **German** | **Spanish** | | | +|  |  | | | ### Button 3 Button 3 (bottom right button) is used to change the colour diff --git a/apps/slidingtext/custom.html b/apps/slidingtext/custom.html index 8c9edada1..5e89e230b 100644 --- a/apps/slidingtext/custom.html +++ b/apps/slidingtext/custom.html @@ -4,7 +4,7 @@
-Please select watch languages
+Please select watch languages (Max 3, only the first 3 selected will be loaded)