@simon-says-build/ssb-overlay 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.d.ts +6 -0
- package/package.json +1 -1
- package/src/SsbHost.js +21 -6
- package/src/core.js +18 -1
package/index.d.ts
CHANGED
|
@@ -39,6 +39,12 @@ export function SsbHost(props: {
|
|
|
39
39
|
* Without it there is no Talk button.
|
|
40
40
|
*/
|
|
41
41
|
voice?: { Room: new (opts?: object) => any; startAudio?: () => Promise<void> | void; stopAudio?: () => Promise<void> | void };
|
|
42
|
+
/**
|
|
43
|
+
* What this build is, over what the overlay reads itself (0.7.0): sent with the
|
|
44
|
+
* push token so SSB knows what is installed. `devClient: false` makes "Ready to
|
|
45
|
+
* see" pushes say the news without a preview link this build can't open.
|
|
46
|
+
*/
|
|
47
|
+
client?: { app?: string; build?: string; ota?: string; os?: string; devClient?: boolean };
|
|
42
48
|
/** Keep the button off the home indicator / tab bar. Default {top: 60, bottom: 40}. */
|
|
43
49
|
insets?: { top?: number; bottom?: number };
|
|
44
50
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@simon-says-build/ssb-overlay",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "The SSB button inside a native app SimonSays controls: screenshot the screen, mark it, and ask SSB for a change. Renders nothing for anyone SSB does not let in.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
package/src/SsbHost.js
CHANGED
|
@@ -25,10 +25,10 @@ import {
|
|
|
25
25
|
} from 'react-native';
|
|
26
26
|
// The app's demo player (a peer): ▶ Demo hands it the demo to play in this
|
|
27
27
|
// build. An older player has no playDemo, and the button is not offered.
|
|
28
|
-
import { playDemo } from '@simon-says-build/demo-player';
|
|
28
|
+
import { playDemo, PLAYER_VERSION } from '@simon-says-build/demo-player';
|
|
29
29
|
import {
|
|
30
30
|
FAB, addPoint, clampFab, demoBanner, fabHome, isDrag, describeHost, draftsOf, fieldTop, inAppApi, namedHosts, newReply, offerOf,
|
|
31
|
-
STATE_WORD, boxItem, bundleOriginOf, elsewhereLine, workView, drawingBox, drawingMark, drawingPoint, itemRect, overlayConfig, pollEvery, SNAPSHOT_TOPIC, snapshotOf, talkLine, segmentsOf, sendBody, smallestAt, ssbLinkOf,
|
|
31
|
+
STATE_WORD, boxItem, bundleOriginOf, clientInfo, elsewhereLine, workView, drawingBox, drawingMark, drawingPoint, itemRect, overlayConfig, pollEvery, SNAPSHOT_TOPIC, snapshotOf, talkLine, segmentsOf, sendBody, smallestAt, ssbLinkOf,
|
|
32
32
|
} from './core.js';
|
|
33
33
|
|
|
34
34
|
const h = React.createElement;
|
|
@@ -73,11 +73,26 @@ const scriptURL = () => {
|
|
|
73
73
|
try { const sc = NativeModules.SourceCode; return sc?.getConstants?.()?.scriptURL ?? sc?.scriptURL ?? ''; } catch { return ''; }
|
|
74
74
|
};
|
|
75
75
|
|
|
76
|
-
|
|
76
|
+
// What this build is, for the push registration (core.js clientInfo). Each
|
|
77
|
+
// read is optional: an app without expo-application or a dev launcher still
|
|
78
|
+
// registers, it just says less.
|
|
79
|
+
function buildInfo(override) {
|
|
80
|
+
const mods = globalThis.expo?.modules || {};
|
|
81
|
+
const appMod = mods.ExpoApplication || NativeModules.ExpoApplication || {};
|
|
82
|
+
const updates = mods.ExpoUpdates || NativeModules.ExpoUpdates || {};
|
|
83
|
+
const hasLauncher = !!(mods.ExpoDevLauncher || mods.ExpoDevLauncherInternal || NativeModules.EXDevLauncher || NativeModules.EXDevLauncherInternal);
|
|
84
|
+
return clientInfo({
|
|
85
|
+
player: PLAYER_VERSION, app: appMod.nativeApplicationVersion, build: appMod.nativeBuildVersion,
|
|
86
|
+
os: `${Platform.OS} ${Platform.Version ?? ''}`.trim(),
|
|
87
|
+
runtime: typeof updates.runtimeVersion === 'string' ? updates.runtimeVersion : undefined, hasLauncher, bundleOrigin: bundleOriginOf(scriptURL()), override,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function SsbHost({ appId, backend, api, getToken, sessionKey, route, capture, storage, pushToken, notifications, voice, insets, bundle, client, children }) {
|
|
77
92
|
const config = useMemo(() => overlayConfig({ appId, backend, api }), [appId, backend, api]);
|
|
78
93
|
useSsbLinks(notifications);
|
|
79
94
|
if (!config || typeof getToken !== 'function') return children ?? null;
|
|
80
|
-
return h(Host, { config, getToken, sessionKey, route, capture, storage, pushToken, voice, bundle, insets: { ...DEFAULT_INSETS, ...(insets || {}) } }, children);
|
|
95
|
+
return h(Host, { config, getToken, sessionKey, route, capture, storage, pushToken, voice, bundle, client, insets: { ...DEFAULT_INSETS, ...(insets || {}) } }, children);
|
|
81
96
|
}
|
|
82
97
|
|
|
83
98
|
// A tapped "Ready to see" notification (functions/in-app-notify.mjs) opens
|
|
@@ -93,7 +108,7 @@ function useSsbLinks(notifications) {
|
|
|
93
108
|
}, [notifications]);
|
|
94
109
|
}
|
|
95
110
|
|
|
96
|
-
function Host({ config, getToken, sessionKey, route, capture, storage, pushToken, voice, insets, bundle, children }) {
|
|
111
|
+
function Host({ config, getToken, sessionKey, route, capture, storage, pushToken, voice, insets, bundle, client, children }) {
|
|
97
112
|
// WHICH BUILD THIS IS (docs/IN-APP-SSB.md "Ready is this build"): Ready is
|
|
98
113
|
// only what this bundle holds. `bundle` overrides (the harness); else the
|
|
99
114
|
// origin the JS came from.
|
|
@@ -147,7 +162,7 @@ function Host({ config, getToken, sessionKey, route, capture, storage, pushToken
|
|
|
147
162
|
if (!live) return;
|
|
148
163
|
setGate(g?.show ? g : null);
|
|
149
164
|
// This device, for "it's done, tap to see it" — only for someone SSB let in.
|
|
150
|
-
if (g?.show && pushToken) Promise.resolve(pushToken()).then((t) => (t ? ssb.pushToken(t, Platform.OS) : null)).catch(() => {});
|
|
165
|
+
if (g?.show && pushToken) Promise.resolve(pushToken()).then((t) => (t ? ssb.pushToken(t, Platform.OS, buildInfo(client)) : null)).catch(() => {});
|
|
151
166
|
}).catch(() => { if (live) setGate(null); });
|
|
152
167
|
return () => { live = false; };
|
|
153
168
|
}, [ssb, sessionKey]);
|
package/src/core.js
CHANGED
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
// (functions/annotate.mjs), so the shapes below are the extension's.
|
|
4
4
|
|
|
5
5
|
export const DEFAULT_API = 'https://simonsays.build';
|
|
6
|
+
// What this overlay is, said when it registers for pushes (clientInfo below).
|
|
7
|
+
// Kept equal to package.json by test/core.test.mjs.
|
|
8
|
+
export const OVERLAY_VERSION = '0.7.0';
|
|
6
9
|
export const HOST = 5;
|
|
7
10
|
export const TEXT = 6;
|
|
8
11
|
const PIN_SLOP = 12; // a drag shorter than this is a tap: a pin, not a box
|
|
@@ -41,7 +44,8 @@ export function inAppApi(config, getToken, fetchImpl = globalThis.fetch) {
|
|
|
41
44
|
send: (body) => post('/annotations', body),
|
|
42
45
|
chat: (id) => call(`/chats/${encodeURIComponent(id)}`),
|
|
43
46
|
decide: (chatId, proposalId, action, body) => post(`/chats/${encodeURIComponent(chatId)}/proposals/${encodeURIComponent(proposalId)}/${action}`, body),
|
|
44
|
-
|
|
47
|
+
// `client`: what this build is (clientInfo), so SSB knows what is installed.
|
|
48
|
+
pushToken: (token, platform, client) => post('/push-token', { token, platform, ...(client ? { client } : {}) }),
|
|
45
49
|
voice: (body) => post('/voice', body),
|
|
46
50
|
// `bundle`: where this app's JS came from (a preview's tunnel), so SSB
|
|
47
51
|
// scopes Ready to this build; undefined = the whole list, as before.
|
|
@@ -325,3 +329,16 @@ export function elsewhereLine(readyElsewhere = []) {
|
|
|
325
329
|
if (!n) return '';
|
|
326
330
|
return `${n === 1 ? '1 more change is' : `${n} more changes are`} ready in another build — open its preview to see ${n === 1 ? 'it' : 'them'}.`;
|
|
327
331
|
}
|
|
332
|
+
|
|
333
|
+
// WHAT IS INSTALLED (0.7.0, docs/IN-APP-SSB.md "What is installed"): said with
|
|
334
|
+
// the push token, so SSB knows which builds can open a "Ready to see" preview.
|
|
335
|
+
// `devClient`: a dev launcher is in the binary → true; none, and the JS came
|
|
336
|
+
// from a file (a store or release build) → false; otherwise unknown (absent),
|
|
337
|
+
// and SSB sends the link as before. The host's `client` prop outranks all of it.
|
|
338
|
+
export function clientInfo({ player, app, build, os, runtime, hasLauncher, bundleOrigin, override } = {}) {
|
|
339
|
+
const devClient = hasLauncher ? true : bundleOrigin === '' ? false : undefined;
|
|
340
|
+
// `runtime`: expo-updates' runtimeVersion, which under the fingerprint policy
|
|
341
|
+
// IS the native fingerprint a preview is gated on (docs/DEV-CLIENTS.md).
|
|
342
|
+
const out = { overlay: OVERLAY_VERSION, player, app, build, os, runtime, devClient, ...(override || {}) };
|
|
343
|
+
return Object.fromEntries(Object.entries(out).filter(([, v]) => v !== undefined && v !== null && v !== ''));
|
|
344
|
+
}
|