@webority/mobile-core 0.0.26 → 0.0.28
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/README.md +69 -1
- package/lib/commonjs/api/retry.js +17 -1
- package/lib/commonjs/api/userClient.js +1 -1
- package/lib/commonjs/auth/authStore.js +49 -16
- package/lib/commonjs/config/index.js +8 -2
- package/lib/commonjs/formatters/currency.js +2 -1
- package/lib/commonjs/formatters/date.js +5 -6
- package/lib/commonjs/formatters/dateMath.js +2 -1
- package/lib/commonjs/formatters/intlCache.js +37 -0
- package/lib/commonjs/formatters/number.js +4 -3
- package/lib/commonjs/index.js +7 -0
- package/lib/commonjs/initSDK.js +1 -1
- package/lib/commonjs/network/networkStatus.js +40 -2
- package/lib/commonjs/push/index.js +18 -0
- package/lib/commonjs/push/push.js +177 -15
- package/lib/commonjs/push/task.js +43 -0
- package/lib/commonjs/utils/base64.js +24 -0
- package/lib/module/api/retry.js +17 -1
- package/lib/module/api/userClient.js +2 -2
- package/lib/module/auth/authStore.js +49 -16
- package/lib/module/config/index.js +7 -1
- package/lib/module/formatters/currency.js +2 -1
- package/lib/module/formatters/date.js +5 -6
- package/lib/module/formatters/dateMath.js +2 -1
- package/lib/module/formatters/intlCache.js +30 -0
- package/lib/module/formatters/number.js +4 -3
- package/lib/module/index.js +2 -0
- package/lib/module/initSDK.js +2 -2
- package/lib/module/network/networkStatus.js +37 -0
- package/lib/module/push/index.js +1 -1
- package/lib/module/push/push.js +170 -15
- package/lib/module/push/task.js +38 -0
- package/lib/module/utils/base64.js +19 -0
- package/lib/typescript/commonjs/config/index.d.ts +6 -0
- package/lib/typescript/commonjs/formatters/intlCache.d.ts +6 -0
- package/lib/typescript/commonjs/index.d.ts +1 -0
- package/lib/typescript/commonjs/initSDK.d.ts +1 -1
- package/lib/typescript/commonjs/network/networkStatus.d.ts +6 -0
- package/lib/typescript/commonjs/push/index.d.ts +2 -2
- package/lib/typescript/commonjs/push/push.d.ts +88 -0
- package/lib/typescript/commonjs/push/task.d.ts +15 -0
- package/lib/typescript/commonjs/utils/base64.d.ts +7 -0
- package/lib/typescript/module/config/index.d.ts +6 -0
- package/lib/typescript/module/formatters/intlCache.d.ts +6 -0
- package/lib/typescript/module/index.d.ts +1 -0
- package/lib/typescript/module/initSDK.d.ts +1 -1
- package/lib/typescript/module/network/networkStatus.d.ts +6 -0
- package/lib/typescript/module/push/index.d.ts +2 -2
- package/lib/typescript/module/push/push.d.ts +88 -0
- package/lib/typescript/module/push/task.d.ts +15 -0
- package/lib/typescript/module/utils/base64.d.ts +7 -0
- package/package.json +15 -1
|
@@ -18,6 +18,13 @@ const DEFAULT_STATUS = {
|
|
|
18
18
|
* One backend also means one behaviour, rather than each app choosing.
|
|
19
19
|
*/
|
|
20
20
|
let override = null;
|
|
21
|
+
let lastKnown = null;
|
|
22
|
+
let stopFollowing = null;
|
|
23
|
+
const stopFollowingNetwork = () => {
|
|
24
|
+
stopFollowing?.();
|
|
25
|
+
stopFollowing = null;
|
|
26
|
+
lastKnown = null;
|
|
27
|
+
};
|
|
21
28
|
|
|
22
29
|
/**
|
|
23
30
|
* Replace the backend. Intended for TESTS and for the showcase, which uses it
|
|
@@ -26,6 +33,7 @@ let override = null;
|
|
|
26
33
|
*/
|
|
27
34
|
export const setNetworkStatusImplementation = impl => {
|
|
28
35
|
override = impl;
|
|
36
|
+
stopFollowingNetwork();
|
|
29
37
|
};
|
|
30
38
|
const resolveNetInfo = () => override ?? expoNetworkBackend;
|
|
31
39
|
|
|
@@ -96,6 +104,35 @@ export const addNetworkStatusListener = listener => {
|
|
|
96
104
|
return ni.addEventListener(state => listener(normalize(state)));
|
|
97
105
|
};
|
|
98
106
|
|
|
107
|
+
/**
|
|
108
|
+
* The connectivity the HTTP client checks before every request. One listener,
|
|
109
|
+
* attached on first use, keeps it current, so a request costs no native probe:
|
|
110
|
+
* one probe seeds the value and the listener's events replace it.
|
|
111
|
+
*/
|
|
112
|
+
export const getLastKnownNetworkStatus = async () => {
|
|
113
|
+
if (!stopFollowing) {
|
|
114
|
+
try {
|
|
115
|
+
stopFollowing = addNetworkStatusListener(status => {
|
|
116
|
+
lastKnown = status;
|
|
117
|
+
});
|
|
118
|
+
} catch (error) {
|
|
119
|
+
Logger.error('[network] could not follow network changes', error);
|
|
120
|
+
return getNetworkStatus();
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
if (lastKnown) {
|
|
124
|
+
return lastKnown;
|
|
125
|
+
}
|
|
126
|
+
const following = stopFollowing;
|
|
127
|
+
const probed = await getNetworkStatus();
|
|
128
|
+
if (stopFollowing !== following) {
|
|
129
|
+
return probed;
|
|
130
|
+
}
|
|
131
|
+
// An event that arrived during the probe is newer than the probe.
|
|
132
|
+
lastKnown ??= probed;
|
|
133
|
+
return lastKnown;
|
|
134
|
+
};
|
|
135
|
+
|
|
99
136
|
/**
|
|
100
137
|
* React hook that returns the current network status and re-renders on change.
|
|
101
138
|
* Reports an optimistic online default when NetInfo is not installed.
|
package/lib/module/push/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
export { disablePush, enablePush, initPush, setBadgeCount, setPushImplementation, usePush } from "./push.js";
|
|
3
|
+
export { disablePush, enablePush, initPush, notifyLocal, onAction, setBadgeCount, setCategories, setPushImplementation, usePush } from "./push.js";
|
|
4
4
|
//# sourceMappingURL=index.js.map
|
package/lib/module/push/push.js
CHANGED
|
@@ -4,6 +4,12 @@ import { useSyncExternalStore } from 'react';
|
|
|
4
4
|
import { Platform } from 'react-native';
|
|
5
5
|
import { Logger } from "../logger/index.js";
|
|
6
6
|
|
|
7
|
+
/** A button on a notification category. */
|
|
8
|
+
|
|
9
|
+
/** A set of buttons a push names through its category id. */
|
|
10
|
+
|
|
11
|
+
/** A button tap on a notification. */
|
|
12
|
+
|
|
7
13
|
/** The slice of expo-notifications this module calls, so the optional peer stays untyped at build. */
|
|
8
14
|
|
|
9
15
|
let override = null;
|
|
@@ -23,9 +29,9 @@ export const setPushImplementation = impl => {
|
|
|
23
29
|
/**
|
|
24
30
|
* The only place expo-notifications and expo-application are named. Expo Go is
|
|
25
31
|
* checked first because expo-notifications refuses remote push there and its
|
|
26
|
-
* import throws on Android.
|
|
32
|
+
* import throws on Android. Exported for `./task`; not on the `/push` entry.
|
|
27
33
|
*/
|
|
28
|
-
const resolveModules = () => {
|
|
34
|
+
export const resolveModules = () => {
|
|
29
35
|
if (override) {
|
|
30
36
|
return override;
|
|
31
37
|
}
|
|
@@ -67,7 +73,18 @@ const setState = next => {
|
|
|
67
73
|
let config = null;
|
|
68
74
|
let channelsReady = Promise.resolve();
|
|
69
75
|
let tokenSubscription = null;
|
|
70
|
-
let
|
|
76
|
+
let actionHandler = null;
|
|
77
|
+
let listening = false;
|
|
78
|
+
/** Responses that arrived before anything could handle them, e.g. the launching tap before initPush. */
|
|
79
|
+
const pendingResponses = [];
|
|
80
|
+
/** Response key to when it was routed. */
|
|
81
|
+
const routedAt = new Map();
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* The cold-start read, the live listener and, on Android, the background task
|
|
85
|
+
* can each report the same response a moment apart.
|
|
86
|
+
*/
|
|
87
|
+
const REPEAT_WINDOW_MS = 10_000;
|
|
71
88
|
const requireConfig = () => {
|
|
72
89
|
if (!config) {
|
|
73
90
|
throw new Error('[@webority/mobile-core] call initPush before enablePush or disablePush.');
|
|
@@ -92,22 +109,109 @@ const toStringData = data => {
|
|
|
92
109
|
}
|
|
93
110
|
return out;
|
|
94
111
|
};
|
|
95
|
-
const
|
|
96
|
-
|
|
112
|
+
const responseData = response => {
|
|
113
|
+
const content = response.notification.request.content;
|
|
114
|
+
if (content.data) {
|
|
115
|
+
return toStringData(content.data);
|
|
116
|
+
}
|
|
117
|
+
if (typeof content.dataString === 'string') {
|
|
118
|
+
try {
|
|
119
|
+
return toStringData(JSON.parse(content.dataString));
|
|
120
|
+
} catch (error) {
|
|
121
|
+
Logger.error('[push] notification data is not JSON', error);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return {};
|
|
125
|
+
};
|
|
126
|
+
export const toPushAction = response => ({
|
|
127
|
+
actionId: response.actionIdentifier,
|
|
128
|
+
...(response.userText ? {
|
|
129
|
+
userText: response.userText
|
|
130
|
+
} : {}),
|
|
131
|
+
data: responseData(response),
|
|
132
|
+
notificationId: response.notification.request.identifier
|
|
133
|
+
});
|
|
134
|
+
export const toNotificationActions = actions => actions.map(action => ({
|
|
135
|
+
identifier: action.id,
|
|
136
|
+
buttonTitle: action.title,
|
|
137
|
+
...(action.textInput ? {
|
|
138
|
+
textInput: {
|
|
139
|
+
submitButtonTitle: action.textInput.submitTitle,
|
|
140
|
+
placeholder: action.textInput.placeholder
|
|
141
|
+
}
|
|
142
|
+
} : {}),
|
|
143
|
+
options: {
|
|
144
|
+
opensAppToForeground: action.opensApp ?? true,
|
|
145
|
+
isDestructive: action.destructive ?? false,
|
|
146
|
+
isAuthenticationRequired: action.authenticationRequired ?? false
|
|
147
|
+
}
|
|
148
|
+
}));
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Sends a button tap to the action handler and a plain tap to `onOpen`. A
|
|
152
|
+
* button tap with no action handler opens like a plain tap. Resolves once the
|
|
153
|
+
* handler has finished, so a background task stays alive for its request.
|
|
154
|
+
*/
|
|
155
|
+
const routeResponse = async (m, response) => {
|
|
156
|
+
const key = `${response.notification.request.identifier}:${response.actionIdentifier}`;
|
|
157
|
+
const last = routedAt.get(key);
|
|
158
|
+
if (last !== undefined && Date.now() - last < REPEAT_WINDOW_MS) {
|
|
97
159
|
return;
|
|
98
160
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
161
|
+
const isAction = response.actionIdentifier !== m.DEFAULT_ACTION_IDENTIFIER;
|
|
162
|
+
if (isAction && actionHandler) {
|
|
163
|
+
routedAt.set(key, Date.now());
|
|
164
|
+
try {
|
|
165
|
+
await actionHandler(toPushAction(response));
|
|
166
|
+
} catch (error) {
|
|
167
|
+
Logger.error('[push] onAction threw', error);
|
|
168
|
+
}
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
if (!config) {
|
|
172
|
+
pendingResponses.push(response);
|
|
102
173
|
return;
|
|
103
174
|
}
|
|
104
|
-
|
|
175
|
+
routedAt.set(key, Date.now());
|
|
105
176
|
try {
|
|
106
|
-
config.onOpen(
|
|
177
|
+
config.onOpen(responseData(response));
|
|
107
178
|
} catch (error) {
|
|
108
179
|
Logger.error('[push] onOpen threw', error);
|
|
109
180
|
}
|
|
110
181
|
};
|
|
182
|
+
const drainPending = async m => {
|
|
183
|
+
const queued = pendingResponses.splice(0);
|
|
184
|
+
for (const response of queued) {
|
|
185
|
+
await routeResponse(m, response);
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
/** Follows taps and button taps, including the one that launched the app. Wired once per process. */
|
|
190
|
+
const listenForResponses = m => {
|
|
191
|
+
if (listening) {
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
listening = true;
|
|
195
|
+
m.addNotificationResponseReceivedListener(response => {
|
|
196
|
+
void routeResponse(m, response);
|
|
197
|
+
});
|
|
198
|
+
void m.getLastNotificationResponseAsync().then(async response => {
|
|
199
|
+
if (response) {
|
|
200
|
+
await routeResponse(m, response);
|
|
201
|
+
}
|
|
202
|
+
return m.clearLastNotificationResponseAsync?.();
|
|
203
|
+
}).catch(error => Logger.error('[push] reading the launch notification failed', error));
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
/** The payload of the background notification task: routes button taps, ignores received pushes. */
|
|
207
|
+
export const routeTaskPayload = async payload => {
|
|
208
|
+
const mods = resolveModules();
|
|
209
|
+
const response = payload;
|
|
210
|
+
if (!mods || typeof response?.actionIdentifier !== 'string' || typeof response.notification?.request?.identifier !== 'string') {
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
await routeResponse(mods.notifications, response);
|
|
214
|
+
};
|
|
111
215
|
const createChannels = async (m, channels) => {
|
|
112
216
|
for (const channel of channels) {
|
|
113
217
|
try {
|
|
@@ -170,11 +274,8 @@ export const initPush = next => {
|
|
|
170
274
|
if (Platform.OS === 'android' && next.androidChannels?.length) {
|
|
171
275
|
channelsReady = createChannels(m, next.androidChannels);
|
|
172
276
|
}
|
|
173
|
-
m
|
|
174
|
-
void m
|
|
175
|
-
handleResponse(response);
|
|
176
|
-
return m.clearLastNotificationResponseAsync?.();
|
|
177
|
-
}).catch(error => Logger.error('[push] reading the launch notification failed', error));
|
|
277
|
+
listenForResponses(m);
|
|
278
|
+
void drainPending(m);
|
|
178
279
|
void m.getPermissionsAsync().then(response => setState({
|
|
179
280
|
status: toPermissionStatus(response)
|
|
180
281
|
})).catch(error => Logger.error('[push] permission check failed', error));
|
|
@@ -249,6 +350,60 @@ export const setBadgeCount = async count => {
|
|
|
249
350
|
}
|
|
250
351
|
await mods.notifications.setBadgeCountAsync(count);
|
|
251
352
|
};
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* Registers the button sets a push can name by category id. Call it at every
|
|
356
|
+
* start, with the same ids on both platforms. On Android the buttons show only
|
|
357
|
+
* on notifications expo-notifications draws, such as `notifyLocal`.
|
|
358
|
+
*/
|
|
359
|
+
export const setCategories = async categories => {
|
|
360
|
+
const mods = resolveModules();
|
|
361
|
+
if (!mods) {
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
for (const category of categories) {
|
|
365
|
+
await mods.notifications.setNotificationCategoryAsync(category.id, toNotificationActions(category.actions));
|
|
366
|
+
}
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Handles button taps while JavaScript is running; a plain tap still goes to
|
|
371
|
+
* `onOpen`. For taps on a killed app use `definePushActionTask` from
|
|
372
|
+
* `/push/task`, which sets this handler too. Returns a function that removes it.
|
|
373
|
+
*/
|
|
374
|
+
export const onAction = handler => {
|
|
375
|
+
actionHandler = handler;
|
|
376
|
+
const mods = resolveModules();
|
|
377
|
+
if (mods) {
|
|
378
|
+
listenForResponses(mods.notifications);
|
|
379
|
+
void drainPending(mods.notifications);
|
|
380
|
+
}
|
|
381
|
+
return () => {
|
|
382
|
+
if (actionHandler === handler) {
|
|
383
|
+
actionHandler = null;
|
|
384
|
+
}
|
|
385
|
+
};
|
|
386
|
+
};
|
|
387
|
+
|
|
388
|
+
/** Shows a notification from the phone itself, for example when a button's request failed. */
|
|
389
|
+
export const notifyLocal = async ({
|
|
390
|
+
title,
|
|
391
|
+
body,
|
|
392
|
+
data
|
|
393
|
+
}) => {
|
|
394
|
+
const mods = resolveModules();
|
|
395
|
+
if (!mods) {
|
|
396
|
+
return;
|
|
397
|
+
}
|
|
398
|
+
await mods.notifications.scheduleNotificationAsync({
|
|
399
|
+
content: {
|
|
400
|
+
title,
|
|
401
|
+
body,
|
|
402
|
+
data: data ?? {}
|
|
403
|
+
},
|
|
404
|
+
trigger: null
|
|
405
|
+
});
|
|
406
|
+
};
|
|
252
407
|
const subscribe = notify => {
|
|
253
408
|
subscribers.add(notify);
|
|
254
409
|
return () => {
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { Platform } from 'react-native';
|
|
4
|
+
import { Logger } from "../logger/index.js";
|
|
5
|
+
import { onAction, resolveModules, routeTaskPayload } from "./push.js";
|
|
6
|
+
const PUSH_ACTION_TASK = 'webority-push-action';
|
|
7
|
+
/**
|
|
8
|
+
* Handles notification button taps in every app state, the killed app
|
|
9
|
+
* included. Call it once at module scope in the app's entry file (index.js),
|
|
10
|
+
* before the root component registers: a tap on a killed app starts the
|
|
11
|
+
* JavaScript bundle without the UI, so nothing later in the app runs.
|
|
12
|
+
*
|
|
13
|
+
* Android runs the handler from a background notification task
|
|
14
|
+
* (expo-task-manager). iOS has no such task for button taps: it launches the
|
|
15
|
+
* app in the background and the response reaches the listener this sets up.
|
|
16
|
+
* The handler's promise is awaited, so a request it makes can finish first.
|
|
17
|
+
*/
|
|
18
|
+
export const definePushActionTask = handler => {
|
|
19
|
+
onAction(handler);
|
|
20
|
+
const mods = resolveModules();
|
|
21
|
+
if (!mods || Platform.OS !== 'android') {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
/** The one place `expo-task-manager` is named. Import `/push/task` only if you use button taps. */
|
|
25
|
+
const taskManager = require('expo-task-manager');
|
|
26
|
+
taskManager.defineTask(PUSH_ACTION_TASK, async ({
|
|
27
|
+
data,
|
|
28
|
+
error
|
|
29
|
+
}) => {
|
|
30
|
+
if (error) {
|
|
31
|
+
Logger.error('[push] the notification task failed', error);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
await routeTaskPayload(data);
|
|
35
|
+
});
|
|
36
|
+
void mods.notifications.registerTaskAsync(PUSH_ACTION_TASK).catch(registerError => Logger.error('[push] registering the notification task failed', registerError));
|
|
37
|
+
};
|
|
38
|
+
//# sourceMappingURL=task.js.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
// Small enough for every engine's argument limit in `String.fromCharCode.apply`.
|
|
4
|
+
const CHUNK = 0x2000;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Base64 of raw bytes, for a `data:` URI. Builds a Latin-1 string a chunk at a
|
|
8
|
+
* time and hands it to the engine's native `btoa` (Hermes ships it), which is
|
|
9
|
+
* many times faster on the JS thread than encoding byte by byte in JS.
|
|
10
|
+
*/
|
|
11
|
+
export const encodeBase64 = buffer => {
|
|
12
|
+
const bytes = new Uint8Array(buffer);
|
|
13
|
+
let binary = '';
|
|
14
|
+
for (let i = 0; i < bytes.length; i += CHUNK) {
|
|
15
|
+
binary += String.fromCharCode.apply(null, bytes.subarray(i, i + CHUNK));
|
|
16
|
+
}
|
|
17
|
+
return btoa(binary);
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=base64.js.map
|
|
@@ -34,6 +34,12 @@ export interface Config {
|
|
|
34
34
|
*/
|
|
35
35
|
logCurl: boolean;
|
|
36
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* Info lines (each token refresh, each unauthorised URL) reach the device log
|
|
39
|
+
* and any remote sink, so a release build that sets nothing logs warnings and
|
|
40
|
+
* errors only.
|
|
41
|
+
*/
|
|
42
|
+
export declare const DEFAULT_LOG_LEVEL: LogLevel;
|
|
37
43
|
/**
|
|
38
44
|
* Set global configuration for all Webority packages
|
|
39
45
|
*/
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const numberFormat: (locale: string, options?: Intl.NumberFormatOptions) => Intl.NumberFormat;
|
|
2
|
+
export declare const dateTimeFormat: (locale: string, options: Intl.DateTimeFormatOptions) => Intl.DateTimeFormat;
|
|
3
|
+
export declare const relativeTimeFormat: (RelativeTimeFormat: new (locale: string, options?: {
|
|
4
|
+
numeric?: "always" | "auto";
|
|
5
|
+
}) => Intl.RelativeTimeFormat, locale: string) => Intl.RelativeTimeFormat;
|
|
6
|
+
//# sourceMappingURL=intlCache.d.ts.map
|
|
@@ -48,6 +48,7 @@ export type { NetworkConnectionType, NetworkStatus, NetworkStatusLike, NetworkSt
|
|
|
48
48
|
export { addNetworkStatusListener, getNetworkStatus, setNetworkStatusImplementation, useNetworkStatus } from './network';
|
|
49
49
|
export type { AsyncStorageLike, StorageApi } from './storage';
|
|
50
50
|
export { isStorageAvailable, Storage, setStorageImplementation } from './storage';
|
|
51
|
+
export { encodeBase64 } from './utils/base64';
|
|
51
52
|
export type { PasswordRules } from './validators';
|
|
52
53
|
export { isAadhaar, isAlphanumeric, isBetween, isEmail, isGstin, isHexColor, isIfsc, isIndianMobile, isIndianPincode, isInteger, isNonEmpty, isNumeric, isPan, isPhone, isStrongPassword, isUrl, maxLength, minLength } from './validators';
|
|
53
54
|
export type { DeviceInfoLike, ParsedVersion, Platform, UpdateInfo, UpdateType, VersionCheckResult, VersionCheckType, VersionComparison, VersionData } from './versionCheck';
|
|
@@ -11,7 +11,7 @@ export interface InitConfig {
|
|
|
11
11
|
baseUrl: string;
|
|
12
12
|
/** Enable/disable logging. Defaults to `true`. */
|
|
13
13
|
loggingEnabled?: boolean;
|
|
14
|
-
/** Log level. Defaults to `'info'
|
|
14
|
+
/** Log level. Defaults to `'info'` in development and `'warn'` in a release build. */
|
|
15
15
|
logLevel?: LogLevel;
|
|
16
16
|
/** Environment. Defaults to `'Development'`. */
|
|
17
17
|
environment?: Environment;
|
|
@@ -34,6 +34,12 @@ export declare const getNetworkStatus: () => Promise<NetworkStatus>;
|
|
|
34
34
|
* Subscribe to network status changes. Returns an unsubscribe function.
|
|
35
35
|
*/
|
|
36
36
|
export declare const addNetworkStatusListener: (listener: NetworkStatusListener) => (() => void);
|
|
37
|
+
/**
|
|
38
|
+
* The connectivity the HTTP client checks before every request. One listener,
|
|
39
|
+
* attached on first use, keeps it current, so a request costs no native probe:
|
|
40
|
+
* one probe seeds the value and the listener's events replace it.
|
|
41
|
+
*/
|
|
42
|
+
export declare const getLastKnownNetworkStatus: () => Promise<NetworkStatus>;
|
|
37
43
|
/**
|
|
38
44
|
* React hook that returns the current network status and re-renders on change.
|
|
39
45
|
* Reports an optimistic online default when NetInfo is not installed.
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export type { PushAndroidChannel, PushConfig, PushDevice, PushModules, PushNotificationsLike, PushPlatform, PushState, PushStatus } from './push';
|
|
2
|
-
export { disablePush, enablePush, initPush, setBadgeCount, setPushImplementation, usePush } from './push';
|
|
1
|
+
export type { PushAction, PushActionHandler, PushAndroidChannel, PushCategory, PushCategoryAction, PushConfig, PushDevice, PushLocalNotification, PushModules, PushNotificationsLike, PushPlatform, PushState, PushStatus } from './push';
|
|
2
|
+
export { disablePush, enablePush, initPush, notifyLocal, onAction, setBadgeCount, setCategories, setPushImplementation, usePush } from './push';
|
|
3
3
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -26,6 +26,42 @@ export interface PushConfig {
|
|
|
26
26
|
/** Whether a notification shown while the app is open plays its sound. Defaults to true. */
|
|
27
27
|
playSoundInForeground?: () => boolean;
|
|
28
28
|
}
|
|
29
|
+
/** A button on a notification category. */
|
|
30
|
+
export interface PushCategoryAction {
|
|
31
|
+
id: string;
|
|
32
|
+
title: string;
|
|
33
|
+
/** Whether the tap brings the app to the foreground. Defaults to true. */
|
|
34
|
+
opensApp?: boolean;
|
|
35
|
+
/** iOS only: the title shows in red. */
|
|
36
|
+
destructive?: boolean;
|
|
37
|
+
/** Turns the button into a reply box; the text arrives as `userText`. */
|
|
38
|
+
textInput?: {
|
|
39
|
+
submitTitle: string;
|
|
40
|
+
placeholder: string;
|
|
41
|
+
};
|
|
42
|
+
/** iOS only: the phone must be unlocked before the action runs. */
|
|
43
|
+
authenticationRequired?: boolean;
|
|
44
|
+
}
|
|
45
|
+
/** A set of buttons a push names through its category id. */
|
|
46
|
+
export interface PushCategory {
|
|
47
|
+
id: string;
|
|
48
|
+
actions: PushCategoryAction[];
|
|
49
|
+
}
|
|
50
|
+
/** A button tap on a notification. */
|
|
51
|
+
export interface PushAction {
|
|
52
|
+
actionId: string;
|
|
53
|
+
/** What the person typed, for a `textInput` action. */
|
|
54
|
+
userText?: string;
|
|
55
|
+
data: Record<string, string>;
|
|
56
|
+
/** The notification's identifier on the phone, not a server id in `data`. */
|
|
57
|
+
notificationId: string;
|
|
58
|
+
}
|
|
59
|
+
export type PushActionHandler = (action: PushAction) => Promise<void> | void;
|
|
60
|
+
export interface PushLocalNotification {
|
|
61
|
+
title: string;
|
|
62
|
+
body: string;
|
|
63
|
+
data?: Record<string, string>;
|
|
64
|
+
}
|
|
29
65
|
export type PushStatus = 'unknown' | 'granted' | 'denied' | 'unavailable';
|
|
30
66
|
export interface PushState {
|
|
31
67
|
status: PushStatus;
|
|
@@ -41,15 +77,31 @@ interface SubscriptionLike {
|
|
|
41
77
|
}
|
|
42
78
|
interface NotificationResponseLike {
|
|
43
79
|
actionIdentifier: string;
|
|
80
|
+
userText?: string;
|
|
44
81
|
notification: {
|
|
45
82
|
request: {
|
|
46
83
|
identifier: string;
|
|
84
|
+
/** A background task receives the raw content, where data may still be a JSON `dataString`. */
|
|
47
85
|
content: {
|
|
48
86
|
data?: Record<string, unknown> | null;
|
|
87
|
+
dataString?: string;
|
|
49
88
|
};
|
|
50
89
|
};
|
|
51
90
|
};
|
|
52
91
|
}
|
|
92
|
+
interface NotificationActionLike {
|
|
93
|
+
identifier: string;
|
|
94
|
+
buttonTitle: string;
|
|
95
|
+
textInput?: {
|
|
96
|
+
submitButtonTitle: string;
|
|
97
|
+
placeholder: string;
|
|
98
|
+
};
|
|
99
|
+
options: {
|
|
100
|
+
opensAppToForeground: boolean;
|
|
101
|
+
isDestructive: boolean;
|
|
102
|
+
isAuthenticationRequired: boolean;
|
|
103
|
+
};
|
|
104
|
+
}
|
|
53
105
|
interface DevicePushTokenLike {
|
|
54
106
|
type: string;
|
|
55
107
|
data: unknown;
|
|
@@ -76,10 +128,22 @@ export interface PushNotificationsLike {
|
|
|
76
128
|
importance: number;
|
|
77
129
|
}) => Promise<unknown>;
|
|
78
130
|
setBadgeCountAsync: (count: number) => Promise<boolean>;
|
|
131
|
+
setNotificationCategoryAsync: (identifier: string, actions: NotificationActionLike[]) => Promise<unknown>;
|
|
132
|
+
scheduleNotificationAsync: (request: {
|
|
133
|
+
content: {
|
|
134
|
+
title: string;
|
|
135
|
+
body: string;
|
|
136
|
+
data: Record<string, string>;
|
|
137
|
+
};
|
|
138
|
+
trigger: null;
|
|
139
|
+
}) => Promise<string>;
|
|
140
|
+
registerTaskAsync: (taskName: string) => Promise<unknown>;
|
|
79
141
|
AndroidImportance: {
|
|
80
142
|
DEFAULT: number;
|
|
81
143
|
HIGH: number;
|
|
82
144
|
};
|
|
145
|
+
/** The `actionIdentifier` of a plain tap on the notification body. */
|
|
146
|
+
DEFAULT_ACTION_IDENTIFIER: string;
|
|
83
147
|
}
|
|
84
148
|
export interface PushModules {
|
|
85
149
|
notifications: PushNotificationsLike;
|
|
@@ -92,6 +156,16 @@ export interface PushModules {
|
|
|
92
156
|
* included. Pass `null` to restore expo-notifications.
|
|
93
157
|
*/
|
|
94
158
|
export declare const setPushImplementation: (impl: PushModules | null) => void;
|
|
159
|
+
/**
|
|
160
|
+
* The only place expo-notifications and expo-application are named. Expo Go is
|
|
161
|
+
* checked first because expo-notifications refuses remote push there and its
|
|
162
|
+
* import throws on Android. Exported for `./task`; not on the `/push` entry.
|
|
163
|
+
*/
|
|
164
|
+
export declare const resolveModules: () => PushModules | null;
|
|
165
|
+
export declare const toPushAction: (response: NotificationResponseLike) => PushAction;
|
|
166
|
+
export declare const toNotificationActions: (actions: PushCategoryAction[]) => NotificationActionLike[];
|
|
167
|
+
/** The payload of the background notification task: routes button taps, ignores received pushes. */
|
|
168
|
+
export declare const routeTaskPayload: (payload: unknown) => Promise<void>;
|
|
95
169
|
/**
|
|
96
170
|
* Wires push at startup: the foreground handler, Android channels, and tap
|
|
97
171
|
* handling, including the tap that launched the app. Calling it again only
|
|
@@ -110,6 +184,20 @@ export declare const enablePush: () => Promise<"granted" | "denied" | "unavailab
|
|
|
110
184
|
export declare const disablePush: () => Promise<void>;
|
|
111
185
|
/** Sets the app icon badge; a no-op where push is unavailable or the launcher has no badge. */
|
|
112
186
|
export declare const setBadgeCount: (count: number) => Promise<void>;
|
|
187
|
+
/**
|
|
188
|
+
* Registers the button sets a push can name by category id. Call it at every
|
|
189
|
+
* start, with the same ids on both platforms. On Android the buttons show only
|
|
190
|
+
* on notifications expo-notifications draws, such as `notifyLocal`.
|
|
191
|
+
*/
|
|
192
|
+
export declare const setCategories: (categories: PushCategory[]) => Promise<void>;
|
|
193
|
+
/**
|
|
194
|
+
* Handles button taps while JavaScript is running; a plain tap still goes to
|
|
195
|
+
* `onOpen`. For taps on a killed app use `definePushActionTask` from
|
|
196
|
+
* `/push/task`, which sets this handler too. Returns a function that removes it.
|
|
197
|
+
*/
|
|
198
|
+
export declare const onAction: (handler: PushActionHandler) => (() => void);
|
|
199
|
+
/** Shows a notification from the phone itself, for example when a button's request failed. */
|
|
200
|
+
export declare const notifyLocal: ({ title, body, data }: PushLocalNotification) => Promise<void>;
|
|
113
201
|
/** Push status for a settings switch, re-rendering when it changes. */
|
|
114
202
|
export declare const usePush: () => PushState & {
|
|
115
203
|
enable: () => Promise<void>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type PushActionHandler } from './push';
|
|
2
|
+
export type { PushAction, PushActionHandler } from './push';
|
|
3
|
+
/**
|
|
4
|
+
* Handles notification button taps in every app state, the killed app
|
|
5
|
+
* included. Call it once at module scope in the app's entry file (index.js),
|
|
6
|
+
* before the root component registers: a tap on a killed app starts the
|
|
7
|
+
* JavaScript bundle without the UI, so nothing later in the app runs.
|
|
8
|
+
*
|
|
9
|
+
* Android runs the handler from a background notification task
|
|
10
|
+
* (expo-task-manager). iOS has no such task for button taps: it launches the
|
|
11
|
+
* app in the background and the response reaches the listener this sets up.
|
|
12
|
+
* The handler's promise is awaited, so a request it makes can finish first.
|
|
13
|
+
*/
|
|
14
|
+
export declare const definePushActionTask: (handler: PushActionHandler) => void;
|
|
15
|
+
//# sourceMappingURL=task.d.ts.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base64 of raw bytes, for a `data:` URI. Builds a Latin-1 string a chunk at a
|
|
3
|
+
* time and hands it to the engine's native `btoa` (Hermes ships it), which is
|
|
4
|
+
* many times faster on the JS thread than encoding byte by byte in JS.
|
|
5
|
+
*/
|
|
6
|
+
export declare const encodeBase64: (buffer: ArrayBuffer) => string;
|
|
7
|
+
//# sourceMappingURL=base64.d.ts.map
|
|
@@ -34,6 +34,12 @@ export interface Config {
|
|
|
34
34
|
*/
|
|
35
35
|
logCurl: boolean;
|
|
36
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* Info lines (each token refresh, each unauthorised URL) reach the device log
|
|
39
|
+
* and any remote sink, so a release build that sets nothing logs warnings and
|
|
40
|
+
* errors only.
|
|
41
|
+
*/
|
|
42
|
+
export declare const DEFAULT_LOG_LEVEL: LogLevel;
|
|
37
43
|
/**
|
|
38
44
|
* Set global configuration for all Webority packages
|
|
39
45
|
*/
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const numberFormat: (locale: string, options?: Intl.NumberFormatOptions) => Intl.NumberFormat;
|
|
2
|
+
export declare const dateTimeFormat: (locale: string, options: Intl.DateTimeFormatOptions) => Intl.DateTimeFormat;
|
|
3
|
+
export declare const relativeTimeFormat: (RelativeTimeFormat: new (locale: string, options?: {
|
|
4
|
+
numeric?: "always" | "auto";
|
|
5
|
+
}) => Intl.RelativeTimeFormat, locale: string) => Intl.RelativeTimeFormat;
|
|
6
|
+
//# sourceMappingURL=intlCache.d.ts.map
|
|
@@ -48,6 +48,7 @@ export type { NetworkConnectionType, NetworkStatus, NetworkStatusLike, NetworkSt
|
|
|
48
48
|
export { addNetworkStatusListener, getNetworkStatus, setNetworkStatusImplementation, useNetworkStatus } from './network/index.js';
|
|
49
49
|
export type { AsyncStorageLike, StorageApi } from './storage/index.js';
|
|
50
50
|
export { isStorageAvailable, Storage, setStorageImplementation } from './storage/index.js';
|
|
51
|
+
export { encodeBase64 } from './utils/base64.js';
|
|
51
52
|
export type { PasswordRules } from './validators/index.js';
|
|
52
53
|
export { isAadhaar, isAlphanumeric, isBetween, isEmail, isGstin, isHexColor, isIfsc, isIndianMobile, isIndianPincode, isInteger, isNonEmpty, isNumeric, isPan, isPhone, isStrongPassword, isUrl, maxLength, minLength } from './validators/index.js';
|
|
53
54
|
export type { DeviceInfoLike, ParsedVersion, Platform, UpdateInfo, UpdateType, VersionCheckResult, VersionCheckType, VersionComparison, VersionData } from './versionCheck/index.js';
|
|
@@ -11,7 +11,7 @@ export interface InitConfig {
|
|
|
11
11
|
baseUrl: string;
|
|
12
12
|
/** Enable/disable logging. Defaults to `true`. */
|
|
13
13
|
loggingEnabled?: boolean;
|
|
14
|
-
/** Log level. Defaults to `'info'
|
|
14
|
+
/** Log level. Defaults to `'info'` in development and `'warn'` in a release build. */
|
|
15
15
|
logLevel?: LogLevel;
|
|
16
16
|
/** Environment. Defaults to `'Development'`. */
|
|
17
17
|
environment?: Environment;
|
|
@@ -34,6 +34,12 @@ export declare const getNetworkStatus: () => Promise<NetworkStatus>;
|
|
|
34
34
|
* Subscribe to network status changes. Returns an unsubscribe function.
|
|
35
35
|
*/
|
|
36
36
|
export declare const addNetworkStatusListener: (listener: NetworkStatusListener) => (() => void);
|
|
37
|
+
/**
|
|
38
|
+
* The connectivity the HTTP client checks before every request. One listener,
|
|
39
|
+
* attached on first use, keeps it current, so a request costs no native probe:
|
|
40
|
+
* one probe seeds the value and the listener's events replace it.
|
|
41
|
+
*/
|
|
42
|
+
export declare const getLastKnownNetworkStatus: () => Promise<NetworkStatus>;
|
|
37
43
|
/**
|
|
38
44
|
* React hook that returns the current network status and re-renders on change.
|
|
39
45
|
* Reports an optimistic online default when NetInfo is not installed.
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export type { PushAndroidChannel, PushConfig, PushDevice, PushModules, PushNotificationsLike, PushPlatform, PushState, PushStatus } from './push.js';
|
|
2
|
-
export { disablePush, enablePush, initPush, setBadgeCount, setPushImplementation, usePush } from './push.js';
|
|
1
|
+
export type { PushAction, PushActionHandler, PushAndroidChannel, PushCategory, PushCategoryAction, PushConfig, PushDevice, PushLocalNotification, PushModules, PushNotificationsLike, PushPlatform, PushState, PushStatus } from './push.js';
|
|
2
|
+
export { disablePush, enablePush, initPush, notifyLocal, onAction, setBadgeCount, setCategories, setPushImplementation, usePush } from './push.js';
|
|
3
3
|
//# sourceMappingURL=index.d.ts.map
|