Overlay Notifications

Posted on
Page
of 2
Prev
/ 2
  • Hi - Thanks for the PR.

    Obviously it's a draft but there are some issues I can see...

    • it looks like this breaks music for Android at the moment
    • apps that work on the events can no longer mark a message as 'handled' (so all messages get saved and load the messages app)
    • no iOS support there either

    As you say Bangle.on("message", .. require); doesn't add much extra memory use or load time. It will add some though, which I doubt Bangle.js 1 owners will be super happy about given how tight memory is for them at the moment.

    If we did something like:

    Bangle.on("message",function(type,event)­{
        if (!event.handled) require("messages").pushMessage(event);  
    });
    

    It would solve the 'handled' issue as long as other apps 'numbered' their boot code so they could ensure it got executed first. I'd be inclined to push call through the same message event too - I don't really see many benefits of having a new event type for that as it just means more handlers = more memory and boot delay.

    What do others think?

    Adding a handler for the Bangle.on("message" seems to work right now. So why are we doing this? does it actually let you do anything you couldn't do before, or is it just because you don't like the current arrangement?

    • Is it more efficient? When a message arrives it may save maybe 2ms of processing time.
    • Does it save memory? No - it uses slightly more RAM - all the time
    • Does it make things faster? No - it slows down boot slightly - for every app.

    Right now, a message comes in from the phone, is handled by the Android app, goes to the messages library where it is stored, and then the messages app displays it.

    • Is it that you want to be able to display the message differently in the messages app? You were posting earlier about splitting out the GUI. We could do definitely something like that...
    • or do you want to be able to handle/display messages without them even being stored on the device? Do you still want to be able to store some messages? Or do you not want to store any?
  • Obviously it's a draft but there are some issues I can see...

    yes yes, I know there are some problems, before continuing I wanted to know if the methodology could be good.

    It would solve the 'handled' issue

    that's more or less the solution I was thinking of (and which is currently implemented as a workaround in the "message")

    I'd be inclined to push call through the same message event too

    at the beginning I had implemented only one event; logically it seemed clearer to me to divide it ( message, call, music, other... ).
    It actually consumes slightly more ram; I might go back to the "old" method. (only the "message" event for all )

    So why are we doing this?

    certainly a more "open" program uses more resources but I think it's more convenient, in a modular environment like this, to manage the various apps as separate things.
    write, hardcoded, that an app calls another app ( require("message").pushMessage directly from the android/IOS app )
    it means creating a bond that goes against the logic of apps.

    the point is to try to understand if we want to implement a logic where multiple apps can manage various types of messages, or if the "notifications" world must be closed (it is true that everyone can implement their app as they see fit, but this means code fragmentation and poor management/updates).

    I think so:
    android/IOS raise an event -> any app can handle it
    (the "official" message app is capable of event handling).

    Does it save memory?
    not directly, it depends on the implementations:
    currently my version of message is lighter than the official one because it doesn't store messages in mass memory and has a "cleaner" UI with fewer settings.

    if, on the other hand, we don't want to give the possibility of managing notifications to multiple apps, it would be convenient to be able to change the app that is called by the Android/IOS app

    give the possibility to write the name of the app to be called in the "android.settings.json" file (by default it would be "message") and then replace the occurrences with:

    require(settings.appName).pushMessage(ev­ent);
    

    so that if one wants to implement his own app he could do something like this:
    in the settings of the app create a button like "set me as message manager" which calls

    require("android.lib.js").setAppName("my­_custom_app.js")
    //( or IOS )
    

    all apps should work as usual and you would have the possibility to manage messages with any app (if desired, the custom app could still call the require("message").pushMessage(...) )

    let's say this solution is a hybrid.

    it shouldn't add any boot code, just an additional variable in the "android.settings.json" file (which is already read during boot so it doesn't slow down / take up more space)

    splitting out the GUI

    it was an idea, but perhaps much more complex to apply and which made everything even more restrictive in some respects.

  • 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.

  • It feels rather hacky, but it works

    yes it works, but I don't really like the approach... I think that keeping these methodologies leads to some apps struggling to communicate with others in the end.

    At this point I would override the "require" function so as not to directly load the "message" library (and its pushMessage )

  • since at the moment there is another PR who is modifying the app message ( https://github.com/espruino/BangleApps/p­ull/1498 ) and who is implementing some sort of events; I would say that it is useful to understand how to proceed (so as to avoid writing unnecessarily code )

  • One reason I'm a bit against this is that you assume that require("messages").pushMessage(event); should only go to the messages app.

    As I'd said above we can trivially modify the dependency field in the app loader (the code for this is already there now I've pulled out the icons to messageicons) so that the 'messages' library can be provided by any app that wants to handle messages.

    For example right now we have require("textinput") - but textinput can be provided by any different keyboard app. Or require("sched") - we have a default scheduler, but any app can implement a new one. It's simple, it's fast, and efficient. I don't really see the issue with doing this for messages too.

    I don't think you ever really answered this, but IMO it's important:

    do you want to be able to handle/display messages without them even being stored on the device? Do you still want to be able to store some messages? Or do you not want to store any?

    It makes a difference where we need to open up the API.

    For instance it's no use implementing the event as you say if all you want to do is change the way messages are displayed in the messages app - because then you'd just end up duplicating all the code to handle reading/writing messages.json.

    In that case, what we really care about is what you said initially - a way to split off the GUI parts to different apps/files. And I'm all for that, because I think it solves a real problem - one of the main complaints is people want to display messages differently (although nobody is yet to make a PR to actually just improve the standard message app :( ).

  • @rigrig obviously you're working on https://github.com/espruino/BangleApps/p­ull/2205 at the moment

    As we are sending an event, do you think it's compatible with just sending the event direct from Android/iOS?

    Right now the messages app probably wants to handle event.t=="remove" even if something else has got the event (so it can be sure it's 100% gone from the messages list) - but I guess it could do that and then check 'event.handled'?

    I think it would really help to think about what we want to use this for

    All I can think right now is:

    Music

    We get the event in the music app, mark it handled so it doesn't get stored in messages.json - all good.

    Although if we 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.

    'new message' overlay

    What this thread was initially about.

    Personally, I'm imagining that the message (or part of it) would appear in an overlay in the current app, but then if you tap it, you go to the messages app where you can see it in more detail (maybe scrolling). Swiping the overlay could dismiss it and mark it read.

    So in that case, we probably still want the messages library to be storing the message? but we don't want it to automatically load the messages app - we want to let the overlay do that.

    So maybe we want msg.handled and msg.noMessageApp?

    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.

    Messages widget

    We already have widmsggrid and it probably makes sense to split the messages widget into a separate app, and then users can install whichever one they want (or not have one, and have the message overlay instead)?

    Calls

    Again, I guess an overlay for this is good. And in this case maybe we don't want to store anything in messages.json? So we just set handled:true.

    ....

    ... is there any other use case I'm missing?

    But I'm still struggling to see why we need to emit the event from Android/iOS (apart from it maybe being a bit tidier). I think we can pretty much do what's needed as-is?

    As I mentioned in the last post, there can always be different apps implementing the message library - but I think it's important that you only have one installed at a time? *And that there is one always installed by default*.

    By having the event, we potentially end up in a situation where we have multiple apps storing the same message in different ways. And then if you delete the message on one app, it's not deleted in the other one. It also doesn't ensure that when a user installs Android Integration they actually get a messages implementation that works.

    The more I think about this, the more I feel like we could have one messages library that all apps can interact with to add/remove messages. But we make sure that library can be implemented by any app that wants to (eg like sched or textinput)

  • do you want to be able to handle/display messages without them even being stored on the device? Do you still want to be able to store some messages? Or do you not want to store any?

    The more I think about this, the more I feel like we could have one messages library that all apps can interact with to add/remove messages. But we make sure that library can be implemented by any app that wants to (eg like sched or textinput)

    that's exactly what I meant, move all the logic ( saving messages, managing music... ) to an app/library/... and move the GUI to a separate app (perhaps with an app type like for example "clock" )
    to make everything more compatible I thought of using events, so as to be able to manage each app independently, but I see that we don't really like that idea.

    I believe this "library" should provide the basic methods which can then be used and configured by the user / by whoever will program the GUI.

    for example I find it "wrong" that the pushMessage automatically saves the messages that arrive; I believe that the two things ( message management / message saving ) are 2 separate things and the library should give the possibility to use the two functions separately.

    ( PERSONAL OPINION: I find that the management of saves, views, etc via "handled"/"noMessageApp" is confusing and in the long run difficult to manage, maintain and document correctly; but I repeat it is a PERSONAL OPINION )

    By having the event, we potentially end up in a situation where we have multiple apps storing the same message in different ways. And then if you delete the message on one app, it's not deleted in the other one.

    however it could also be that different apps need to store different types of messages and therefore not centralize everything in a single list... mine are just hypotheses

    For example right now we have require("textinput") - but textinput can be provided by any different keyboard app. Or require("sched") - we have a default scheduler, but any app can implement a new one. It's simple, it's fast, and efficient. I don't really see the issue with doing this for messages too.

    this methodology for me has a "problem" (I'm not saying it's serious but more "annoying")
    when you install the Android/IOS app, the messages app is also installed from the dependencies; at this point the user can also install the app he wants to view the messages which will overwrite the "messages" file by inserting his own code so that by calling require("messages") the custom app is called.
    now in the custom "messages" file it is necessary to reimplement all the pushMessage,clearAll, getMessages, status, buzz, stopBuzz functions going to create a duplication of the code.
    having overwritten the original "messages" you can't even recall the functionality of the other file.
    (premise: I'm not sure about this point, I haven't done any tests) if the original "messages" app is updated, does it overwrite the "messages" file and therefore the custom app should be re-installed?
    and even if you uninstall the "message" app, when the "Android/IOS" app is updated, for the dependencies the "message" app is also reinstalled (overwriting the files)?

    in theory, these problems could be solved (at least partially) by providing a specific type of app for displaying messages. (I saw that the "notify" type exists but from what I understand it's an "old" method for handling notifications, right? )

    TL;DR;

    • create a library with the common features -> yes, perhaps providing more functions but which allow greater customization

    a way to split off the GUI parts to different apps/files

    • it is already done automatically with the creation of the library
    • the methodology of overwriting the "message" file (or any other file) -> I think it needs an improvement to work smoothly (I'm talking more about user experience)


    PS: with @rigrig 's suggestion i implemented a message app which i'll ask for a PR.
    I overwrote the require function to make everything work; I don't like it, but it would seem to work.
    PPS:

    although nobody is yet to make a PR to actually just improve the standard message app :(

    I think the problem is that everyone would like an ad-hoc app, and honestly I wouldn't want to touch the GUI/functionality of a program when others like it, I prefer to implement my own version.
    But if there are shared choices and you need a helping hand, work permitting, I'm here :)

  • 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 deduplicate android/ios code (and combine musicinfo+musicstate events)

    I think that since this commit, we can split the library into a "module".
    android/ios could still depend on messages(the default GUI), which would depend on the library, so fresh installations still work out of the box, and custom apps would set events to handled, 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.

  • Ok, great! I think we're basically in agreement then..

    So we'll split out:

    • Messages library (keep pushMessage in the library)
    • Messages app
    • Messages widget

    (I already split out the icons)

    And maybe we'll have to think about how the messages app can be split up such that we can have override-able displays for messages/map/media.

    I think that since this commit, we can split the library into a "module".

    Yes, I think so...

    • Android/iOS will depend on a messages library
    • messages library will depend on a messagesgui and maybe a messageswidget (we want a widget to be installed by default, even if it's not required)

    "notify" type exists but from what I understand it's an "old" method for handling notifications, right?

    Yes, unfortunately - although we should now at least make a proper notify for Bangle.js 2 that uses overlays

    PERSONAL OPINION: I find that the management of saves, views, etc via "handled"/"noMessageApp" is confusing and in the long run difficult to manage, maintain and document correctly

    Yes, I agree. It's just how to handle each of:

    • save message, go to app
    • do something, save message, don't go to app
    • do something, don't save message, don't go to app

    But maybe as @rigrig says we make the save explicit? I'm not sure I've got my head around how yet though.

    But potentially with the new fast load functionality, we don't even have to save the messages before loading the messages app (and then we leave the messages app to save them when it exits).

    ... and if it can 'fast exit' and go to the clock, it wouldn't even need to save then either.

    An idea: maybe simply not handle music in the messages app at all, and we can have a separate overlay app to show music?

    Could do... The messages app (and notify icon) was an easy way to get to music though... I don't know if people use it, but it seemed convenient

  • An idea: maybe simply not handle music in the messages app at all, and we can have a separate overlay app to show music?

    Could do... The messages app (and notify icon) was an easy way to get to music though... I don't know if people use it, but it seemed convenient

    There're metrics hinting regarding this, namely installs and favourites of Messages Music in the app loader, 5 and 7 respectively when I view it now. How to interpret those I'm not sure though.

  • 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 a messagewidget 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.

  • Only just saw this - I made some comments on the PR though: https://github.com/espruino/BangleApps/p­ull/2297

    This seems great. I'm not sure if you have any thoughts on this, but (as a second step after this) 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.

    I'm thinking something like:

    /// mymessage.messagegui.js
    (function(msg) {  return {
      handled : msg.src=="slack",
      open : () => { Bangle.load("mymessage.gui.js") }
    })
    /// mymessage.app.js
    ... actually display the message here however you want it
    

    Then the messages library (or messagesgui) can have a function that loads all of the mymessage.messagegui.js, checks if any of them want handle it, and calls those.

    It's not great, but it's hard to have something that:

    a) doesn't take up RAM (or extra boot time) all the time
    b) allows more than one app to be installed that can handle different message types

    We also do similar things for settings, recorder plugins, and clock_info so this isn't that new

  • 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)

  • 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...

    That sounds neat! I guess in that case your new messagesgui app (that is the list) just always says 'yes I can display this message'. I guess it still leaves open the possibility that some other app (like navigation?) might be installed and would want to handle the message instead, in which case I guess that is still fine?

    Another thing we might look at is response actions

    Yes, that'd be a neat one for later.

    get GadgetBridge to pass action buttons

    I hope so... I seem to recall it can pass some info already?

  • @Gordon, navigation directions staying up with a large direction arrow, etc, this would be awesome. An active google maps navigation session would be cool. Pebble's NavMe might be a good starting point.

  • There's already something in Gadgetbridge that handles OpenStreetMap directions at https://codeberg.org/Freeyourgadget/Gadg­etbridge/issues/2387 - unfortunately Google Maps doesn't appear to expose directions in anything other than a notification but I think that if the above code is merged in, it shouldn't be too hard to parse navigation directions out of the Google Maps notification (at least for english language)

  • @Gordon, ya! That's what I was thinking.

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

Overlay Notifications

Posted by Avatar for Sir_Indy @Sir_Indy

Actions