-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Add a new app, the F3 Widget Tuner. #4198
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| *~ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| 1.00: Initial release. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,188 @@ | ||
| # F3 Widget Tuner | ||
|
|
||
| <b>F3 Widget Tuner</b> is an app for [Espruino Bangle.js 2](https://banglejs.com/) | ||
| wristwatches that allows one to tune the layout and visiblity of widgets, | ||
| with the tuning dependent on the current app showing on the watch. | ||
|
|
||
| <b>F3 Widget Tuner</b> also introduces some new features to widget layouts: | ||
| * stable sort of widget order (e.g., order no longer depends on how widgets | ||
| were installed onto the watch); | ||
| * centering, padding, and hiding. | ||
|
|
||
| <b>F3 Widget Tuner</b> is brought to you by the | ||
| [FatFingerFederation](https://codeberg.org/FatFingerFederation/). | ||
|
|
||
| ## Usage | ||
| <b>F3 Widget Tuner</b> takes over widget layout as soon as it is installed. | ||
| There is nothing to run; it operates as a bootscript that redefines | ||
| `Bangle.loadWidgets()` and `Bangle.drawWidgets()`. To return to life | ||
| without <b>F3 Widget Tuner</b>, simply remove/uninstall it. | ||
|
|
||
| To configure its operation, look for <b>F3 Widget Tuner</b> in the Settings app: | ||
| ``` | ||
| Settings -> Apps -> F3 Widget Tuner | ||
| ``` | ||
|
|
||
| Configuration involves two steps: | ||
| 1. Create a _context_ to specify _when_ you want a set of tunings to take effect. | ||
| 2. Add _tunings_ to the context, to specify _how_ to tweak specific widgets. | ||
|
|
||
| ### Context | ||
| A context is a collection of tunings. | ||
|
|
||
| Contexts are keyed by app; you create a context by specifying which app it | ||
| applies to. There are three additional wildcard contexts you can create: | ||
| * `[any clock]` - applies only to clock apps | ||
| * `[any non-clock]` - applies to any app except for clocks | ||
| * `[any app]` - applies to any app at all | ||
|
|
||
| Only a single context will ever be in effect at any given time, and it will | ||
| always be the most specific context. For example, suppose you have defined | ||
| contexts for _[any clock]_, _[any app]_, and _Anton Clock_. Then, when | ||
| Anton Clock is running, only the _Anton Clock_ context will be in effect, | ||
| and only its tunings will be applied to your widgets. | ||
|
|
||
| There is no cascading of contexts; only the tunings defined in the most | ||
| specific applicable context will be applied to widgets. | ||
|
|
||
| ### Tuning | ||
| A tuning is a set of parameter overrides keyed to a specific widget. | ||
|
|
||
| The tunable parameters are: | ||
| * `hide`: hide the widget; | ||
| * `location`: change which area of the screen the widget is rendered into; | ||
| * `priority`: change the sorting order; | ||
| * `pad left` and `pad right`: add positive/negative horizontal padding. | ||
|
|
||
| Every tuning must override at least one parameter; "empty" tunings are | ||
| simply removed from the context. | ||
|
|
||
| Hidden widgets are still drawn, so as not to interfere with any functionality | ||
| of the widget tied to its `draw()` call. However, they are rendered offscreen | ||
| so they are invisible and do not affect the layout. | ||
|
|
||
| The `location` option allows overriding the widget's choice of rendering area, | ||
| and introduces "center" as a new option. There are six widget areas to choose | ||
| from: {top, bottom} X {left, center, right}. | ||
|
|
||
|
|
||
| ## Settings Menus | ||
|
|
||
| Note that some menu options only appear when they are applicable. For example, | ||
| `<Delete context>` will only appear if there is a context to delete; | ||
| `<Save changes>` will only appear if there are changes to save. | ||
|
|
||
| ### Top-level: `Contexts:` | ||
|  | ||
| ... ... ... | ||
|  | ||
|
|
||
| * _list of existing contexts_: click one to go to Edit Context menu | ||
| * `<Add context>`: click to go to Add Context menu | ||
| * `<Delete context>`: click to to go Delete Context menu | ||
|
|
||
| ### Add Context: `Add context for:` | ||
| * _list of apps that do not yet have a context_ | ||
|
|
||
| ### Delete Context: `Delete context:` | ||
| * _list of existing contexts_ | ||
|
|
||
| ### Edit Context: `Ctxt: CONTEXT-NAME` | ||
|  | ||
| ... ... ... | ||
|  | ||
|
|
||
| If _Live preview_ is enabled, the widgets will be outlined with blue | ||
| bounding boxes. Zero-width widgets will be displayed as a vertical stripe. | ||
| Any padding applied to widgets will be outside the bounding boxes. | ||
|
|
||
| * `<Save changes>`: appears when there are unsaved changes to the context | ||
| * _list of widgets that have tunings_ | ||
| * `<Add tuning>` | ||
| * `<Delete tuning>` | ||
| * `<Live preview?>`: checkbox to turn layout preview on/off | ||
|
|
||
| ### Add Tuning: `Add tuning for:` | ||
| * _list of widgets that do not yet have a tuning_ | ||
|
|
||
| ### Delete Tuning: `Delete tuning:` | ||
| * _list of existing tunings_ | ||
|
|
||
| ### Edit Tuning: `Tune: WIDGET-NAME` | ||
|  | ||
| ... ... ... | ||
|  | ||
|
|
||
| If _Live preview_ is enabled, the widget which is being tuned will be | ||
| highlighted in magenta (instead of blue). | ||
|
|
||
| * `hide`: remove the widget from the layout (in which case, the | ||
| rest of the parameters will have no effect) | ||
| * `location`: zone in which widget will be place | ||
| * `priority`: override the priority for sorting; higher values come | ||
| first in the layout | ||
| * `<Reset priority>`: reset priority to the widget's default; only | ||
| appears if the priority is *not* set to the default | ||
| * `pad left`: add/remove pixels on left side of widget | ||
| * `pad right`: add/remove pixels on right side of widget | ||
|
|
||
| ## Configuration Schema | ||
|
|
||
| For reference, the configuration for <b>F3 Widget Tuner</b> is stored | ||
| in `f3wdgttune.json`, and follows the following schema: | ||
| ``` | ||
| CONFIG = {"CONTEXT-KEY": CONTEXT, | ||
| ... | ||
| } | ||
|
|
||
| CONTEXT = {w: {"WIDGET-ID": TUNING, | ||
| ... | ||
| }} | ||
|
|
||
| TUNING = {hide: BOOL, true = hide widget | ||
| padl: INT, left-padding | ||
| padr: INT, right-padding | ||
| area: AREA-CODE, rendering group | ||
| order: INT sorting ordinal | ||
| } | ||
|
|
||
| AREA-CODE = one of "tl", "tc", "tr", "bl", "bc", "br" | ||
| == {top, bottom} x {left, center, right} | ||
|
|
||
| CONTEXT-KEY = the app-filename of an app (e.g., 'antonclk.app.js'), OR | ||
| one of "*", "*clk", "*!clk" | ||
|
|
||
| WIDGET-ID = a key in the WIDGETS object | ||
| ``` | ||
|
|
||
| * The order of elements generally does not matter to widget rendering. | ||
| * However, the Settings UI keeps contexts and tunings sorted by | ||
| app/widget name, to make it easier to show coherent, sorted lists | ||
| to user. | ||
| * In `TUNING`, all elements are optional. Absence of an element implies | ||
| default behavior, i.e., no customization. However, a `TUNING` must | ||
| contain at least one element; empty `TUNING`s are not allowed. | ||
| * A `CONTEXT` without any `TUNING`s _is_ allowed. An empty, more-specific | ||
| context can be used to ignore the customizations of a more-general | ||
| context. | ||
|
|
||
| Example: | ||
| ``` | ||
| {c: {"*": {w: {"widalarm": {padl: 6} | ||
| }}, | ||
| "*clk": {w: {"widid": {hide: true}, | ||
| "widbt": {area: "tl", | ||
| order: 10} | ||
| }}, | ||
| "about.app.js": {w: {}} | ||
| }} | ||
| ``` | ||
|
|
||
| ## Reporting Issues | ||
|
|
||
| Upstream development happens at | ||
| [FatFingerFederation/F3WidgetTuner](https://codeberg.org/FatFingerFederation/F3WidgetTuner); | ||
| please report any bugs/issues/etc there directly. | ||
|
|
||
| ## Creator | ||
| - [Matt Marjanovic](https://codeberg.org/maddog) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| #!/bin/sh | ||
|
|
||
| magick tuner-splash-frame1.png -crop 30x90+45+0 +repage splash-chunk1.png | ||
| magick tuner-splash-frame2.png -crop 30x90+45+0 +repage splash-chunk2.png | ||
|
|
||
| magick tuner-splash-frame1.png -crop 45x90+0+0 +repage splash-chunk-L.png | ||
| magick tuner-splash-frame1.png -crop 45x90+75+0 +repage splash-chunk-R.png | ||
| magick tuner-splash-frame1.png -crop 120x30+0+90 +repage splash-chunk-B.png |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| // This file is part of F3 Widget Tuner. | ||
| // Copyright 2026 Matt Marjanovic <maddog@mir.com> | ||
| // This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. | ||
|
Comment on lines
+1
to
+3
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need a license header in every file? Also, @gfwilliams are you ok with this license in the repo?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Discussion at https://github.com/orgs/espruino/discussions/7952 |
||
|
|
||
| (function() { | ||
| let stockLoadWidgets = Bangle.loadWidgets; | ||
|
|
||
| Bangle.loadWidgets = function () { | ||
| stockLoadWidgets(); | ||
| require("f3wdgttune.lib.js").applyContext(); | ||
| }; | ||
|
|
||
| Bangle.drawWidgets = function () { | ||
| if (! global.WIDGETS) { return; } | ||
| let WT = require("f3wdgttune.lib.js"); | ||
| WT.applyContext(); | ||
| WT.drawWidgetsByContext(); | ||
| }; | ||
| })() | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be in your user's gitignore - have a look for "gitignore global" :)