1
0
Fork 0

Merge branch 'espruino:master' into master

master
xxDUxx 2022-08-02 16:38:54 +02:00 committed by GitHub
commit 296919571d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 98 additions and 32 deletions

View File

@ -1,2 +1,3 @@
0.01: Basic agenda with events from GB 0.01: Basic agenda with events from GB
0.02: Added settings page to force calendar sync 0.02: Added settings page to force calendar sync
0.03: Disable past events display from settings

View File

@ -24,6 +24,7 @@ var fontLarge = g.getFonts().includes("6x15")?"6x15:2":"6x8:4";
//FIXME maybe write the end from GB already? Not durationInSeconds here (or do while receiving?) //FIXME maybe write the end from GB already? Not durationInSeconds here (or do while receiving?)
var CALENDAR = require("Storage").readJSON("android.calendar.json",true)||[]; var CALENDAR = require("Storage").readJSON("android.calendar.json",true)||[];
var settings = require("Storage").readJSON("agenda.settings.json",true)||{};
CALENDAR=CALENDAR.sort((a,b)=>a.timestamp - b.timestamp) CALENDAR=CALENDAR.sort((a,b)=>a.timestamp - b.timestamp)
@ -89,6 +90,12 @@ function showEvent(ev) {
} }
function showList() { function showList() {
//it might take time for GB to delete old events, decide whether to show them grayed out or hide entirely
if(!settings.pastEvents) {
let now = new Date();
//TODO add threshold here?
CALENDAR = CALENDAR.filter(ev=>ev.timestamp + ev.durationInSeconds > now/1000);
}
if(CALENDAR.length == 0) { if(CALENDAR.length == 0) {
E.showMessage("No events"); E.showMessage("No events");
return; return;
@ -101,10 +108,10 @@ function showList() {
g.setColor(g.theme.fg); g.setColor(g.theme.fg);
g.clearRect(r.x,r.y,r.x+r.w, r.y+r.h); g.clearRect(r.x,r.y,r.x+r.w, r.y+r.h);
if (!ev) return; if (!ev) return;
var isPast = ev.timestamp + ev.durationInSeconds < (new Date())/1000; var isPast = false;
var x = r.x+2, title = ev.title; var x = r.x+2, title = ev.title;
var body = formatDateShort(getDate(ev.timestamp))+"\n"+ev.location; var body = formatDateShort(getDate(ev.timestamp))+"\n"+(ev.location?ev.location:/*LANG*/"No location");
var m = ev.title+"\n"+ev.location, longBody=false; if(settings.pastEvents) isPast = ev.timestamp + ev.durationInSeconds < (new Date())/1000;
if (title) g.setFontAlign(-1,-1).setFont(fontBig) if (title) g.setFontAlign(-1,-1).setFont(fontBig)
.setColor(isPast ? "#888" : g.theme.fg).drawString(title, x,r.y+2); .setColor(isPast ? "#888" : g.theme.fg).drawString(title, x,r.y+2);
if (body) { if (body) {
@ -114,10 +121,8 @@ function showList() {
l = l.slice(0,3); l = l.slice(0,3);
l[l.length-1]+="..."; l[l.length-1]+="...";
} }
longBody = l.length>2;
g.drawString(l.join("\n"), x+10,r.y+20); g.drawString(l.join("\n"), x+10,r.y+20);
} }
//if (!longBody && msg.src) g.setFontAlign(1,1).setFont("6x8").drawString(msg.src, r.x+r.w-2, r.y+r.h-2);
g.setColor("#888").fillRect(r.x,r.y+r.h-1,r.x+r.w-1,r.y+r.h-1); // dividing line between items g.setColor("#888").fillRect(r.x,r.y+r.h-1,r.x+r.w-1,r.y+r.h-1); // dividing line between items
}, },
select : idx => showEvent(CALENDAR[idx]), select : idx => showEvent(CALENDAR[idx]),

View File

@ -1,7 +1,7 @@
{ {
"id": "agenda", "id": "agenda",
"name": "Agenda", "name": "Agenda",
"version": "0.02", "version": "0.03",
"description": "Simple agenda", "description": "Simple agenda",
"icon": "agenda.png", "icon": "agenda.png",
"screenshots": [{"url":"screenshot_agenda_overview.png"}, {"url":"screenshot_agenda_event1.png"}, {"url":"screenshot_agenda_event2.png"}], "screenshots": [{"url":"screenshot_agenda_overview.png"}, {"url":"screenshot_agenda_event1.png"}, {"url":"screenshot_agenda_event2.png"}],
@ -13,5 +13,6 @@
{"name":"agenda.app.js","url":"agenda.js"}, {"name":"agenda.app.js","url":"agenda.js"},
{"name":"agenda.settings.js","url":"settings.js"}, {"name":"agenda.settings.js","url":"settings.js"},
{"name":"agenda.img","url":"agenda-icon.js","evaluate":true} {"name":"agenda.img","url":"agenda-icon.js","evaluate":true}
] ],
"data": [{"name":"agenda.settings.json"}]
} }

