@timmo001/groundwork-mobile 0.0.0 → 0.14.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/package.json +5 -4
- package/src/bridge.ts +37 -1
- package/src/view.ts +47 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@timmo001/groundwork-mobile",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "The page side of Groundwork's Android shell: the app config, the typed bridge to the shell, and a fallback to the PWA outside it",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -16,7 +16,8 @@
|
|
|
16
16
|
"LICENSE"
|
|
17
17
|
],
|
|
18
18
|
"publishConfig": {
|
|
19
|
-
"access": "public"
|
|
19
|
+
"access": "public",
|
|
20
|
+
"provenance": true
|
|
20
21
|
},
|
|
21
22
|
"repository": {
|
|
22
23
|
"type": "git",
|
|
@@ -32,8 +33,8 @@
|
|
|
32
33
|
"format:check": "prettier --check ."
|
|
33
34
|
},
|
|
34
35
|
"dependencies": {
|
|
35
|
-
"@timmo001/groundwork-pwa": "0.
|
|
36
|
-
"@timmo001/groundwork-tokens": "0.
|
|
36
|
+
"@timmo001/groundwork-pwa": "0.14.0",
|
|
37
|
+
"@timmo001/groundwork-tokens": "0.14.0",
|
|
37
38
|
"effect": "4.1.2"
|
|
38
39
|
},
|
|
39
40
|
"devDependencies": {
|
package/src/bridge.ts
CHANGED
|
@@ -26,13 +26,43 @@ export const Notice = Schema.Struct({
|
|
|
26
26
|
|
|
27
27
|
export interface Notice extends Schema.Schema.Type<typeof Notice> {}
|
|
28
28
|
|
|
29
|
-
/**
|
|
29
|
+
/**
|
|
30
|
+
* A share from another app, the same shape the PWA's share target gives,
|
|
31
|
+
* plus the id of the sharing shortcut it was sent to, in the shell.
|
|
32
|
+
*/
|
|
30
33
|
export const ShellShare = Schema.Struct({
|
|
31
34
|
title: Schema.optionalKey(Schema.String),
|
|
32
35
|
text: Schema.optionalKey(Schema.String),
|
|
33
36
|
url: Schema.optionalKey(Schema.String),
|
|
37
|
+
shortcutId: Schema.optionalKey(Schema.String),
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
export interface ShellShare extends Schema.Schema.Type<typeof ShellShare> {}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* A launcher shortcut that opens `url` as a deep link: on a long press of
|
|
44
|
+
* the app's icon, pinned to the home screen, and with `share` in the share
|
|
45
|
+
* sheet's direct row too.
|
|
46
|
+
*/
|
|
47
|
+
export const Shortcut = Schema.Struct({
|
|
48
|
+
/** Stays the same across updates, so a pinned one keeps working. */
|
|
49
|
+
id: Schema.String,
|
|
50
|
+
label: Schema.String,
|
|
51
|
+
/** Shown where there's room, such as in the long-press menu. */
|
|
52
|
+
longLabel: Schema.optionalKey(Schema.String),
|
|
53
|
+
/** An allowed origin's page, or the app's own scheme. */
|
|
54
|
+
url: Schema.String,
|
|
55
|
+
/** An SVG path on a 24 unit grid, such as a Material Design Icon. */
|
|
56
|
+
icon: Schema.optionalKey(Schema.String),
|
|
57
|
+
/**
|
|
58
|
+
* A sharing shortcut, whose shares carry its id as `shortcutId`. It shows
|
|
59
|
+
* on a long press as well, so list it after the ones meant for that.
|
|
60
|
+
*/
|
|
61
|
+
share: Schema.optionalKey(Schema.Boolean),
|
|
34
62
|
});
|
|
35
63
|
|
|
64
|
+
export interface Shortcut extends Schema.Schema.Type<typeof Shortcut> {}
|
|
65
|
+
|
|
36
66
|
export const DeepLink = Schema.Struct({ url: Schema.String });
|
|
37
67
|
|
|
38
68
|
export interface DeepLink extends Schema.Schema.Type<typeof DeepLink> {}
|
|
@@ -145,6 +175,12 @@ export const mobileRequests = {
|
|
|
145
175
|
discoverServices: Schema.Array(DiscoveredService),
|
|
146
176
|
/** Scans a QR code with the camera: its text, or `null` when cancelled. */
|
|
147
177
|
scanQr: Schema.NullOr(Schema.String),
|
|
178
|
+
/** Replaces the dynamic shortcuts: how many the launcher took. */
|
|
179
|
+
setShortcuts: Schema.Number,
|
|
180
|
+
/** Asks the launcher to pin a shortcut: false where it can't. */
|
|
181
|
+
pinShortcut: Schema.Boolean,
|
|
182
|
+
/** Removes shortcuts, greying out pinned ones. */
|
|
183
|
+
disableShortcuts: Schema.Boolean,
|
|
148
184
|
} as const;
|
|
149
185
|
|
|
150
186
|
/** The shell's messages, each with the schema its data is read with. */
|
package/src/view.ts
CHANGED
|
@@ -23,7 +23,6 @@ import {
|
|
|
23
23
|
unsubscribePush,
|
|
24
24
|
type Pwa,
|
|
25
25
|
type PwaConfig,
|
|
26
|
-
type Share,
|
|
27
26
|
} from "@timmo001/groundwork-pwa/view";
|
|
28
27
|
import { Option, Schema } from "effect";
|
|
29
28
|
|
|
@@ -35,6 +34,7 @@ import {
|
|
|
35
34
|
mobileRequests,
|
|
36
35
|
Notice,
|
|
37
36
|
ShellShare,
|
|
37
|
+
Shortcut,
|
|
38
38
|
type BridgeMessage,
|
|
39
39
|
type DiscoveredService,
|
|
40
40
|
type DiscoveryMode,
|
|
@@ -77,8 +77,11 @@ export interface MobilePushOptions {
|
|
|
77
77
|
export interface ConnectMobileOptions {
|
|
78
78
|
/** The PWA config, for the floor's service worker, install and share target. */
|
|
79
79
|
readonly pwa?: PwaConfig;
|
|
80
|
-
/**
|
|
81
|
-
|
|
80
|
+
/**
|
|
81
|
+
* Called with each share, from the shell or the share target, with the
|
|
82
|
+
* sharing shortcut's id when it was sent to one.
|
|
83
|
+
*/
|
|
84
|
+
readonly onShare?: (share: ShellShare) => void;
|
|
82
85
|
/** Called with each deep link the shell opens the app with. */
|
|
83
86
|
readonly onDeepLink?: (url: string) => void;
|
|
84
87
|
/**
|
|
@@ -146,6 +149,25 @@ export interface Mobile {
|
|
|
146
149
|
readonly scanQr: (options?: {
|
|
147
150
|
readonly hint?: string;
|
|
148
151
|
}) => Promise<string | undefined>;
|
|
152
|
+
/**
|
|
153
|
+
* Replaces the dynamic shortcuts with these, in order, and answers how
|
|
154
|
+
* many the launcher took. Answers 0 outside the shell, where the PWA
|
|
155
|
+
* manifest's `shortcuts` give the long-press menu.
|
|
156
|
+
*/
|
|
157
|
+
readonly setShortcuts: (shortcuts: readonly Shortcut[]) => Promise<number>;
|
|
158
|
+
/**
|
|
159
|
+
* Asks the launcher to pin a shortcut to the home screen. False where it
|
|
160
|
+
* can't, and outside the shell.
|
|
161
|
+
*/
|
|
162
|
+
readonly pinShortcut: (shortcut: Shortcut) => Promise<boolean>;
|
|
163
|
+
/**
|
|
164
|
+
* Removes the shortcuts with these ids. Pinned ones stay, greyed out,
|
|
165
|
+
* showing `message` when tapped. Does nothing outside the shell.
|
|
166
|
+
*/
|
|
167
|
+
readonly disableShortcuts: (
|
|
168
|
+
ids: readonly string[],
|
|
169
|
+
message?: string,
|
|
170
|
+
) => Promise<void>;
|
|
149
171
|
}
|
|
150
172
|
|
|
151
173
|
interface Waiting {
|
|
@@ -171,13 +193,18 @@ const read = <S extends Schema.ConstraintDecoder<unknown>>(
|
|
|
171
193
|
|
|
172
194
|
const noticeJson = Schema.encodeSync(Schema.toCodecJson(Notice));
|
|
173
195
|
|
|
196
|
+
const shortcutJson = Schema.encodeSync(Schema.toCodecJson(Shortcut));
|
|
197
|
+
|
|
198
|
+
/** The `disableShortcuts` request's params. */
|
|
199
|
+
type DisableParams = { ids: string[]; message?: string };
|
|
200
|
+
|
|
174
201
|
const pushParams = ({ service, client, headers = {} }: MobilePushOptions) => ({
|
|
175
202
|
service,
|
|
176
203
|
client: { id: client.id, name: client.name, platform: client.platform },
|
|
177
204
|
headers: { ...headers },
|
|
178
205
|
});
|
|
179
206
|
|
|
180
|
-
const dispatchShare = (share:
|
|
207
|
+
const dispatchShare = (share: ShellShare) =>
|
|
181
208
|
window.dispatchEvent(new CustomEvent("gw-share", { detail: share }));
|
|
182
209
|
|
|
183
210
|
const dispatchDeepLink = (link: DeepLink) =>
|
|
@@ -240,6 +267,9 @@ const connectFloor = (
|
|
|
240
267
|
scanQr: async () => {
|
|
241
268
|
throw new Error("The QR scanner needs the Android shell");
|
|
242
269
|
},
|
|
270
|
+
setShortcuts: async () => 0,
|
|
271
|
+
pinShortcut: async () => false,
|
|
272
|
+
disableShortcuts: async () => {},
|
|
243
273
|
};
|
|
244
274
|
};
|
|
245
275
|
|
|
@@ -395,5 +425,18 @@ export const connectMobile = async (
|
|
|
395
425
|
|
|
396
426
|
return (await call("scanQr", mobileRequests.scanQr, params)) ?? undefined;
|
|
397
427
|
},
|
|
428
|
+
setShortcuts: (shortcuts) =>
|
|
429
|
+
call("setShortcuts", mobileRequests.setShortcuts, {
|
|
430
|
+
shortcuts: shortcuts.map((shortcut) => shortcutJson(shortcut)),
|
|
431
|
+
}),
|
|
432
|
+
pinShortcut: (shortcut) =>
|
|
433
|
+
call("pinShortcut", mobileRequests.pinShortcut, shortcutJson(shortcut)),
|
|
434
|
+
disableShortcuts: async (ids, message) => {
|
|
435
|
+
const params: DisableParams = { ids: [...ids] };
|
|
436
|
+
|
|
437
|
+
if (message !== undefined) params["message"] = message;
|
|
438
|
+
|
|
439
|
+
await call("disableShortcuts", mobileRequests.disableShortcuts, params);
|
|
440
|
+
},
|
|
398
441
|
};
|
|
399
442
|
};
|