Scoping Badges is Complicated
Closed this issue · 21 comments
Likely related to #5
Currently, we are proposing that each badge apply to a scope. However, scopes can be complicated and unwieldy. For example, clearing a badge at one scope could cause it to acquire the badge from another, less specific scope, while setting the badge at a scope might affect a number of pages.
There are a number of constraints that lead us to the current proposal:
- It must be possible to apply different badges to different pages.
This enables some pages to display a notification count, while other pages might display a status (such as your PR is ready to merge). - It must be possible for pages to set the badge for pages above them.
This enables/app/page1
to set a badge for/app
which would be displayed in the operating system when installed. - Ideally, it would be possible to badge a number of pages at once.
This would allow all tabs of a social networking site to display the same notification count.
This problem feels similar to what we're doing with Service Worker Registration Scope and Web App Navigation Scope.
That said, we're open to alternatives that allow the problem to be solved in a less complicated manner.
Also related to #1
It must be possible for pages to set the badge for pages above them.
2b. It must be possible for a service worker to set the badge for pages in its scope (or just for its entire scope).
On the service worker side, maybe it just applies to installed web apps? Otherwise, we get into the managing scopes problem again.
So, if app is installed and there are not clients, self.Badge.set()
sets at the OS level... otherwise, if there are clients, the SW can ping ping a client over postMessage()
or BroadcastChannel
to set a badge.
I think regardless of what we do, we'll need some kind of scope management. As pointed out in #5, multiple web apps can be controlled by a single service worker.
As we're trying to design an API that works with two things that have scopes (ServiceWorkers, WebApp scope), so it doesn't seem unreasonable to me that our API should also be concerned with scopes.
Discussed with @fallaciousreasoning.
Initially I was receptive to the separate SW (setting app badge) and foreground (setting just the badge for that client). But the more I think about it, it seems to counteract the philosophy I thought we were trying to have with doing both tab and app badging in the same API. Which is that developers shouldn't care about whether they're setting an app badge or a tab badge, they should just say "I want this badge to apply to these pages" and then UAs can interpret that for either app badges, tab badges, or both. In this light, Jay's scopes proposal (while complex) seems the best.
Imagine that Chrome takes the position of "we're only going to implement app badges" and Firefox "we're only going to implement tab badges". Now if a developer using Chrome only decides to implement app badges, under this proposed separate APIs, the badge will only show up in apps installed in Chrome, and never in Firefox. Similarly, a developer who badges all pages in their app will show the badge in Firefox, but never in Chrome even if the app is installed.
Whereas with the combined proposal (with scopes), the developer sets a badge for a given set of URLs, possibly just "/", and then the same badge will show up in Chrome on the app icon, and Firefox on all the tab icons. Seems to be the most webby approach: developers set a semantic intention ("the following badge information is relevant on this set of pages") and the UA interprets that to display the information to the user with whatever UI they think is best.
I’d still like to be 100% sure that developers can’t manage scope on their own for tabs before we think about adding anything. For installed web applications, scope makes sense - but for regular web pages, I’m still not sure we need to do anything beyond badging a tab: specially if a developer then has the capability to add other badges through cross document messages as needed.
@marcoscaceres I am having a hard time understanding your comment.
For installed web applications, scope makes sense - but for regular web pages, I’m still not sure we need to do anything beyond badging a tab
But then how do we do badging for installed web applications? I'm trying to avoid a situation where the developer has to treat app badging and tab badging separately (such that if they only bother to do one of those, they don't get the other). I would rather a developer sets "a badge" and gets both for free (see my previous comment).
But then how do we do badging for installed web applications?
The manifest scope applies. But the developer's working assumption is that the browser always clears on navigation (continue to treat installation as progressive enhancement - not a different mode). The UA may also have cleared it randomly, for whatever reason.
I'm trying to avoid a situation where the developer has to treat app badging and tab badging separately (such that if they only bother to do one of those, they don't get the other). I would rather a developer sets "a badge" and gets both for free (see my previous comment).
Yes, I share that goal too - but I guess this is where opinions vary on how this is solved: in my mind (and hopefully in the developer's mind), they are the same: It just happens that the when you navigate a tab or leave the scope, the browser clears the badge. And in an installed app, it persists if the app stay in scope (not observable)... but clears if the app leaves the scope. It the app returns to being a scope, the developer needs to set()
again.
Managing on a per tab basis is still fine, even in a installed app... a developer just always does:
Navigates to page1.html -> Badge.set(1);
Navigates to page2.html -> Badge.set(1);
Navigates to page3.html -> outside scope - clears.
Navigates to page2.html -> Badge.set(1);
In an installed app, the badge won't change, because it's already set to 1. In a tab (or outside the scope), the badge still gets set()
.
I don't think we require the UA to always clear scope when navigating away, we just want developers to act as if it does (and set the badges on each navigation). Each user agent can choose to handle this the way it thinks is best.
I don't think we require the UA to always clear scope when navigating away, we just want developers to act as if it does (and set the badges on each navigation). Each user agent can choose to handle this the way it thinks is best.
Sorry, do you mean, "clear a badge" instead of "clear scope" above?
If yes (it doesn't clear the badge on navigation), then I think it matters: If a developer targets a browser the doesn't clear the badge, then they will be surprised if they jump onto another browser that does clear the badge on navigation.
Sorry, do you mean, "clear a badge" instead of "clear scope" above?
Whoops, yes I do.
If yes (it doesn't clear the badge on navigation), then I think it matters: If a developer targets a browser the doesn't clear the badge, then they will be surprised if they jump onto another browser that does clear the badge on navigation.
Perhaps we recommend they SHOULD clear a badge on navigating away then? That way browsers will do it in most scenarios (forcing developers to cater to it), while leaving room for browsers to not clear the value where it doesn't make sense (which is likely UA specific).
Perhaps we recommend they SHOULD clear a badge on navigating away then?... but leaves room for browsers to not clear the value where it doesn't make sense (which is likely UA specific).
Ok, but let's not work on hypotheticals: If it looks like there are valid UA/Chrome specific reasons for it not to clear on navigation of the tab, its likely Firefox will hit those too. Are you thinking of something in particular? I've not given this much thought, but I'd be open to it.
In particular, I see it being useful when there are longer lived places to display the badge than the favicon. The two examples that spring to mind are
- OS specific contexts (taskbar, homescreen, dock, startmenu)
- Bookmarks
Thinking a bit more about it, perhaps what we actually want has nothing to do with navigations. Instead, the user agent should clear a badge when there is no place it is being displayed, and no place it might be displayed (e.g. we should keep the badge for /
around when we're showing a badge for /page
, as we should display the badge for /
if we clear the badge for /page
). This sounds really complicated though.
/ around when we're showing a badge for /page
This makes assumptions about conceptual scopes of web applications which only the developer can know about. Consider: i have a Github folder called “playground” that has a bunch of different “apps” and experiments... some are in sub folders, others are at the base directory (it’s all garbage, just to illustrate my point):
https://github.com/marcoscaceres/playground?files=1
As I only know what delineates what constitutes the scope of the app, I might as well just keep setting the badge on load. But keeping a badge from “/“ doesn’t make sense in “/calculator/“. They are different apps.
I think the badge from /
being displayed for /calculator
is more related to #42, around the behavior of clear. I agree that it's not clear (hah!) what we want to do here.
I was just having a look at what the current state of the art in JS land is like for changing the favicon. There's a really cool library favico.js which let's you set numerical badges with lot's of fancy animations and configuration (you can even play videos in the favicon!).
They've got some demos which honestly look really cool.
On the per-tab badging front, I'm kind of concerned that we would be making an API strictly less useful than this one they offer (we could only badge numbers, we won't do fancy animations). What would be the incentive to use our API (other than, presumably, a slightly smaller size).
That said, there definitely seem to be lightweight options. I don't know baking a (less powerful) API into the browser is the right approach here.
Library | Size | Github |
---|---|---|
FavIco.js | 8k | https://github.com/ejci/favico.js/ |
Tinycon | 1.5k | https://github.com/tommoor/tinycon |
Notify Better | 8.5k | https://github.com/peachananr/notify-better |
Favicon.js | 0.8k | https://github.com/Dlom/favicon.js |
BadgableFavicon | 3k | https://github.com/fallaciousreasoning/badgable-favicon |
Note: I made the last one the other day, it's like a worse version of FavIco.js
What would be the incentive to use our API?
Accessibility, consistency, user control.
Don't we get a limited accessibility story through updating the title?
E.g. (1 unread message) Your Email
don't we get a limited accessibility story through updating the title?
yes, but it's somewhat ambiguous: is the title reflecting the favicon or it reflecting the badge aspect? The semantics of the Badge.set()
are quite clear. It also disassociates the badge from the favicon - allowing them both to be treated/presented independently.
Note: When we've made the changes in #55 this will no longer be relevant.
Scope has been removed.