MASSIVE REFACTOR

New Bangle.js firmwares remove 8 char name restriction so we're ditching the first char -> file type and using normal file extensions
Took the opportunity to remove code for older Bangle.js (since the new stuff won't work anyway)
Also removed the need for an 'app.json' - it's now renamed 'app.info' on the watch, and we just auto-generate it
Renamed a few apps so widgets all start with 'wid'
pull/191/head
Gordon Williams 2020-02-28 11:44:25 +00:00
parent 95a42582f3
commit 50e3c852fb
106 changed files with 287 additions and 741 deletions

View File

@ -17,11 +17,11 @@ listed in `apps.json`, loads them, and sends them over Web Bluetooth.
Filenames in storage are limited to 8 characters. To
easily distinguish between file types, we use the following:
* `+stuff` is JSON for an app
* `*stuff` is an image
* `-stuff` is JS code
* `=stuff` is JS code for stuff that is run at boot time - eg. handling settings or creating widgets on the clock screen
* `@stuff` is used for JSON settings for an app
* `stuff.info` is JSON that describes an app - this is auto-generated by the App Loader
* `stuff.img` is an image
* `stuff.app.js` is JS code
* `stuff.wid.js` is JS code for widgets
* `stuff.json` is used for JSON settings for an app
## Developing your own app
@ -32,35 +32,25 @@ easily distinguish between file types, we use the following:
## Adding your app to the menu
* Come up with a unique 7 character name, we'll assume `7chname`
* Come up with a unique (all lowercase, nu spaces) name, we'll assume `7chname`. Bangle.js
is limited to 28 char filenames and appends a file extension (eg `.js`) so please
try and keep filenames short to avoid overflowing the buffer.
* Create a folder called `apps/<id>`, lets assume `apps/7chname`
* We'd recommend that you copy files from 'Example Applications' (below) as a base, or...
* `apps/7chname/app.png` should be a 48px icon
* Use http://www.espruino.com/Image+Converter to create `apps/7chname/app-icon.js`, using a 1 bit, 4 bit or 8 bit Web Palette "Image String"
* Create an entry in `apps/7chname/app.json` as follows:
```
{
"name":"Short Name",
"icon":"*7chname",
"src":"-7chname"
}
```
See `app.json / widget.json` below for more info on the correct format.
* Create an entry in `apps.json` as follows:
```
{ "id": "7chname",
"name": "My app's human readable name",
"shortName" : "Short Name",
"icon": "app.png",
"description": "A detailed description of my great app",
"tags": "",
"storage": [
{"name":"+7chname","url":"app.json"},
{"name":"-7chname","url":"app.js"},
{"name":"*7chname","url":"app-icon.js","evaluate":true}
{"name":"7chname.app.js","url":"app.js"},
{"name":"7chname.img","url":"app-icon.js","evaluate":true}
],
},
```
@ -81,32 +71,26 @@ Be aware of the delay between commits and updates on github.io - it can take a f
### Offline
You can add the following to the Espruino Web IDE:
Using the 'Storage' icon in [the Web IDE](https://www.espruino.com/ide/)
(4 discs), upload your files into the places described in your JSON:
```
// replace with your 7chname app name
var appname = "mygreat";
* `app-icon.js` -> `7chname.img`
require("Storage").write('*'+appname,
// place app-icon.js contents here
);
Now load `app.js` up in the editor, and click the down-arrow to the bottom
right of the `Send to Espruino` icon. Click `Storage` and then either choose
`7chname.app.js` (if you'd uploaded your app previously), or `New File`
and then enter `7chname.app.js` as the name.
//
require("Storage").write("+"+appname,{
"name":"My Great App","type":"",
"icon":"*"+appname,
"src":"-"+appname,
});
Now, clicking the `Send to Espruino` icon will load the app directly into
Espruino **and** will automatically run it.
require("Storage").write("-"+appname,`
// place contents of app.js here
// be aware of double-quoting templated strings
`
```
When you upload code this way, your app will be uploaded to Bangle.js's menu
When you upload code this way, your app will even be uploaded to Bangle.js's menu
without you having to use the `Bangle App Loader`
**Note:** Widgets need to be run inside a clock or app, so if you're
developing a widget you need to go go `Settings` -> `Communications` -> `Load after saving`
and set it to `Load default application`.
## Example Applications
To make the process easier we've come up with some example applications that you can use as a base
@ -114,21 +98,23 @@ when creating your own. Just come up with a unique 7 character name, copy `apps/
or `apps/_example_widget` to `apps/7chname`, and add `apps/_example_X/add_to_apps.json` to
`apps.json`.
**If you're making a widget** please start the name with `wid` to make
it easy to find!
### App Example
The app example is available in [`apps/_example_app`](apps/_example_app)
Apps are listed in the Bangle.js menu, accessible from a clock app via the middle button.
* `add_to_apps.json` - insert into `apps.json`, describes the widget to bootloader and loader
* `add_to_apps.json` - insert into `apps.json`, describes the app to bootloader and loader
* `app.png` - app icon - 48x48px
* `app-icon.js` - JS version of the icon (made with http://www.espruino.com/Image+Converter) for use in Bangle.js's menu
* `app.json` - short app name for Bangle.js menu and storage filenames
* `app.js` - app code
#### `app-icon.js`
The icon image and short description is used in the menu entry as selection posibility.
The icon image and short description is used in the menu entry as selection possibility.
Use the Espruino [image converter](https://www.espruino.com/Image+Converter) and upload your `app.png` file.
@ -155,13 +141,12 @@ Keep in mind to use this converter for creating images you like to draw with `g.
The widget example is available in [`apps/_example_widget`](apps/_example_widget)
* `add_to_apps.json` - insert into `apps.json`, describes the widget to bootloader and loader
* `widget.json` - short widget name and storage names
* `widget.js` - widget code
### `app.json` / `widget.json` format
### `app.info` format
This is the file that's loaded onto Bangle.js, which gives information
about the app.
This is the file that's **auto-generated** and loaded onto Bangle.js by the App Loader,
and which gives information about the app for the Launcher.
```
{
@ -184,9 +169,10 @@ about the app.
```
{ "id": "appid", // 7 character app id
"name": "Readable name", // readable name
"shortName": "Short name", // short name for launcher
"icon": "icon.png", // icon in apps/
"description": "...", // long description
"type":"...", // optional(if app) - 'app'/'widget'/'launch'
"type":"...", // optional(if app) - 'app'/'widget'/'launch'/'bootloader'
"tags": "", // comma separated tag list for searching
"custom": "custom.html", // if supplied, apps/custom.html is loaded in an
@ -203,7 +189,7 @@ about the app.
// add an icon to allow your app to be tested
"storage": [ // list of files to add to storage
{"name":"-appid", // filename to use in storage
{"name":"appid.js", // filename to use in storage
"url":"", // URL of file to load (currently relative to apps/)
"content":"..." // if supplied, this content is loaded directly
"evaluate":true // if supplied, data isn't quoted into a String before upload
@ -245,13 +231,8 @@ version of what's in `apps.json`:
sendCustomizedApp({
id : "7chname",
storage:[
{name:"-7chname", content:app_source_code},
{name:"+7chname", content:JSON.stringify({
name:"My app's name",
icon:"*7chname",
src:"-7chname"
})},
{name:"*7chname", content:'require("heatshrink").decompress(atob("mEwg...4"))', evaluate:true},
{name:"7chname.app.js", content:app_source_code},
{name:"7chname.img", content:'require("heatshrink").decompress(atob("mEwg...4"))', evaluate:true},
]
});
});
@ -299,7 +280,7 @@ See [apps/gpsrec/interface.html](the GPS Recorder) for a full example.
## Coding hints
- Need to save state? Use the `E.on('kill',...)` event to save JSON to a file called `@7chname`, then load it at startup.
- Need to save state? Use the `E.on('kill',...)` event to save JSON to a file called `7chname.json`, then load it at startup.
- use `g.setFont(.., size)` to multiply the font size, eg ("6x8",3) : "18x24"

View File

@ -20,21 +20,12 @@ var AppInfo = {
})).then(fileContents => { // now we just have a list of files + contents...
// filter out empty files
fileContents = fileContents.filter(x=>x!==undefined);
// What about minification?
// Add app's info JSON
return AppInfo.createAppJSON(app, fileContents);
}).then(fileContents => {
// then map each file to a command to load into storage
fileContents.forEach(storageFile => {
// check if this is the JSON file
if (storageFile.name[0]=="+") {
storageFile.evaluate = true;
var json = {};
try {
json = JSON.parse(storageFile.content);
} catch (e) {
reject(storageFile.name+" is not valid JSON");
}
if (app.version) json.version = app.version;
json.files = fileContents.map(storageFile=>storageFile.name).join(",");
storageFile.content = JSON.stringify(json);
}
// format ready for Espruino
var js;
if (storageFile.evaluate) {
@ -49,6 +40,35 @@ var AppInfo = {
}).catch(err => reject(err));
});
},
createAppJSON : (app, fileContents) => {
return new Promise((resolve,reject) => {
var appJSONName = app.id+".info";
// Check we don't already have a JSON file!
var appJSONFile = fileContents.find(f=>f.name==appJSONName);
if (appJSONFile) reject("App JSON file explicitly specified!");
// Now actually create the app JSON
var json = {
id : app.id
};
if (app.shortName) json.name = app.shortName;
else json.name = app.name;
if (app.type && app.type!="app") json.type = app.type;
if (fileContents.find(f=>f.name==app.id+".app.js"))
json.src = app.id+".app.js";
if (fileContents.find(f=>f.name==app.id+".img"))
json.icon = app.id+".img";
if (app.sortorder) json.sortorder = app.sortorder;
if (app.version) json.version = app.version;
var fileList = fileContents.map(storageFile=>storageFile.name);
fileList.unshift(appJSONName); // do we want this? makes life easier!
json.files = fileList.join(",");
fileContents.push({
name : appJSONName,
content : JSON.stringify(json)
});
resolve(fileContents);
});
}
};
if ("undefined"!=typeof module)

342
apps.json
View File

@ -5,22 +5,23 @@
"version":"0.06",
"description": "This is needed by Bangle.js to automatically load the clock, menu, widgets and settings",
"tags": "tool,system",
"type":"bootloader",
"storage": [
{"name":".boot0","url":"boot0.js"},
{"name":".bootcde","url":"bootloader.js"},
{"name":"+boot","url":"bootloader.json"}
{"name":".bootcde","url":"bootloader.js"}
],
"sortorder" : -10
},
{ "id": "launch",
"name": "Default Launcher",
"shortName":"Launcher",
"icon": "app.png",
"version":"0.01",
"description": "This is needed by Bangle.js to display a menu allowing you to choose your own applications. You can replace this with a customised launcher.",
"tags": "tool,system,launcher",
"type":"launch",
"storage": [
{"name":"+launch","url":"app.json"},
{"name":"-launch","url":"app.js"}
{"name":"launch.app.js","url":"app.js"}
],
"sortorder" : -10
},
@ -32,9 +33,8 @@
"tags": "tool,system",
"allow_emulator":true,
"storage": [
{"name":"+about","url":"app.json"},
{"name":"-about","url":"app.js"},
{"name":"*about","url":"app-icon.js","evaluate":true}
{"name":"about.app.js","url":"app.js"},
{"name":"about.img","url":"app-icon.js","evaluate":true}
]
},
{ "id": "welcome",
@ -45,9 +45,8 @@
"tags": "welcome",
"allow_emulator":true,
"storage": [
{"name":"+welcome","url":"app.json"},
{"name":"-welcome","url":"app.js"},
{"name":"*welcome","url":"app-icon.js","evaluate":true}
{"name":"welcome.app.js","url":"app.js"},
{"name":"welcome.img","url":"app-icon.js","evaluate":true}
]
},
{ "id": "gbridge",
@ -57,10 +56,9 @@
"description": "The default notification handler for Gadgetbridge notifications from Android",
"tags": "tool,system,android,widget",
"storage": [
{"name":"+gbridge","url":"app.json"},
{"name":"-gbridge","url":"app.js"},
{"name":"*gbridge","url":"app-icon.js","evaluate":true},
{"name":"=gbridge","url":"widget.js"}
{"name":"gbridge.app.js","url":"app.js"},
{"name":"gbridge.img","url":"app-icon.js","evaluate":true},
{"name":"gbridge.wid.js","url":"widget.js"}
]
},
{ "id": "mclock",
@ -72,9 +70,8 @@
"type":"clock",
"allow_emulator":true,
"storage": [
{"name":"+mclock","url":"clock-morphing.json"},
{"name":"-mclock","url":"clock-morphing.js"},
{"name":"*mclock","url":"clock-morphing-icon.js","evaluate":true}
{"name":"mclock.app.js","url":"clock-morphing.js"},
{"name":"mclock.img","url":"clock-morphing-icon.js","evaluate":true}
],
"sortorder" : -9
},
@ -85,25 +82,24 @@
"description": "A menu for setting up Bangle.js",
"tags": "tool,system",
"storage": [
{"name":"+setting","url":"settings.json"},
{"name":"-setting","url":"settings.js"},
{"name":"@setting","url":"settings-default.json","evaluate":true},
{"name":"*setting","url":"settings-icon.js","evaluate":true}
{"name":"setting.app.js","url":"settings.js"},
{"name":"setting.json","url":"settings-default.json","evaluate":true},
{"name":"setting.img","url":"settings-icon.js","evaluate":true}
],
"sortorder" : -2
},
{ "id": "alarm",
"name": "Default Alarm",
"shortName":"Alarms",
"icon": "app.png",
"version":"0.01",
"description": "Set and respond to alarms",
"tags": "tool,alarm,widget",
"storage": [
{"name":"+alarm","url":"app.json"},
{"name":"-alarm","url":"app.js"},
{"name":"@alarm","content":"[]"},
{"name":"*alarm","url":"app-icon.js","evaluate":true},
{"name":"=alarm","url":"widget.js"}
{"name":"alarm.app.js","url":"app.js"},
{"name":"alarm.json","content":"[]"},
{"name":"alarm.img","url":"app-icon.js","evaluate":true},
{"name":"alarm.wid.js","url":"widget.js"}
]
},
{ "id": "wclock",
@ -115,9 +111,8 @@
"type":"clock",
"allow_emulator":true,
"storage": [
{"name":"+wclock","url":"clock-word.json"},
{"name":"-wclock","url":"clock-word.js"},
{"name":"*wclock","url":"clock-word-icon.js","evaluate":true}
{"name":"wclock.app.js","url":"clock-word.js"},
{"name":"wclock.img","url":"clock-word-icon.js","evaluate":true}
]
},
{ "id": "aclock",
@ -129,9 +124,8 @@
"type":"clock",
"allow_emulator":true,
"storage": [
{"name":"+aclock","url":"clock-analog.json"},
{"name":"-aclock","url":"clock-analog.js"},
{"name":"*aclock","url":"clock-analog-icon.js","evaluate":true}
{"name":"aclock.app.js","url":"clock-analog.js"},
{"name":"aclock.img","url":"clock-analog-icon.js","evaluate":true}
]
},
{ "id": "clck3x2",
@ -142,9 +136,8 @@
"tags": "clock",
"allow_emulator":true,
"storage": [
{"name":"+clck3x2","url":"clock3x2.json"},
{"name":"-clck3x2","url":"clock3x2.js"},
{"name":"*clck3x2","url":"clock3x2-icon.js","evaluate":true}
{"name":"clck3x2.app.js","url":"clock3x2.js"},
{"name":"clck3x2.img","url":"clock3x2-icon.js","evaluate":true}
]
},
{ "id": "trex",
@ -155,9 +148,8 @@
"tags": "game",
"allow_emulator":true,
"storage": [
{"name":"+trex","url":"trex.json"},
{"name":"-trex","url":"trex.js"},
{"name":"*trex","url":"trex-icon.js","evaluate":true}
{"name":"trex.app.js","url":"trex.js"},
{"name":"trex.img","url":"trex-icon.js","evaluate":true}
]
},
{ "id": "astroid",
@ -168,9 +160,8 @@
"tags": "game",
"allow_emulator":true,
"storage": [
{"name":"+astroid","url":"asteroids.json"},
{"name":"-astroid","url":"asteroids.js"},
{"name":"*astroid","url":"asteroids-icon.js","evaluate":true}
{"name":"astroid.app.js","url":"asteroids.js"},
{"name":"astroid.img","url":"asteroids-icon.js","evaluate":true}
]
},
{ "id": "clickms",
@ -180,9 +171,8 @@
"description": "Get several friends to start the game, then compete to see who can press BTN1 the most!",
"tags": "game",
"storage": [
{"name":"+clickms","url":"click-master.json"},
{"name":"-clickms","url":"click-master.js"},
{"name":"*clickms","url":"click-master-icon.js","evaluate":true}
{"name":"clickms.app.js","url":"click-master.js"},
{"name":"clickms.img","url":"click-master-icon.js","evaluate":true}
]
},
{ "id": "horsey",
@ -192,9 +182,8 @@
"description": "Get several friends to start the game, then compete to see who can press BTN1 the most!",
"tags": "game",
"storage": [
{"name":"+horsey","url":"horse-race.json"},
{"name":"-horsey","url":"horse-race.js"},
{"name":"*horsey","url":"horse-race-icon.js","evaluate":true}
{"name":"horsey.app.js","url":"horse-race.js"},
{"name":"horsey.img","url":"horse-race-icon.js","evaluate":true}
]
},
{ "id": "compass",
@ -204,9 +193,8 @@
"description": "Simple compass that points North",
"tags": "tool,outdoors",
"storage": [
{"name":"+compass","url":"compass.json"},
{"name":"-compass","url":"compass.js"},
{"name":"*compass","url":"compass-icon.js","evaluate":true}
{"name":"compass.app.js","url":"compass.js"},
{"name":"compass.img","url":"compass-icon.js","evaluate":true}
]
},
{ "id": "gpstime",
@ -216,9 +204,8 @@
"description": "Update the Bangle.js's clock based on the time from the GPS receiver",
"tags": "tool,gps",
"storage": [
{"name":"+gpstime","url":"gpstime.json"},
{"name":"-gpstime","url":"gpstime.js"},
{"name":"*gpstime","url":"gpstime-icon.js","evaluate":true}
{"name":"gpstime.app.js","url":"gpstime.js"},
{"name":"gpstime.img","url":"gpstime-icon.js","evaluate":true}
]
},
{ "id": "openloc",
@ -228,8 +215,7 @@
"description": "Convert your current GPS location to a series of characters",
"tags": "tool,outdoors,gps",
"storage": [
{"name":"+openloc","url":"openlocation.json"},
{"name":"-openloc","url":"openlocation.js","evaluate":true}
{"name":"openloc.app.js","url":"openlocation.js","evaluate":true}
]
},
{ "id": "speedo",
@ -239,9 +225,8 @@
"description": "Show the current speed according to the GPS",
"tags": "tool,outdoors,gps",
"storage": [
{"name":"+speedo","url":"speedo.json"},
{"name":"-speedo","url":"speedo.js"},
{"name":"*speedo","url":"speedo-icon.js","evaluate":true}
{"name":"speedo.app.js","url":"speedo.js"},
{"name":"speedo.img","url":"speedo-icon.js","evaluate":true}
]
},
{ "id": "gpsrec",
@ -252,11 +237,10 @@
"description": "Application that allows you to record a GPS track. Can run in background",
"tags": "tool,outdoors,gps,widget",
"storage": [
{"name":"+gpsrec","url":"app.json"},
{"name":"-gpsrec","url":"app.js"},
{"name":"@gpsrec","url":"app-settings.json","evaluate":true},
{"name":"*gpsrec","url":"app-icon.js","evaluate":true},
{"name":"=gpsrec","url":"widget.js"}
{"name":"gpsrec.app.js","url":"app.js"},
{"name":"gpsrec.json","url":"app-settings.json","evaluate":true},
{"name":"gpsrec.img","url":"app-icon.js","evaluate":true},
{"name":"gpsrec.wid.js","url":"widget.js"}
]
},
{ "id": "slevel",
@ -266,9 +250,8 @@
"description": "Show the current angle of the watch, so you can use it to make sure something is absolutely flat",
"tags": "tool",
"storage": [
{"name":"+slevel","url":"spiritlevel.json"},
{"name":"-slevel","url":"spiritlevel.js"},
{"name":"*slevel","url":"spiritlevel-icon.js","evaluate":true}
{"name":"slevel.app.js","url":"spiritlevel.js"},
{"name":"slevel.img","url":"spiritlevel-icon.js","evaluate":true}
]
},
{ "id": "files",
@ -278,33 +261,30 @@
"description": "Show currently installed apps, free space, and allow their deletion from the watch",
"tags": "tool,system",
"storage": [
{"name":"+files","url":"files.json"},
{"name":"-files","url":"files.js"},
{"name":"*files","url":"files-icon.js","evaluate":true}
{"name":"files.app.js","url":"files.js"},
{"name":"files.img","url":"files-icon.js","evaluate":true}
]
},
{ "id": "sbat",
{ "id": "widbat",
"name": "Battery Level Widget",
"icon": "widget-battery.png",
"icon": "widget.png",
"version":"0.02",
"description": "Show the current battery level and charging status in the top right of the clock",
"tags": "widget,battery",
"type":"widget",
"storage": [
{"name":"+sbat","url":"widget-battery.json"},
{"name":"=sbat","url":"widget-battery.js"}
{"name":"widbat.wid.js","url":"widget.js"}
]
},
{ "id": "sbt",
{ "id": "widbt",
"name": "Bluetooth Widget",
"icon": "widget-bluetooth.png",
"icon": "widget.png",
"version":"0.01",
"description": "Show the current Bluetooth connection status in the top right of the clock",
"tags": "widget,bluetooth",
"type":"widget",
"storage": [
{"name":"+sbt","url":"widget-bluetooth.json"},
{"name":"=sbt","url":"widget-bluetooth.js"}
{"name":"widbt.wid.js","url":"widget.js"}
]
},
{ "id": "hrm",
@ -314,20 +294,18 @@
"description": "Measure your current heart rate",
"tags": "health",
"storage": [
{"name":"+hrm","url":"heartrate.json"},
{"name":"-hrm","url":"heartrate.js"},
{"name":"*hrm","url":"heartrate-icon.js","evaluate":true}
{"name":"hrm.app.js","url":"heartrate.js"},
{"name":"hrm.img","url":"heartrate-icon.js","evaluate":true}
]
},
{ "id": "whrm",
{ "id": "widhrm",
"name": "Simple Heart Rate widget",
"icon": "widget.png",
"version":"0.01",
"description": "When the screen is on, the widget turns on the heart rate monitor and displays the current heart rate (or last known in grey). For this to work well you'll need at least a 15 second LCD Timeout.",
"tags": "health,widget",
"storage": [
{"name":"+whrm","url":"widget.json"},
{"name":"=whrm","url":"widget.js"}
{"name":"widhrm.wid.js","url":"widget.js"}
]
},
{ "id": "stetho",
@ -337,9 +315,8 @@
"description": "Hear your heart rate",
"tags": "health",
"storage": [
{"name":"+stetho","url":"stetho.json"},
{"name":"-stetho","url":"stetho.js"},
{"name":"*stetho","url":"stetho-icon.js","evaluate":true}
{"name":"stetho.app.js","url":"stetho.js"},
{"name":"stetho.img","url":"stetho-icon.js","evaluate":true}
]
},
{ "id": "swatch",
@ -350,9 +327,8 @@
"tags": "health",
"allow_emulator":true,
"storage": [
{"name":"+swatch","url":"stopwatch.json"},
{"name":"-swatch","url":"stopwatch.js"},
{"name":"*swatch","url":"stopwatch-icon.js","evaluate":true}
{"name":"swatch.app.js","url":"stopwatch.js"},
{"name":"swatch.img","url":"stopwatch-icon.js","evaluate":true}
]
},
{ "id": "hidmsic",
@ -362,9 +338,8 @@
"description": "Enable HID in settings, pair with your phone, then use this app to control music from your watch!",
"tags": "bluetooth",
"storage": [
{"name":"+hidmsic","url":"hid-music.json"},
{"name":"-hidmsic","url":"hid-music.js"},
{"name":"*hidmsic","url":"hid-music-icon.js","evaluate":true}
{"name":"hidmsic.app.js","url":"hid-music.js"},
{"name":"hidmsic.img","url":"hid-music-icon.js","evaluate":true}
]
},
{ "id": "hidkbd",
@ -374,9 +349,8 @@
"description": "Enable HID in settings, pair with your phone/PC, then use this app to control other apps",
"tags": "bluetooth",
"storage": [
{"name":"+hidkbd","url":"hid-keyboard.json"},
{"name":"-hidkbd","url":"hid-keyboard.js"},
{"name":"*hidkbd","url":"hid-keyboard-icon.js","evaluate":true}
{"name":"hidkbd.app.js","url":"hid-keyboard.js"},
{"name":"hidkbd.img","url":"hid-keyboard-icon.js","evaluate":true}
]
},
{ "id": "hidbkbd",
@ -386,9 +360,8 @@
"description": "Enable HID in settings, pair with your phone/PC, then type messages using the onscreen keyboard by tapping repeatedly on the key you want",
"tags": "bluetooth",
"storage": [
{"name":"+hidbkbd","url":"hid-binary-keyboard.json"},
{"name":"-hidbkbd","url":"hid-binary-keyboard.js"},
{"name":"*hidbkbd","url":"hid-binary-keyboard-icon.js","evaluate":true}
{"name":"hidbkbd.app.js","url":"hid-binary-keyboard.js"},
{"name":"hidbkbd.img","url":"hid-binary-keyboard-icon.js","evaluate":true}
]
},
{ "id": "animals",
@ -398,17 +371,16 @@
"description": "Simple toddler's game - displays a different number of animals each time the screen is pressed",
"tags": "game",
"storage": [
{"name":"+animals","url":"animals.json"},
{"name":"-animals","url":"animals.js"},
{"name":"*animals","url":"animals-icon.js","evaluate":true},
{"name":"*snake","url":"animals-snake.js","evaluate":true},
{"name":"*duck","url":"animals-duck.js","evaluate":true},
{"name":"*swan","url":"animals-swan.js","evaluate":true},
{"name":"*fox","url":"animals-fox.js","evaluate":true},
{"name":"*camel","url":"animals-camel.js","evaluate":true},
{"name":"*pig","url":"animals-pig.js","evaluate":true},
{"name":"*sheep","url":"animals-sheep.js","evaluate":true},
{"name":"*mouse","url":"animals-mouse.js","evaluate":true}
{"name":"animals.app.js","url":"animals.js"},
{"name":"animals.img","url":"animals-icon.js","evaluate":true},
{"name":"animals-snake.img","url":"animals-snake.js","evaluate":true},
{"name":"animals-duck.img","url":"animals-duck.js","evaluate":true},
{"name":"animals-swan.img","url":"animals-swan.js","evaluate":true},
{"name":"animals-fox.img","url":"animals-fox.js","evaluate":true},
{"name":"animals-camel.img","url":"animals-camel.js","evaluate":true},
{"name":"animals-pig.img","url":"animals-pig.js","evaluate":true},
{"name":"animals-sheep.img","url":"animals-sheep.js","evaluate":true},
{"name":"animals-mouse.img","url":"animals-mouse.js","evaluate":true}
]
},
{ "id": "qrcode",
@ -419,9 +391,8 @@
"tags": "",
"custom": "qrcode.html",
"storage": [
{"name":"-qrcode"},
{"name":"+qrcode"},
{"name":"=qrcode"}
{"name":"qrcode.app.js"},
{"name":"qrcode.wid.js"}
]
},
{ "id": "beer",
@ -432,9 +403,8 @@
"tags": "",
"custom": "beercompass.html",
"storage": [
{"name":"-beer"},
{"name":"+beer"},
{"name":"=beer"}
{"name":"beer.app.js"},
{"name":"beer.wid.js"}
]
},
{ "id": "route",
@ -445,9 +415,8 @@
"tags": "",
"custom": "route.html",
"storage": [
{"name":"-route"},
{"name":"+route"},
{"name":"=route"}
{"name":"route.app.js"},
{"name":"route.wid.js"}
]
},
@ -461,14 +430,13 @@
"description": "NodeConfEU 2019 'First Start' Sequence",
"tags": "start",
"storage": [
{"name":"+ncstart","url":"start.json"},
{"name":".boot3","url":"start.js"},
{"name":"*ncstart","url":"start-icon.js","evaluate":true},
{"name":"*bangle","url":"start-bangle.js","evaluate":true},
{"name":"*nceu","url":"start-nceu.js","evaluate":true},
{"name":"*nfr","url":"start-nfr.js","evaluate":true},
{"name":"*nodew","url":"start-nodew.js","evaluate":true},
{"name":"*tf","url":"start-tf.js","evaluate":true}
{"name":"ncstart.img","url":"start-icon.js","evaluate":true},
{"name":"bangle.img","url":"start-bangle.js","evaluate":true},
{"name":"nceu.img","url":"start-nceu.js","evaluate":true},
{"name":"nfr.img","url":"start-nfr.js","evaluate":true},
{"name":"nodew.img","url":"start-nodew.js","evaluate":true},
{"name":"tf.img","url":"start-tf.js","evaluate":true}
]
},
{ "id": "ncfrun",
@ -478,21 +446,19 @@
"description": "Display a map of the NodeConf EU 2019 5K Fun Run route and your location on it",
"tags": "health",
"storage": [
{"name":"+ncfrun","url":"nceu-funrun.json"},
{"name":"-ncfrun","url":"nceu-funrun.js"},
{"name":"*ncfrun","url":"nceu-funrun-icon.js","evaluate":true}
{"name":"ncfrun.app.js","url":"nceu-funrun.js"},
{"name":"ncfrun.img","url":"nceu-funrun-icon.js","evaluate":true}
]
},
{ "id": "nceuwid",
{ "id": "widnceu",
"name": "NCEU Logo Widget",
"icon": "nceu-widget.png",
"icon": "widget.png",
"version":"0.01",
"description": "Show the NodeConf EU logo in the top left",
"tags": "widget",
"type":"widget",
"storage": [
{"name":"+nceuwid","url":"nceu-widget.json"},
{"name":"=nceuwid","url":"nceu-widget.js"}
{"name":"widnceu.wid.js","url":"widget.js"}
]
},
@ -507,9 +473,8 @@
"type":"clock",
"allow_emulator":true,
"storage": [
{"name":"+sclock","url":"clock-simple.json"},
{"name":"-sclock","url":"clock-simple.js"},
{"name":"*sclock","url":"clock-simple-icon.js","evaluate":true}
{"name":"sclock.app.js","url":"clock-simple.js"},
{"name":"sclock.img","url":"clock-simple-icon.js","evaluate":true}
]
},
{ "id": "gesture",
@ -520,11 +485,10 @@
"tags": "gesture,ai",
"type":"app",
"storage": [
{"name":"+gesture","url":"gesture.json"},
{"name":"-gesture","url":"gesture.js"},
{"name":"gesture.app.js","url":"gesture.js"},
{"name":".tfnames","url":"gesture-tfnames.js","evaluate":true},
{"name":".tfmodel","url":"gesture-tfmodel.js","evaluate":true},
{"name":"*gesture","url":"gesture-icon.js","evaluate":true}
{"name":"gesture.img","url":"gesture-icon.js","evaluate":true}
]
},
{ "id": "pparrot",
@ -536,9 +500,8 @@
"type":"app",
"allow_emulator":true,
"storage": [
{"name":"+pparrot","url":"party-parrot.json"},
{"name":"-pparrot","url":"party-parrot.js"},
{"name":"*pparrot","url":"party-parrot-icon.js","evaluate":true}
{"name":"pparrot.app.js","url":"party-parrot.js"},
{"name":"pparrot.img","url":"party-parrot-icon.js","evaluate":true}
]
},
{ "id": "hrings",
@ -550,9 +513,8 @@
"type":"app",
"allow_emulator":true,
"storage": [
{"name":"+hrings","url":"hypno-rings.json"},
{"name":"-hrings","url":"hypno-rings.js"},
{"name":"*hrings","url":"hypno-rings-icon.js","evaluate":true}
{"name":"hrings.app.js","url":"hypno-rings.js"},
{"name":"hrings.img","url":"hypno-rings-icon.js","evaluate":true}
]
},
{ "id": "morse",
@ -563,9 +525,8 @@
"tags": "morse,sound,visual,input",
"type":"app",
"storage": [
{"name":"+morse","url":"morse-code.json"},
{"name":"-morse","url":"morse-code.js"},
{"name":"*morse","url":"morse-code-icon.js","evaluate":true}
{"name":"morse.app.js","url":"morse-code.js"},
{"name":"morse.img","url":"morse-code-icon.js","evaluate":true}
]
},
{
@ -576,9 +537,8 @@
"description": "Scan for advertising BLE devices",
"tags" : "bluetooth",
"storage" : [
{"name":"+blescan","url":"blescan.json"},
{"name":"-blescan","url":"blescan.js"},
{"name":"*blescan","url":"blescan-icon.js", "evaluate":true}
{"name":"blescan.app.js","url":"blescan.js"},
{"name":"blescan.img","url":"blescan-icon.js", "evaluate":true}
]
},
{ "id": "mmonday",
@ -588,9 +548,8 @@
"description": "The Bangles make a comeback",
"tags": "sound",
"storage": [
{"name":"+mmonday","url":"manic-monday.json"},
{"name":"-mmonday","url":"manic-monday.js"},
{"name":"*mmonday","url":"manic-monday-icon.js","evaluate":true}
{"name":"mmonday.app.js","url":"manic-monday.js"},
{"name":"mmonday.img","url":"manic-monday-icon.js","evaluate":true}
]
},
{ "id": "jbells",
@ -601,9 +560,8 @@
"tags": "sound",
"type":"app",
"storage": [
{"name":"+jbells","url":"jbells.json"},
{"name":"-jbells","url":"jbells.js"},
{"name":"*jbells","url":"jbells-icon.js","evaluate":true}
{"name":"jbells.app.js","url":"jbells.js"},
{"name":"jbells.img","url":"jbells-icon.js","evaluate":true}
]
},
{ "id": "scolor",
@ -615,9 +573,8 @@
"type":"app",
"allow_emulator":true,
"storage": [
{"name":"+scolor","url":"show-color.json"},
{"name":"-scolor","url":"show-color.js"},
{"name":"*scolor","url":"show-color-icon.js","evaluate":true}
{"name":"scolor.app.js","url":"show-color.js"},
{"name":"scolor.img","url":"show-color-icon.js","evaluate":true}
]
},
{ "id": "miclock",
@ -629,9 +586,8 @@
"type":"clock",
"allow_emulator":true,
"storage": [
{"name":"+miclock","url":"clock-mixed.json"},
{"name":"-miclock","url":"clock-mixed.js"},
{"name":"*miclock","url":"clock-mixed-icon.js","evaluate":true}
{"name":"miclock.app.js","url":"clock-mixed.js"},
{"name":"miclock.img","url":"clock-mixed-icon.js","evaluate":true}
]
},
{ "id": "bclock",
@ -643,9 +599,8 @@
"type":"clock",
"allow_emulator":true,
"storage": [
{"name":"+bclock","url":"clock-binary.json"},
{"name":"-bclock","url":"clock-binary.js"},
{"name":"*bclock","url":"clock-binary-icon.js","evaluate":true}
{"name":"bclock.app.js","url":"clock-binary.js"},
{"name":"bclock.img","url":"clock-binary-icon.js","evaluate":true}
]
},
{ "id": "clotris",
@ -656,9 +611,8 @@
"tags": "game",
"allow_emulator":true,
"storage": [
{"name":"+clotris","url":"clock-tris.json"},
{"name":"-clotris","url":"clock-tris.js"},
{"name":"*clotris","url":"clock-tris-icon.js","evaluate":true},
{"name":"clotris.app.js","url":"clock-tris.js"},
{"name":"clotris.img","url":"clock-tris-icon.js","evaluate":true},
{"name":".trishig","url":"clock-tris-high"}
]
},
@ -670,9 +624,8 @@
"tags": "game",
"allow_emulator":true,
"storage": [
{"name":"+flappy","url":"app.json"},
{"name":"-flappy","url":"app.js"},
{"name":"*flappy","url":"app-icon.js","evaluate":true}
{"name":"flappy.app.js","url":"app.js"},
{"name":"flappy.img","url":"app-icon.js","evaluate":true}
]
},
{
@ -713,9 +666,8 @@
"type":"clock",
"allow_emulator":true,
"storage": [
{"name":"+blobclk","url":"clock-blob.json"},
{"name":"-blobclk","url":"clock-blob.js"},
{"name":"*blobclk","url":"clock-blob-icon.js","evaluate":true}
{"name":"blobclk.app.js","url":"clock-blob.js"},
{"name":"blobclk.img","url":"clock-blob-icon.js","evaluate":true}
]
},
{ "id": "boldclk",
@ -727,33 +679,30 @@
"type":"clock",
"allow_emulator":true,
"storage": [
{"name":"+boldclk","url":"bold_clock.json"},
{"name":"-boldclk","url":"bold_clock.js"},
{"name":"*boldclk","url":"bold_clock-icon.js","evaluate":true}
{"name":"boldclk.app.js","url":"bold_clock.js"},
{"name":"boldclk.img","url":"bold_clock-icon.js","evaluate":true}
]
},
{ "id": "wdclk",
{ "id": "widclk",
"name": "Digital clock widget",
"icon": "digital_clock_widget.png",
"icon": "widget.png",
"version":"0.01",
"description": "A simple digital clock widget",
"tags": "widget,clock",
"type":"widget",
"storage": [
{"name":"+wdclk","url":"digital_clock_widget.json"},
{"name":"=wdclk","url":"digital_clock_widget.js"}
{"name":"widclk.wid.js","url":"widget.js"}
]
},
{ "id": "wpedom",
"name": "Pedometer widget",
"icon": "pedometer_widget.png",
"icon": "widget.png",
"version":"0.06",
"description": "Daily pedometer widget",
"tags": "widget",
"type":"widget",
"storage": [
{"name":"+wpedom","url":"pedometer_widget.json"},
{"name":"=wpedom","url":"pedometer_widget.js"}
{"name":"wpedom.wid.js","url":"widget.js"}
]
},
{ "id": "berlinc",
@ -765,9 +714,8 @@
"type":"clock",
"allow_emulator":true,
"storage": [
{"name":"+berlinc","url":"berlin-clock.json"},
{"name":"-berlinc","url":"berlin-clock.js"},
{"name":"*berlinc","url":"berlin-clock-icon.js","evaluate":true}
{"name":"berlinc.app.js","url":"berlin-clock.js"},
{"name":"berlinc.img","url":"berlin-clock-icon.js","evaluate":true}
]
},
{ "id": "ctrclk",
@ -779,9 +727,8 @@
"type":"clock",
"allow_emulator":true,
"storage": [
{"name":"+ctrclk","url":"app.json"},
{"name":"-ctrclk","url":"app.js"},
{"name":"*ctrclk","url":"app-icon.js","evaluate":true}
{"name":"ctrclk.app.js","url":"app.js"},
{"name":"ctrclk.img","url":"app-icon.js","evaluate":true}
]
},
{ "id": "demoapp",
@ -793,9 +740,8 @@
"type":"app",
"allow_emulator":true,
"storage": [
{"name":"+demoapp","url":"app.json"},
{"name":"-demoapp","url":"app.js"},
{"name":"*demoapp","url":"app-icon.js","evaluate":true}
{"name":"demoapp.app.js","url":"app.js"},
{"name":"demoapp.img","url":"app-icon.js","evaluate":true}
],
"sortorder" : -9
},
@ -805,9 +751,8 @@
"description": "App to send a command to another Espruino to cause it to raise a flag",
"tags": "",
"storage": [
{"name":"+flagrse","url":"app.json"},
{"name":"-flagrse","url":"app.js"},
{"name":"*flagrse","url":"app-icon.js","evaluate":true}
{"name":"flagrse.app.js","url":"app.js"},
{"name":"flagrse.img","url":"app-icon.js","evaluate":true}
]
},
{
@ -820,9 +765,8 @@
"type":"clock",
"allow_emulator":true,
"storage": [
{"name":"+pipboy","url":"app.json"},
{"name":"-pipboy","url":"app.js"},
{"name":"*pipboy","url":"app-icon.js","evaluate":true}
{"name":"pipboy.app.js","url":"app.js"},
{"name":"pipboy.img","url":"app-icon.js","evaluate":true}
]
}
]

