Skip to content
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

Notifications Portal v2 proposal #983

Open
jonas2515 opened this issue Mar 8, 2023 · 77 comments
Open

Notifications Portal v2 proposal #983

jonas2515 opened this issue Mar 8, 2023 · 77 comments
Assignees
Labels
needs discussion Needs discussion on how to implement or fix the corresponding task new api This requires adding API to an existing portal portal: notifications Notifications portal

Comments

@jonas2515
Copy link

jonas2515 commented Mar 8, 2023

Quick introduction for those who don't know me: I'm Jonas (aka verdre) from the GNOME community, mostly working on gnome-shell/mutter but also across the stack to get things ready for phones.

The notifications portal is currently of very limited use for apps with more advanced notification needs, especially with smartphone use-cases in mind.

Here's a proposal for a new version of the notifications portal, trying to kickstart development and open room for discussion.

Things we want

  • Playing sound or vibrating on notifications
  • Persistent notifications that remain at the top of the tray and can't be dismissed (see also https://gitlab.gnome.org/Teams/Design/os-mockups/-/issues/193)
  • Standardized hints about the content of the notification, inspired by the ideas in Desktop Notification Specication
  • Standardized actions that are useful for a range of similar apps, eg. for inline replies to chat messages
  • Grouping similar notifications, eg. for multiple chat messages from one contact
  • Presenting rich content in notifications, eg. progress bars or images

Things we don't want

  • Notifications are always presented immediately to the user, we don't want API to defer the presentation to a later point.
  • We don't want API for showing "n unseen notifications" badges on app icons.
  • We don't want persistent notifications to be abused as app indicators, that's why they are removed when app closes.
  • We don't want to expose notification urgency as it is right now to avoid abuse by apps.

Proposed API

Permission requests

  • Every app has to request permission to send notifications using the RequestNotifications() method.
  • Access to notifications may later be revoked by the user, so AddNotification() can fail.

Content Hints

Used for all notifications that need specific handling, eg.

  • giving a low-battery notification priority
  • overriding do not disturb state for extreme weather warnings
  • ringing alarm clocks with a special and recurring ringtone

There are three different namespaces that any hint must adhere to:

  • class: What type of content the notification is. Possible hints are standardized with the protocol. Only a single class hint may be used per notification.

    • class.im.message
    • class.alarm.ringing
    • class.call.incoming
    • class.call.ongoing
    • class.call.missed
    • class.weather.warning.extreme
    • class.cellbroadcast.danger.extreme
    • class.cellbroadcast.danger.severe
    • class.cellbroadcast.amberalert
    • class.cellbroadcast.test
    • class.os.battery.low
    • class.browser.webNotification
  • important: Marks the content as important. This might make the system present it differently, for example ignoring the Do Not Disturb setting. May only be used if explicitly requested by user, for example when marking a contact as important. Anything else that the app considers important must use an appropriate class hint instead.

  • custom: Custom application-defined tags, unlimited number can be passed.

Requests and Responses

Requests and responses are the new API for actions.

  • Requests are offered to the user in the notification banner and in the notification tray like existing actions
  • Interacting with a request triggers a response, that is a GAction (name of that action is passed as responseAction) that's activated on the application

Requests have an application-defined requestId (s) and requestParams (a{sv}).

The response object is passed to the responseAction GAction as the parameter (format ssa{sv}: notificationId (s), requestId (s), responseParams (a{sv})). The responseParams are usually empty and only set when using a preset request ID.

Preset request IDs

There's special request IDs for common requests in the preset namespace, proposed IDs (standardize with the protocol?):

  • preset.onClicked: Get notified when the notification itself (so not a specific request) has been clicked
  • preset.onDismiss: Get notified when the notification is dismissed
  • preset.accept: For accept/decline requests
  • preset.decline: For accept/decline requests
  • preset.cancel: Cancelling an ongoing event
  • preset.done: End an ongoing event
  • preset.im.replyWithText: Inline replies for chat apps. Hints the system to show a reply button with the notification that allows entering text. In the responseParams, a replyText (s) will be set.
  • preset.im.muteSimilarNotifications: For chat apps that might send lots of notifications. As chatName (s) parameter, pass a string describing what is going to be muted. The string should fit into "Mute notifications for %chatName?". In the responseParams, forDurationSeconds (t) will be set.
  • preset.call.toggleSpeakerphone: To be used by call apps. Pass speakerphoneInUse (b) in the requestParams.
  • preset.call.returnCall: To be used by call apps.

Presentation hints

Presentation hints allow configuring specifics of how a notification should be presented. The system may ignore those depending on its policy.

Supported presentation hints are listed in presentationHints field returned by GetCapabilites().

Standardized hints:

  • sound (s): Specify a custom sound file to play, set empty string to play no sound at all.
  • vibrationPattern (s): Vibration pattern to use according to Web Vibration API specification, set empty string to request not vibrating at all.
  • ledColor (s): Notification LED color as 6 digit hexadecimal value, set empty string to request not lighting the notification LED.
  • dontShowBanner (b): Pass true to avoid showing the notification banner and potentially disrupt the user.
  • dontAddToTray (b): Pass true so that the notification won't be added to the notification tray.
  • presentNonDisrupting (b): Pass true to avoid all ways of actively alerting the user.

Custom methods of alerting

