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

WIP: Simplify Badging API for first attempt #16

Merged
merged 4 commits into from
Dec 11, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 38 additions & 72 deletions explainer.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@ The purpose of this API is:
* To give the application a small but visible place to subtly notify the user
that there is new activity that might require their attention, without showing
a full [notification](https://notifications.spec.whatwg.org/).
* To indicate a small amount of additional information, such as an unread count
or symbol indicating the type of event.
* To indicate a small amount of additional information, such as an unread count.
* To allow the application to convey this information regardless of whether any
of the application's windows are open.

Expand All @@ -40,17 +39,17 @@ Possible areas for expansion:
proposal is just for installed apps (designed to show up in the operating
system shelf area). We could also explore icon badging on the drive-by web.
This naturally leads into...
* Provide per-window badging information. The current proposal is for a global
badge for the application, not per-window or per-tab. See
[#1](https://github.com/WICG/badging/issues/1).
* Providing per-tab and per-window badging. The current proposal is for a global badge
for the application. See [#1](https://github.com/WICG/badging/issues/1).
* Support apps that want to render a small status indicator (e.g., a music app shows ▶️
or ⏸️; a weather app shows ⛈️ or ⛅️).
* Setting the badge from a service worker (e.g. an email app updating an unread count).

Examples of sites that may use this API:

* Chat, email and social apps, to signal that new messages have arrived.
* Productivity apps, to signal that a long-running background task (such as
rendering an image or video) has completed.
* Apps that want to render a small status indicator (e.g., a music app shows ▶️
or ⏸️; a weather app shows ⛈️ or ⛅️).
* Games, to signal that a player action is required (e.g., in Chess, when it is
the player's turn).

Expand All @@ -71,56 +70,44 @@ for all new messages including group chats not directly addressed to the user.)

There is a single global badge associated with each Web
application (as defined in [Web app
manifest](https://www.w3.org/TR/appmanifest/)). At any time, the badge is set to
either:
manifest](https://www.w3.org/TR/appmanifest/)). At any time, the badge is set with:

* Nothing (the badge is "cleared"), or
* A "flag" indicating the presence of a badge with no contents, or
* A non-empty string containing a single *[grapheme
cluster](http://unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries)*
(roughly: a single Unicode character), or
* A positive integer.

The model does not allow a badge that is the empty string, a negative integer,
or the integer value 0.

The grapheme cluster allows a single character to be represented, but also
for combining characters to be combined into what the user thinks of as a single
character. Examples of grapheme clusters include:

* "a" (a single character, Latin "a")
* "நி" (a base character + combining character, Tamil "ni")
* 👩🏾‍🔬️ (emoji combination with skin tone modifier, Woman Scientist with
Medium-Dark Skin Tone)

Clients are encouraged to use integers instead of digit characters, because some
operating systems may *only* support integer badges, so using the digit
character would not display correctly. Also integers can be localized better for
the user.
The model does not allow a badge that is a negative integer, or the integer value 0
(setting the badge to 0 is equivalent to clearing the badge).

### The API

The `Badge` interface is a member object on
[`Window`](https://html.spec.whatwg.org/#the-window-object) and
[`Worker`](https://www.w3.org/TR/workers/#worker). It contains two methods:
[`Window`](https://html.spec.whatwg.org/#the-window-object). It contains two methods:

* `void set(optional USVString or long)`: Sets the associated app's badge to the
* `void set(optional long)`: Sets the associated app's badge to the
given data, or just "flag" if the argument is not given.
* `void clear()`: Sets the associated app's badge to nothing.

These can be called from either a foreground page or a service worker (in either
case, affecting the whole app, not just the current page).
These can be called from a foreground page only (calling from a service worker is being
considered for the future).

TODO: An issue is that if the methods are called from a service worker whose
scope is a parent of the web app manifest scope, it would be ambiguous which web
app is being identified. We need to take an optional scope parameter.

Example code (from in a service worker):
Example code (from the main window):

Setting an integer badge (as in an email app):
```js
Badge.set(getUnreadCount());
```

Setting and clearing a boolean flag (as in a game of chess):
```js
self.addEventListener('sync', () => {
self.Badge.set(getUnreadCount());
});
if (myTurn())
Badge.set();
else
Badge.clear();
```
fallaciousreasoning marked this conversation as resolved.
Show resolved Hide resolved

## UX treatment
Expand All @@ -145,8 +132,6 @@ self.addEventListener('sync', () => {
character but the OS only allows a number), the user agent should try the best
to map into the OS representation. This may involve:
* Saturating a number; e.g., 351 -> "99+".
* Representing a character as a number; e.g., "?" -> "1".
* Truncating a grapheme cluster; e.g., "நி" -> "ந".

## Specific operating system treatment

Expand All @@ -163,9 +148,6 @@ Requires macOS 10.5 or higher.
[here](https://eternalstorms.wordpress.com/2016/10/29/how-to-badge-an-apps-icon-in-the-dock/).
The API is
[`NSDockTile.setBadgeLabel`](https://developer.apple.com/documentation/appkit/nsdocktile/1524433-badgelabel).
* String badges are just passed to `setBadgeLabel`. All single-grapheme-cluster
strings should show without truncation. The character is shown as white text
in a red circle.
* Flag badges are passed as an empty string to `setBadgeLabel` (if that works,
otherwise pass a space character). This shows an empty red circle.
* Integer badges are saturated to 3 or 4 digits (with a "+" if overflowing), and
Expand All @@ -185,9 +167,6 @@ hence don't have access to the necessary APIs.
* Integer badges are just passed straight through into this API.
* Flag badges are passed as a fixed glyph, perhaps "attention", since I don't
think there is a way to show an empty circle.
* String badges: if the string equals a Unicode character corresponding to one
of the fixed glyphs, use that glyph (e.g., "✉" -> "newMessage"). Otherwise,
fall back to the same as the Flag badge, "attention".

This will show up on both the Taskbar and Start Menu tile.

Expand All @@ -202,11 +181,11 @@ Requires Windows 7 or higher.
* Due to the nature of being a 16x16-pixel icon, the user agent must render the
text or number into an image. It pretty much has to be 1–2 characters.
* Flag badges are just passed as a coloured circle.
* String badges are passed as a rendering of the single grapheme cluster in a
coloured circle.
* Integer badges are rendered as the number, if a single digit, or "+", if
greater than 9.

Note: This API only allows badging on a currently open window.
fallaciousreasoning marked this conversation as resolved.
Show resolved Hide resolved

### Android

Requires Android 8.0 (Oreo) or higher.
Expand All @@ -231,8 +210,6 @@ application icons.
[`UIApplication.applicationIconBadgeNumber`](https://developer.apple.com/documentation/uikit/uiapplication/1622918-applicationiconbadgenumber),
which lets you set a positive integer only.
* Integer badges are passed directly to the host API.
* Strings that are numeric digits are converted to a number and passed to the
host API.
* Flag badges and strings other than digits are just represented by the number
"1".

Expand All @@ -255,43 +232,32 @@ Requires Ubuntu (no general API for Linux).
Thus, a fallback option for platforms that do not support arbitrary characters
(e.g., choose whether to show a number, or nothing) may be necessary.

## FAQ

### What data types are supported in different operating systems?
fallaciousreasoning marked this conversation as resolved.
Show resolved Hide resolved
### What data types are supported in different operating systems?

See above.

### Could the API take a fallback type?

The proposal is: what if instead of just taking *one of* the string or integer,
we allow sites to pass both, with an order of preference. This way, you could
supply a string, but if strings aren't supported, fall back to a given number,
or vice versa.
### Why limit support to just an integer? What about other characters?

This is something we're considering. My concern is that it makes the API too
complex, where practically it isn't required (e.g., I believe all major
platforms support at least one character strings).
It isn't a technical limitation, it's an attempt to keep behavior as consistent as possible
on different host platforms (UWP only supports a set of symbols, while iOS, Android
and Ubuntu don't support them at all).

### Why limit the support to a single grapheme cluster? Is there a technical limitation?
fallaciousreasoning marked this conversation as resolved.
Show resolved Hide resolved
Limiting support to integers makes behavior more predictable, though we are considering
whether it might be worth adding support for other characters or symbols in future.

It isn't a technical limitation. It's an attempt to keep the behaviour as
consistent as possible between different host platforms.
### Why isn't this API available from a Service Worker?

We could say "provide an arbitrarily long string, and we'll truncate it", but
having some platforms truncate to just 1 or 2 characters, and others showing a
bit more text, makes it too unpredictable. Limiting to precisely one character
levels the playing field.
Ideally, it would be, and we're considering this for a future version of this API.
However, the API will require some more thought, as there can be multiple apps installed
for a single service worker, so we would need some way of specifying which one should
be badged.

### Is there an upper limit on the size of the integer? And if so, what's the behavior if that limit is reached?

There is no upper limit (besides 2<sup>31</sup>). However, each user agent is
free to impose a limit and silently saturate the value (e.g., display all values
above 99 as "99+").

This is different to the string, since truncating a string may change or destroy
its meaning, whereas the integer always has the semantics of counting, and thus
saturating the integer still preserves most of its meaning (i.e., "lots").

### Are you concerned about apps perpetually showing a large unread count?

Yes. If users habitually leave mail or chats unread, and mail or chat apps
Expand Down