View File

@ -1,6 +1,7 @@
// Create an entry in apps.json as follows:
{ "id": "7chname",
"name": "My app's human readable name",
"shortName":"Short Name",
"icon": "app.png",
"version":"0.01",
"description": "A detailed description of my great app",

View File

@ -1,5 +0,0 @@
{
"name":"Short Name",
"icon":"*7chname",
"src":"-7chname"
}

View File

@ -1,10 +1,12 @@
// Create an entry in apps.json as follows:
{ "id": "7chname",
"name": "My widget's human readable name",
"shortName":"Short Name",
"icon": "widget.png",
"version":"0.01",
"description": "A detailed description of my great widget",
"tags": "widget",
"type": "widget",
"storage": [
{"name":"+7chname","url":"widget.json"},
{"name":"=7chname","url":"widget.js"}

View File

@ -1,4 +0,0 @@
{
"name":"widgetname", "type":"widget",
"src":"=7chname"
}

View File

@ -1,5 +0,0 @@
{
"name":"About",
"icon":"*about",
"src":"-about"
}

View File

@ -1,6 +0,0 @@
{
"name":"Analog Clock","type":"clock",
"icon":"*aclock",
"src":"-aclock",
"sortorder":-10
}

View File

@ -1,7 +1,7 @@
Bangle.loadWidgets();
Bangle.drawWidgets();
var alarms = require("Storage").readJSON("@alarm")||[];
var alarms = require("Storage").readJSON("alarm.json")||[];
/*alarms = [
{ on : true,
hr : 6.5, // hours + minutes/60
@ -57,13 +57,11 @@ function editAlarm(alarmIndex) {
value: hrs,
min: 0,
max: 23,
onchange: v=>hrs=v
onchange: v=>{if (v<0)v=23;if (v>23)v=0;hrs=v;this.value=v;}
},
'Minutes': {
value: mins,
min: 0,
max: 60,
onchange: v=>mins=v
onchange: v=>{if (v<0)v=59;if (v>59)v=0;mins=v;this.value=v;}
},
'Enabled': {
value: en,
@ -91,13 +89,13 @@ function editAlarm(alarmIndex) {
if (newAlarm) {
menu["> New Alarm"] = function() {
alarms.push(getAlarm());
require("Storage").write("@alarm",JSON.stringify(alarms));
require("Storage").write("alarm.json",JSON.stringify(alarms));
showMainMenu();
};
} else {
menu["> Save"] = function() {
alarms[alarmIndex] = getAlarm();
require("Storage").write("@alarm",JSON.stringify(alarms));
require("Storage").write("alarm.json",JSON.stringify(alarms));
showMainMenu();
};
}
@ -121,7 +119,7 @@ function showAlarm(alarm) {
alarm.last = (new Date()).getDate();
if (!alarm.rp) alarm.on = false;
}
require("Storage").write("@alarm",JSON.stringify(alarms));
require("Storage").write("alarm.json",JSON.stringify(alarms));
load();
});
function buzz() {

View File

@ -1,5 +0,0 @@
{
"name":"Alarms",
"icon":"*alarm",
"src":"-alarm"
}

View File

@ -1,5 +1,5 @@
(() => {
var alarms = require('Storage').readJSON('@alarm')||[];
var alarms = require('Storage').readJSON('alarm.json')||[];
alarms = alarms.filter(alarm=>alarm.on);
if (!alarms.length) return;
delete alarms;

View File

@ -13,7 +13,7 @@ function next(e) {
} while (current && current==last);
g.clear();
var n = 1 + (0|(Math.random()*3.9));
var img = require("Storage").read("*"+current);
var img = require("Storage").read("animals-"+current+".img");
if (n==1)
g.drawImage(img,120,120,{scale:4,rotate:Math.random()-0.5});
else

View File

@ -1,5 +0,0 @@
{
"name":"Animals Game", "type":"app",
"icon":"*animals",
"src":"-animals"
}

View File

@ -1,5 +0,0 @@
{
"name":"Asteroids!","type":"app",
"icon":"*astroid",
"src":"-astroid"
}

View File

@ -1,7 +0,0 @@
{
"name":"Binary Clock",
"type":"clock",
"icon":"*bclock",
"src":"-bclock"
}

View File

@ -196,20 +196,12 @@ Bangle.on('mag', function(m) {
Bangle.setCompassPower(1);
Bangle.setGPSPower(1);
g.clear();`;
var json = JSON.stringify({
name:"Beer Compass",
icon:"*beer",
src:"-beer"
});
var icon = `require("heatshrink").decompress(atob("mEwghC/AB0O/4AG8AXNgYXHmAXl94XH+AXNn4XH/wXW+YX/C6oWHAAIXN7sz9vdAAoXN9sznvuAAXf/vuC53jC4Xd7wXQ93jn3u9vv9vt7wXT/4tBAgIXQ7wvCC4PgC5sO6czIQJfBC6PumaPDC6wwCC50NYAJcBVgIDBCxrAFbgYXP7yoDF6TADL4YXPVAIXCRyAXC7wXW9zwBC6cNC9zABC4gWQC653CR4fQC6x3TF6gXXI4M9d6wAEC9EN73dAAZfQgczAAkwC/4XXAH4"))`;
sendCustomizedApp({
id : "beer",
storage:[
{name:"-beer", content:app},
{name:"+beer", content:json},
{name:"*beer", content:icon, evaluate:true},
{name:"beer.app.js", content:app},
{name:"beer.img", content:icon, evaluate:true},
]
});
});

View File

@ -1,6 +0,0 @@
{
"name":"Berlin Clock",
"type":"clock",
"icon":"*berlinc",
"src":"-berlinc"
}

View File

@ -1,7 +0,0 @@
{
"name": "BLE Scanner",
"type":"app",
"icon": "*blescan",
"src": "-blescan"
}

View File

@ -1,7 +0,0 @@
{
"name":"Large Clock",
"type":"clock",
"icon":"*blobclk",
"src":"-blobclk",
"sortorder":-10
}

View File

@ -1,7 +0,0 @@
{
"name":"Bold Clock",
"type":"clock",
"icon":"*boldclk",
"src":"-boldclk",
"sortorder":-10
}

View File

@ -1,7 +1,7 @@
// This ALWAYS runs at boot
E.setFlags({pretokenise:1});
// Load settings...
var s = require('Storage').readJSON('@setting')||{};
var s = require('Storage').readJSON('setting.json')||{};
if (s.ble!==false) {
if (s.HID) { // Humen interface device
Bangle.HID = E.toUint8Array(atob("BQEJBqEBhQIFBxngKecVACUBdQGVCIEClQF1CIEBlQV1AQUIGQEpBZEClQF1A5EBlQZ1CBUAJXMFBxkAKXOBAAkFFQAm/wB1CJUCsQLABQwJAaEBhQEVACUBdQGVAQm1gQIJtoECCbeBAgm4gQIJzYECCeKBAgnpgQIJ6oECwA=="));
@ -10,8 +10,7 @@ if (s.ble!==false) {
}
if (s.blerepl===false) { // If not programmable, force terminal off Bluetooth
if (s.log) Terminal.setConsole(true); // if showing debug, force REPL onto terminal
else if (E.setConsole) E.setConsole(null,{force:true}); // on new (2v05+) firmware we have E.setConsole which allows a 'null' console
else LoopbackA.setConsole(true); // for old builds, doing this will use some data as LoopbackB stores some of the chars
else E.setConsole(null,{force:true}); // on new (2v05+) firmware we have E.setConsole which allows a 'null' console
} else {
if (s.log) Terminal.setConsole(); // if showing debug, put REPL on terminal (until connection)
else Bluetooth.setConsole(true); // else if no debug, force REPL to Bluetooth
@ -27,23 +26,23 @@ E.setTimeZone(s.timezone);
delete s;
// check for alarms
function checkAlarm() {
var alarms = require('Storage').readJSON('@alarm')||[];
var alarms = require('Storage').readJSON('alarm.json')||[];
var time = new Date();
var active = alarms.filter(a=>a.on&&(a.last!=time.getDate()));
if (active.length) {
active = active.sort((a,b)=>a.hr-b.hr);
var hr = time.getHours()+(time.getMinutes()/60);
if (!require('Storage').read("-alarm")) {
if (!require('Storage').read("alarm.app.js")) {
console.log("No alarm app!");
require('Storage').write('@alarm',"[]")
require('Storage').write('alarm.json',"[]")
} else {
if (active[0].hr < hr) {
// fire alarm now
load("-alarm");
load("alarm.app.js");
} else {
// execute alarm at the correct time
setTimeout(function() {
load("-alarm");
load("alarm.app.js");
},3600000*(active[0].hr-hr));
}
}
@ -67,42 +66,3 @@ if ((new Date()).getFullYear()==1970) {
Bangle.setGPSPower(1);
} else checkAlarm();
delete checkAlarm;
// Check for
// All of this is just shim for older Bangles
if (!Bangle.loadWidgets) {
Bangle.loadWidgets = function(){
global.WIDGETPOS={tl:32,tr:g.getWidth()-32,bl:32,br:g.getWidth()-32};
global.WIDGETS={};
require("Storage").list().filter(a=>a[0]=='=').forEach(widget=>eval(require("Storage").read(widget)));
};
Bangle.drawWidgets = function(){
for(var w of WIDGETS)w.draw()
};
Bangle.showLauncher = function(){
var l = require("Storage").list().filter(a=>a[0]=='+').map(app=>{
try { return require("Storage").readJSON(app); } catch (e) {}
}).find(app=>app.type=="launch");
if (l) load(l.src);
else E.showMessage("Launcher\nnot found");
};
var _load = load;
global.load = function(x) {
if (!x) _load(x);
else setTimeout(function(){
// attempt to remove any currently-running code
delete Bangle.buzz;
delete Bangle.beep;
Bangle.setLCDOffset&&Bangle.setLCDOffset(0);
Bangle.setLCDMode("direct");
g.clear();
clearInterval();
clearWatch();
Bangle.removeAllListeners();
NRF.removeAllListeners();
Bluetooth.removeAllListeners();
E.removeAllListeners();
for (var i in global) if (i!="g") delete global[i];
setTimeout('eval(require("Storage").read("'+x+'"));',20);
},20);
}
}

View File

@ -1,6 +1,6 @@
// This runs after a 'fresh' boot
var settings={};
try { settings = require("Storage").readJSON('@setting'); } catch (e) {}
try { settings = require("Storage").readJSON('setting.json'); } catch (e) {}
if (!settings.welcomed && require("Storage").read("-welcome")!==undefined) {
setTimeout(()=>load("-welcome"));
} else {
@ -8,7 +8,7 @@ if (!settings.welcomed && require("Storage").read("-welcome")!==undefined) {
var clockApp = settings.clock;
if (clockApp) clockApp = require("Storage").read(clockApp)
if (!clockApp) {
var clockApps = require("Storage").list().filter(a=>a[0]=='+').map(app=>{
var clockApps = require("Storage").list(/\.info$/).map(app=>{
try { return require("Storage").readJSON(app); }
catch (e) {}
}).filter(app=>app.type=="clock").sort((a, b) => a.sortorder - b.sortorder);

View File

@ -1,3 +0,0 @@
{
"name":"Bootloader","type":"boot"
}

View File

@ -1,6 +0,0 @@
{
"name":"Clock 3x2 Pix",
"type":"clock",
"icon":"*clck3x2",
"src":"-clck3x2"
}

View File

@ -1,5 +0,0 @@
{
"name":"Click Master",
"icon": "*clickms",
"src":"-clickms"
}

View File

@ -1,5 +0,0 @@
{
"name":"Clock-Tris",
"icon":"*clotris",
"src":"-clotris"
}

View File

@ -1,5 +0,0 @@
{
"name":"Compass","type":"app",
"icon":"*compass",
"src":"-compass"
}

View File

@ -1,6 +0,0 @@
{
"name": "Centerclock",
"type": "clock",
"icon": "*ctrclk",
"src": "-ctrclk"
}

View File

@ -1,6 +0,0 @@
{
"name":"Cube",
"type":"app",
"icon":"*cube",
"src":"-cube"
}

View File

@ -1,5 +0,0 @@
{
"name":"Demo Loop",
"icon":"*demoapp",
"src":"-demoapp"
}

View File

@ -66,8 +66,8 @@ function showApps() {
'< Back': () => m = showMainMenu(),
};
var list = storage.list().filter((a)=> {
return a[0]=='+' && a !== '+setting';
var list = storage.list(/\.info$/).filter((a)=> {
return a !== 'setting.info';
}).sort().map((app) => {
var ret = storage.readJSON(app);
ret[''] = app;

View File

@ -1,5 +0,0 @@
{
"name":"App Manager","type":"app",
"icon":"*files",
"src":"-files"
}

View File

@ -1,5 +0,0 @@
{
"name":"Flag Raiser",
"icon":"*flagrse",
"src":"-flagrse"
}

View File

@ -1,5 +0,0 @@
{
"name":"Flappy Bird",
"icon":"*flappy",
"src":"-flappy"
}

View File

@ -1,5 +0,0 @@
{
"name":"Gadgetbridge",
"icon":"*gbridge",
"src":"-gbridge"
}

View File

@ -1,5 +0,0 @@
{
"name":"Gesture Test", "type":"app",
"icon":"*gesture",
"src":"-gesture"
}

View File

@ -1,6 +0,0 @@
{
"name": "GPS Info",
"type": "app",
"icon": "*gpsinfo",
"src": "-gpsinfo"
}

View File

@ -1,5 +0,0 @@
{
"recording":false,
"file":0,
"period":1
}

View File

@ -1,14 +1,14 @@
Bangle.loadWidgets();
Bangle.drawWidgets();
var settings = require("Storage").readJSON("@gpsrec")||{};
var settings = require("Storage").readJSON("gpsrec.json")||{};
function getFN(n) {
return ".gpsrc"+n.toString(36);
}
function updateSettings() {
require("Storage").write("@gpsrec", settings);
require("Storage").write("gpsrec.json", settings);
if (WIDGETS["gpsrec"])
WIDGETS["gpsrec"].reload();
}

View File

@ -1,5 +0,0 @@
{
"name":"GPS Recorder",
"icon":"*gpsrec",
"src":"-gpsrec"
}

View File

@ -55,7 +55,7 @@
// Called by the GPS app to reload settings and decide what's
function reload() {
settings = require("Storage").readJSON("@gpsrec")||{};
settings = require("Storage").readJSON("gpsrec.json")||{};
settings.period = settings.period||1;
settings.file |= 0;

View File

@ -1,5 +0,0 @@
{
"name":"GPS Time","type":"app",
"icon":"*gpstime",
"src":"-gpstime"
}

View File

@ -5,7 +5,7 @@ the touchscreen
var storage = require('Storage');
const settings = storage.readJSON('@setting') || { HID: false };
const settings = storage.readJSON('setting.json') || { HID: false };
const KEY = {
A : 4 ,
B : 5 ,

View File

@ -1,5 +0,0 @@
{
"name": "Binary Keyboard","type":"app",
"icon": "*hidbkbd",
"src": "-hidbkbd"
}

View File

@ -1,6 +1,6 @@
var storage = require('Storage');
const settings = storage.readJSON('@setting') || { HID: false };
const settings = storage.readJSON('setting.json') || { HID: false };
var sendHid, next, prev, toggle, up, down, profile;

View File

@ -1,5 +0,0 @@
{
"name": "Keyboard Control","type":"app",
"icon": "*hidkbd",
"src": "-hidkbd"
}

View File

@ -1,6 +1,6 @@
var storage = require('Storage');
const settings = storage.readJSON('@setting') || { HID: false };
const settings = storage.readJSON('setting.json') || { HID: false };
var sendHid, next, prev, toggle, up, down, profile;

View File

@ -1,5 +0,0 @@
{
"name": "Music Control","type":"app",
"icon": "*hidmsic",
"src": "-hidmsic"
}

View File

@ -1,5 +0,0 @@
{
"name":"Horse Race",
"icon": "*horsey",
"src":"-horsey"
}

View File

@ -1,5 +0,0 @@
{
"name":"Hypno Rings","type":"app",
"icon":"*hrings",
"src":"-hrings"
}

View File

@ -1,5 +0,0 @@
{
"name":"Heart Rate","type":"app",
"icon":"*hrm",
"src":"-hrm"
}

View File

@ -1,5 +0,0 @@
{
"name":"Jingle Bells","type":"app",
"icon":"*jbells",
"src":"-jbells"
}

View File

@ -1,5 +1,5 @@
var s = require("Storage");
var apps = s.list().filter(a=>a[0]=='+').map(app=>{
var apps = s.list(/\.info$/).map(app=>{
try { return s.readJSON(app); }
catch (e) { return {name:"DEAD: "+app.substr(1)} }
}).filter(app=>app.type=="app" || app.type=="clock" || !app.type);

View File

@ -1,4 +0,0 @@
{
"name":"Launcher","type":"launch",
"src":"-launch"
}

View File

@ -1,6 +0,0 @@
{
"name":"Morphing Clock","type":"clock",
"icon":"*mclock",
"src":"-mclock",
"sortorder":-10
}

View File

@ -1,6 +0,0 @@
{
"name":"Mixed Clock","type":"clock",
"icon":"*miclock",
"src":"-miclock",
"sortorder":-10
}

View File

@ -1,5 +0,0 @@
{
"name":"Manic Monday tone",
"icon": "*mmonday",
"src":"-mmonday"
}

View File

@ -1,5 +0,0 @@
{
"name":"Morse Code","type":"app",
"icon":"*morse",
"src":"-morse"
}

View File

@ -1,5 +0,0 @@
{
"name":"nceuwid",
"type":"widget",
"src":"=nceuwid"
}

View File

@ -1,6 +0,0 @@
{
"name":"5K Fun Run","type":"app",
"icon":"*ncfrun",
"src":"-ncfrun",
"sortorder":-1
}

View File

@ -1,6 +0,0 @@
{
"name": "NCEU Start",
"type": "app",
"icon": "*ncstart",
"src": ".boot3"
}

0
apps/nyancat/code.js Normal file
View File

View File

@ -1,5 +0,0 @@
{
"name":"Open Location","type":"app",
"icon":"*openloc",
"src":"-openloc"
}

View File

@ -1,5 +0,0 @@
{
"name":"Pipboy",
"icon":"*pipboy",
"src":"-pipboy"
}

View File

@ -1,5 +0,0 @@
{
"name":"Pomodoro","type":"app",
"icon":"*pomodo",
"src":"-pomodo"
}

View File

@ -1,5 +0,0 @@
{
"name":"Party Parrot","type":"app",
"icon":"*pparrot",
"src":"-pparrot"
}

View File

@ -41,19 +41,11 @@ g.setColor(0,0,0);
g.drawString(url,120,230);
g.setColor(1,1,1);
`;
var json = JSON.stringify({
name:"QR Code",
icon:"*qrcode",
src:"-qrcode"
});
var icon = `require("heatshrink").decompress(atob("mEwgP/AEX8gE8nkAn4FSngCWF6xfYDgIABHAQFPDQXD4YgDApxNDMooFOAQIdDAqIvWfcYA="))`;
sendCustomizedApp({
id : "qrcode",
storage:[
{name:"-qrcode", content:app},
{name:"+qrcode", content:json},
{name:"*qrcode", content:icon, evaluate:true},
{name:"qrcode.app.js", content:app},
{name:"qrcode.img", content:icon, evaluate:true},
]
});

View File

@ -240,20 +240,12 @@ Bangle.setGPSPower(1);
Bangle.setCompassPower(1);
g.clear();
`;
var json = JSON.stringify({
name:"Run Route",
icon:"*route",
src:"-route"
});
var icon = `require("heatshrink").decompress(atob("mEwgIkhvgFE/wEDgOHAocDgYFEgOAAp4XEEYsB4w1E5hBKnByFKw8/AQNAAQP/4EAAIMB4HggBABHoNwCwUGE4kOgEYBAMAhk+hgIBAoM/hkEAoMIv8MC4QFChARCAoIMCDoQXChkcjA1EAoJBBg5dCJoJHDKYWAsCGD4AJBAAXBDYIlCsYFBGwUzPok+AokcsOOmIUCAogAWA=="))`;
sendCustomizedApp({
id : "route",
storage:[
{name:"-route", content:app},
{name:"+route", content:json},
{name:"*route", content:icon, evaluate:true},
{name:"route.app.js", content:app},
{name:"route.img", content:icon, evaluate:true},
]
});
});

View File

@ -1,4 +0,0 @@
{
"name":"Battery Level","type":"widget",
"src":"=sbat"
}

View File

@ -1,4 +0,0 @@
{
"name":"bluetooth","type":"widget",
"src":"=sbt"
}

View File

@ -11,7 +11,7 @@ const yposYear = 175;
const yposGMT = 220;
// Check settings for what type our clock should be
var is12Hour = (require("Storage").readJSON("@setting")||{})["12hour"];
var is12Hour = (require("Storage").readJSON("setting.json")||{})["12hour"];
function drawSimpleClock() {
// get date

View File

@ -1,7 +0,0 @@
{
"name":"Simple Clock",
"type":"clock",
"icon":"*sclock",
"src":"-sclock",
"sortorder":-10
}

View File

@ -1,5 +0,0 @@
{
"name":"Show Color","type":"app",
"icon":"*scolor",
"src":"-scolor"
}

View File

@ -5,8 +5,8 @@ const storage = require('Storage');
let settings;
function updateSettings() {
//storage.erase('@setting'); // - not needed, just causes extra writes if settings were the same
storage.write('@setting', settings);
//storage.erase('setting.json'); // - not needed, just causes extra writes if settings were the same
storage.write('setting.json', settings);
}
function resetSettings() {
@ -28,7 +28,7 @@ function resetSettings() {
}
try {
settings = storage.readJSON('@setting');
settings = storage.readJSON('setting.json');
} catch (e) {}
if (!settings) resetSettings();
@ -187,7 +187,7 @@ function makeConnectable() {
});
}
function showClockMenu() {
var clockApps = require("Storage").list().filter(a=>a[0]=='+').map(app=>{
var clockApps = require("Storage").list(/\.info$/).map(app=>{
try { return require("Storage").readJSON(app); }
catch (e) {}
}).filter(app=>app.type=="clock").sort((a, b) => a.sortorder - b.sortorder);

View File

@ -1,6 +0,0 @@
{
"name": "Settings","type":"app",
"icon": "*setting",
"src": "-setting",
"sortorder": -15
}

View File

@ -1,5 +0,0 @@
{
"name":"Spirit Level","type":"app",
"icon":"*slevel",
"src":"-slevel"
}

View File

@ -1,5 +0,0 @@
{
"name":"Speedo","type":"app",
"icon":"*speedo",
"src":"-speedo"
}

View File

@ -1,5 +0,0 @@
{
"name":"Stethoscope","type":"app",
"icon":"*stetho",
"src":"-stetho"
}

View File

@ -1,5 +0,0 @@
{
"name":"Stopwatch","type":"app",
"icon":"*swatch",
"src":"-swatch"
}

View File

@ -1,5 +0,0 @@
{
"name":"T-Rex","type":"app",
"icon":"*trex",
"src":"-trex"
}

View File

@ -1,6 +0,0 @@
{
"name":"Word Clock","type":"clock",
"icon":"*wclock",
"src":"-wclock",
"sortorder":-10
}

View File

@ -1,5 +0,0 @@
{
"name":"Digital Clock Widget", "type":"widget",
"src":"=wdclk"
}

View File

@ -284,9 +284,9 @@ setWatch(()=>{
// If we're on the last page
if (sceneNumber == scenes.length-1) {
try {
var settings = require("Storage").readJSON('@setting');
var settings = require("Storage").readJSON('setting.json');
settings.welcomed = true;
require("Storage").write('@setting',settings);
require("Storage").write('setting.json',settings);
} catch (e) {}
load();
}

View File

@ -1,5 +0,0 @@
{
"name":"Welcome",
"icon":"*welcome",
"src":"-welcome"
}

View File

@ -1,4 +0,0 @@
{
"name":"Heart Rate Widget", "type":"widget",
"src":"=whrm"
}

View File

Before

Width:  |  Height:  |  Size: 297 B

After

Width:  |  Height:  |  Size: 297 B

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 422 B

After

Width:  |  Height:  |  Size: 422 B

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -1,5 +0,0 @@
{
"name":"Pedometer Widget", "type":"widget",
"src":"=wpedom"
}

View File

@ -1,5 +1,5 @@
(() => {
const PEDOMFILE = "@wpedom";
const PEDOMFILE = "wpedom.json";
// add the width
// WIDGETPOS.tr is originally 208 without any widgets
var xpos = WIDGETPOS.tl;

Some files were not shown because too many files have changed in this diff Show More