View File

@ -3,6 +3,10 @@
Bluetooth.println(""); Bluetooth.println("");
Bluetooth.println(JSON.stringify(message)); Bluetooth.println(JSON.stringify(message));
} }
var settings = require("Storage").readJSON("agenda.settings.json",1)||{};
function updateSettings() {
require("Storage").writeJSON("agenda.settings.json", settings);
}
var CALENDAR = require("Storage").readJSON("android.calendar.json",true)||[]; var CALENDAR = require("Storage").readJSON("android.calendar.json",true)||[];
var mainmenu = { var mainmenu = {
"" : { "title" : "Agenda" }, "" : { "title" : "Agenda" },
@ -32,6 +36,13 @@
E.showAlert(/*LANG*/"You are not connected").then(()=>E.showMenu(mainmenu)); E.showAlert(/*LANG*/"You are not connected").then(()=>E.showMenu(mainmenu));
} }
}, },
/*LANG*/"Show past events" : {
value : !!settings.pastEvents,
onchange: v => {
settings.pastEvents = v;
updateSettings();
}
},
}; };
E.showMenu(mainmenu); E.showMenu(mainmenu);
}) })

View File

@ -11,4 +11,5 @@
0.10: Fix SMS bug 0.10: Fix SMS bug
0.12: Use default Bangle formatter for booleans 0.12: Use default Bangle formatter for booleans
0.13: Added Bangle.http function (see Readme file for more info) 0.13: Added Bangle.http function (see Readme file for more info)
0.14: Fix timeout of http function not beeing cleaned up 0.14: Fix timeout of http function not being cleaned up
0.15: Allow method/body/headers to be specified for `http` (needs Gadgetbridge 0.68.0b or later)

View File

