From 9d02a5b2304c63deec4fcb972f91ec562025de95 Mon Sep 17 00:00:00 2001 From: bjoern Date: Tue, 26 Nov 2024 13:19:26 +0100 Subject: [PATCH] docs: webxdc notify & privacy preserving selfAddr (#90) Add API for notifications and refined `selfAddr` and based on discussions with r10s, adb, hocuri, link2xt and others. --- src-docs/faq/compat.md | 2 + src-docs/spec/format.md | 7 +-- src-docs/spec/selfAddr_and_selfName.md | 73 +++++++++++++++++++++----- src-docs/spec/sendUpdate.md | 73 +++++++++++++++++--------- src-docs/spec/setUpdateListener.md | 3 ++ 5 files changed, 119 insertions(+), 39 deletions(-) diff --git a/src-docs/faq/compat.md b/src-docs/faq/compat.md index 7d0cb8c..667acda 100644 --- a/src-docs/faq/compat.md +++ b/src-docs/faq/compat.md @@ -8,6 +8,8 @@ Webxdc apps run in a restricted environment, but the following practices are per - `localStorage`, `sessionStorage`, `indexedDB` - `visibilitychange` events - `window.navigator.language` +- `window.location.href` but you can not specify or assume anything + about the scheme or domain part of the url. - internal links, such as `` - `mailto` links, such as `` - `` is useful especially as webviews from different platforms have different defaults diff --git a/src-docs/spec/format.md b/src-docs/spec/format.md index 63a6df2..5cdfda3 100644 --- a/src-docs/spec/format.md +++ b/src-docs/spec/format.md @@ -7,13 +7,14 @@ - the ZIP-file MUST contain at least the file `index.html` - the ZIP-file MAY contain a `manifest.toml` and `icon.png` or `icon.jpg` files -- if the webxdc app is started, `index.html` MUST be opened in a [restricted webview](./messenger.md#webview-constraints-for-running-apps) that only allows accessing +- if the webxdc app is started, `index.html` MUST be opened in a + [restricted webview](../faq/compat.html) that only allows accessing resources from the ZIP-file. ### The manifest.toml File If the ZIP-file contains a `manifest.toml` in its root directory, -the following basic information MUST be read from it: +the following basic information MUST be read from it: ```toml name = "My App Name" @@ -27,7 +28,7 @@ source_code_url = "https://example.org/orga/repo" Messenger implementors may make the url accessible via a "Help" menu in the webxdc window. -### Icon Files +### Icon Files If the ZIP-root contains an `icon.png` or `icon.jpg`, these files are used as the icon for the webxdc. diff --git a/src-docs/spec/selfAddr_and_selfName.md b/src-docs/spec/selfAddr_and_selfName.md index 84874d4..c5eacab 100644 --- a/src-docs/spec/selfAddr_and_selfName.md +++ b/src-docs/spec/selfAddr_and_selfName.md @@ -1,27 +1,76 @@ # selfAddr & selfName +## selfName + +```js +window.webxdc.selfName +``` + +`selfName` is the nick or display name for the user +which can be displayed in the user interface of the webxdc application. + + ## selfAddr ```js window.webxdc.selfAddr ``` -A string with an unique ID identifying the user in the current webxdc. -Every user of an webxdc must get a different ID -and that ID must be the same if the webxdc is started again later for the same user. -The same user in different webxdc, however, may have different IDs. +`selfAddr` is a unique string within a webxdc application that -Especially useful if you want to differentiate between different peers - -just send the ID along with the payload, -and, if needed, compare the payload addresses against `selfAddr` later on. +- has no meaning outside the webxdc app, -## selfName +- can be used in other webxdc APIs, + +- should not be shown in the user interface of the webxdc application, + +- is identical across multiple invocations of the same webxdc application, + +- is identical on multiple devices of the user using the same webxdc application. + +- is not linkable to addresses in other webxdc apps: + even if a web app manipulates users to share addresses via copy+paste with another web app, + addresses between the two web apps can not be correlated. + + +## Example using selfAddr and selfName + +Here is a simple chat app that sends out a reply using the display names +but uses the addresses for notifications. ```js -window.webxdc.selfName -``` -Name of the current account, as defined in settings. -If empty, this defaults to the peer's address. +// Receive a message from anyone in the chat +let users = new Set(); + +setUpdateListener((update) => { + const prompt = `${update.payload.senderName} (${update.payload.senderAddr}):`; + users.add(update.payload.senderAddr); + console.log(`${prompt} ${update.message}`); +}) + +// start some user interface which calls the following function for +// message sending + +sendMessage(text) => { + let payload = { + senderAddr: webxdc.selfAddr, + senderName: webxdc.selfName, + message: text + }; + + // notify all users who ever sent a message in the chat app + let notify = {}; + for (const addr of users) { + notify[addr] = `new message from ${webxdc.selfName}`; + } + + sendUpdate({ + payload: payload, + notify: notify + }) +}) +``` +[`sendUpdate()`]: ./sendUpdate.html diff --git a/src-docs/spec/sendUpdate.md b/src-docs/spec/sendUpdate.md index 84e45c8..57bef80 100644 --- a/src-docs/spec/sendUpdate.md +++ b/src-docs/spec/sendUpdate.md @@ -6,34 +6,60 @@ window.webxdc.sendUpdate(update); Send an update to all peers. -- `update`: an object with the following properties: - - `update.payload`: string, number, boolean, array, object or `null`. - MUST NOT be `undefined`. - Everything that is not JSON serializable will be skipped, - this especially affects Binary data buffers as used in `File`, `Blob`, `Int*Array` etc.; - if needed, use eg. base64. - - `update.info`: optional, short, informational message that will be added to the chat, - e.g. "Alice voted" or "Bob scored 123 in MyGame". - Do not add linebreaks; implementations will truncate the text at about 50 characters or less. - If there are series of info messages, older ones may be dropped. - use this option sparingly to not spam the chat. - - `update.document`: optional, name of the document in edit - (eg. the title of a poll or the name of a text in an editor) - Implementations show the document name e.g. beside the app icon or in the title bar. - MUST NOT be used if the webxdc does not create documents, e.g. in games. - Do not add linebreaks; implementations will truncate the text at about 20 characters or less. - - `update.summary`: optional, short text, shown beside the app icon; - it is recommended to use some aggregated value, e.g. "8 votes", "Highscore: 123". - Do not add linebreaks; implementations will truncate the text at about 20 characters or less. - All peers, including the sending one, will receive the update by the callback given to [`setUpdateListener()`](./setUpdateListener.html). There are situations where the user cannot send messages to a chat, e.g. if the webxdc instance comes as a contact request or if the user has left a group. -In these cases, you can still call `sendUpdate()`, -however, the update won't be sent to other peers -and you won't get the update by [`setUpdateListener()`](./setUpdateListener.html). +In these cases, an app can still call `sendUpdate()`, +but the update won't be sent to other peers +and it will not be passed to [`setUpdateListener()`](./setUpdateListener.html). + +The `update` object has the following properties: + +- `update.payload`: string, number, boolean, array, object or `null`. + MUST NOT be `undefined`. + Everything that is not JSON serializable will be skipped, + this especially affects Binary data buffers as used in `File`, `Blob`, `Int*Array` etc.; + if needed, use eg. base64. + +- `update.info`: optional, short, informational message that will be added to the chat, + e.g. "Alice voted" or "Bob scored 123 in MyGame". + Do not add linebreaks; implementations will truncate the text at about 50 characters or less. + If there are series of info messages, older ones may be dropped. + use this option sparingly to not spam the chat. + +- `update.notify`: optional dictionary mapping an [address](./selfAddr_and_selfName.md) + to a text that should be shown as a user-visible notification to the addressed user. + The optional special key "\*" serves as a catch-all address + whose text shall be notified if `selfAddr` is not contained in the dictionary. + +- `update.href`: optional string that specifies a relative URL + (for example `index.html#about`) + When a receiver starts the webxdc app based on the update object + the app will be navigated to the `href` location with the application root url prepended. + +- `update.document`: optional, name of the document in edit + (eg. the title of a poll or the name of a text in an editor) + mplementations show the document name e.g. beside the app icon or in the title bar. + MUST NOT be used if the webxdc does not create documents, e.g. in games. + Do not add linebreaks; implementations will truncate the text at about 20 characters or less. + +- `update.summary`: optional, short text, shown beside the app icon; + it is recommended to use some aggregated value, e.g. "8 votes", "Highscore: 123". + Do not add linebreaks; implementations will truncate the text + at about 20 characters or less. + + +## Using `info` and `href` to provide navigation + +If a user clicks on an `info` message that has a `href` specified +then the webxdc app will be started and navigate to the specified location. + +For example, a calendar app can send an update to add a new calendar event. +The info would be shown in the chat and if the user taps or clicks on it +the app is started (if it is not running already) and navigates +to the new href which can for example directly show the day and highlight the added event. ## Messaging layer limits for sendUpdate @@ -69,4 +95,3 @@ updates might get queued for a longer time than just the `sendUpdateInterval`. Moreover, an editor can also inspect `sendUpdateMaxSize` and send oversized updates in smaller chunks and recombine them on the receiving side. - diff --git a/src-docs/spec/setUpdateListener.md b/src-docs/spec/setUpdateListener.md index ff5a063..fabf2f7 100644 --- a/src-docs/spec/setUpdateListener.md +++ b/src-docs/spec/setUpdateListener.md @@ -9,6 +9,9 @@ sent by [`sendUpdate()`]. The callback is called for updates sent by you or othe The `serial` specifies the last serial that you know about (defaults to 0). The returned promise resolves when the listener has processed all the update messages known at the time when `setUpdateListener` was called. + +## Application update object + Each `update` which is passed to the callback comes with the following properties: - `update.payload`: equals the payload given to [`sendUpdate()`]