-
I guess you could try the relay:
On your phone: connect from https://www.espruino.com/ide/relay
On your PC: enter the key under Settings>Communications>Relay Key -
it would be nice to split out the different GUI parts - so if you tapped on a message in the list in the Messages app, it could be handled by a different app.
On the one hand, it seems a nice idea.
On the other hand: I'm working on a GUI that doesn't have a separate list: you just start with the top message, and scroll down to the next message. And I'm not sure how that would work with custom displays... (but maybe I'll think of something once we get this sorted out, and I actually finish that GUI)Another thing we might look at is response actions, I'd like to have an easy way to just add custom response actions for e.g. Home-Assistant notifications, without having to code up a new screen. (But that's on the list below figuring out responses, and whether we can get GadgetBridge to pass action buttons)
-
I made a draft PR.
How it works now:
how to handle each of:
save message, go to app
Bangle.on("message", (type,message) => { if (message.handled) return; // already handled require("messages").save(message); if (wantToLoadAppfor(message)) require("messages").openGUI(message); });
do something, save message, don't go to app
Bangle.on("message", (type,message) => { if (message.handled) return; // already handled doSomethingWith(message); require("messages").save(message); message.handled = true; });
do something, don't save message, don't go to app
Bangle.on("message", (type,message) => { if (message.handled) return; // already handled doSomethingWith(message); message.handled = true; });
Note that the
if (message.handled) return; // already handled
is only meant to be used if the code does something like e.g. displaying the message, widgets just always show an icon for new messages.Some things I ran into:
- Depending on GUI apps/widgets as "module" seems a bit of a mismatch (right now the sanitychecker complains it expects e.g. a
messagewidget
file to exist if an app provides amessagewidget
module. We could work around that I guess, but it seems Wrong...) - What should we do about the settings? I guess split the menus out into e.g. "Message GUI", "Message Widget", "Message Behaviour" settings, but maybe we should still save them all in
messages.settings.json
? Even for custom apps, and just accept that it might pollute the file a bit?
The messages app (and notify icon) was an easy way to get to music though...
Yeah, probably best to leave it in, and custom music apps can catch the event before it leaves the default GUI.
- Depending on GUI apps/widgets as "module" seems a bit of a mismatch (right now the sanitychecker complains it expects e.g. a
-
although nobody is yet to make a PR to actually just improve the standard message app :(
Well, I'm working on my own messages app, but it makes big changes to how messages are displayed, so I'd be reluctant to make a PR to "completely replace" the messages app.
So maybe we want msg.handled and msg.noMessageApp?
My idea was that
msg.handled
= don't take any visible action (like loading apps)Or do we want to not store the message until there's a user interaction with the overlay? That could be tricky, and if something happens (maybe an alarm goes off and the alarm app is loaded?) the message could get lost.
We can save it in
on("kill")
split out the GUI for the existing music app in the messages app, that could maybe fix this more nicely, and would reduce duplication on the watch.
A problem with
music
specifically is that you expect a lot of those events to happen, we don't really want to write any of them to flash anyway, but need to for the app to pick them up.
An idea: maybe simply not handle them in the messages app at all, and we can have a separate overlay app to show music?the messages app probably wants to handle event.t=="remove" (...) but I guess it could do that and then check 'event.handled'?
Yeah, that was the idea. Same goes for widgets.
move all the logic ( saving messages, managing music... ) to an app/library/... and move the GUI to a separate app
I find it "wrong" that the pushMessage automatically saves the messages that arrive
I agree, and I think right now things are confusing because a) we bundle the library with the default GUI, and b) the library+GUI are too tightly coupled.
What I'd like to do:
- completely split out the default GUI from the
messages
library, and make it event-driven. - keep
pushMessage
in the library: it would be much simplified but just to deduplicateandroid
/ios
code (and combinemusicinfo
+musicstate
events)
I think that since this commit, we can split the library into a "module".
android
/ios
could still depend onmessages
(the default GUI), which would depend on the library, so fresh installations still work out of the box, and custom apps would set events tohandled
, without needing to uninstall the default.Proposed
require("messages")
API:pushMessage(event): emit appropriate "message" event, *does not save it* save(message): save message to flash (if not already saved), sets `message.saved=true` status(): checks saved messages, returns "new"/"old"/"none" getMessages(): returns array of saved messages accept(message): send positive message response dismiss(message): send negative message response, erase message from flash, only if it existed: emit "message" event with `{t:"remove"}` launch(message): launches the default GUI by emitting a `type="launch"` event write(messages): replace all stored messages with given array (for use by GUI on exit) // not 100% sure about these, but otherwise it would be duplicated in most message apps... buzz(message): start buzzing for new message stopBuzz(): stop buzzing
The overlay notification app can then
- listen to
on("message", (type,msg) => if (type==="text") // set msg.handled=true, display msg, etc.
- On tap: launch the full app by doing
require("messages").launch(msg)
- On swipe:
require("messages").dismiss(msg)
- Do
on("kill", ()=>require("messages").save(msg)
to prevent them getting
And we could think about adding music/call overlays either to the default GUI, or as separate apps.
- completely split out the default GUI from the
-
it would be convenient to be able to change the app that is called by the Android/IOS app
smessages
has this in a boot file:global.load = (_load => file => { if (file==="messages.app.js") file = "smessages.app.js"; _load(file); })(load);
It feels rather hacky, but it works, and is cleaned up automatically when you uninstall the app.
-
-
metadata.json
is documented in the BangleApps README -
Maybe it could be another option in the App Loader for now so that it can be turned on for those that are interested?
That sounds like a good idea.
But I was also asking because I really don't know enough about Espruino to estimate whether it is likely to have any real impact on top of the pretokenization. But if you think it might I'd be happy to spend some time investigating it. -
Not sure if it's worth it, but the app loader tried minifying all code a while ago. Back then it broke apps, because Espruino didn't support
let
/const
scopes, so variable mangling ended up with duplicates.
But now that scopes are properly supported, maybe it could be turned back on?
I know the code is already pretokenized, but at least variable mangling might speed things up a bit? (and maybe the minifier knows some other tricks) -
the message app still shows as installed, and listed in the launcher
Good point.
Do we even need a message library if we change to firing events rather than importing
message
?The library also handles storing messages and buzzing/icons, we don't want to duplicate all that code for every custom app. (And moving it to a module would mean it getting included into boot code)
Here's an idea: change the
metadata.json
format to (optionally) inlude app type:- split
messages
into the library:"id":"messages", "type": "messages"
, and the default app:"id":"msgapp", "type": "app/messages"
. - The
android
/ios
apps then depend on"dependencies": {"messages":"type", "app/messages":"type"}
. (Not sure if it already works like this)
- split
-
Yeah, it's a bit complicated :-(
- We also have iOS support, the
message
library exists for shared code between Android and iOS. - We could disconnect the library from the default app, but bundling them makes sure there is an app installed: We can just tell new users to "Install the
android
/ios
app", both automatically pull inmessages
, so it works right away.
I am trying to separate the library/app code some more, so that it will really be like just two things (library and app) that just happen to be installed together.
So then you have:
Phone ->android
/ios
->message
library -> (custom app ||message
app) - We also have iOS support, the
-
-
This seems to be the widgets being drawn
AnDark doesn't call
loadWidgets
at all, so the problem seems to be that widgets are/were loaded+drawn anyway. -
That's not because of
wid_edit
, it's themessages
widget: it already had anupdate
method which expects an incoming message as argument.Actually, I think I'd like to rewrite the
messages
library/app/widget some more, so it just passes everything throughBangle.emit("message", type, message);
, instead of directly calling widget methods or global functions. -
I updated
smessages
to depend on the defaultmessages
app instead of duplicating code.
New caveats:- This is mostly just a big change to deduplicate the library code: it works, but you might want to wait a few days for me to polish it some more.
- I moved the widget code to a separate app (PR)
- It now depends on the default app, the installation procedure now is
- Install the default
messages
app from my repo - you need the version from my repo, as it depends on some library changes that are only present in the storage file version. - Install the
smessages
app from my repo
Edit: icons are fixed now.
- This is mostly just a big change to deduplicate the library code: it works, but you might want to wait a few days for me to polish it some more.
-
-
-
Maybe an alternative to this would be keeping the widgets loaded, but hiding them in apps not loading widgets? RAM could be an issue,
How many apps don't load widgets, and why? It might be best to just slow-
load()
those apps.
I can't think of a good way to determine if an app is going to load widgets though :-(scanning the 40+ apps I have installed.
It looks like
quicklaunch
could be improved a bit to not do this every boot, but just check if an app exists before loading it.Maybe we should add a debug bootloader that logs per-bootfile timings to the console on boot?
-
Apps could use the
E.kill
event to save state to a file, and check if the file exists and restore it when loading the app. -
divide the book up in chunks that the app can manage without hitting ram limits
If you upload it as a plain text file, you can use
require("Storage").read(name, offset, length)
to read in chunks. Memory should not be a problem, as it returns a memory-mapped String that points to the ROM anyway. -
This seems to work (in the emulator at least):
function removeListeners(events) { saved = {}; events.forEach(event=>{ let listeners = Bangle['#on'+event]; if (!listeners) return; saved[event] = listeners; Bangle.removeAllListeners(event); }); return saved; } function restoreListeners(saved) { for (const event in saved) { let listeners = saved[event]; if (typeof listeners !== 'object') listeners = [listeners]; listeners.forEach(listener => Bangle.on(event, listener)); delete saved[event]; } } // disable event listeners const eventsToRemove = ['touch','swipe','drag','stroke','tap','gesture','aiGesture']; let saved = removeListeners(eventsToRemove); // do Stuff // when done: restoreListeners(saved);
-
@Sir_Indy Oh, it isn't solely for your benefit ;-) It would also allow me to remove duplicate code from
smessages
, and just use the default messages library.
I made a PR for message events. With those changes you could do something like this:// aanotifi.boot.js Bangle.on("message", (type, message)=> { if (type !== "text") return; // let default app handle e.g. "music" or "call" require("notify").show(message); require("messages").buzz(message.src); message.handled = true; // prevent default app from launching });
-
it's trivial to change this to
"dependencies": {"messages":"type"}
,
It looks like I'll end up having to do this anyway for @rigrig's.I tried that and reverted it, as it turned out to be a bit tricky: if you change
messages
to"type":"messages"
it won't show up in app launchers anymore...And hopefully you won't have to anyway, my Plan now is:
- PR for master
messages/lib.js
so it does theemit
+custom app stuff
(I thought about it some more, and think this wouldn't be that big a change after all, so wouldn't really cause merge problems) - modify my
smessages
to work with that, so It won't need a duplicatemessages
library :-) - @Sir_Indy could just add a
boot.js
toaanotifi
to listen for message events, show them with aSetLCDOverlay
and prevent the default app from launching.
- PR for master
-
Right now a bunch of clocks either never show widgets, or have a setting to toggle them.
As far as I can tell, this is all about display preference, so how would people feel about making it a global setting instead?
My proposal would be to aim for:
I'm asking because I figured it wouldn't be too hard to create some boot-app that uses widget_utils to (kind of) do 1. But without cleaning out the apps it would increase the mess of settings even more, and I expect it will need some app support, which feels a bit out of place if it's just for some optional app.