@ -150,6 +150,9 @@
//send the request //send the request
var req = {t: "http", url:url, id:options.id}; var req = {t: "http", url:url, id:options.id};
if (options.xpath) req.xpath = options.xpath; if (options.xpath) req.xpath = options.xpath;
if (options.method) req.method = options.method;
if (options.body) req.body = options.body;
if (options.headers) req.headers = options.headers;
gbSend(req); gbSend(req);
//create the promise //create the promise
var promise = new Promise(function(resolve,reject) { var promise = new Promise(function(resolve,reject) {

View File

@ -2,7 +2,7 @@
"id": "android", "id": "android",
"name": "Android Integration", "name": "Android Integration",
"shortName": "Android", "shortName": "Android",
"version": "0.14", "version": "0.15",
"description": "Display notifications/music/etc sent from the Gadgetbridge app on Android. This replaces the old 'Gadgetbridge' Bangle.js widget.", "description": "Display notifications/music/etc sent from the Gadgetbridge app on Android. This replaces the old 'Gadgetbridge' Bangle.js widget.",
"icon": "app.png", "icon": "app.png",
"tags": "tool,system,messages,notifications,gadgetbridge", "tags": "tool,system,messages,notifications,gadgetbridge",

View File

@ -1 +1,4 @@
0.01: New App! 0.01: New App!
0.02: Add 'pre' code that can erase the device
Wait more between sending code snippets
Now force use of 'Storage' (assume 2v00 or later)

View File

@ -13,6 +13,9 @@ Click on the Customise button in the app loader to set up the programmer.
* First you need to choose the kind of devices you want to upload to. This is * First you need to choose the kind of devices you want to upload to. This is
the text that should match the Bluetooth advertising name. So `Puck.js` for Puck.js the text that should match the Bluetooth advertising name. So `Puck.js` for Puck.js
devices, or `Bangle.js` for Bangles. devices, or `Bangle.js` for Bangles.
* In the next box, you have code to run before the upload of the main code. By default
the code `require("Storage").list().forEach(f=>require("Storage").erase(f));reset();` will
erase all files on the device and reset it.
* Now paste in the code you want to write to the device. This is automatically * Now paste in the code you want to write to the device. This is automatically
written to flash (`.bootcde`). See https://www.espruino.com/Saving#save-on-send-to-flash- written to flash (`.bootcde`). See https://www.espruino.com/Saving#save-on-send-to-flash-
for more information. for more information.
@ -35,8 +38,6 @@ To stop scanning, long-press the button to return to the clock.
## Notes ## Notes
* Right now the Espruino Tools used here are unaware of the device they're writing to, * This assumes the device being written to is at least version 2v00 of Espruino
and as a result they don't use Storage and so the size of the files you can
write to the device are quite limited. You should be find with up to 4k of code.
* Currently, code is not minified before upload (so you need to supply pre-minified * Currently, code is not minified before upload (so you need to supply pre-minified
code if you want that) code if you want that)

View File

@ -58,21 +58,31 @@ function scanAndConnect() {
term.print("Connected...\r\n"); term.print("Connected...\r\n");
uart.removeAllListeners(); uart.removeAllListeners();
uart.on('data', function(d) { term.print(d); }); uart.on('data', function(d) { term.print(d); });
uart.write(json.code+"\n").then(() => { term.print("Upload initial...\r\n");
term.print("\r\nUpload Complete...\r\n"); uart.write((json.pre||"")+"\n").then(() => {
// main upload completed - wait a bit term.print("\r\Done.\r\n");
uploadTimeout = setTimeout(function() { uploadTimeout = setTimeout(function() {
term.print("\r\nFinal Upload...\r\n"); uploadTimeout = undefined;
// now upload the code to run after... term.print("\r\nUpload Code...\r\n");
uart.write(json.post+"\n").then(() => { uart.write((json.code||"")+"\n").then(() => {
term.print("\r\nDone.\r\n"); term.print("\r\Done.\r\n");
// now wait and disconnect (if not already done!) // main upload completed - wait a bit
uploadTimeout = setTimeout(function() { uploadTimeout = setTimeout(function() {
term.print("\r\nDisconnecting...\r\n"); uploadTimeout = undefined;
if (uart) uart.disconnect(); term.print("\r\Upload final...\r\n");
}, 500); // now upload the code to run after...
uart.write((json.post||"")+"\n").then(() => {
term.print("\r\nDone.\r\n");
// now wait and disconnect (if not already done!)
uploadTimeout = setTimeout(function() {
uploadTimeout = undefined;
term.print("\r\nDisconnecting...\r\n");
if (uart) uart.disconnect();
}, 500);
});
}, 2000);
}); });
}, 1000); }, 2000);
}); });
}); });
}).catch(err => { }).catch(err => {

View File

@ -17,6 +17,8 @@
<script src="https://cdnjs.cloudflare.com/ajax/libs/jshint/2.11.0/jshint.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jshint/2.11.0/jshint.min.js"></script>
<p>Upload code to devices with names starting with:</p> <p>Upload code to devices with names starting with:</p>
<p><input type="text" id="nameprefix"></input></p> <p><input type="text" id="nameprefix"></input></p>
<p>Enter the code to send before upload here:</p>
<p><textarea id="pre-code"></textarea></p>
<p>Enter your program to upload here:</p> <p>Enter your program to upload here:</p>
<p><textarea id="js-code"></textarea></p> <p><textarea id="js-code"></textarea></p>
<p>Enter the code to send after upload here:</p> <p>Enter the code to send after upload here:</p>
@ -24,12 +26,17 @@
<p>Then click <button id="upload" class="btn btn-primary">Upload</button>&nbsp;<span id="btninfo" style="color:orange"></span> </p> <p>Then click <button id="upload" class="btn btn-primary">Upload</button>&nbsp;<span id="btninfo" style="color:orange"></span> </p>
<p><a id="setdefault">Click here</a> to reset to defaults.</p> <p><a id="setdefault">Click here</a> to reset to defaults.</p>
<script> <script>
const LS_PRECODE = "espruinoprog.precode";
const LS_JSCODE = "espruinoprog.code"; const LS_JSCODE = "espruinoprog.code";
const LS_POSTCODE = "espruinoprog.postcode"; const LS_POSTCODE = "espruinoprog.postcode";
const LS_NAMEPREFIX = "espruinoprog.namePrefix"; const LS_NAMEPREFIX = "espruinoprog.namePrefix";
var jseditor,posteditor; var preeditor,jseditor,posteditor;
function setDefaults() { function setDefaults() {
if (localStorage.getItem(LS_PRECODE) === null) {
localStorage.setItem(LS_PRECODE, `// Erase all files (faster than eraseall)
require("Storage").list().forEach(f=>require("Storage").erase(f));reset();`);
}
if (localStorage.getItem(LS_JSCODE) === null) { if (localStorage.getItem(LS_JSCODE) === null) {
localStorage.setItem(LS_JSCODE, `// Flash LED2 every 2 seconds localStorage.setItem(LS_JSCODE, `// Flash LED2 every 2 seconds
setInterval(function() { setInterval(function() {
@ -47,6 +54,8 @@ LED.set();NRF.sleep();`);
if (localStorage.getItem(LS_NAMEPREFIX) === null) { if (localStorage.getItem(LS_NAMEPREFIX) === null) {
localStorage.setItem(LS_NAMEPREFIX, "Puck.js"); localStorage.setItem(LS_NAMEPREFIX, "Puck.js");
} }
document.getElementById("pre-code").value = localStorage.getItem(LS_PRECODE);
if (preeditor) preeditor.setValue(document.getElementById("pre-code").value);
document.getElementById("js-code").value = localStorage.getItem(LS_JSCODE); document.getElementById("js-code").value = localStorage.getItem(LS_JSCODE);
if (jseditor) jseditor.setValue(document.getElementById("js-code").value); if (jseditor) jseditor.setValue(document.getElementById("js-code").value);
document.getElementById("post-code").value = localStorage.getItem(LS_POSTCODE); document.getElementById("post-code").value = localStorage.getItem(LS_POSTCODE);
@ -55,8 +64,6 @@ LED.set();NRF.sleep();`);
} }
setDefaults(); setDefaults();
// The code editor // The code editor
var lintFlags = { var lintFlags = {
esversion: 6, // Enable ES6 for literals, arrow fns, binary esversion: 6, // Enable ES6 for literals, arrow fns, binary
@ -64,6 +71,17 @@ LED.set();NRF.sleep();`);
laxbreak: true, // don't warn about newlines in expressions laxbreak: true, // don't warn about newlines in expressions
laxcomma: true // don't warn about commas at the start of the line laxcomma: true // don't warn about commas at the start of the line
}; };
preeditor = CodeMirror.fromTextArea(document.getElementById("pre-code"), {
width: "100%",
height: "auto",
matchBrackets: true,
mode: { name: "javascript", globalVars: false },
lineWrapping: true,
showTrailingSpace: true,
lint: lintFlags,
gutters: ["CodeMirror-linenumbers", "CodeMirror-lint-markers"],
lineNumbers: true
});
jseditor = CodeMirror.fromTextArea(document.getElementById("js-code"), { jseditor = CodeMirror.fromTextArea(document.getElementById("js-code"), {
width: "100%", width: "100%",
height: "auto", height: "auto",
@ -87,7 +105,9 @@ LED.set();NRF.sleep();`);
lineNumbers: true lineNumbers: true
}); });
function hasWarnings() { function hasWarnings() {
return jseditor.state.lint.marked.length!=0 || posteditor.state.lint.marked.length!=0; return preeditor.state.lint.marked.length!=0 ||
jseditor.state.lint.marked.length!=0 ||
posteditor.state.lint.marked.length!=0;
} }
var editorChangedTimeout; var editorChangedTimeout;
function editorChanged() { function editorChanged() {
@ -95,26 +115,34 @@ LED.set();NRF.sleep();`);
editorChangedTimeout = setTimeout(function() { editorChangedTimeout = setTimeout(function() {
if (hasWarnings()) { if (hasWarnings()) {
document.getElementById("btninfo").innerHTML = "There are warnings in the code to be uploaded"; document.getElementById("btninfo").innerHTML = "There are warnings in the code to be uploaded";
document.getElementById("upload").classList.add("disabled"); //document.getElementById("upload").classList.add("disabled");
} else { } else {
document.getElementById("btninfo").innerHTML = ""; document.getElementById("btninfo").innerHTML = "";
document.getElementById("upload").classList.remove("disabled"); //document.getElementById("upload").classList.remove("disabled");
} }
}, 500); }, 500);
} }
preeditor.on("change", editorChanged);
jseditor.on("change", editorChanged); jseditor.on("change", editorChanged);
posteditor.on("change", editorChanged); posteditor.on("change", editorChanged);
document.getElementById("upload").addEventListener("click", function() { document.getElementById("upload").addEventListener("click", function() {
if (!hasWarnings()) { if (!hasWarnings()) {
var precode = preeditor.getValue();
var jscode = jseditor.getValue(); var jscode = jseditor.getValue();
var postcode = posteditor.getValue(); var postcode = posteditor.getValue();
var namePrefix = document.getElementById("nameprefix").value; var namePrefix = document.getElementById("nameprefix").value;
localStorage.setItem(LS_PRECODE, precode);
localStorage.setItem(LS_JSCODE, jscode); localStorage.setItem(LS_JSCODE, jscode);
localStorage.setItem(LS_POSTCODE, postcode); localStorage.setItem(LS_POSTCODE, postcode);
localStorage.setItem(LS_NAMEPREFIX, namePrefix); localStorage.setItem(LS_NAMEPREFIX, namePrefix);
// force version - as long as we're above 1v96 we get the ability to upload to different storage files
var ENV = Espruino.Core.Env.getData();
ENV.VERSION_MAJOR = 2;
ENV.VERSION_MINOR = 0;
// Now compile
Espruino.transform(jscode, { Espruino.transform(jscode, {
SET_TIME_ON_WRITE : false, // time would just be out of date SET_TIME_ON_WRITE : false, // time would just be out of date
SAVE_ON_SEND : 1, // save to flash SAVE_ON_SEND : 1, // save to flash
@ -125,6 +153,7 @@ LED.set();NRF.sleep();`);
sendCustomizedApp({ sendCustomizedApp({
storage: [{ name: "espruinoprog.json", content: JSON.stringify({ storage: [{ name: "espruinoprog.json", content: JSON.stringify({
namePrefix : namePrefix, namePrefix : namePrefix,
pre : Espruino.Core.CodeWriter.reformatCode(precode),
code : Espruino.Core.CodeWriter.reformatCode(content), code : Espruino.Core.CodeWriter.reformatCode(content),
post : Espruino.Core.CodeWriter.reformatCode(postcode) post : Espruino.Core.CodeWriter.reformatCode(postcode)
})}] })}]
@ -134,6 +163,7 @@ LED.set();NRF.sleep();`);
}); });
document.getElementById("setdefault").addEventListener("click", function(e) { document.getElementById("setdefault").addEventListener("click", function(e) {
e.preventDefault(); e.preventDefault();
localStorage.removeItem(LS_PRECODE);
localStorage.removeItem(LS_JSCODE); localStorage.removeItem(LS_JSCODE);
localStorage.removeItem(LS_POSTCODE); localStorage.removeItem(LS_POSTCODE);
localStorage.removeItem(LS_NAMEPREFIX); localStorage.removeItem(LS_NAMEPREFIX);

View File

@ -2,7 +2,7 @@
"id": "espruinoprog", "id": "espruinoprog",
"name": "Espruino Programmer", "name": "Espruino Programmer",
"shortName": "Programmer", "shortName": "Programmer",
"version": "0.01", "version": "0.02",
"description": "Finds Bluetooth devices with a specific name (eg 'Puck.js'), connects and uploads code. Great for programming many devices at once!", "description": "Finds Bluetooth devices with a specific name (eg 'Puck.js'), connects and uploads code. Great for programming many devices at once!",
"icon": "app.png", "icon": "app.png",
"tags": "tool,bluetooth", "tags": "tool,bluetooth",

2
core

@ -1 +1 @@
Subproject commit 8830108ebb0c18106eabfcfa18dbee4fd79c58c6 Subproject commit ab6fefe5f06d54d2a22b89d4c9dd61a4e3815df1