diff --git a/apps/boxclk/README.md b/apps/boxclk/README.md index 613c74fe0..7a0f3bb81 100644 --- a/apps/boxclk/README.md +++ b/apps/boxclk/README.md @@ -10,13 +10,15 @@ This intuitive feature allows you to reposition any element (box) on the clock f __JSON Configuration:__ -Each box can be customized extensively via a simple JSON configuration. You can also add a custom text string to your configuration with the "string": "Your custom text here", attribute. Here's what an example configuration might look like: +Each box can be customized extensively via a simple JSON configuration. You can also add a custom text string to your configuration with the "string" attribute. Here's what an example configuration might look like: + +## Config File Structure ``` { - "customBox": { - "string": "Your custom text here", - "font": "CustomFont", + "customBox": { // + "string": "Your text here", + "font": "CustomFont", // Custom fonts must be in main program and removed in setUI "fontSize": 1, "outline": 2, "color": "#FF9900", @@ -28,11 +30,12 @@ Each box can be customized extensively via a simple JSON configuration. You can "yOffset": 3, "boxPos": { "x": 0.5, "y": 0.5 } }, - "bg": { + "bg": { // Can also be removed for no backround "img": "YourImageName.img" } } ``` + * **string:** The text string to be displayed inside the box. * **font:** The font name given to g.setFont() @@ -55,6 +58,12 @@ Each box can be customized extensively via a simple JSON configuration. You can * **bg:** This specifies a custom background image, with the img property defining the name of the image file on the Bangle.js storage. +## Multiple Configurations + +The app includes a settings menu that allows you to switch between different configurations. The selected configuration is stored in the default JSON file alongside the other configuration data using the selectedConfig property. + +If the selectedConfig property is not present or is set to 0, the app will use the default configuration. To create additional configurations, create separate JSON files with the naming convention boxclk-N.json, where N is the configuration number. The settings menu will list all available configurations. + ## Compatibility This app was built and tested with Bangle.js 2. diff --git a/apps/boxclk/metadata.json b/apps/boxclk/metadata.json index 8ec9f1bba..351686fe7 100644 --- a/apps/boxclk/metadata.json +++ b/apps/boxclk/metadata.json @@ -15,6 +15,7 @@ "allow_emulator": true, "storage": [ {"name":"boxclk.app.js","url":"app.js"}, + {"name": "boxclk.settings.js","url":"settings.js"}, {"name":"boxclk.img","url":"icon.js","evaluate":true}, {"name":"boxclk.beachhouse.img","url":"beachhouse.js","evaluate":true} ], diff --git a/apps/boxclk/settings.js b/apps/boxclk/settings.js new file mode 100644 index 000000000..7d6262a65 --- /dev/null +++ b/apps/boxclk/settings.js @@ -0,0 +1,75 @@ +let storage = require("Storage"); +let fileRegex = /^boxclk-(\d+)\.json$/; +let selectedConfig; + +function getNextConfigNumber() { + let maxNumber = 0; + storage.list().forEach(file => { + let match = file.match(fileRegex); + if (match) { + let number = parseInt(match[1]); + if (number > maxNumber) { + maxNumber = number; + } + } + }); + return maxNumber + 1; +} + +(function () { + let configs = {}; + let hasDefaultConfig = false; + + function handleSelection(config) { + return function () { + selectedConfig = config === "Default" ? 0 : config; + menu["Cfg:"].value = selectedConfig === 0 ? "Default" : selectedConfig; + E.showMenu(menu); + + // Retrieve existing data and update selectedConfig + let defaultConfig = storage.readJSON("boxclk.json", 1) || {}; + defaultConfig.selectedConfig = selectedConfig; + storage.writeJSON("boxclk.json", defaultConfig); + }; + } + + storage.list().forEach(file => { + let match = file.match(fileRegex); + if (match) { + let configNumber = match[1]; + configs[configNumber] = handleSelection(configNumber); + } else if (file === "boxclk.json") { + hasDefaultConfig = true; + let defaultConfig = storage.readJSON(file, 1); + if (defaultConfig && defaultConfig.selectedConfig) { + selectedConfig = defaultConfig.selectedConfig === 0 ? 0 : defaultConfig.selectedConfig; + } + } + }); + + if (!selectedConfig) { + if (hasDefaultConfig) { + selectedConfig = "Default"; + } else { + let nextConfigNumber = getNextConfigNumber(); + selectedConfig = nextConfigNumber.toString(); + configs[selectedConfig] = handleSelection(selectedConfig); + } + } + + let menu = { + '': { 'title': '-- Box Clock --' }, + '< Back': () => Bangle.showLauncher(), + 'Cfg:': { value: selectedConfig === 0 ? "Default" : selectedConfig, format: () => selectedConfig === 0 ? "Default" : selectedConfig }, + }; + + if (hasDefaultConfig) { + menu['Default'] = handleSelection('Default'); + } + + Object.keys(configs).forEach(config => { + menu[config] = handleSelection(config); + }); + + E.showMenu(menu); +})();