Apps may use custom methods of alerting the user, for example to play audio from a special source like an online stream of a radio station.

  • AddNotification() returns an appPresentationPolicy (s):
    • mayNotAlert: The app may not alert the user in any way.
    • mayAlertDisrupting: The app may alert in a way that is disrupting to the user and only the user, eg. using vibration.
    • mayAlertVeryDisrupting: The app may alert the user in a way that is disrupting to the user and potentially to other people, eg. by playing a sound on the speakers.

DBus API

Methods:

  • RequestNotifications

    IN
      options (a{sv}): Vardict with options
        handle_token (s): The existing token if the app already owns one
    OUT
      handle (o): Object path for the org.freedesktop.portal.Request object representing this call
    
  • GetCapabilities

    OUT
      specificationVersion (i): The version of the specification the system complies with
      contentHints (as): Array of content hints that the system knows how to handle. If a content hint is included in this array, full support for the type of notification can be assumed.
      presetRequestIDs (as): Array of preset request IDs that the system supports
      additionalContent (as): Array of additionalContent options that the system supports
      presentationHints (as): Array of presentation methods that the system supports, eg. if this doesn't include "sound", it should be assumed the system can't use sounds to alert notifications.
    
  • AddNotification

    IN
      appId (s): App ID of the application
      id (s): Application-provided ID for this notification
      contentHints (as): Hints what the content is about
      title (s): Title
      subtitle (s): Subtitle
      body (s): Body text (can be markup)
      image (s): Icon to show with the notification (serialized GIcon)
      isPersistent (b): Whether the notification is persistent
      responseAction (s): GAction to activate on the app for responses
      requests (a{sa{sv}}):
        requestId (s): ID of the request, can be a preset request ID
        requestParams (a{sv}):
          title (s): Title to display for the request
          icon (v): Icon to display (serialized GIcon)
      metadata (a{sv}):
        time (i): Optional timestamp when the event happened or begins
        endTime (i): Optional timestamp when the event ends, useful for things like calendar appointments
        groupingId (s): Optional ID to allow grouping with other notifications from app
        priority (u): Optional priority in relation to other notifications from the app, might be used by the system when sorting notifications
      additionalContent (a{sv}):
        progress (f)
      presentationHints (a{sv})
        sound (s)
        vibrationPattern (s)
        ledColor (s)
        dontShowBanner (b)
        dontAddToTray (b)
        presentNonDisrupting (b)
    OUT
      appPresentationPolicy (s): Presentation policy for apps which want to alert the user on their own
    
  • RemoveNotification

    IN
      appId (s): App ID of the application
      id (s): Notification ID
    

Open questions

  • how do we want to deal with data like images, audio etc?

How would I do x with this?

Create and ring an alarm clock
  1. Create "next alarm" notification a few hours before alarm

    • Set content hints to class.alarm
    • Add preset.cancel request to allow removing alarm again
    • Set presentNonDisrupting presentation hint so that the notification silently shows in the tray
  2. When alarm rings, remove old notification and create a new one:

    • Set content hint to class.alarm.ringing
    • Add preset.done and snooze requests
    • Set isPersistent to true
    • In case a window of the app is already open and focused, set the dontShowBanner presentation hint
  3. On response:

    • When preset.done is invoked, remove notification
    • When snooze is invoked, remove notification and go to 1)
Notifying an incoming call
  1. Create the notification

    • Set content hint to class.call.incoming, this magically makes the system:
      • Style the notification banner in the "incoming call" style
      • Repeatedly play a ringtone and vibration pattern
    • Add preset.accept and preset.decline requests
    • Set isPersistent to true
    • In case a window of the app is already open and focused, set the dontShowBanner presentation hint
  2. Handle responses and missed call

    • When preset.accept gets invoked, accept the call and update the existing notification
      • Change the content hint to class.call.ongoing
      • Replace requests with preset.cancel and preset.call.toggleSpeakerphone
    • When preset.deny gets invoked, deny call and remove notification
    • When the user didn't trigger a response until the the call was missed, update the existing notification
      • Set content hint to class.call.missed
      • Set isPersistent to false
      • Replace requests with preset.call.returnCall
@Mikenux
Copy link

Mikenux commented Mar 11, 2023

Hello Jonas,

I think this requires organization by use case: progress notifications, alarms, calls/messages (contacts), weather/amber alerts... And those use cases may have other conditions.

Examples (non-exhaustive):

  • Progress notifications. As mentioned in the issue you mentioned, we want to show them when the app closes. This means that we want to prevent applications from using them at will. There are certainly other things to discuss.
  • Alarms. I think it's about registering them, so access to sound and vibration is conditional on that. This avoids applications using sounds/vibrations/LEDs for no reason.
  • Calls and Messages. Maybe a good opportunity to condition this with applications exposing the contacts. In this way, contacts can be identified and this can allow playing the corresponding ringtone, vibration pattern and/or LED pattern, selection of specific contacts in DND mode and having contacts for sharing portal.

@Mikenux
Copy link

Mikenux commented Mar 12, 2023

  • preset.onClicked: Get notified when the notification itself (so not a specific request) has been clicked

  • preset.onDismiss: Get notified when the notification is dismissed

Could you provide examples of use cases? This appears to be tracking... (apart from tracking when an action is triggered; e.g. clicking on a news notification opens the relevant news and the app is aware of it).

