1
0
Fork 0

Merge branch 'espruino:master' into master

master
Peer David 2022-01-19 10:10:04 +01:00 committed by GitHub
commit 2ad5076443
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 158 additions and 125 deletions

View File

@ -170,16 +170,15 @@
"id": "launch",
"name": "Launcher",
"shortName": "Launcher",
"version": "0.10",
"version": "0.11",
"description": "This is needed to display a menu allowing you to choose your own applications. You can replace this with a customised launcher.",
"icon": "app.png",
"type": "launch",
"tags": "tool,system,launcher",
"supports": ["BANGLEJS","BANGLEJS2"],
"storage": [
{"name":"launch.app.js","url":"app-bangle1.js","supports":["BANGLEJS"]},
{"name":"launch.app.js","url":"app-bangle2.js","supports":["BANGLEJS2"]},
{"name":"launch.settings.js","url":"settings.js","supports":["BANGLEJS2"]}
{"name":"launch.app.js","url":"app.js"},
{"name":"launch.settings.js","url":"settings.js"}
],
"data": [{"name":"launch.json"}],
"sortorder": -10
@ -839,9 +838,10 @@
{
"id": "slevel",
"name": "Spirit Level",
"version": "0.02",
"version": "0.04",
"description": "Show the current angle of the watch, so you can use it to make sure something is absolutely flat",
"icon": "spiritlevel.png",
"screenshots": [{"url":"screenshot.png"}],
"tags": "tool",
"supports": ["BANGLEJS","BANGLEJS2"],
"storage": [
@ -1359,12 +1359,12 @@
{
"id": "pparrot",
"name": "Party Parrot",
"version": "0.01",
"version": "0.02",
"description": "Party with a parrot on your wrist",
"icon": "party-parrot.png",
"type": "app",
"tags": "party,parrot,lol",
"supports": ["BANGLEJS"],
"supports": ["BANGLEJS", "BANGLEJS2"],
"allow_emulator": true,
"screenshots": [{"url":"bangle1-party-parrot-screenshot.png"}],
"storage": [
@ -1541,7 +1541,7 @@
{
"id": "gpsinfo",
"name": "GPS Info",
"version": "0.09",
"version": "0.10",
"description": "An application that displays information about altitude, lat/lon, satellites and time",
"icon": "gps-info.png",
"type": "app",

View File

@ -6,3 +6,4 @@
0.07: Resolve one FIFO_FULL case and exit App with button press
0.08: Leave GPS power switched on on exit (will switch off after 0.5 seconds anyway)
0.09: Fix FIFO_FULL error
0.10: Show satellites "in view" separated by GNS-system

View File

@ -16,9 +16,8 @@ var lastFix = {
time: 0,
satellites: 0
};
var SATinView = 0;
var nofBD = 0;
var nofGP = 0;
var SATinView = 0, lastSATinView = -1, nofGP = 0, nofBD = 0, nofGL = 0;
const leaveNofixLayout = 1; // 0 = stay on initial screen for debugging (default = 1)
var listenerGPSraw = 0;
function formatTime(now) {
@ -63,7 +62,7 @@ function getMaidenHead(param1,param2){
function onGPS(fix) {
if (lastFix.fix != fix.fix) {
// if fix is different, change the layout
if (fix.fix) {
if (fix.fix && leaveNofixLayout) {
layout = new Layout( {
type:"v", c: [
{type:"txt", font:"6x8:2", label:"GPS Info" },
@ -92,11 +91,12 @@ function onGPS(fix) {
g.clearRect(0,24,g.getWidth(),g.getHeight());
layout.render();
}
//lastFix = fix;
if (fix.fix) {
if (fix.fix && leaveNofixLayout) {
if (listenerGPSraw == 1) {
Bangle.removeListener('GPS-raw', onGPSraw);
listenerGPSraw = 0;
lastSATinView = -1;
Bangle.buzz(50);
}
var locale = require("locale");
var satellites = fix.satellites;
@ -115,27 +115,31 @@ function onGPS(fix) {
layout.sat.label = fix.satellites;
layout.render(layout.sat);
}
if (SATinView != lastFix.SATinView) {
if (SATinView != lastSATinView) {
if (!leaveNofixLayout) SATinView = -1;
lastSATinView = SATinView;
layout.clear(layout.progress);
layout.progress.label = "in view: " + SATinView;
layout.progress.label = "in view GP/BD/GL: " + nofGP + " " + nofBD + " " + nofGL;
// console.log("in view GP/BD/GL: " + nofGP + " " + nofBD + " " + nofGL);
layout.render(layout.progress);
}
}
//layout.render();
if (listenerGPSraw == 0 && !fix.fix) {
setTimeout(() => Bangle.on('GPS-raw', onGPSraw), 10);
listenerGPSraw = 1;
}
lastFix = fix;
lastFix.SATinView = SATinView;
}
function onGPSraw(nmea) {
if (nmea.slice(0,7) == "$BDGSV,") nofBD = Number(nmea.slice(11,13));
if (nmea.slice(0,7) == "$GPGSV,") nofGP = Number(nmea.slice(11,13));
SATinView = nofBD + nofGP;
if (nmea.slice(3,6) == "GSV") {
// console.log(nmea.slice(1,3) + " " + nmea.slice(11,13));
if (nmea.slice(0,7) == "$GPGSV,") nofGP = Number(nmea.slice(11,13));
if (nmea.slice(0,7) == "$BDGSV,") nofBD = Number(nmea.slice(11,13));
if (nmea.slice(0,7) == "$GLGSV,") nofGL = Number(nmea.slice(11,13));
SATinView = nofGP + nofBD + nofGL;
}
}

View File

@ -9,3 +9,4 @@
0.09: Bangle.js 2 - pressing the button goes back to clock (fix #971)
After 10s of being locked, the launcher goes back to the clock screen
0.10: added in selectable font in settings including scalable vector font
0.11: Merge Bangle.js 1 and 2 launchers, again

View File

@ -1,75 +0,0 @@
var s = require("Storage");
var apps = s.list(/\.info$/).map(app=>{var a=s.readJSON(app,1);return a&&{name:a.name,type:a.type,icon:a.icon,sortorder:a.sortorder,src:a.src};}).filter(app=>app && (app.type=="app" || app.type=="clock" || !app.type));
apps.sort((a,b)=>{
var n=(0|a.sortorder)-(0|b.sortorder);
if (n) return n; // do sortorder first
if (a.name<b.name) return -1;
if (a.name>b.name) return 1;
return 0;
});
var selected = 0;
var menuScroll = 0;
var menuShowing = false;
function drawMenu() {
g.reset().setFont("6x8",2).setFontAlign(-1,0);
var w = g.getWidth();
var h = g.getHeight();
var m = w/2;
var n = Math.floor((h-48)/64);
if (selected>=n+menuScroll) menuScroll = 1+selected-n;
if (selected<menuScroll) menuScroll = selected;
// arrows
g.setColor(menuScroll ? g.theme.fg : g.theme.bg);
g.fillPoly([m,6,m-14,20,m+14,20]);
g.setColor((apps.length>n+menuScroll) ? g.theme.fg : g.theme.bg);
g.fillPoly([m,h-7,m-14,h-21,m+14,h-21]);
// draw
g.setColor(g.theme.fg);
for (var i=0;i<n;i++) {
var app = apps[i+menuScroll];
if (!app) break;
var y = 24+i*64;
if (i+menuScroll==selected) {
g.setColor(g.theme.bgH).fillRect(0,y,w-1,y+63);
g.setColor(g.theme.fgH).drawRect(0,y,w-1,y+63);
} else {
g.clearRect(0, y, w-1, y+63);
g.setColor(g.theme.fg);
}
g.drawString(app.name,64,y+32);
var icon=undefined;
if (app.icon) icon = s.read(app.icon);
if (icon) try {g.drawImage(icon,8,y+8);} catch(e){}
}
}
g.clear();
drawMenu();
Bangle.setUI("updown",dir=>{
if (dir) {
selected += dir;
if (selected<0) selected = apps.length-1;
if (selected>=apps.length) selected = 0;
drawMenu();
} else {
if (!apps[selected].src) return;
if (require("Storage").read(apps[selected].src)===undefined) {
E.showMessage("App Source\nNot found");
setTimeout(drawMenu, 2000);
} else {
E.showMessage("Loading...");
load(apps[selected].src);
}
}
});
Bangle.loadWidgets();
Bangle.drawWidgets();
// 10s of inactivity goes back to clock
if (Bangle.setLocked) Bangle.setLocked(false); // unlock initially
var lockTimeout;
Bangle.on('lock', locked => {
if (lockTimeout) clearTimeout(lockTimeout);
lockTimeout = undefined;
if (locked)
lockTimeout = setTimeout(_=>load(), 10000);
});

View File

@ -63,8 +63,11 @@ E.showScroller({
}
});
// pressing button goes back
setWatch(_=>load(), BTN1, {edge:"falling"});
// on bangle.js 2, the screen is used for navigating, so the single button goes back
// on bangle.js 1, the buttons are used for navigating
if (process.env.HWVERSION==2) {
setWatch(_=>load(), BTN1, {edge:"falling"});
}
// 10s of inactivity goes back to clock
Bangle.setLocked(false); // unlock initially

View File

@ -1 +1,2 @@
0.01: New App!
0.02: Bangle.js 2 compatibility

View File

@ -5,16 +5,17 @@ var imgs = [
atob("qE5xH+AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4AdwOBlcAAAsrq2BJn+BqxMHKX5NFJhgAFqxO5TYcruug0HLAAoIBvdQCIZN11icDqBLHAA+gMYRQ0TgcrvhNOAAaiCeWWBTgZNSKAuBJ17rDvZOVeQK4C1hOxdaYAFvbxvdgZOGbgMlLCF8DwSgrJxSKCKALvRUFmslbsJJ4YMG0F1qElld10ATGgGBJ9BOCvaLHHYgNEIoqsBKAIJFUFDtCurbIvhPHcgcrAAL9DBQclUFDtCGQIAJIIUAcYQHDq2ArmAqxsDfIL2BKFAxCvhPK0F7uoODSYVWrgACwBXCLwYQDlaekE4ROKAA97CwJODAAJuCfwYABuqglwKeNAA9QMoJPFrjwDAAjxBlesd0hOSHgeAJwjwDWRCgh1guBqBPTHYKfHOBIIBqxPhEgN7J6yfFJ5VQBILwgwJPWWwJPK0DwpJ66LBd6OgJ8TvXuoXBJ6HLBINWJ8VQJ6d8HYROEwD5BkpP/bYpPFrgIBuoUHqEAlZPiZxAAMHYWAdw18CY91BYOsJ8WgJ6d7UAzuBN5JPCwJPivagUC4MrJwoeJJ4VcJ72BJ4UrJ6igCKALtCqASJqDvhJ4bwVHodWTwQcJ0AQCJz3+QASCMABclDYd1MBmBJ76ABkrYCvZPUR4QABBxInCT0DuCJYJ3CeKt1NJZdClesd0RKBFIbxVqEldtusdwJJDvgqBqDxVTxjtgdwd8Fgd7KC77MT0H+TwLQGKAT4CJ/9WTwxQGupPbd4QABldWq2B1hPbTwwvDVYJRCUbRxDAAhTCJyusSRowEktQAAKhXvd1qBSHKKmBdxIwFuotFUjQjBvgkElZPWlaOCABRPFChwAPEYpPSqy9GAGlWJ6JO7UJgA=="),
atob("qE5xH+AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4AtwNWlcAAAUrq2BJP5MJAApS/JoRMJAApR7JotPumfAA10VQlWJ2+AHwZMB4nDABHEz9PeoesJ2icDp5NLKIpkCKGesG4UlJoJOBKJQJBBYT1BeQRQwwJOCTgI/Bb4V0KAxIBp8llb+BCYlWJ2V0IYbzCgBCBJwgKDBoefkoFCUFuBGISWEIglPBI8rAAIYDCYeAJ2hPJcgmArmAqylGJ9ZODz5OEJ5IICq1cAAZQGlZOuJoiWFVQIICcgRPFrhLCuklAgOBJ0+AlZOJJAYABAwgUBJwtcDwMr4itCeE+sJwV0dgoAKU4UrwBPFeARuBUAMr1jslJyhPBIAMlJ5auCeEotCJyRPBMwRPLeAVWJ0eAE4NPJqLvR4iglwIlBFgQATH4ROFJ4qgmFYUAdqRPSWASghTwclJ6qPDJ4srBIIQGwCejT63DksAlZPHp4iD4gQCT0SfXb4ZPFA4N0CIl0eECeCZgSfWeA4hCz4QHJ7usEANPOgQtFeCagDOYV0OIpPCeDruCugkCZoqgUlbtDkpwGB4UAJ7mATYXEQoNPeC3EXYVWTwS/HJ8ErD4IlBeDXDEAQABNxBPfPQTqCEoSgXIIhtJf4ZOawIeBkomDUDYbCNhJPCwBOZwB6Hz8lK4oAT4lPNZRcCwJOheL10DJHEO4LuZdgUAugoHPAQ2JADDubToZOHAATVBBpb6YgGsJy1WdhJQIlYQMTylWJ05QEUQOfejd0EAOBJzElRh/EFwRRDAATuWkrBBJysrbaufKIhqCd1ydCJyZREQYIACDizuWJzLUDdoLyBDSq9CJ6eBJzYAbJ4WsTyuf4gAzT6usCoKfBp4AzlY4BwBPRCoQA5qxPRJ3ZQMA==")
];
var scale = g.getWidth()<200 ? 2 : 3;
function drawImg (i) {
g.drawImage({
width: 80, height: 57, bpp: 8,
buffer: require("heatshrink").decompress(imgs[i])
}, 0, 0, {scale: 3});
}, (g.getWidth()-80*scale)/2, (g.getHeight()-57*scale)/2, {scale: scale});
}
var currImg = 0;
g.clear();
g.setBgColor(0).clear();
drawImg(currImg);
setInterval(function() {
currImg = (currImg + 1) % imgs.length;

View File

@ -1,2 +1,4 @@
0.01: New App!
0.02: Updated to work with both Bangle.js 1 and 2.
0.03: Now also visible on Bangle.js 2
0.04: Now work with different themes

BIN
apps/slevel/screenshot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -2,6 +2,7 @@ g.clear();
var old = {x:0,y:0};
var W = g.getWidth();
var H = g.getHeight();
Bangle.on('accel',function(v) {
var max = Math.max(Math.abs(v.x),Math.abs(v.y),Math.abs(v.z));
if (Math.abs(v.y)==max) {
@ -12,21 +13,26 @@ Bangle.on('accel',function(v) {
var d = Math.sqrt(v.x*v.x+v.y*v.y);
var ang = Math.atan2(d,Math.abs(v.z))*180/Math.PI;
g.setColor(1,1,1);
g.setFont("6x8",2);
g.setFontAlign(0,-1);
g.clearRect(W*(1/4),0,W*(3/4),H*(1/16));
g.drawString(ang.toFixed(1),W/2,0);
g.reset();
g.clearRect(W*(1/4),0,W*(3/4),16);// clear behind text
g.setFont("6x8",2).setFontAlign(0,-1).drawString(ang.toFixed(1),W/2,0);
var n = {
x:E.clip(W/2+v.x*256,4,W-4),
y:E.clip(H/2+v.y*256,4,H-4)};
g.clearRect(old.x-3,old.y-3,old.x+6,old.y+6);
g.setColor(1,1,1);
g.fillRect(n.x-3,n.y-3,n.x+6,n.y+6);
g.setColor(1,0,0);
g.clearRect(old.x-3,old.y-3,old.x+6,old.y+6); // clear old marker
g.setColor("#0f0");
g.fillRect(n.x-3,n.y-3,n.x+6,n.y+6); // draw new marker
// draw rings
g.setColor("#f00");
g.drawCircle(W/2,H/2,W*(1/12));
g.drawCircle(W/2,H/2,W*(1/4));
g.drawCircle(W/2,H/2,W*(5/12));
old = n;
});
setWatch(_=>load(), BTN1);
if (global.BTN2) {
setWatch(_=>load(), BTN2);
setWatch(_=>load(), BTN3);
}

View File

@ -2,15 +2,20 @@
/* Scans for strings that may be in English in each app, and
outputs a list of strings that have been found.
Early work towards internationalisation.
See https://github.com/espruino/BangleApps/issues/136
See https://github.com/espruino/BangleApps/issues/1311
*/
var IGNORE_STRINGS = [
"5x5",
"5x9Numeric7Seg",
"Vector"
];
var BASEDIR = __dirname+"/../";
Espruino = require(BASEDIR+"core/lib/espruinotools.js");
var fs = require("fs");
var APPSDIR = BASEDIR+"apps/";
function ERROR(s) {
console.error("ERROR: "+s);
process.exit(1);
@ -18,6 +23,9 @@ function ERROR(s) {
function WARN(s) {
console.log("Warning: "+s);
}
function log(s) {
console.log(s);
}
var appsFile, apps;
try {
@ -39,31 +47,65 @@ function isNotString(s) {
if (s.endsWith(".json") || s.endsWith(".img")) return true; // a filename
if (s.endsWith("=")) return true; // probably base64
if (s.startsWith("BTN")) return true; // button name
if (IGNORE_STRINGS.includes(s)) return true; // one we know to ignore
return false;
}
var textStrings = [];
// A string that *could* be translated?
var untranslatedStrings = [];
// Strings that are marked with 'LANG'
var translatedStrings = [];
console.log("Scanning...");
console.log("Scanning apps...");
apps.forEach((app,appIdx) => {
var appDir = APPSDIR+app.id+"/";
app.storage.forEach((file) => {
if (!file.url || !file.name.endsWith(".js")) return;
var fileContents = fs.readFileSync(appDir+file.url).toString();
var lex = Espruino.Core.Utils.getLexer(fileContents);
var lastIdx = 0;
var tok = lex.next();
while (tok!==undefined) {
var previousString = fileContents.substring(lastIdx, tok.startIdx);
if (tok.type=="STRING") {
if (!isNotString(tok.value)) {
//console.log(tok.str);
if (!textStrings.includes(tok.value))
textStrings.push(tok.value);
if (previousString.includes("/*LANG*/")) { // translated!
if (!translatedStrings.includes(tok.value))
translatedStrings.push(tok.value);
} else { // untranslated - potential to translate?
if (!isNotString(tok.value)) {
if (!untranslatedStrings.includes(tok.value))
untranslatedStrings.push(tok.value);
}
}
}
lastIdx = tok.endIdx;
tok = lex.next();
}
});
});
console.log("Done");
textStrings.sort();
console.log(textStrings.join("\n"));
untranslatedStrings.sort();
translatedStrings.sort();
var report = "";
/* // too many! don't output these
log("Possible English Strings that could be translated");
log("=================================================================");
log("");
log("Add these to IGNORE_STRINGS if the don't make sense...");
log("");
log(untranslatedStrings.map(s=>JSON.stringify(s)).join(",\n"));*/
log("");
var languages = JSON.parse(fs.readFileSync(BASEDIR+"/lang/index.json").toString());
languages.forEach(language => {
console.log("Scanning "+language.code);
log(language.code);
log("==========");
var translations = JSON.parse(fs.readFileSync(BASEDIR+"/lang/"+language.url).toString());
translatedStrings.forEach(str => {
if (!translations.GLOBAL[str])
console.log(`Missing translation for ${JSON.stringify(str)}`);
});
log("");
});
console.log("Done.");

View File

@ -141,6 +141,11 @@
<input type="checkbox" id="settings-settime">
<i class="form-icon"></i> Always update time when we connect
</label>
<div class="form-group">
<select class="form-select form-inline" id="settings-lang" style="width: 10em">
<option value="">None (English)</option>
</select>&nbsp;&nbsp;<span>Translations (<a href="https://github.com/espruino/BangleApps/issues/1311" target="_blank">BETA - more info</a>)</span>
</div>
<button class="btn" id="defaultsettings">Default settings</button>
</div>
</div>

View File

@ -1,9 +1,9 @@
{
"//":"British English language translations - the default strings in apps are all english anyway, so no need to have translations for most things",
"GLOBAL": {
"//":"Translations that apply for all apps",
"//":"Translations that apply for all apps"
},
"alarm": {
"//":"App-specific overrides",
"//":"App-specific overrides"
}
}

View File

@ -164,6 +164,48 @@ window.addEventListener('load', (event) => {
showToast("App Install failed, "+err,"error");
});
});
// Load language list
httpGet("lang/index.json").then(languagesJSON=>{
var languages;
try {
languages = JSON.parse(languagesJSON);
} catch(e) {
console.error("lang/index.json Corrupted", e);
}
function reloadLanguage() {
LANGUAGE = undefined;
if (SETTINGS.language) {
var language = languages.find(l=>l.code==SETTINGS.language);
if (language) {
var langURL = "lang/"+language.url;
httpGet(langURL).then(languageJSON=>{
try {
LANGUAGE = JSON.parse(languageJSON);
console.log(`${langURL} loaded successfully`);
} catch(e) {
console.error(`${langURL} Corrupted`, e);
}
});
} else {
console.error(`Language code ${JSON.stringify(SETTINGS.language)} not found in lang/index.json`);
}
}
}
var selectLang = document.getElementById("settings-lang");
console.log(languages);
languages.forEach(lang => {
selectLang.innerHTML += `<option value="${lang.code}" ${SETTINGS.language==lang.code?"selected":""}>${lang.name} (${lang.code})</option>`;
});
selectLang.addEventListener("change",event=>{
SETTINGS.language = event.target.value;
reloadLanguage();
saveSettings();
});
reloadLanguage();
});
});
function onAppJSONLoaded() {