2019-11-06 17:25:02 +00:00
Bangle.js App Loader (and Apps)
================================
2022-06-15 07:23:14 +00:00
[](https://github.com/espruino/BangleApps/actions/workflows/nodejs.yml)
2020-02-28 14:48:22 +00:00
2020-03-26 08:37:18 +00:00
* Try the **release version** at [banglejs.com/apps ](https://banglejs.com/apps )
2021-10-29 21:37:33 +00:00
* Try the **development version** at [espruino.github.io ](https://espruino.github.io/BangleApps/ )
2019-11-07 20:37:46 +00:00
2020-05-12 07:08:19 +00:00
**All software (including apps) in this repository is MIT Licensed - see [LICENSE ](LICENSE )** By
2020-04-04 13:33:43 +00:00
submitting code to this repository you confirm that you are happy with it being MIT licensed,
and that it is not licensed in another way that would make this impossible.
2020-04-04 13:30:46 +00:00
2019-11-26 10:27:31 +00:00
## How does it work?
2019-11-06 17:25:02 +00:00
2022-01-19 16:21:07 +00:00
* A list of apps is in `apps.json` (this is auto-generated from all the `apps/yourapp/metadata.json` using Jekyll or `bin/create_apps_json.sh` )
2019-11-17 22:42:32 +00:00
* Each element references an app in `apps/<id>` which is uploaded
2019-11-06 17:25:02 +00:00
* When it starts, BangleAppLoader checks the JSON and compares
it with the files it sees in the watch's storage.
* To upload an app, BangleAppLoader checks the files that are
listed in `apps.json` , loads them, and sends them over Web Bluetooth.
2020-03-26 08:37:18 +00:00
## Getting Started
Check out:
* [Building your first Bangle.js Application ](https://www.espruino.com/Bangle.js+First+App )
* [Adding an app to the Bangle.js App Loader ](https://www.espruino.com/Bangle.js+App+Loader )
* [Customising the App Loader ](https://www.espruino.com/Bangle.js+App+Loader+Custom )
2019-11-26 10:27:31 +00:00
## What filenames are used
2019-11-06 17:25:02 +00:00
2020-04-08 12:27:19 +00:00
Filenames in storage are limited to 28 characters. To
2019-11-06 17:25:02 +00:00
easily distinguish between file types, we use the following:
2020-02-28 11:44:25 +00:00
* `stuff.info` is JSON that describes an app - this is auto-generated by the App Loader
* `stuff.img` is an image
2020-03-31 14:04:51 +00:00
* `stuff.app.js` is JS code for applications
2020-02-28 11:44:25 +00:00
* `stuff.wid.js` is JS code for widgets
2020-04-03 22:00:14 +00:00
* `stuff.settings.js` is JS code for the settings menu
2020-03-31 14:04:51 +00:00
* `stuff.boot.js` is JS code that automatically gets run at boot time
2020-02-28 11:44:25 +00:00
* `stuff.json` is used for JSON settings for an app
2019-11-06 17:25:02 +00:00
2019-11-26 10:27:31 +00:00
## Developing your own app
* Head over to [the Web IDE ](https://www.espruino.com/ide/ ) and ensure `Save on Send` in settings set to the *default setting* of `To RAM`
* We'd recommend that you start off using code from 'Example Applications' (below) to get started...
* Load [`app.js` ](apps/_example_app/app.js ) or [`widget.js` ](apps/_example_widget/widget.js ) into the IDE and start developing.
* The `Upload` button will load your app to Bangle.js temporarily
## Adding your app to the menu
2019-11-06 17:25:02 +00:00
2021-11-19 08:35:36 +00:00
* Come up with a unique (all lowercase, no spaces) name, we'll assume `myappid` . Bangle.js
2020-02-28 11:44:25 +00:00
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.
2021-11-19 08:35:36 +00:00
* Create a folder called `apps/<id>` , lets assume `apps/myappid`
2022-01-19 16:21:07 +00:00
* We'd recommend that you copy files from one of the Examples in `apps/_example_*` (see below), or...
2021-11-19 08:35:36 +00:00
* `apps/myappid/app.png` should be a 48px icon
* Use http://www.espruino.com/Image+Converter to create `apps/myappid/app-icon.js` , using a 1 bit, 4 bit or 8 bit Web Palette "Image String"
2022-01-19 16:21:07 +00:00
* Create/modify `apps/myappid/metadata.json` as follows:
2019-11-06 17:25:02 +00:00
```
2021-11-19 08:35:36 +00:00
{ "id": "myappid",
2019-11-06 17:25:02 +00:00
"name": "My app's human readable name",
2020-02-28 11:44:25 +00:00
"shortName" : "Short Name",
2019-11-26 10:27:31 +00:00
"icon": "app.png",
2019-11-06 17:25:02 +00:00
"description": "A detailed description of my great app",
"tags": "",
"storage": [
2021-11-19 08:35:36 +00:00
{"name":"myappid.app.js","url":"app.js"},
{"name":"myappid.img","url":"app-icon.js","evaluate":true}
2019-11-07 08:43:56 +00:00
],
2019-11-06 17:25:02 +00:00
},
```
2022-03-21 08:50:56 +00:00
### Screenshots
2022-04-25 10:45:17 +00:00
In the app `metadata.json` file you can add a list of screenshots with a line like: `"screenshots" : [ { "url":"screenshot.png" } ],`
2022-03-21 08:50:56 +00:00
To get a screenshot you can:
* Type `g.dump()` in the left-hand side of the Web IDE when connected to a Bangle.js 2 - you can then
right-click and save the image shown in the terminal (this only works on Bangle.js 2 - Bangle.js 1 is
unable to read data back from the LCD controller).
* Run your code in the emulator and use the screenshot button in the bottom right of the window.
2019-11-26 10:27:31 +00:00
## Testing
### Online
This is the best way to test...
* Fork the https://github.com/espruino/BangleApps git repository
* Add your files
* Go to GitHub Settings and activate GitHub Pages
* Run your personal `Bangle App Loader` at https://\<your-github-username\>.github.io/BangleApps/index.html to load apps onto your device
* Your apps should be inside it - if there are problems, check your web browser's 'developer console' for errors
2020-02-28 14:17:22 +00:00
**Note:** It's a great idea to get a local copy of the repository on your PC,
then run `bin/sanitycheck.js` - it'll run through a bunch of common issues
that there might be.
2019-11-26 10:27:31 +00:00
Be aware of the delay between commits and updates on github.io - it can take a few minutes (and a 'hard refresh' of your browser) for changes to take effect.
### Offline
2020-02-28 11:44:25 +00:00
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:
2019-11-26 10:27:31 +00:00
2021-11-19 08:35:36 +00:00
* `app-icon.js` -> `myappid.img`
2020-02-28 11:44:25 +00:00
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
2021-11-19 08:35:36 +00:00
`myappid.app.js` (if you'd uploaded your app previously), or `New File`
and then enter `myappid.app.js` as the name.
2020-02-28 11:44:25 +00:00
Now, clicking the `Send to Espruino` icon will load the app directly into
Espruino **and** will automatically run it.
2019-11-26 10:27:31 +00:00
2020-02-28 11:44:25 +00:00
When you upload code this way, your app will even be uploaded to Bangle.js's menu
2019-11-26 10:27:31 +00:00
without you having to use the `Bangle App Loader`
2020-02-28 11:44:25 +00:00
**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` .
2019-11-26 10:27:31 +00:00
## Example Applications
To make the process easier we've come up with some example applications that you can use as a base
2021-11-19 08:35:36 +00:00
when creating your own. Just come up with a unique name (ideally lowercase, under 20 chars), copy `apps/_example_app`
2022-01-19 16:21:07 +00:00
or `apps/_example_widget` to `apps/myappid` , and edit `apps/myappid/metadata.json` accordingly.
2019-11-26 10:27:31 +00:00
2021-11-19 08:35:36 +00:00
**Note:** the max filename length is 28 chars, so we suggest an app ID of under
20 so that when `.app.js` /etc gets added to the end the filename isn't cropped.
2020-02-28 11:44:25 +00:00
**If you're making a widget** please start the name with `wid` to make
it easy to find!
2019-11-26 10:27:31 +00:00
### 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.
2022-01-19 16:21:07 +00:00
* `metadata.json` - describes the app to bootloader and loader
2019-11-26 10:27:31 +00:00
* `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
2019-12-03 17:07:15 +00:00
* `app.js` - app code
2022-02-11 11:09:10 +00:00
* `ChangeLog` - A file containing a list of changes to your app so users can see what's changed
2019-11-26 10:27:31 +00:00
#### `app-icon.js`
2020-03-05 13:15:27 +00:00
The icon image and short description is used in Bangle.js's launcher.
2019-11-26 10:27:31 +00:00
Use the Espruino [image converter ](https://www.espruino.com/Image+Converter ) and upload your `app.png` file.
Follow this steps to create a readable icon as image string.
2022-01-19 16:21:07 +00:00
1. upload a 48x48 png file - THE IMAGE SHOULD BE 48x48 OR LESS
2019-11-26 10:27:31 +00:00
2. set _X_ Use Compression
3. set _X_ Transparency (optional)
4. set Diffusion: _flat_
2022-01-19 16:21:07 +00:00
5. set Colours: _1 bit_ , any of the Optimised options, or _8 bit Web Palette_ are best
2019-11-26 10:27:31 +00:00
6. set Output as: _Image String_
Replace this line with the image converter output:
2019-12-03 17:07:15 +00:00
2019-11-26 10:27:31 +00:00
```
2020-03-05 13:15:27 +00:00
require("heatshrink").decompress(atob("mEwwJC/AH4A/AH4AgA=="))
2019-11-26 10:27:31 +00:00
```
2022-01-19 16:21:07 +00:00
**Do not add a trailing semicolon**
2020-03-05 13:15:27 +00:00
You can also use this converter for creating images you like to draw with `g.drawImage()` with your app.
2019-11-26 10:27:31 +00:00
2020-03-05 13:15:27 +00:00
Apps that need widgets can call `Bangle.loadWidgets()` **once** at startup to load
them, and then `Bangle.drawWidgets()` to draw them onto the screen whenever the app
has call to completely clear the screen. Widgets themselves will update as and when needed.
2019-11-26 10:27:31 +00:00
### Widget Example
The widget example is available in [`apps/_example_widget` ](apps/_example_widget )
2022-01-19 16:21:07 +00:00
* `metadata.json` - describes the widget to bootloader and loader
2019-12-03 17:07:15 +00:00
* `widget.js` - widget code
2019-11-26 10:27:31 +00:00
2020-03-05 13:15:27 +00:00
Widgets are just small bits of code that run whenever an app that supports them
calls `Bangle.loadWidgets()` . If they want to display something in the 24px high
2022-05-03 08:21:13 +00:00
widget bar at the top of the screen they can add themselves to the global
2022-01-17 18:49:37 +00:00
`WIDGETS` array with:
2020-03-05 13:15:27 +00:00
```
WIDGETS["mywidget"]={
2022-06-16 08:28:25 +00:00
area:"tl", // tl (top left), tr (top right), bl (bottom left), br (bottom right)
2022-01-17 18:49:37 +00:00
sortorder:0, // (Optional) determines order of widgets in the same corner
2020-03-05 13:15:27 +00:00
width: 24, // how wide is the widget? You can change this and call Bangle.drawWidgets() to re-layout
draw:draw // called to draw the widget
};
```
When the widget is to be drawn, `x` and `y` values are set up in `WIDGETS["mywidget"]`
and `draw` can then use `this.x` and `this.y` to figure out where it needs to draw to.
2022-02-11 11:09:10 +00:00
### ChangeLog
This is a file containing a list of changes to your app so users can see what's changed, for example:
```
0.01: New App!
0.02: Changed the colors
0.03: Made the app run quicker
```
Entries should be newest last, with the version number of the last entry matching the version in `metadata.json`
Please keep the same format at the example as the file needs to be parsed by the BangleApps tools.
2020-02-28 11:44:25 +00:00
### `app.info` format
2019-12-05 14:48:56 +00:00
2022-02-11 11:09:10 +00:00
This is the file that's **auto-generated** from `metadata.json` and loaded onto Bangle.js by the App Loader,
2020-02-28 11:44:25 +00:00
and which gives information about the app for the Launcher.
2019-12-05 14:48:56 +00:00
```
{
"name":"Short Name", // for Bangle.js menu
2021-11-19 08:35:36 +00:00
"icon":"*myappid", // for Bangle.js menu
"src":"-myappid", // source file
2022-04-29 08:31:06 +00:00
"type":"widget/clock/app/bootloader/...", // optional, default "app"
// see 'type' in 'metadata.json format' below for more options/info
2019-12-05 14:48:56 +00:00
"version":"1.23",
2022-01-19 16:21:07 +00:00
// added by BangleApps loader on upload based on metadata.json
2019-12-05 14:48:56 +00:00
"files:"file1,file2,file3",
// added by BangleApps loader on upload - lists all files
// that belong to the app so it can be deleted
2020-04-15 19:30:44 +00:00
"data":"appid.data.json,appid.data?.json;appidStorageFile,appidStorageFile*"
2020-05-12 07:08:19 +00:00
// added by BangleApps loader on upload - lists files that
2020-04-11 22:26:08 +00:00
// the app might write, so they can be deleted on uninstall
// typically these files are not uploaded, but created by the app
// these can include '*' or '?' wildcards
2019-12-05 14:48:56 +00:00
}
```
2019-11-26 10:27:31 +00:00
2022-01-19 16:21:07 +00:00
### `metadata.json` format
2019-11-06 17:25:02 +00:00
```
{ "id": "appid", // 7 character app id
"name": "Readable name", // readable name
2020-02-28 11:44:25 +00:00
"shortName": "Short name", // short name for launcher
2021-10-20 14:11:04 +00:00
"version": "0v01", // the version of this app
2020-05-28 13:34:40 +00:00
"description": "...", // long description (can contain markdown)
2021-10-20 14:11:04 +00:00
"icon": "icon.png", // icon in apps/
2022-05-03 08:21:13 +00:00
"screenshots" : [ { "url":"screenshot.png" } ], // optional screenshot for app
2020-09-23 10:38:02 +00:00
"type":"...", // optional(if app) -
// 'app' - an application
2022-03-08 11:43:04 +00:00
// 'clock' - a clock - required for clocks to automatically start
2020-09-23 10:38:02 +00:00
// 'widget' - a widget
2022-11-21 16:37:04 +00:00
// 'module' - this provides a module that can be used with 'require'.
// 'provides_modules' should be used if type:module is specified
2022-04-29 08:29:02 +00:00
// 'bootloader' - an app that at startup (app.boot.js) but doesn't have a launcher entry for 'app.js'
2022-05-26 11:50:44 +00:00
// 'settings' - apps that appear in Settings->Apps (with appname.settings.js) but that have no 'app.js'
2022-11-21 16:37:04 +00:00
// 'clkinfo' - Provides a 'myapp.clkinfo.js' file that can be used to display info in clocks - see modules/clock_info.js
2020-09-23 10:38:02 +00:00
// 'RAM' - code that runs and doesn't upload anything to storage
2022-04-29 08:29:02 +00:00
// 'launch' - replacement 'Launcher'
// 'textinput' - provides a 'textinput' library that allows text to be input on the Bangle
2022-05-03 08:21:13 +00:00
// 'scheduler' - provides 'sched' library and boot code for scheduling alarms/timers
2022-04-29 08:29:02 +00:00
// (currently only 'sched' app)
// 'notify' - provides 'notify' library for showing notifications
2022-05-03 08:21:13 +00:00
// 'locale' - provides 'locale' library for language-specific date/distance/etc
2022-04-29 08:29:02 +00:00
// (a version of 'locale' is included in the firmware)
2019-11-06 17:25:02 +00:00
"tags": "", // comma separated tag list for searching
2022-11-21 16:37:04 +00:00
// common types are:
// 'clock' - it's a clock
// 'widget' - it is (or provides) a widget
// 'outdoors' - useful for outdoor activities
// 'tool' - a useful utility (timer, calculator, etc)
// 'game' - a game
// 'bluetooth' - uses Bluetooth LE
// 'system' - used by the system
// 'clkinfo' - provides or uses clock_info module for data on your clock face (see modules/clock_info.js)
2021-10-20 14:11:04 +00:00
"supports": ["BANGLEJS2"], // List of device IDs supported, either BANGLEJS or BANGLEJS2
2022-04-29 08:29:02 +00:00
"dependencies" : { "notify":"type" } // optional, app 'types' we depend on (see "type" above)
2021-11-04 17:16:02 +00:00
"dependencies" : { "messages":"app" } // optional, depend on a specific app ID
2020-08-21 14:17:16 +00:00
// for instance this will use notify/notifyfs is they exist, or will pull in 'notify'
2022-12-06 10:25:32 +00:00
"dependencies" : { "messageicons":"module" } // optional, depend on a specific library to be used with 'require' - see provides_modules
"dependencies" : { "message":"widget" } // optional, depend on a specific type of widget - see provides_widgets
2022-11-16 15:17:28 +00:00
"provides_modules" : ["messageicons"] // optional, this app provides a module that can be used with 'require'
2022-12-06 10:25:32 +00:00
"provides_widgets" : ["battery"] // optional, this app provides a type of widget - 'alarm/battery/bluetooth/pedometer/message'
"default" : true, // set if an app is the default implementer of something (a widget/module/etc)
2020-04-07 07:59:24 +00:00
"readme": "README.md", // if supplied, a link to a markdown-style text file
// that contains more information about this app (usage, etc)
// A 'Read more...' link will be added under the app
2019-11-06 17:25:02 +00:00
"custom": "custom.html", // if supplied, apps/custom.html is loaded in an
// iframe, and it must post back an 'app' structure
// like this one with 'storage','name' and 'id' set up
2020-02-10 13:49:36 +00:00
// see below for more info
2019-11-06 17:25:02 +00:00
2021-09-02 10:51:17 +00:00
"customConnect": true, // if supplied, ensure we are connected to a device
// before the "custom.html" iframe is loaded. An
// onInit function in "custom.html" is then called
// with info on the currently connected device.
2020-02-07 17:16:45 +00:00
"interface": "interface.html", // if supplied, apps/interface.html is loaded in an
// iframe, and it may interact with the connected Bangle
// to retrieve information from it
2020-02-10 13:49:36 +00:00
// see below for more info
2020-02-07 17:16:45 +00:00
2019-12-03 17:07:15 +00:00
"allow_emulator":true, // if 'app.js' will run in the emulator, set to true to
// add an icon to allow your app to be tested
2019-11-06 17:25:02 +00:00
"storage": [ // list of files to add to storage
2020-09-23 10:18:20 +00:00
{"name":"appid.js", // filename to use in storage.
// If name=='RAM', the code is sent directly to Bangle.js and is not saved to a file
2019-11-06 17:25:02 +00:00
"url":"", // URL of file to load (currently relative to apps/)
2021-04-09 08:58:38 +00:00
"content":"...", // if supplied, this content is loaded directly
"evaluate":true, // if supplied, data isn't quoted into a String before upload
2019-11-06 17:25:02 +00:00
// (eg it's evaluated as JS)
2021-04-09 08:58:38 +00:00
"noOverwrite":true // if supplied, this file will not be overwritten if it
// already exists
2021-10-28 11:14:02 +00:00
"supports": ["BANGLEJS2"]// if supplied, this file will ONLY be uploaded to the device
// types named in the array. This allows different versions of
// the app to be uploaded for different platforms
2019-11-06 17:25:02 +00:00
},
2020-04-11 22:26:08 +00:00
]
"data": [ // list of files the app writes to
{"name":"appid.data.json", // filename used in storage
"storageFile":true // if supplied, file is treated as storageFile
2021-04-09 08:58:38 +00:00
"url":"", // if supplied 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
// (eg it's evaluated as JS)
2020-04-11 22:26:08 +00:00
},
{"wildcard":"appid.data.*" // wildcard of filenames used in storage
2020-05-12 07:08:19 +00:00
}, // this is mutually exclusive with using "name"
2020-04-11 22:26:08 +00:00
],
2019-11-07 08:43:56 +00:00
"sortorder" : 0, // optional - choose where in the list this goes.
// this should only really be used to put system
// stuff at the top
2019-11-06 17:25:02 +00:00
}
```
2019-11-26 10:27:31 +00:00
* name, icon and description present the app in the app loader.
2022-07-19 11:19:40 +00:00
* tags is used for grouping apps in the library, separate multiple entries by comma. Known tags are `tool` , `system` , `clock` , `game` , `sound` , `gps` , `widget` , `launcher` , `bluetooth` or empty.
2019-11-26 10:27:31 +00:00
* storage is used to identify the app files and how to handle them
2020-04-11 22:26:08 +00:00
* data is used to clean up files when the app is uninstalled
2019-11-26 10:27:31 +00:00
2022-01-19 16:21:07 +00:00
### `metadata.json`: `custom` element
2020-02-10 13:49:36 +00:00
2022-01-19 16:21:07 +00:00
Apps that can be customised need to define a `custom` element in `metadata.json` ,
2020-02-10 13:49:36 +00:00
which names an HTML file in that app's folder.
When `custom` is defined, the 'upload' button is replaced by a customize
button, and when clicked it opens the HTML page specified in an iframe.
In that HTML file you're then responsible for handling a button
press and calling `sendCustomizedApp` with your own customised
2022-01-19 16:21:07 +00:00
version of what's in `metadata.json` :
2020-02-10 13:49:36 +00:00
```
< html >
< head >
< link rel = "stylesheet" href = "../../css/spectre.min.css" >
< / head >
< body >
< p > < button id = "upload" class = "btn btn-primary" > Upload< / button > < / p >
< script src = "../../lib/customize.js" > < / script >
< script >
document.getElementById("upload").addEventListener("click", function() {
sendCustomizedApp({
2021-11-19 08:35:36 +00:00
id : "myappid",
2020-02-10 13:49:36 +00:00
storage:[
2021-11-19 08:35:36 +00:00
{name:"myappid.app.js", url:"app.js", content:app_source_code},
{name:"myappid.img", content:'require("heatshrink").decompress(atob("mEwg...4"))', evaluate:true},
2020-02-10 13:49:36 +00:00
]
});
});
< / script >
< / body >
< / html >
```
This'll then be loaded in to the watch. See [apps/qrcode/grcode.html ](the QR Code app )
for a clean example.
2020-09-01 13:43:54 +00:00
**Note:** we specify a `url` for JS files even though it doesn't have to exist
and will never be loaded. This is so the app loader can tell if it's a JavaScript
file based on the extension, and if so it can minify and pretokenise it.
2022-01-19 16:21:07 +00:00
### `metadata.json`: `interface` element
2020-02-10 13:49:36 +00:00
2022-01-19 16:21:07 +00:00
Apps that create data that can be read back can define a `interface` element in `metadata.json` ,
2020-02-10 13:49:36 +00:00
which names an HTML file in that app's folder.
When `interface` is defined, a `Download from App` button is added to
the app's description, and when clicked it opens the HTML page specified
in an iframe.
```
< html >
< head >
< link rel = "stylesheet" href = "../../css/spectre.min.css" >
< / head >
< body >
< script src = "../../lib/interface.js" > < / script >
< div id = "t" > Loading...< / div >
< script >
function onInit() {
Puck.eval("E.getTemperature()", temp=> {
document.getElementById("t").innerHTML = temp;
});
}
< / script >
< / body >
< / html >
```
When the page is ready a function called `onInit` is called,
and in that you can call `Puck.write` and `Puck.eval` to get
the data you require from Bangle.js.
See [apps/gpsrec/interface.html ](the GPS Recorder ) for a full example.
2020-04-03 22:00:14 +00:00
### Adding configuration to the "Settings" menu
Apps (or widgets) can add their own settings to the "Settings" menu under "App/widget settings".
To do so, the app needs to include a `settings.js` file, containing a single function
that handles configuring the app.
2020-05-12 07:08:19 +00:00
When the app settings are opened, this function is called with one
2020-04-03 22:00:14 +00:00
argument, `back` : a callback to return to the settings menu.
2021-11-20 16:52:44 +00:00
Usually it will save any information in `myappid.json` where `myappid` is the name
2020-05-12 07:08:19 +00:00
of your app - so you should change the example accordingly.
2020-04-03 22:00:14 +00:00
Example `settings.js`
```js
// make sure to enclose the function in parentheses
(function(back) {
2021-12-01 18:34:52 +00:00
let settings = require('Storage').readJSON('myappid.json',1)||{};
2022-05-03 08:21:13 +00:00
if (typeof settings.monkeys !== "number") settings.monkeys = 12; // default value
2021-12-01 18:34:52 +00:00
function save(key, value) {
settings[key] = value;
require('Storage').write('myappid.json', settings);
}
2020-04-03 22:00:14 +00:00
const appMenu = {
'': {'title': 'App Settings'},
'< Back ' : back ,
'Monkeys': {
2021-12-01 18:34:52 +00:00
value: settings.monkeys,
onchange: (m) => {save('monkeys', m)}
2020-04-03 22:00:14 +00:00
}
};
E.showMenu(appMenu)
})
```
2022-01-19 16:21:07 +00:00
In this example the app needs to add `myappid.settings.js` to `storage` in `metadata.json` .
2021-11-20 16:52:44 +00:00
It should also add `myappid.json` to `data` , to make sure it is cleaned up when the app is uninstalled.
2020-04-03 22:00:14 +00:00
```json
2021-11-20 16:52:44 +00:00
{ "id": "myappid",
2020-04-03 22:00:14 +00:00
...
"storage": [
...
2021-11-20 16:52:44 +00:00
{"name":"myappid.settings.js","url":"settings.js"}
2020-04-16 15:06:25 +00:00
],
"data": [
2021-11-20 16:52:44 +00:00
{"name":"myappid.json"}
2020-04-03 22:00:14 +00:00
]
},
```
2020-12-09 13:43:29 +00:00
## Modules
You can include any of [Espruino's modules ](https://www.espruino.com/Modules ) as
2022-11-20 05:03:55 +00:00
normal with `require("modulename")` . To include [Bangle's modules ](modules ) for use in the Web
IDE, [upload the modules to internal storage ](modules#upload-the-module-to-the-bangles-internal-storage )
or [change the IDE's search path ](modules#change-the-web-ide-search-path-to-include-banglejs-modules ).
If you want to develop your own module for your
2020-12-09 13:43:29 +00:00
app(s) then you can do that too. Just add the module into the `modules` folder
then you can use it from your app as normal.
You won't be able to develop apps using your own modules with the IDE,
so instead we'd recommend you write your module to a Storage File called
`modulename` on Bangle.js. You can then develop your app as normal on Bangle.js
from the IDE.
2019-11-26 10:27:31 +00:00
## Coding hints
- use `g.setFont(.., size)` to multiply the font size, eg ("6x8",3) : "18x24"
- use `g.drawString(text,x,y,true)` to draw with background color to overwrite existing text
- use `g.clearRect()` to clear parts of the screen, instead of using `g.clear()`
- use `g.fillPoly()` or `g.drawImage()` for complex graphic elements
- using `g.clear()` can cause screen flicker
- using `g.setLCDBrightness()` can save you power during long periods with lcd on
2020-02-07 13:47:59 +00:00
- chaining graphics methods, eg `g.setColor(0xFD20).setFontAlign(0,0).setfont("6x8",3)`
2019-11-26 10:27:31 +00:00
2020-02-28 14:17:22 +00:00
### Misc Notes
2021-11-19 08:35:36 +00:00
- Need to save state? Use the `E.on('kill',...)` event to save JSON to a file called `myappid.json` , then load it at startup.
2020-02-28 14:17:22 +00:00
2020-02-28 17:02:26 +00:00
- 'Alarm' apps define a file called `alarm.js` which handles the actual alarm window.
- Locale is handled by `require("locale")` . An app may create a `locale` file in Storage which is
a module that overwrites Bangle.js's default locale.
2020-02-28 14:17:22 +00:00
2019-12-03 17:07:15 +00:00
### Graphic areas
2019-11-26 10:27:31 +00:00
The screen is parted in a widget and app area for lcd mode `direct` (default).
| areas | as rectangle or point |
2019-12-03 17:07:15 +00:00
| :-:| :-: |
| Widget | (0,0,239,23) |
2022-01-17 18:49:37 +00:00
| Apps | (0,24,239,239) |
2019-11-26 10:27:31 +00:00
| BTN1 | (230, 55) |
| BTN2 | (230, 140) |
| BTN3 | (230, 210) |
2019-12-03 17:07:15 +00:00
| BTN4 | (0,0,119, 239)|
| BTN5 | (120,0,239,239) |
2019-11-26 10:27:31 +00:00
2019-12-03 17:07:15 +00:00
- Use `g.setFontAlign(0, 0, 3)` to draw rotated string to BTN1-BTN3 with `g.drawString()` .
2019-11-26 10:27:31 +00:00
- For BTN4-5 the touch area is named
2019-12-03 17:07:15 +00:00
## Available colors
2019-11-26 10:27:31 +00:00
2019-11-26 16:51:23 +00:00
You can use `g.setColor(r,g,b)` OR `g.setColor(16bitnumber)` - some common 16 bit colors are below:
2019-11-26 10:27:31 +00:00
| color-name | color-value|
| :-: | :-: |
2019-12-03 17:07:15 +00:00
| Black | 0x0000 |
2019-11-26 10:27:31 +00:00
| Navy | 0x000F |
| DarkGreen | 0x03E0 |
| DarkCyan | 0x03EF |
| Maroon | 0x7800 |
| Purple | 0x780F |
| Olive | 0x7BE0
| LightGray | 0xC618
| DarkGrey | 0x7BEF
| Blue | 0x001F
| Green | 0x07E0 |
| Cyan | 0x07FF |
| RED | 0xF800 |
| Magenta | 0xF81F |
| Yellow | 0xFFE0 |
| White | 0xFFFF |
| Orange | 0xFD20 |
| GreenYellow | 0xAFE5 |
| Pink | 0xF81F |
## API Reference
[Reference ](http://www.espruino.com/Reference#software )
[Bangle Class ](https://banglejs.com/reference#Bangle )
[Graphics Class ](https://banglejs.com/reference#Graphics )
## 'Testing' folder
The [`testing` ](testing ) folder contains snippets of code that might be useful for your apps.
* `testing/colors.js` - 16 bit colors as name value pairs
2020-02-07 13:47:59 +00:00
* `testing/gpstrack.js` - code to store a GPS track in Bangle.js storage and output it back to the console
2019-11-26 10:27:31 +00:00
## Credits
2019-11-06 17:25:02 +00:00
The majority of icons used for these apps are from [Icons8 ](https://icons8.com/ ) - we have a commercial license but icons are also free for Open Source projects.