Presentation hints and custom methods of alerting: Even though it depends on system policy, I don't see the point of having them when things should be controlled by the user.

@jonas2515
Copy link
Author

Hi @Mikenux,

Maybe a good opportunity to condition this with applications exposing the contacts

Fwiw what you're talking about here is some kind of "People" API, that's what iOS and Android use for this kind of stuff these days. I think we'll eventually need something similar, yes. That said, this is is a whole different topic and very complicated problem in itself, which I'd rather solve properly. Once we have a format to expose and store contacts between apps, we can still add that to the notifications portal.

Could you provide examples of use cases? This appears to be tracking

Telling an app that its notification has been dismissed hardly sounds like tracking to me. The current APIs allow for this already, and iOS has API for that as well.

Even though it depends on system policy, I don't see the point of having them when things should be controlled by the user.

As mentioned in the proposal, it's API to support niche use-cases such as internet radio alarm clocks. There's no way we can integrate playing an online music stream into our API, so in this case, the app has to play the sound itself. The appPresentationPolicy gives the rules for the app whether it may use the speakers itself or not, this is what makes sure the global notification policy is still enforced.

@Mikenux
Copy link

Mikenux commented Mar 14, 2023

Yes, I have no doubt that it is complicated, especially for contacts. The goal is to limit things to relevant use cases. Currently, the proposal seems to allow any app to use anything...

@swick
Copy link
Contributor

swick commented Mar 15, 2023

We don't want persistent notifications to be abused as app indicators, that's why they are removed when app closes.

What do you mean by closed? When the app has no windows?

Permission requests
Every app has to request permission to send notifications using the RequestNotifications() method.

The alternative here is to let apps provide all the data and then decide if and how to show notifications in the backend based on permissions without ever telling the app about the decision.

Is there a reason to prefer the explicit permission requests?

@jonas2515
Copy link
Author

What do you mean by closed? When the app has no windows?

Yup, exactly.

Is there a reason to prefer the explicit permission requests?

Good question, off-hand the other approach sounds fine to me too. The upside of an explicit permission request would be that we can show a dialog to users asking whether the app may send notifications. I found that dialog quite useful on ios, eg. when you're starting a game, you know right away that the notifications will be ads, so you say no right away.

@swick
Copy link
Contributor

swick commented Mar 17, 2023

Yup, exactly.

Then what about apps running in the background? People use those, we show them in the quick settings menu and they can be interacted with. Why should they not be able to show a persistent notification when they're running?

The upside of an explicit permission request would be that we can show a dialog to users asking whether the app may send notifications. I found that dialog quite useful on ios, eg. when you're starting a game, you know right away that the notifications will be ads, so you say no right away.

Apps currently expect to be able to send notifications by default. Does that mean every app which potentially sends notifications will bother me with a popup asking for permission to send notifications? IMO sending notifications should be allowed by default and be turned off potentially in some granular way.

You also talk about the concept of important notifications and notifications which can still show when do-not-disturb is enabled. Should that require additional permissions?

If a user wants messages from a certain person to show even when do-not-disturb is enabled, that's something the app doesn't have to care about. On the other hand, if the app is warning about an incoming thunderstorm, that's a notification the app should have control over.

@Mikenux
Copy link

Mikenux commented Mar 18, 2023

For progress notifications, perhaps these should be drawn by the system, not the apps for a consistent interface. By identifying the requested progress notification, the system can decide the UX. Examples: show alarms when appropriate, show file download when app is closed and/or when app has no focus or is covered by other windows.

For alarms, it's important that they should register when they start, so that apps can't play sound at will using notifications (given that the app is running in the background).

@alice-mkh
Copy link
Contributor

Everything in the proposal, incl. progress notifications are always drawn by the system. Apps cannot draw any of this even if they wanted, even outside flatpak.

@Mikenux
Copy link

Mikenux commented Mar 19, 2023

One thing I'm thinking about is whether preventing apps from using progress notifications for content fetching (e.g. fetching mails, news) is wanted.

Also, what about "autostart"? In GNOME, background app autostart is wanted, except for app that are closed to continue ongoing activity (e.g. web browser, Builder). However, I mentioned the case of download apps (e.g. downloading torrents), where some downloads may be completed, while others may be paused. So, is autostart still a thing, and does it apply to download apps?

@alice-mkh
Copy link
Contributor

Please keep it on topic. Autostart is a background portal thing and already exists, this is about notifications.

@Mikenux
Copy link

Mikenux commented Mar 19, 2023

Knowing the autostart experience might be needed to know what differentiation needs to be done for progress notifications... except if it can be done on the background portal side.

Examples:

  • Download/File progress: Files are saved to a user location (e.g. Downloads folder, a Conversion folder).
  • Content Fetching Progress: Files are saved in the app's location (i.e. a folder that the app owns and which is usually hidden).

Or are these conditions for the background portal, or something else? (e.g. progress notification + folder location).

Just to be sure...

@alice-mkh

This comment was marked as off-topic.

@Mikenux

This comment was marked as off-topic.

@alice-mkh

This comment was marked as off-topic.

@jonas2515
Copy link
Author

jonas2515 commented Mar 19, 2023

Then what about apps running in the background? People use those, we show them in the quick settings menu and they can be interacted with. Why should they not be able to show a persistent notification when they're running?

