This explainer is for the Shortcut API
Some platforms like Windows and Android have ways to add menu items to the app launcher icon itself, here after called shortcuts. These can perform certain app actions. On Android in addition, you can drag these shortcuts to the homescreen.
The shortcut list (aka menu) contains a mixture of static and dynamic shortcuts and has a limit which may be different per platform or per launcher used. The amount of shortcuts on the homescreen is not limited so though the shortcut list may change overtime, existing shortcuts on the homescreen can still be updated (say change icon) though not removed.
The shortcuts are quite useful as /shortcuts/ to common actions, like starting a chat with the person you chat with the most, or say launch the web app to a specific place inside the app (deep link).
These are becoming quite popular, like for instance in GMaps you can add a shortcut to your contributions page.
The ShortcutInfo dictionary is reusing name, short_name and icons from the manifest specification and can itself be embedded in the manifest.json inside the shortcuts
member which takes an array of ShortcutInfo
.
dictionary ShortcutInfo {
DOMString id;
DOMString name;
DOMString short_name;
sequence icons;
dictionary data;
}
partial interface Navigator {
readonly attribute int maxVisibleShortcuts;
sequence<ShortcutInfo> getManifestShortcuts();
sequence<ShortcutInfo> getDynamicShortcuts();
Promise addShortcut(ShortcutInfo);
Promise removeShortcut(ShortcutInfo);
Promise setShortcut(ShortcutInfo);
Promise requestPinShortcut(ShortcutInfo);
};
[Constructor(DOMString type, optional ShortcutEventInit eventInitDict), Exposed=ServiceWorker]
Interface ShortcutEvent : ExtendableEvent {
readonly attribute DOMString id;
readonly attribute any data;
};
{
"name": "Cool Email",
"start_url": "https://coolemail.com",
…
"shortcuts": [{
"name": "Email Mom",
"id": "send-email",
"data": { "email": "[email protected]" },
"icons": [{
"src": "icon/hd_hi.svg",
"sizes": "any"
}]
}]
}
Similarly to the Push API, when shortcuts are clicked, the shortcutclick
event is fired in the Service Worker.
At that point you have access to the id and data of the shortcut and can easily access any existing open window for the PWA or open the app using openWindow
. postMessage
can be used to talk to the open instance.
This is quite flexible. Using a Service Worker, the app can load URLs, execute JavaScript and communicate with a running instance of the PWA, even without giving it focus.
self.addEventListener('shortcutclick', function(event) {
console.log('[Service Worker] Shortcut click Received.');
if (event.id != "send-email) {
return;
}
async function getWindow() {
const client = await clients.matchAll(options).then(function(clientList) {
if (clients.length > 0) {
return clients[0];
}
return clients.openWindow('https://inbox.coolemail.com');
});
client.postMessage({ action: event.id, data: event.data });
await client.focus();
}
event.waitUntil(getWindow());
});
navigator.requestPinShortcut({
name: "Email Mom",
id: "send-email",
data: { email: "[email protected]" },
icons: [{
src: "icon/hd_hi.svg",
sizes: "any"
}]
}).then(info => {
console.log(`Added ${info.title} shortcut`);
})
As it is quite a common case to just load different URLs (deep links into the app), it makes sense to add start_url
to the ShortcutInfo
. Questions is how to handle that. Without Service Worker it could just load the URL direclty.
- Should
shortcutclick
be dispatched when astart_url
is available as the URL might already be part offetch
event if in scope?
https://developer.android.com/guide/topics/ui/shortcuts.html https://developer.android.com/preview/features/pinning-shortcuts-widgets.html https://docs.microsoft.com/en-us/uwp/api/windows.ui.startscreen.jumplist https://github.com/android/platform_frameworks_base/blob/master/core/java/android/content/pm/ShortcutManager.java https://developer.android.com/reference/android/content/pm/ShortcutManager.html https://developer.android.com/reference/android/content/pm/ShortcutInfo.html https://developer.apple.com/ios/3d-touch/ https://developer.apple.com/documentation/uikit/uiapplicationshortcutitem https://electron.atom.io/docs/tutorial/desktop-environment-integration/
Anyone, how to get notified when people add comments here?
@PaulKinlan: You are right, we should not have Manifest in the name, and a property seems much better.
Regarding addShortCut/removeShortCut. As far as I understand on Android, these persists. I assume they are written to some kind of Android settings.
Currently no fallback to meta tags. I think we can require manifest for this advanced feature - the idea was never to make the manifest 100% optional on the web platform.
@justinribeiro The idea was never that they were queried out of the manifest itself, but out of the system. So if Android adds the shortcuts from the manifest (potentially ignoring stuff it doesn't understand), the queried values would come from the system itself. And that might even differ depending on the launcher (that is how I understand that Android works), ie. one launcher might only show 3 items, and another might show up to 10.
I am not sure the disableShortcuts it necessary. You can disable old URLs in your service worker and redirect to a 404 or similar error page. That seems to work just like it does for native apps.