Added showModal/hideModal utility functions

Added readStorageFile/eraseStorageFile to handle efficiently downloading large files (fix #119)
master
Gordon Williams 2020-03-31 14:39:59 +01:00
parent 04f8cbcd13
commit dd0e3c89d1
5 changed files with 123 additions and 76 deletions

View File

@ -5,32 +5,9 @@
<body>
<div id="tracks"></div>
<div class="modal active" id="status-modal">
<div class="modal-overlay"></div>
<div class="modal-container">
<div class="modal-header">
<div class="modal-title h5">Please wait</div>
</div>
<div class="modal-body">
<div class="content">
Loading...
</div>
</div>
</div>
</div>
<script src="../../lib/interface.js"></script>
<script>
var domTracks = document.getElementById("tracks");
var domModal = document.getElementById("status-modal");
function showModal(title) {
domModal.querySelector(".content").innerHTML = title;
domModal.classList.add("active");
}
function hideModal(title) {
domModal.classList.remove("active");
}
function saveKML(track,title) {
var kml = `<?xml version="1.0" encoding="UTF-8"?>
@ -107,19 +84,15 @@ function trackLineToObject(l, hasTrackNumber) {
}
function downloadTrack(trackid, callback) {
showModal("Downloading Track...");
Puck.write(`\x10(function() {
var f = require("Storage").open(".gpsrc${trackid.toString(36)}","r");
var l = f.readLine();
while (l!==undefined) { Bluetooth.print(l); l = f.readLine(); }
})()\n`,tracklist=>{
hideModal();
var track = tracklist.trim().split("\n").map(l=>trackLineToObject(l,false));
Util.showModal("Downloading Track...");
Util.readStorageFile(`.gpsrc${trackid.toString(36)}`,data=>{
Util.hideModal();
var track = data.trim().split("\n").map(l=>trackLineToObject(l,false));
callback(track);
});
}
function getTrackList() {
showModal("Loading Tracks...");
Util.showModal("Loading Tracks...");
domTracks.innerHTML = "";
Puck.write(`\x10(function() {
for (var n=0;n<36;n++) {
@ -171,7 +144,7 @@ function getTrackList() {
</div>
</div>`;
domTracks.innerHTML = html;
hideModal();
Util.hideModal();
var buttons = domTracks.querySelectorAll("button");
for (var i=0;i<buttons.length;i++) {
buttons[i].addEventListener("click",event => {
@ -179,9 +152,9 @@ function getTrackList() {
var trackid = parseInt(button.getAttribute("trackid"));
var task = button.getAttribute("task");
if (task=="delete") {
showModal("Deleting Track...");
Puck.write(`\x10require("Storage").open(".gpsrc${trackid.toString(36)}","r").erase()\n`,()=>{
hideModal();
Util.showModal("Deleting Track...");
Util.eraseStorageFile(`.gpsrc${trackid.toString(36)}`,()=>{
Util.hideModal();
getTrackList();
});
}

View File

@ -5,32 +5,9 @@
<body>
<div id="records"></div>
<div class="modal active" id="status-modal">
<div class="modal-overlay"></div>
<div class="modal-container">
<div class="modal-header">
<div class="modal-name h5">Please wait</div>
</div>
<div class="modal-body">
<div class="content">
Loading...
</div>
</div>
</div>
</div>
<script src="../../lib/interface.js"></script>
<script>
var domRecords = document.getElementById("records");
var domModal = document.getElementById("status-modal");
function showModal(name) {
domModal.querySelector(".content").innerHTML = name;
domModal.classList.add("active");
}
function hideModal(name) {
domModal.classList.remove("active");
}
function saveRecord(record,name) {
var csv = `${record.map(rec=>[rec.time, rec.bpm, rec.confidence].join(",")).join("\n")}`;
@ -62,20 +39,16 @@ function recordLineToObject(l, hasRecordNbr) {
}
function downloadRecord(recordNbr, callback) {
showModal("Downloading heart rate record...");
Puck.write(`\x10(function() {
var f = require("Storage").open(".heart${recordNbr.toString(36)}","r");
var l = f.readLine();
while (l!==undefined) { Bluetooth.print(l); l = f.readLine(); }
})()\n`,recordList=>{
hideModal();
var record = recordList.trim().split("\n").map(l=>recordLineToObject(l,false));
Util.showModal("Downloading heart rate record...");
Util.readStorageFile(`.heart${recordNbr.toString(36)}`,data=>{
Util.hideModal();
var record = data.trim().split("\n").map(l=>recordLineToObject(l,false));
callback(record);
});
}
function getRecordList() {
showModal("Loading heart rate records...");
Util.showModal("Loading heart rate records...");
domRecords.innerHTML = "";
Puck.write(`\x10(function() {
for (var n=0;n<36;n++) {
@ -118,7 +91,7 @@ function getRecordList() {
</div>
</div>`;
domRecords.innerHTML = html;
hideModal();
Util.hideModal();
var buttons = domRecords.querySelectorAll("button");
for (var i=0;i<buttons.length;i++) {
buttons[i].addEventListener("click",event => {
@ -126,9 +99,9 @@ function getRecordList() {
var recordNbr = parseInt(button.getAttribute("recordNbr"));
var task = button.getAttribute("task");
if (task=="delete") {
showModal("Deleting record...");
Puck.write(`\x10require("Storage").open(".heart${recordNbr.toString(36)}","r").erase()\n`,()=>{
hideModal();
Util.showModal("Deleting record...");
Util.eraseStorageFile(`.heart${recordNbr.toString(36)}`,()=>{
Util.hideModal();
getRecordList();
});
}

View File

@ -147,5 +147,50 @@ readFile : (file) => {
});
});
});
},
readStorageFile : (filename) => { // StorageFiles are different to normal storage entries
return new Promise((resolve,reject) => {
// Use "\xFF" to signal end of file (can't occur in files anyway)
var fileContent = "";
var fileSize = undefined;
var connection = Puck.getConnection();
connection.received = "";
connection.cb = function(d) {
var finished = false;
var eofIndex = d.indexOf("\xFF");
if (eofIndex>=0) {
finished = true;
d = d.substr(0,eofIndex);
}
fileContent += d;
if (fileSize === undefined) {
var newLineIdx = fileContent.indexOf("\n");
if (newLineIdx>=0) {
fileSize = parseInt(fileContent.substr(0,newLineIdx));
console.log("File size is "+fileSize);
fileContent = fileContent.substr(newLineIdx+1);
}
} else {
showProgress(undefined,100*fileContent.length / (fileSize||1000000));
}
if (finished) {
hideProgress();
connection.received = "";
connection.cb = undefined;
resolve(fileContent);
}
};
console.log(`Reading StorageFile ${JSON.stringify(filename)}`);
connection.write(`\x03\x10(function() {
var f = require("Storage").open(${JSON.stringify(filename)},"r");
Bluetooth.println(f.getLength());
var l = f.readLine();
while (l!==undefined) { Bluetooth.print(l); l = f.readLine(); }
Bluetooth.print("\xFF");
})()\n`,() => {
showProgress(`Reading ${JSON.stringify(filename)}`,0);
console.log(`StorageFile read started...`);
});
});
}
};

View File

@ -229,6 +229,14 @@ function handleAppInterface(app) {
id : msg.id
});
});
} else if (msg.type=="readstoragefile") {
Comms.readStorageFile(msg.data/*filename*/).then(function(result) {
iwin.postMessage({
type : "readstoragefilersp",
data : result,
id : msg.id
});
});
}
}, false);
iwin.postMessage({type:"init"});

View File

@ -3,10 +3,21 @@ be used from within BangleApps
See: README.md / `apps.json`: `interface` element
This exposes a 'Puck' object like the puck.js library,
and calls `onInit` when it's ready. `Puck` can be used
for sending/receiving data to the correctly connected
This exposes a 'Puck' object (a simple version of
https://github.com/espruino/EspruinoWebTools/blob/master/puck.js)
and calls `onInit` when it's ready. `Puck` can be used for
sending/receiving data to the correctly connected
device with Puck.eval/write.
Puck.write(data,callback)
Puck.eval(data,callback)
There is also:
Util.readStorageFile(filename,callback)
Util.eraseStorageFile(filename,callback)
Util.showModal(title)
Util.hideModal()
*/
var __id = 0, __idlookup = [];
var Puck = {
@ -20,11 +31,48 @@ var Puck = {
window.postMessage({type:"write",data:data,id:__id});
}
};
var Util = {
readStorageFile : function(filename,callback) {
__id++;
__idlookup[__id] = callback;
window.postMessage({type:"readstoragefile",data:filename,id:__id});
},
eraseStorageFile : function(filename,callback) {
Puck.write(`\x10require("Storage").open(${JSON.stringify(filename)}","r").erase()\n`,callback);
},
showModal : function(title) {
if (!Util.domModal) {
Util.domModal = document.createElement('div');
Util.domModal.id = "status-modal";
Util.domModal.classList.add("modal");
Util.domModal.classList.add("active");
Util.domModal.innerHTML = `<div class="modal-overlay"></div>
<div class="modal-container">
<div class="modal-header">
<div class="modal-title h5">Please wait</div>
</div>
<div class="modal-body">
<div class="content">
Loading...
</div>
</div>
</div>`;
document.body.appendChild(Util.domModal);
}
Util.domModal.querySelector(".content").innerHTML = title;
Util.domModal.classList.add("active");
},
hideModal : function() {
if (!Util.domModal) return;
Util.domModal.classList.remove("active");
}
};
window.addEventListener("message", function(event) {
var msg = event.data;
if (msg.type=="init") {
onInit();
} else if (msg.type=="evalrsp" || msg.type=="writersp") {
} else if (msg.type=="evalrsp" || msg.type=="writersp"|| msg.type=="readstoragefilersp") {
var cb = __idlookup[msg.id];
delete __idlookup[msg.id];
cb(msg.data);