Well, it's a compromise, I don't see another way of avoiding that apps running in the background just put a persistent notification into the tray to let users know what they're up to. In theory that's the exact use-case covered by https://gitlab.gnome.org/Teams/Design/os-mockups/-/issues/150, but then again I'm not a fan of status notifiers either. IMHO apps which don't have a window open should never annoy users in any persistent way, that starts with music players which shouldn't be playing music when they're closed and ends with backup apps which should just quietly and resource-friendly do their job in the background.

Apps currently expect to be able to send notifications by default. Does that mean every app which potentially sends notifications will bother me with a popup asking for permission to send notifications? IMO sending notifications should be allowed by default and be turned off potentially in some granular way.

Fair point, that is what we're doing right now after all and it seems to be working okay-ish, as longs as we manage to keep apps which are actively hostile towards users (aka financed by ads) away from our platform, I think it'll be fine.

You also talk about the concept of important notifications and notifications which can still show when do-not-disturb is enabled. Should that require additional permissions?

I think it's fine to allow everyone to mark their notifications as important by default, you do want that feature in basically every chat app for example. I think the interesting part here is the "only if explicitly requested by user": I'm not sure how to enforce that other than shaming apps for violating the spec, but if everyone respects that we should be fine?

Fwiw, ios does allow this by default, but it can be disabled per-app in the notification settings, I think we could do the same.

If a user wants messages from a certain person to show even when do-not-disturb is enabled, that's something the app doesn't have to care about. On the other hand, if the app is warning about an incoming thunderstorm, that's a notification the app should have control over.

The thing is you want the UI for things like marking contacts or chat groups as important inside the app, because that's where users will look for it and that's where the context is. Android kinda moves that UI to the system with its notification channels, and that duplicates things and is generally quite awkward when it comes to features like this.

Things obviously get more complicated if we start to have a system-wide API for persons where you can actually mark one contact as important system-wide. In this case indeed the UI would be part of the system, and the "important" bit should no longer be set by the app. I don't see this happening anytime soon though, but if it would I don't think anything in here would stop that in particular.

@swick
Copy link
Contributor

swick commented Mar 20, 2023

IMHO apps which don't have a window open should never annoy users in any persistent way, that starts with music players which shouldn't be playing music when they're closed and ends with backup apps which should just quietly and resource-friendly do their job in the background.

The reality is that apps can run in the background, they can show the media controls which pretty much appear as a persistent notification, we list apps running in the background in the quick settings menu and we're adding more context to apps running in the background with the background portal.

I don't think it makes a lot of sense to restrict persistent notifications out of all the things to apps with windows only.

I think it's fine to allow everyone to mark their notifications as important by default, you do want that feature in basically every chat app for example. [...]
Fwiw, ios does allow this by default, but it can be disabled per-app in the notification settings, I think we could do the same.

Sounds good.

The thing is you want the UI for things like marking contacts or chat groups as important inside the app, because that's where users will look for it and that's where the context is. Android kinda moves that UI to the system with its notification channels, and that duplicates things and is generally quite awkward when it comes to features like this.

I still think that would be ideal. Punching though do-not-disturb can be really bad if it is unwanted so delegating it to the system makes a lot of sense.

Right now we really don't have the infrastructure for it though. So I'm fine with leaving it up to apps as long as we have a way forward to delegate it to the system eventually.

@Mikenux
Copy link

Mikenux commented Mar 20, 2023

It would be good to know for which applications a persistent notification is necessary, except for media players using MPRIS and progress notifications...

@ispanos
Copy link

ispanos commented Mar 28, 2023

We don't want persistent notifications to be abused as app indicators, that's why they are removed when app closes.

My only note would apply to this. Do not remove the notification. Make it removable by the user once the app closes.

Also, there are valid use-cases for persistent notifications. I can think of many use-cases. , a company that make some smart buttons (Bluetooth switches) used to have a persistent notification to allow you to press digital buttons from your notifications panel on android. I know this is not an actual notification, but it was the absolute best way to do it. Maybe what I'm describing should ultimately be a widget panel, next to the notification panel, but that's a bit excessive.

@jonas2515
Copy link
Author

jonas2515 commented Mar 31, 2023

I don't think it makes a lot of sense to restrict persistent notifications out of all the things to apps with windows only.

Yeah I don't really have a strong opinion on that. I'd be happy to try that approach first, can always restrict it more if apps will abuse it. Then again I am pretty sure they will abuse it if this API gets implemented before the app indicator one.

Maybe what I'm describing should ultimately be a widget panel

Yup, that's exactly the point I'm coming from here. That's what persistent notifications are used for on android, but in practice very often what you really want is a proper widget API for apps.

Anyway, IMHO this is ultimately a design question and we should leave the answer to the design team and follow that in the API.

@ispanos
Copy link

ispanos commented Mar 31, 2023

On android I understand that there are some notifications that act like widgets, but there are some that are very annoying. And now that I think of it there are some that treat the notification like an app indicator and they are so annoying (zepp life app) .

Anyway, IMHO this is ultimately a design question and we should leave the answer to the design team and follow that in the API.

Which design team? As a swaywm user, I would rather have a solid API implementation that doesn't restrict dedicated notification daemons. It should definitely be coordinated by both sides, but in a DE agnostic way.

I am pretty sure they will abuse it if this API gets implemented before the app indicator one.

