Merge branch 'master' of github.com:espruino/BangleApps

master
Gordon Williams 2020-02-05 10:31:18 +00:00
commit ba3fd74ca7
11 changed files with 133 additions and 121 deletions

View File

@ -61,7 +61,6 @@
"storage": [
{"name":"+setting","url":"settings.json"},
{"name":"-setting","url":"settings.js"},
{"name":"=setting","url":"settings-init.js"},
{"name":"@setting","url":"settings-default.json","evaluate":true},
{"name":"*setting","url":"settings-icon.js","evaluate":true}
],
@ -309,7 +308,7 @@
"tags": "bluetooth",
"storage": [
{"name":"+hidkbd","url":"hid-keyboard.json"},
{"name":"-hidkbd","url":"hid-keyboard.min.js"},
{"name":"-hidkbd","url":"hid-keyboard.js"},
{"name":"*hidkbd","url":"hid-keyboard-icon.js","evaluate":true}
]
},
@ -343,8 +342,7 @@
{"name":"*pig","url":"animals-pig.js","evaluate":true},
{"name":"*sheep","url":"animals-sheep.js","evaluate":true},
{"name":"*mouse","url":"animals-mouse.js","evaluate":true}
],
"sortorder" : 1
]
},
{ "id": "qrcode",
"name": "Custom QR Code",
@ -404,8 +402,7 @@
{"name":"*nfr","url":"start-nfr.js","evaluate":true},
{"name":"*nodew","url":"start-nodew.js","evaluate":true},
{"name":"*tf","url":"start-tf.js","evaluate":true}
],
"sortorder" : -1
]
},
{ "id": "ncfrun",
"name": "NCEU 5K Fun Run",
@ -417,8 +414,7 @@
{"name":"+ncfrun","url":"nceu-funrun.json"},
{"name":"-ncfrun","url":"nceu-funrun.js"},
{"name":"*ncfrun","url":"nceu-funrun-icon.js","evaluate":true}
],
"sortorder" : -1
]
},
{ "id": "nceuwid",
"name": "NCEU Logo Widget",
@ -430,8 +426,7 @@
"storage": [
{"name":"+nceuwid","url":"nceu-widget.json"},
{"name":"=nceuwid","url":"nceu-widget.js"}
],
"sortorder" : -1
]
},
@ -734,8 +729,7 @@
{"name":"+ctrclk","url":"app.json"},
{"name":"-ctrclk","url":"app.js"},
{"name":"*ctrclk","url":"app-icon.js","evaluate":true}
],
"sortorder" : -9
]
},
{ "id": "demoapp",
"name": "Demo Loop",
@ -755,7 +749,7 @@
{ "id": "flagrse",
"name": "Espruino Flag Raiser",
"icon": "app.png",
"description": "App to send a command to an Espruino-based bluetooth Flag",
"description": "App to send a command to another Espruino to cause it to raise a flag",
"tags": "",
"storage": [
{"name":"+flagrse","url":"app.json"},

View File

@ -1,5 +1,24 @@
// This ALWAYS runs at boot
E.setFlags({pretokenise:1});
// Load settings...
var s = require('Storage').readJSON('@setting')||{};
if (s.ble!==false) {
if (s.HID) { // Humen interface device
Bangle.HID = E.toUint8Array(atob("BQEJBqEBhQIFBxngKecVACUBdQGVCIEClQF1CIEBlQV1AQUIGQEpBZEClQF1A5EBlQZ1CBUAJXMFBxkAKXOBAAkFFQAm/wB1CJUCsQLABQwJAaEBhQEVACUBdQGVAQm1gQIJtoECCbeBAgm4gQIJzYECCeKBAgnpgQIJ6oECwA=="));
NRF.setServices({}, {uart:true, hid:Bangle.HID});
}
}
// If not programmable, force terminal onto screen
if (s.dev===false) Terminal.setConsole(true);
// we just reset, so BLE should be on
if (s.ble===false) NRF.sleep();
// Set time, vibrate, beep, etc
if (!s.vibrate) Bangle.buzz=Promise.resolve;
if (!s.beep) Bangle.beep=Promise.resolve;
Bangle.setLCDTimeout(s.timeout);
if (!s.timeout) Bangle.setLCDPower(1);
E.setTimeZone(s.timezone);
delete s;
// All of this is just shim for older Bangles
if (!Bangle.loadWidgets) {
Bangle.loadWidgets = function(){

View File

@ -31,7 +31,7 @@ function showMainMenu() {
}
function eraseApp(app) {
E.showMessage('Erasing ' + app.name + '...');
E.showMessage('Erasing\n' + app.name + '...');
storage.erase(app['']);
storage.erase(app.icon);
storage.erase(app.src);
@ -44,7 +44,7 @@ function showAppMenu(app) {
},
'< Back': () => m = showApps(),
'Erase': () => {
E.showPrompt('Erase ' + app.name + '?').then((v) => {
E.showPrompt('Erase\n' + app.name + '?').then((v) => {
if (v) {
Bangle.buzz(100, 1);
eraseApp(app);

View File

@ -49,23 +49,20 @@ function drawApp() {
}
if (next) {
if (settings.HIDGestures) {
Bangle.on('aiGesture', (v) => {
switch (v) {
case 'swipeleft':
E.showMessage('next');
setTimeout(drawApp, 1000);
next(() => {});
break;
case 'swiperight':
E.showMessage('prev');
setTimeout(drawApp, 1000);
prev(() => {});
break;
}
});
}
Bangle.on('aiGesture', (v) => {
switch (v) {
case 'swipeleft':
E.showMessage('next');
setTimeout(drawApp, 1000);
next(() => {});
break;
case 'swiperight':
E.showMessage('prev');
setTimeout(drawApp, 1000);
prev(() => {});
break;
}
});
setWatch(function(e) {
var len = e.time - e.lastTime;

View File

@ -1 +0,0 @@
function drawApp(){function b(a){return{width:8,height:a.length,bpp:1,buffer:new Uint8Array(a).buffer};}g.clear(),g.setFont('6x8',2),g.setFontAlign(0,0),g.drawString(profile,120,120);const a=g.getWidth()-18;g.drawImage(b([16,56,124,254,16,16,16,16]),a,40),g.drawImage(b([16,16,16,16,254,124,56,16]),a,194),g.drawImage(b([0,8,12,14,255,14,12,8]),a,116);}var storage=require('Storage');const settings=storage.readJSON('@setting')||{HID:!1};var sendHid,next,prev,toggle,up,down,profile;settings.HID?(profile='Keyboard',sendHid=function(b,a){try{NRF.sendHIDReport([2,0,0,b,0,0,0,0,0],()=>NRF.sendHIDReport([2,0,0,0,0,0,0,0,0],()=>a&&a();););}catch(a){print(a);}},next=function(a){sendHid(79,a);},prev=function(a){sendHid(80,a);},toggle=function(a){sendHid(44,a);},up=function(a){sendHid(82,a);},down=function(a){sendHid(81,a);}):(E.showMessage('HID disabled'),setTimeout(load,1000)),next&&(settings.HIDGestures&&Bangle.on('aiGesture',v=>switch(v){case'swipeleft':E.showMessage('next');setTimeout(drawApp,1000);next(()=>;);break;case'swiperight':E.showMessage('prev');setTimeout(drawApp,1000);prev(()=>;);break;}),setWatch(function(b){var a=b.time-b.lastTime;a>0.3&&a<0.9?(E.showMessage('prev'),setTimeout(drawApp,1000),prev(()=>;)):(E.showMessage('up'),setTimeout(drawApp,1000),up(()=>;));},BTN1,{edge:'falling',repeat:!0,debounce:50}),setWatch(function(b){var a=b.time-b.lastTime;a>0.3&&a<0.9?(E.showMessage('next'),setTimeout(drawApp,1000),next(()=>;)):(E.showMessage('down'),setTimeout(drawApp,1000),down(()=>;));},BTN3,{edge:'falling',repeat:!0,debounce:50}),setWatch(function(a){E.showMessage('toggle'),setTimeout(drawApp,1000),toggle();},BTN2,{edge:'falling',repeat:!0,debounce:50}),drawApp());

View File

@ -1,11 +1,12 @@
{
ble: true, // Bluetooth enabled by default
dev: true, // Espruino IDE enabled by default
timeout: 10, // Default LCD timeout in seconds
vibrate: true, // Vibration enabled by default. App must support
beep: true, // Beep enabled by default. App must support
timezone: 0, // Set the timezone for the device
HID : false, // BLE HID mode, off by default
HIDGestures: false,
debug: false, // Debug mode disabled by default. App must support
ble: true, // Bluetooth enabled by default
dev: true, // Is REPL on Bluetooth - can Espruino IDE be used?
timeout: 10, // Default LCD timeout in seconds
vibrate: true, // Vibration enabled by default. App must support
beep: true, // Beep enabled by default. App must support
timezone: 0, // Set the timezone for the device
HID : false, // BLE HID mode, off by default
clock: null, // a string for the default clock's name
"12hour" : false, // 12 or 24 hour clock?
distance : "kilometer" // or "mile"
}

View File

@ -1,27 +0,0 @@
Bangle.HID = E.toUint8Array(atob("BQEJBqEBhQIFBxngKecVACUBdQGVCIEClQF1CIEBlQV1AQUIGQEpBZEClQF1A5EBlQZ1CBUAJXMFBxkAKXOBAAkFFQAm/wB1CJUCsQLABQwJAaEBhQEVACUBdQGVAQm1gQIJtoECCbeBAgm4gQIJzYECCeKBAgnpgQIJ6oECwA=="));
(function() {
var s = require('Storage').readJSON('@setting');
var adv = { uart: true };
if (s.ble) {
if (s.dev)
Bluetooth.setConsole(true);
else
Terminal.setConsole(true);
if (s.HID) {
adv.hid = Bangle.HID;
} else
delete Bangle.HID;
}
NRF.setServices({}, adv);
// we just reset, so BLE should be on
try { // disable advertising if BLE should be off
if (!s.ble) NRF.sleep();
else NRF.wake();
} catch(e) {}
if (!s.vibrate) Bangle.buzz=Promise.resolve;
if (!s.beep) Bangle.beep=Promise.resolve;
Bangle.setLCDTimeout(s.timeout);
if (!s.timeout) Bangle.setLCDPower(1);
E.setTimeZone(s.timezone);
})()

View File

@ -5,13 +5,7 @@ g.clear();
const storage = require('Storage');
let settings;
function debug(msg, arg) {
if (settings.debug)
console.log(msg, arg);
}
function updateSettings() {
debug('updating settings', settings);
//storage.erase('@setting'); // - not needed, just causes extra writes if settings were the same
storage.write('@setting', settings);
}
@ -25,9 +19,9 @@ function resetSettings() {
beep: true,
timezone: 0,
HID : false,
HIDGestures: false,
debug: false,
clock: null
clock: null,
"12hour" : false,
distance : "kilometer" // or "mile"
};
setLCDTimeout(settings.timeout);
updateSettings();
@ -43,6 +37,7 @@ const boolFormat = (v) => v ? "On" : "Off";
function showMainMenu() {
const mainmenu = {
'': { 'title': 'Settings' },
'Make Connectable': makeConnectable,
'BLE': {
value: settings.ble,
format: boolFormat,
@ -93,7 +88,28 @@ function showMainMenu() {
}
}
},
'Locale': showLocaleMenu,
'Select Clock': showClockMenu,
'HID': {
value: settings.HID,
format: boolFormat,
onchange: () => {
settings.HID = !settings.HID;
updateSettings();
}
},
'Set Time': showSetTimeMenu,
'Reset Settings': showResetMenu,
'Turn Off': Bangle.off,
'< Back': ()=> {load();}
};
return E.showMenu(mainmenu);
}
function showLocaleMenu() {
const localemenu = {
'': { 'title': 'Locale' },
'< Back': showMainMenu,
'Time Zone': {
value: settings.timezone,
min: -11,
@ -104,37 +120,24 @@ function showMainMenu() {
updateSettings();
}
},
'HID': {
value: settings.HID,
format: boolFormat,
onchange: () => {
settings.HID = !settings.HID;
'Clock Style': {
value: !!settings["12hour"],
format : v => v?"12hr":"24hr",
onchange: v => {
settings["12hour"] = v;
updateSettings();
}
},
'HID Gestures': {
value: settings.HIDGestures,
format: boolFormat,
onchange: () => {
settings.HIDGestures = !settings.HIDGestures;
'Distance/Speed': {
value: settings.distanceunit=="mile",
format: v => v?"mile":"kilometer",
onchange: v => {
settings.distanceunit = v?"mile":"kilometer";
updateSettings();
}
},
'Debug': {
value: settings.debug,
format: boolFormat,
onchange: () => {
settings.debug = !settings.debug;
updateSettings();
}
},
'Set Time': showSetTimeMenu,
'Make Connectable': makeConnectable,
'Reset Settings': showResetMenu,
'Turn Off': Bangle.off,
'< Back': ()=> {load();}
};
return E.showMenu(mainmenu);
return E.showMenu(localemenu);
}
function showResetMenu() {
@ -149,16 +152,7 @@ function showResetMenu() {
}
setTimeout(showMainMenu, 50);
});
},
// this is include for debugging. remove for production
/*'Erase': () => {
storage.erase('=setting');
storage.erase('-setting');
storage.erase('@setting');
storage.erase('*setting');
storage.erase('+setting');
E.reboot();
}*/
}
};
return E.showMenu(resetmenu);
}

1
defaultapps.json Normal file
View File

@ -0,0 +1 @@
["boot","launch","mclock","setting","sbat","sbt"]

View File

@ -126,7 +126,8 @@
<h3>Utilities</h3>
<p><button class="btn" id="settime">Set Bangle.js Time</button>
<button class="btn" id="removeall">Remove all Apps</button></p>
<button class="btn" id="removeall">Remove all Apps</button>
<button class="btn" id="installdefault">Install default apps</button></p>
</div>
</div>

View File

@ -422,13 +422,46 @@ document.getElementById("settime").addEventListener("click",event=>{
});
document.getElementById("removeall").addEventListener("click",event=>{
showPrompt("Remove All","Really remove all apps?").then(() => {
Comms.removeAllApps().then(()=>{
appsInstalled = [];
showToast("All apps removed","success");
refreshMyApps();
refreshLibrary();
}, err=>{
showToast("App removal failed, "+err,"error");
});
return Comms.removeAllApps();
}).then(()=>{
appsInstalled = [];
showToast("All apps removed","success");
return getInstalledApps();
}).catch(err=>{
showToast("App removal failed, "+err,"error");
});
});
// Install all default apps in one go
document.getElementById("installdefault").addEventListener("click",event=>{
var defaultApps, appCount;
httpGet("defaultapps.json").then(json=>{
defaultApps = JSON.parse(json);
defaultApps = defaultApps.map( appid => appJSON.find(app=>app.id==appid) );
if (defaultApps.some(x=>x===undefined))
throw "Not all apps found";
appCount = defaultApps.length;
return showPrompt("Install Defaults","Remove everything and install default apps?");
}).then(() => {
return Comms.removeAllApps();
}).then(()=>{
appsInstalled = [];
showToast(`Existing apps removed. Installing ${appCount} apps...`);
return new Promise(resolve => {
function upload() {
var app = defaultApps.shift();
if (app===undefined) return resolve();
Comms.uploadApp(app).then((appJSON) => {
if (appJSON) appsInstalled.push(appJSON);
showToast(`(${appCount-defaultApps.length}/${appCount}) ${app.name} Uploaded`);
upload();
});
}
upload();
});
}).then(()=>{
showToast("Default apps successfully installed!","success");
return getInstalledApps();
}).catch(err=>{
showToast("App Install failed, "+err,"error");
});
});