I don't understand why this is the case, but I am not so educated on that matter. There are already extensions for that on Gnome and other desktops/wm's have app indicators, so maybe this is not so concerning (?).

I don't think I have anything more to contribute. Thank you for opening that issue, I've been waiting for this for a long time.

@Mikenux
Copy link

Mikenux commented Mar 31, 2023

Then again I am pretty sure they will abuse it if this API gets implemented before the app indicator one.

It's best not to implement anything about persistent notifications, even after implementing the status notifier specification, at least if GNOME sticks to its position of having "systray" apps (those that want a menu) in background apps UI. The point is that for users, having quick access to the menu is essential, and the background apps UI in GNOME does not allow this. So, because of this, apps will probably still abuse of persistent notifications even if they are implemented afterwards.

Also, widgets were briefly discussed in the status notifier spec, but were rejected as not being simple (unless they've changed their minds since then, but I doubt that). @ispanos: Feel free to open an issue about it with case examples. This is something wanted and I guess having a specific API for it shouldn't block the location of these (i.e. widgets can be located in the notification area if it is the wanted UX).

@kbroulik
Copy link

kbroulik commented May 6, 2023

Hi, this is the KDE Plasma notification developers and we like your proposal a lot! Here’s a few suggestions and comments we have:

Lock Screen Visibility / Privacy

It should be possible to tag a notification with a visibility/privacy tag, similar to Android’s visibility property so we can decide whether the notification (and/or how much of it, if at all) is shown on the lock screen, shown during screen sharing, synced to your phone, etc.

Markup

Specify what “markup” is supported here. Probably a small subset of HTML (e.g. <b>, <i>, perhaps lists, etc) but we don’t want to see tables or CSS or anything overly complicated in here.

Also, we believe that plain text should be the default, with markup as an opt-in flag on the notification. In the past we’ve often had issues with apps either not escaping their text or ending up with double escape. Making markup a conscious choice on the app side (I enabled markup for this notification so now I have to sanitize my input) would fix that.

Custom sound file

Should this support XDG sound names rather than only custom paths?

On the other hand, a “default” sound could be implied from the class and then be configurable in the shell which sound to use for which class and/or per application.

"empty string" for sound means "play no sound at all". Clarify what the absense of this hint means, play default notification sound, if any, and "empty" suppresses it?

Progress

Is there an indeterminate state? NaN? :-)

Additionally, a preset.pause known action could be useful for suspending a task.

Is it in scope to add an additional progress details dict, e.g. "From" / "To" in a copy job, etc?

GAction

A GAction calls to a well-known DBus name, right? So it is only good for a unique application. What about having multiple instances of an application?

Especially, given you explicitly mention that portal notifications get revoked when the app quits, so there is no DBus activation happening, it seems like an unnecessary restriction.

Unless implied by GAction, there is no mention of the XDG Activation protocol, which is necessary for for raising an application window in response to a notification.

Image

The image, is that the notification icon, like user avatar that sent a message?

Please specify the wire format used (e.g. can we just send an iconName, can we supply multiple sizes and variants of an icon, etc). We don’t like sending image data over DBus when we could have the client pass a file descriptor to an image instead.

Both Plasma and Android support a large preview for example for screenshots or received images, which would be nice to have specified here, too.

Other

  • AddNotification should specify which hints are mandatory.
  • time and endTime should probably be of x type (int64) rather than i.
  • Clarify whether AddNotification replaces an existing notification with the same ID and if so, how (silently/re-popup) and/or allow to influence this behavior.
  • Perhaps add known action presets for toggle webcam, microphone, hangup to control a video call.

@DemiMarie
Copy link

Then what about apps running in the background? People use those, we show them in the quick settings menu and they can be interacted with. Why should they not be able to show a persistent notification when they're running?

Well, it's a compromise, I don't see another way of avoiding that apps running in the background just put a persistent notification into the tray to let users know what they're up to. In theory that's the exact use-case covered by https://gitlab.gnome.org/Teams/Design/os-mockups/-/issues/150, but then again I'm not a fan of status notifiers either. IMHO apps which don't have a window open should never annoy users in any persistent way, that starts with music players which shouldn't be playing music when they're closed and ends with backup apps which should just quietly and resource-friendly do their job in the background.

This should be up to the portal backend, and ultimately to the user. Just because you dislike background status notifications does not mean that everyone else also dislikes them.

@Mikenux
Copy link

Mikenux commented Aug 30, 2023

From what I understand, what is NOT wanted is a notification that stupidly stays at the top of the notification list, especially when it is not showing anything (i.e. no specific status).

There is the background portal which already handles such "persistence", it just lacks the menu for actions.

@DemiMarie
Copy link

From what I understand, what is NOT wanted is a notification that stupidly stays at the top of the notification list, especially when it is not showing anything (i.e. no specific status).

That’s understandable, but at the same time users need chat apps to be able to show a notification (one for each chat message) that persists even when the app is not running.

@GeorgesStavracas GeorgesStavracas added needs discussion Needs discussion on how to implement or fix the corresponding task portal: notifications Notifications portal labels Oct 3, 2023
@DemiMarie
Copy link

Have the concerns regarding chat apps and persistance been addressed? This is a feature present in Windows and Android at the very least.

@Mikenux
Copy link

Mikenux commented Mar 8, 2024

I'm replying to you here.

Context: First two comments in #1298

I'm still for sound being tied to a notification class. This defines a notification class that users can enable and disable. This is especially relevant if you want to set a maximum sound duration (which is a good idea), because the duration of an informative notification is not the same as that of the sound of a custom ringtone or of an alarm.

As a side note, for alarms, maybe applications should make a single request with all relevant alarm parameters to one alarm portal rather than multiple portals (if I'm not wrong). Also see #1098 (comment) on your other MR.

Regarding custom sounds versus system sounds, it's more about what app developers can expect. Setting a custom sound can be part of the app experience. App developers can therefore expect all DEs to use this custom sound. Furthermore, having a custom sound linked to a notification class (yes, again) here allows the user to define a system sound or a custom sound for this notification class (changing the sound when the app is not running).

@jsparber
Copy link
Contributor

jsparber commented Mar 9, 2024

I'm still for sound being tied to a notification class. This defines a notification class that users can enable and disable. This is especially relevant if you want to set a maximum sound duration (which is a good idea), because the duration of an informative notification is not the same as that of the sound of a custom ringtone or of an alarm.

I think it makes sense to link the sound to content hint but that's tangential to what #1298 implements so far.

Please also note that app developers, with #1298, can also specify themable sound names , which are system provided sounds. (just noticed that i didn't add that to the docs)

@DemiMarie
Copy link

@jsparber would it be possible to ensure that it is at least possible, in the future, to support invoking actions on notifications even after the app has exited, and possibly even after a system reboot? In other words, would it be possible to provide each notification with an identifier (such as a 256-bit random number) that will never be reused?

@jsparber
Copy link
Contributor

jsparber commented Mar 9, 2024

@jsparber would it be possible to ensure that it is at least possible, in the future, to support invoking actions on notifications even after the app has exited, and possibly even after a system reboot? In other words, would it be possible to provide each notification with an identifier (such as a 256-bit random number) that will never be reused?

I think there was some confusion about according to this proposal notifications will have an id specified by the app, so the app has to provide an id which will only exist in the context of the app and may be unique.

@DemiMarie
Copy link

@jsparber would it be possible to ensure that it is at least possible, in the future, to support invoking actions on notifications even after the app has exited, and possibly even after a system reboot? In other words, would it be possible to provide each notification with an identifier (such as a 256-bit random number) that will never be reused?

I think there was some confusion about according to this proposal notifications will have an id specified by the app, so the app has to provide an id which will only exist in the context of the app and may be unique.

Ah, nice! I suggest adding something like this to the spec

  • Sandboxed apps must provide their own app ID (this is checked by the portal).
  • Unsandboxed apps can provide any app ID they want.
  • The notification ID can be anything, but MUST be unique for all time, even after the app is uninstalled and reinstalled. The recommended way to achive this is to use 128 or more bits of entropy from a cryptographically secure random number generator.

The last bullet is to ensure that conforming applications are at least ready for when it becomes possible for an action to start up an app.

@Mikenux
Copy link

Mikenux commented Mar 9, 2024

@jsparber: Sorry, I'm confused about what you replied in your comment on your MR and what you replied here. So, does a content hint must be specified? Or does a notification with a sound but no content hint belong to "general"/"information" notifications?

Also, can we already know what content hints will be present?

@ilya-fedin
Copy link
Contributor

ilya-fedin commented Mar 9, 2024

The app ID is needed by most portal interfaces. I propose to have some global SetAppId method for unsandboxed apps that would set the dbus connection <--> app id relation for all the portal interfaces. This would let to not to add appid argument to the methods of each and every interface.

@DemiMarie
Copy link

  • important: Marks the content as important. This might make the system present it differently, for example ignoring the Do Not Disturb setting. May only be used if explicitly requested by user, for example when marking a contact as important. Anything else that the app considers important must use an appropriate class hint instead.

If this is going to be in the spec, then I think certain class hints need to imply important, at least if the app has the permission to use important at all. The reason is that in some cases (such as a weather app reporting a tornado warning), it is necessary to override Do Not Disturb for rather obvious safety reasons!

@ZanderBrown
Copy link
Contributor

@DemiMarie I think you've perhaps not quite followed?

The notification ID is a string provided by the app, and is scoped within an app-id, and what an app does with that is entirely up to the app.

For something like ‘System Updates Are Available’ you have absolutely no need of uniqueness: The response to the notification being activated will always be to open the system update page, and if for some reason the notification was already present you new one should replace it, not duplicate — so the id can simply be system-update.

What really matters is that the id somehow communicates to the app what it should be doing in response to this interaction, and that'll vary app to app — for example a matrix client might use something like mention-[event-id] when the user is mentioned, and then app can simply split the event-id off and jump to that message, a scheme which would neatly give you free deduplication even.

A ‘cryptographically secure random number’ would be rather contrary to this goal, in most cases?

@ZanderBrown
Copy link
Contributor

would it be possible to ensure that it is at least possible, in the future, to support invoking actions on notifications even after the app has exited, and possibly even after a system reboot?

The spec already supports that, that's part of the core design even

@DemiMarie
Copy link

@ZanderBrown Ah, I see!

In the Matrix case, one would want to have something like matrix-[account_id]-[event_id] for multi-account support.

@AdrianVovk
Copy link

Hello 👋!

Tiny bit of motivation for this comment: I'm working on integrating systemd-homed with GNOME as part of the GNOME STF grant. Recently, I've started planning out what GNOME will be doing to provide a lock-screen for users locked via homed: a normal lockscreen cannot work because the user session is frozen, so we need to run a lockscreen outside of the session to facilitate homed's security. This, however, has the potential of breaking apps that may want to appear over top of the lockscreen, which I wanted to avoid. So, I researched the use-cases for apps-on-lockscreen in other OSs, and how the functionality is implemented there. This ended up having a lot of overlap with notifications: incoming calls, ringing alarms, etc are the common use-cases for apps appearing on the lockscreen. My full research can be found here, though I will cover the relevant conclusions in this comment.

I've discussed many of these things with @jonas2515, and we seem to be on a similar page about them all. I want to write my ideas down here, to make sure the results of our discussion aren't lost and to collect feedback about it from other projects.

Calls

On Android, incoming calls are just apps that put themselves on the lockscreen. On iOS, there's a "CallKit" API that lets apps tell the OS about incoming and ongoing calls. The OS, in turn, can provide a rich incoming call UI, integration with the shell, cross-app call waiting, etc. You can find lots of more detail in my research document. Turns out, this Notifications v2 API almost fully covers the needs of CallKit, so here's a wishlist of things still lacking that need to be in the API spec, or recommended to backends, or etc:

  • If the device is idle when it receives an incoming-call, instead of showing a normal small banner notification we show a full-screen incoming call UI instead. Possibly over the lockscreen.
    • Presumably this is drawn by the shell itself, or whatever component is already drawing notification banners, so no special support for stuff appearing on the lockscreen would be needed
  • Activating an incoming call notification would also show this full-screen incoming call UI
  • Activating an ongoing call notification should activate the app's ongoing call UI, possibly over top of the lockscreen. This would be done w/ a special xdg-activation token that the app is given and can use to present the window over top of the screen shield
  • Call waiting: basically the user cannot exist in > 1 call at once, so we must be able to handle call waiting across apps. We can do that relatively trivially via this notification API
    • VOIP apps that can put their call on hold will send the notification w/ a preset.pause action. Won't be rendered as a button in the notification, though I suppose it can, but will just be used as a hint to tell the system the app can have the call paused (i.e. put on hold)
    • If a second app sends an incoming call notification while the system already has an ongoing call notification, behavior would change slightly:
      • preset.accept becomes "End Call & Accept". Selecting it will send preset.cancel to the ongoing call's notification and preset.accept to the incoming call
      • If the ongoing call has a preset.pause action, then we create a new "Hold Call & Accept" button in the UI that sends preset.pause to the ongoing call and preset.accept to the incoming call
  • We should differentiate video calls from audio calls
    • Incoming video calls should have separate "accept with/without video" actions (could just be sent as additional parameter to preset.accept: with_camera_on true/false/unset)
    • Let apps sending incoming video call notifications attach a pipewire FD for camera preview
      • Using an FD like this lets the app do whatever processing it wants (blurring backgrounds, scaling, etc) and hand over an accurate preview of what the app will be showing on the other side of the call. Notification portal also won't have to handle cameras at all, just take the FD and pass it into the backend to be rendered
      • The fullscreen incoming-call UI would make this preview its background, to let the user preview how they'll look before they accept the call
      • If the preview is never shown (i.e. only a banner incoming-call notification was presented because the user was busy doing something else), then we send preset.accept to the notification with with_camera_on unset (which tells the app that preview wasn't seen and lets the app decide what to do: present their own peview UI, start with the camera off, etc)
    • iOS tells the user if they're getting a "AppNameHere Audio" or a "AppNameHere Video" call

Alarms / Timers / Calendar Events / Reminders

On Android, alarms work similarly to incoming calls. iOS doesn't seem to expose an alarms API. Here's the wishlist of what we'd want for alarms in this API:

  • Optionally, the notification API can return an xdg-activation token to alarm apps immediately after they post a class.alarm.ringing notification. This xdg-activation token lets the app render itself over the lockscreen
    • The app needs to hint to the notification server that it wants to show some fancy ringing-notification UI of its own, and the notification server will suppress the banner
    • The server can choose not to give the token (not supported, device is locked in some more secure state, etc etc etc) and will instead show the banner in this case. Apps will need to cope with this.
    • Use-case: fancy alarm clock apps, like "sunrise alarm" apps which slowly raise the screen brightness to emulate sunrise or "solve this challenge to dismiss" alarm apps that help some people wake up by forcing them to think in the morning
  • If the device is idle when it receives a ringing alarm/timer/etc notification, it should present some full-screen UI.
    • Behaves similarly to the incoming call full-screen UI I described above
    • Except if the app tells the system is has a custom UI then activating the banner should trigger that UI (again via special xdg-activation token to put the app on the lockscreen) instead of the full-screen banner UI
  • On Samsung phones, calendar events & reminders are the same thing as an alarm (presented with the same UI, possibly in full-screen) but the only difference being that the sound is only played once and not on repeat. I quite like this: makes these notifications hard to miss especially since they're likely time-sensitive.

Text-to-speech

I haven't discussed this w/ @jonas2515 but I think it's a decent idea. Basically, some special kinds of notifications (incoming calls, ringing alarms, calendar events, emergency alerts) could benefit from having a text-to-speech readout of what they're about. I know lots of people who keep their phone across the room, and having the phone yell out "Incoming call from James Smith" every 10 seconds during the ringing is helpful to decide if it's worth getting up to pick up the phone. Here's some examples from my experiences that may be worth copying somehow:

  • It's quite nice to have alarms yell out their name or the current time (if they have no name) every 20 seconds while they ring. Hearing your alarm yell out "It is eight oh-three" if you really have to be up by 07:45 gives a jolt that just a ringtone might not
  • Calendar events ding the phone once, then yell out what they're about. Example: *Ding* "Dentist Appointment in thirty minutes"
  • Incoming calls, as mentioned, are helpful to read out who the call is from for people that like to keep their phone far away from themselves while they sleep/work/eat/etc

Apps should be required to opt-into this. That way, apps can turn on this functionality on a per-alarm or per-event basis. The notifications API will need to at least be aware of this functionality because it's ultimately in charge of the sounds coming out of the device in response to a notification

Note that this is separate from accessibility. We notably shouldn't use this TTS functionality for people using a11y tools because there's often a better pattern to handle that provided by the a11y backend

@jsparber
Copy link
Contributor

@AdrianVovk Thanks for your input

Calls

I think displaying full screen notifications fit pretty well with the direction the content type property goes in. I think rising an app on top of the lockscreen can also work but it's gonna take a while to get to that point :)

Text-to-speech

Interesting idea, apps should be able to implement that via setting a custom sound file. Obviously needs a lot of work on the app site. But in future it may be interesting to explore 👍

jsparber added a commit to jsparber/xdg-desktop-portal that referenced this issue Mar 15, 2024
This takes the discussion in
flatpak#983 and turns it
into an actual possible v2 of the notification interface.

The permission part was intentionally left out since it's tangential to
the new properties and features proposed here.
jsparber added a commit to jsparber/xdg-desktop-portal that referenced this issue Mar 15, 2024
This takes the discussion in
flatpak#983 and turns it
into an actual possible v2 of the notification interface.

The permission part was intentionally left out since it's tangential to
the new properties and features proposed here.
@Mikenux
Copy link

Mikenux commented Mar 19, 2024

Question: For themes, why are multiple icon names defined if only one is used?

@logiclrd
Copy link

logiclrd commented Jun 7, 2024

Coming to this discussion a bit late, can we consider adding support for newlines in notification body text? In the current implementation, newlines are flattened to spaces. It makes sense for a collapsed one-line view of a notification, but there are cases where some simple formatting can go a long way to improving readability. This doesn't lead directly to large notifications that use a lot of space -- I've seen mention previously of limiting expanded notification bodies to 6 lines of text and that doesn't seem unreasonable.

Where I'm coming from:

I want to display a notification along the lines of:

Upload of the following file failed:

/path/to/file

This may result in consistency issues.

With the current implementation, it's a single-line river of text:

Upload of the following file failed: /path/to/file This may result in consistency issues.

@logiclrd
Copy link

logiclrd commented Jun 9, 2024

I have just this morning learned about the existence of the "Whiteboards" project. Would it be appropriate to open an issue there describing this request?

@ilya-fedin
Copy link
Contributor

Personally I haven't explored the code but if it really strips new lines the it's going to be very annoying. I believe this should be decided on shell level while portal should relay the text just as is.

@logiclrd
Copy link

logiclrd commented Jun 9, 2024

@ilya-fedin I believe this is the offending section:

https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/messageList.js#L546-551

This control is used by the notification code, which creates a subclass called GtkNotificationDaemonNotification:

https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/notificationDaemon.js#L449-456

You can see this in action on currently-released Ubuntu versions. In one terminal, run dbus-monitor, and in another terminal, run notify-send Test 'a\nb'. This sends the literal characters \ and n to notify-send, but there's code in there that translates this to an actual newline, which you can see in the dbus-monitor output:

method call time=1717938452.236905 sender=:1.39 -> destination=:1.32 serial=70 path=/org/freedesktop/Notifications; interface=org.freedesktop.Notifications; member=Notify
   string "notify-send"
   uint32 0
   string ""
   string "Test"
   string "a
b"
   array [
   ]
   ...

But the notification which appears shows "a b", all on one line.

@ilya-fedin
Copy link
Contributor

Ah, so it's not related to this proposal?

@Mikenux
Copy link

Mikenux commented Jun 9, 2024

Whiteboards

I didn't see that here. However, in GNOME there is, but this is not a GNOME-only space here.

Your issue can be discussed at https://github.com/flatpak/xdg-desktop-portal/discussions for further discussion if necessary.

@logiclrd
Copy link

logiclrd commented Jun 9, 2024

Ah, so it's not related to this proposal?

So, I'm new to this and kind of stumbling in the dark. I initially raised my concern in a GNOME desktop specific space, and the answer was, "Well, the current implementation matches the specification."

So my next question was, "Where is this specification?" And the first answer I got to that was this issue here. I'm not in a position to judge how much that makes sense. Just, I was sent here to make my proposal about notifications. :-P

@ilya-fedin
Copy link
Contributor

I guess that was "we're allowed to do this so we're doing this" in formal language

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs discussion Needs discussion on how to implement or fix the corresponding task new api This requires adding API to an existing portal portal: notifications Notifications portal
Projects
Status: Triaged
Status: In Progress
Development

No branches or pull requests