@alfalab/bridge-to-native 1.5.1 → 1.5.2-beta.b951ff8
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/client/bridge-to-native.d.ts +56 -1
- package/client/bridge-to-native.js +68 -1
- package/client/constants.d.ts +4 -1
- package/client/constants.js +8 -1
- package/client/services-and-utils/native-bridge-service.d.ts +38 -0
- package/client/services-and-utils/native-bridge-service.js +134 -0
- package/client/services-and-utils/native-features.d.ts +6 -1
- package/client/services-and-utils/native-features.js +13 -1
- package/client/services-and-utils/native-params-service.d.ts +2 -0
- package/client/services-and-utils/web-features-service.d.ts +37 -0
- package/client/services-and-utils/web-features-service.js +67 -0
- package/client/types.d.ts +23 -0
- package/package.json +123 -118
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
import { type BrowserHistoryApiWrappers, type HistoryPushStateParams, type HistoryReplaceStateParams, type LocationAssignParam, type LogError, type NativeFeatureKey, type PdfType } from './types';
|
|
2
|
+
import { type BrowserHistoryApiWrappers, type HistoryPushStateParams, type HistoryReplaceStateParams, type LocationAssignParam, type LogError, type NativeFeatureKey, type PdfType, type WebFeaturesGeoConfiguration, type WebFeaturesHapticsOptions, type WebFeaturesSheetDragArea } from './types';
|
|
3
3
|
/**
|
|
4
4
|
* Сервис, предоставляет методы для WA, работающего внутри NA.
|
|
5
5
|
*/
|
|
@@ -21,6 +21,8 @@ export declare class BridgeToNative {
|
|
|
21
21
|
private nativeParamsService;
|
|
22
22
|
private externalLinksService;
|
|
23
23
|
private nativeNavigationAndTitleService;
|
|
24
|
+
private nativeBridgeService;
|
|
25
|
+
private webFeaturesService;
|
|
24
26
|
/**
|
|
25
27
|
* Схема NA.
|
|
26
28
|
*/
|
|
@@ -78,6 +80,16 @@ export declare class BridgeToNative {
|
|
|
78
80
|
* ресурс в новом WV.
|
|
79
81
|
*/
|
|
80
82
|
getHrefToOpenInBrowser(link: string): string;
|
|
83
|
+
/**
|
|
84
|
+
* Запрашивает текущую конфигурацию геолокации WebFeatures.
|
|
85
|
+
*
|
|
86
|
+
* ВАЖНО!
|
|
87
|
+
* Доступно только в iOS начиная с версии АМ `17.0.0`.
|
|
88
|
+
* В несовместимом окружении возвращённый промис будет отклонён.
|
|
89
|
+
*
|
|
90
|
+
* @returns Промис с `permission` и `userCoordinate` (`null`, если доступ не разрешён).
|
|
91
|
+
*/
|
|
92
|
+
getGeoConfiguration(): Promise<WebFeaturesGeoConfiguration>;
|
|
81
93
|
/**
|
|
82
94
|
* Делает один шаг назад по браузерной истории и модифицирует внутреннее состояние B2N,
|
|
83
95
|
* чтобы в дальнейшем зарегистрировать этот переход в NA.
|
|
@@ -241,4 +253,47 @@ export declare class BridgeToNative {
|
|
|
241
253
|
* @param nativeTitle Текст заголовка, для «нативной» части WV, пустая строка — отсутствие заголовка.
|
|
242
254
|
*/
|
|
243
255
|
setTitle(nativeTitle: string): void;
|
|
256
|
+
/**
|
|
257
|
+
* Воспроизводит тактильный отклик WebFeatures.
|
|
258
|
+
*
|
|
259
|
+
* ВАЖНО!
|
|
260
|
+
* Доступно только в iOS начиная с версии АМ `17.0.0`.
|
|
261
|
+
* В несовместимом окружении вызов игнорируется.
|
|
262
|
+
* Управляется нативным фича-тоглом `webViewHapticsIOS`.
|
|
263
|
+
*
|
|
264
|
+
* @param options.type Тип тактильного отклика.
|
|
265
|
+
* @param options.intensity Интенсивность `0...1` (только для impact-типов).
|
|
266
|
+
* B2N пробрасывает значение в натив без валидации диапазона.
|
|
267
|
+
*/
|
|
268
|
+
vibrate(options: WebFeaturesHapticsOptions): void;
|
|
269
|
+
/**
|
|
270
|
+
* Задаёт область нативной шторы, за которую можно её перетаскивать.
|
|
271
|
+
*
|
|
272
|
+
* ВАЖНО!
|
|
273
|
+
* Доступно только в iOS начиная с версии АМ `17.0.0`.
|
|
274
|
+
* В несовместимом окружении вызов игнорируется.
|
|
275
|
+
*
|
|
276
|
+
* @param area Область перетаскивания шторы.
|
|
277
|
+
*/
|
|
278
|
+
setSheetDragArea(area: WebFeaturesSheetDragArea): void;
|
|
279
|
+
/**
|
|
280
|
+
* Скрывает нативный таббар.
|
|
281
|
+
*
|
|
282
|
+
* ВАЖНО!
|
|
283
|
+
* Доступно только в iOS начиная с версии АМ `17.0.0`.
|
|
284
|
+
* В несовместимом окружении вызов игнорируется.
|
|
285
|
+
* Управляется нативным фича-тоглом `mainSuperAppIOS`.
|
|
286
|
+
*/
|
|
287
|
+
hideTabbar(): void;
|
|
288
|
+
/**
|
|
289
|
+
* Показывает нативный таббар и, при переданном `selectedId`, выбирает вкладку.
|
|
290
|
+
*
|
|
291
|
+
* ВАЖНО!
|
|
292
|
+
* Доступно только в iOS начиная с версии АМ `17.0.0`.
|
|
293
|
+
* В несовместимом окружении вызов игнорируется.
|
|
294
|
+
* Управляется нативным фича-тоглом `mainSuperAppIOS`.
|
|
295
|
+
*
|
|
296
|
+
* @param selectedId id вкладки, которую выбрать при показе.
|
|
297
|
+
*/
|
|
298
|
+
showTabbar(selectedId?: string): void;
|
|
244
299
|
}
|
|
@@ -3,8 +3,10 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
exports.BridgeToNative = void 0;
|
|
5
5
|
const external_links_service_1 = require("./services-and-utils/external-links-service");
|
|
6
|
+
const native_bridge_service_1 = require("./services-and-utils/native-bridge-service");
|
|
6
7
|
const native_navigation_and_title_service_1 = require("./services-and-utils/native-navigation-and-title-service");
|
|
7
8
|
const native_params_service_1 = require("./services-and-utils/native-params-service");
|
|
9
|
+
const web_features_service_1 = require("./services-and-utils/web-features-service");
|
|
8
10
|
/**
|
|
9
11
|
* Сервис, предоставляет методы для WA, работающего внутри NA.
|
|
10
12
|
*/
|
|
@@ -19,11 +21,13 @@ class BridgeToNative {
|
|
|
19
21
|
* если не передать, B2N не будет логировать ошибки.
|
|
20
22
|
*/
|
|
21
23
|
constructor(options) {
|
|
22
|
-
var _a, _b, _c, _d;
|
|
24
|
+
var _a, _b, _c, _d, _e;
|
|
23
25
|
this.options = options;
|
|
24
26
|
this.nativeParamsService = new native_params_service_1.NativeParamsService((_a = this.options) === null || _a === void 0 ? void 0 : _a.logError);
|
|
25
27
|
this.externalLinksService = new external_links_service_1.ExternalLinksService(this.nativeParamsService, (_b = this.options) === null || _b === void 0 ? void 0 : _b.logError);
|
|
26
28
|
this.nativeNavigationAndTitleService = new native_navigation_and_title_service_1.NativeNavigationAndTitleService(this.nativeParamsService, (_c = this.options) === null || _c === void 0 ? void 0 : _c.browserHistoryApiWrappers, (_d = this.options) === null || _d === void 0 ? void 0 : _d.logError);
|
|
29
|
+
this.nativeBridgeService = new native_bridge_service_1.NativeBridgeService((_e = this.options) === null || _e === void 0 ? void 0 : _e.logError);
|
|
30
|
+
this.webFeaturesService = new web_features_service_1.WebFeaturesService(this.nativeParamsService, this.nativeBridgeService);
|
|
27
31
|
}
|
|
28
32
|
/**
|
|
29
33
|
* Схема NA.
|
|
@@ -102,6 +106,18 @@ class BridgeToNative {
|
|
|
102
106
|
getHrefToOpenInBrowser(link) {
|
|
103
107
|
return this.externalLinksService.getHrefToOpenInBrowser(link);
|
|
104
108
|
}
|
|
109
|
+
/**
|
|
110
|
+
* Запрашивает текущую конфигурацию геолокации WebFeatures.
|
|
111
|
+
*
|
|
112
|
+
* ВАЖНО!
|
|
113
|
+
* Доступно только в iOS начиная с версии АМ `17.0.0`.
|
|
114
|
+
* В несовместимом окружении возвращённый промис будет отклонён.
|
|
115
|
+
*
|
|
116
|
+
* @returns Промис с `permission` и `userCoordinate` (`null`, если доступ не разрешён).
|
|
117
|
+
*/
|
|
118
|
+
getGeoConfiguration() {
|
|
119
|
+
return this.webFeaturesService.getGeoConfiguration();
|
|
120
|
+
}
|
|
105
121
|
/**
|
|
106
122
|
* Делает один шаг назад по браузерной истории и модифицирует внутреннее состояние B2N,
|
|
107
123
|
* чтобы в дальнейшем зарегистрировать этот переход в NA.
|
|
@@ -296,5 +312,56 @@ class BridgeToNative {
|
|
|
296
312
|
setTitle(nativeTitle) {
|
|
297
313
|
this.nativeNavigationAndTitleService.setTitle(nativeTitle);
|
|
298
314
|
}
|
|
315
|
+
/**
|
|
316
|
+
* Воспроизводит тактильный отклик WebFeatures.
|
|
317
|
+
*
|
|
318
|
+
* ВАЖНО!
|
|
319
|
+
* Доступно только в iOS начиная с версии АМ `17.0.0`.
|
|
320
|
+
* В несовместимом окружении вызов игнорируется.
|
|
321
|
+
* Управляется нативным фича-тоглом `webViewHapticsIOS`.
|
|
322
|
+
*
|
|
323
|
+
* @param options.type Тип тактильного отклика.
|
|
324
|
+
* @param options.intensity Интенсивность `0...1` (только для impact-типов).
|
|
325
|
+
* B2N пробрасывает значение в натив без валидации диапазона.
|
|
326
|
+
*/
|
|
327
|
+
vibrate(options) {
|
|
328
|
+
this.webFeaturesService.vibrate(options);
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* Задаёт область нативной шторы, за которую можно её перетаскивать.
|
|
332
|
+
*
|
|
333
|
+
* ВАЖНО!
|
|
334
|
+
* Доступно только в iOS начиная с версии АМ `17.0.0`.
|
|
335
|
+
* В несовместимом окружении вызов игнорируется.
|
|
336
|
+
*
|
|
337
|
+
* @param area Область перетаскивания шторы.
|
|
338
|
+
*/
|
|
339
|
+
setSheetDragArea(area) {
|
|
340
|
+
this.webFeaturesService.setSheetDragArea(area);
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Скрывает нативный таббар.
|
|
344
|
+
*
|
|
345
|
+
* ВАЖНО!
|
|
346
|
+
* Доступно только в iOS начиная с версии АМ `17.0.0`.
|
|
347
|
+
* В несовместимом окружении вызов игнорируется.
|
|
348
|
+
* Управляется нативным фича-тоглом `mainSuperAppIOS`.
|
|
349
|
+
*/
|
|
350
|
+
hideTabbar() {
|
|
351
|
+
this.webFeaturesService.hideTabbar();
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Показывает нативный таббар и, при переданном `selectedId`, выбирает вкладку.
|
|
355
|
+
*
|
|
356
|
+
* ВАЖНО!
|
|
357
|
+
* Доступно только в iOS начиная с версии АМ `17.0.0`.
|
|
358
|
+
* В несовместимом окружении вызов игнорируется.
|
|
359
|
+
* Управляется нативным фича-тоглом `mainSuperAppIOS`.
|
|
360
|
+
*
|
|
361
|
+
* @param selectedId id вкладки, которую выбрать при показе.
|
|
362
|
+
*/
|
|
363
|
+
showTabbar(selectedId) {
|
|
364
|
+
this.webFeaturesService.showTabbar(selectedId);
|
|
365
|
+
}
|
|
299
366
|
}
|
|
300
367
|
exports.BridgeToNative = BridgeToNative;
|
package/client/constants.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type NativeFeaturesFromVersion } from './types';
|
|
1
|
+
import { type NativeFeaturesFromVersion, type WebFeatureAction } from './types';
|
|
2
2
|
export declare const ANDROID_APP_ID = "alfabank";
|
|
3
3
|
export declare const DEEP_LINK_PATTERN: RegExp;
|
|
4
4
|
export declare const NATIVE_FEATURES_FROM_VERSION: NativeFeaturesFromVersion;
|
|
@@ -11,3 +11,6 @@ export declare const VERSION_TO_IOS_APP_ID: {
|
|
|
11
11
|
readonly '13.5.0': "assistmekz";
|
|
12
12
|
readonly '14.5.0': "smartfinancementor";
|
|
13
13
|
};
|
|
14
|
+
export declare const WEB_FEATURES_FROM_VERSION: Readonly<Record<WebFeatureAction, {
|
|
15
|
+
fromVersion: string;
|
|
16
|
+
}>>;
|
package/client/constants.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.VERSION_TO_IOS_APP_ID = exports.NATIVE_FEATURES_FROM_VERSION = exports.DEEP_LINK_PATTERN = exports.ANDROID_APP_ID = void 0;
|
|
3
|
+
exports.WEB_FEATURES_FROM_VERSION = exports.VERSION_TO_IOS_APP_ID = exports.NATIVE_FEATURES_FROM_VERSION = exports.DEEP_LINK_PATTERN = exports.ANDROID_APP_ID = void 0;
|
|
4
4
|
exports.ANDROID_APP_ID = 'alfabank';
|
|
5
5
|
exports.DEEP_LINK_PATTERN = /^(\/|alfabank:\/{3}dashboard\/|alfabank:\/{3}|alfabank:\/{2}|https:\/{2}online.alfabank.ru\/)/;
|
|
6
6
|
exports.NATIVE_FEATURES_FROM_VERSION = {
|
|
@@ -28,3 +28,10 @@ exports.VERSION_TO_IOS_APP_ID = {
|
|
|
28
28
|
'13.5.0': 'assistmekz',
|
|
29
29
|
'14.5.0': 'smartfinancementor',
|
|
30
30
|
};
|
|
31
|
+
exports.WEB_FEATURES_FROM_VERSION = {
|
|
32
|
+
'geo.configuration': { fromVersion: '17.0.0' },
|
|
33
|
+
'haptics.vibrate': { fromVersion: '17.0.0' },
|
|
34
|
+
'sheet.setDragArea': { fromVersion: '17.0.0' },
|
|
35
|
+
'tabbar.hide': { fromVersion: '17.0.0' },
|
|
36
|
+
'tabbar.show': { fromVersion: '17.0.0' },
|
|
37
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { type LogError, type WebFeatureAction } from '../types';
|
|
2
|
+
export declare const CALL_TIMEOUT_MS = 10000;
|
|
3
|
+
/**
|
|
4
|
+
* Сервис-транспорт для взаимодействия WA с NA через WebFeatures-мост.
|
|
5
|
+
*
|
|
6
|
+
* Отправляет сообщения (`send` / `call`) и обрабатывает асинхронные ответы на `call`
|
|
7
|
+
* через `window.webBridge.callback`.
|
|
8
|
+
*
|
|
9
|
+
* Отправляет сообщения напрямую через мост соответствующей платформы.
|
|
10
|
+
*/
|
|
11
|
+
export declare class NativeBridgeService {
|
|
12
|
+
private logError?;
|
|
13
|
+
private pendingCalls;
|
|
14
|
+
private savedCallback?;
|
|
15
|
+
constructor(logError?: LogError | undefined);
|
|
16
|
+
/**
|
|
17
|
+
* Отправляет fire-and-forget сообщение в NA (без ожидания ответа).
|
|
18
|
+
*/
|
|
19
|
+
send(action: WebFeatureAction, data: unknown): void;
|
|
20
|
+
/**
|
|
21
|
+
* Отправляет сообщение типа `call` и возвращает промис с ответом NA.
|
|
22
|
+
*
|
|
23
|
+
* @throws Если транспорт недоступен или ответ не пришёл за {@link CALL_TIMEOUT_MS}.
|
|
24
|
+
*/
|
|
25
|
+
call<Data>(action: WebFeatureAction, data: unknown): Promise<Data>;
|
|
26
|
+
private handleCallback;
|
|
27
|
+
/**
|
|
28
|
+
* Проверяет доступность транспорта для указанного типа сообщения.
|
|
29
|
+
*/
|
|
30
|
+
private hasTransport;
|
|
31
|
+
/**
|
|
32
|
+
* Отправляет тело сообщения доступным транспортом.
|
|
33
|
+
*
|
|
34
|
+
* @returns `true`, если сообщение удалось передать.
|
|
35
|
+
*/
|
|
36
|
+
private dispatch;
|
|
37
|
+
private reportNoTransport;
|
|
38
|
+
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NativeBridgeService = exports.CALL_TIMEOUT_MS = void 0;
|
|
4
|
+
exports.CALL_TIMEOUT_MS = 10000;
|
|
5
|
+
const BRIDGE_KIND_SEND = 'send';
|
|
6
|
+
const BRIDGE_KIND_CALL = 'call';
|
|
7
|
+
let requestIdCounter = 0;
|
|
8
|
+
const generateRequestId = () => {
|
|
9
|
+
if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
|
|
10
|
+
return crypto.randomUUID();
|
|
11
|
+
}
|
|
12
|
+
requestIdCounter += 1;
|
|
13
|
+
return String(requestIdCounter);
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Сервис-транспорт для взаимодействия WA с NA через WebFeatures-мост.
|
|
17
|
+
*
|
|
18
|
+
* Отправляет сообщения (`send` / `call`) и обрабатывает асинхронные ответы на `call`
|
|
19
|
+
* через `window.webBridge.callback`.
|
|
20
|
+
*
|
|
21
|
+
* Отправляет сообщения напрямую через мост соответствующей платформы.
|
|
22
|
+
*/
|
|
23
|
+
class NativeBridgeService {
|
|
24
|
+
constructor(logError) {
|
|
25
|
+
var _a;
|
|
26
|
+
this.logError = logError;
|
|
27
|
+
this.pendingCalls = new Map();
|
|
28
|
+
this.handleCallback = this.handleCallback.bind(this);
|
|
29
|
+
this.savedCallback = (_a = window.webBridge) === null || _a === void 0 ? void 0 : _a.callback;
|
|
30
|
+
window.webBridge = Object.assign(Object.assign({}, window.webBridge), { callback: this.handleCallback });
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Отправляет fire-and-forget сообщение в NA (без ожидания ответа).
|
|
34
|
+
*/
|
|
35
|
+
send(action, data) {
|
|
36
|
+
const body = {
|
|
37
|
+
kind: BRIDGE_KIND_SEND,
|
|
38
|
+
action,
|
|
39
|
+
requestId: generateRequestId(),
|
|
40
|
+
data,
|
|
41
|
+
};
|
|
42
|
+
if (!this.dispatch(body)) {
|
|
43
|
+
this.reportNoTransport('send', action);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Отправляет сообщение типа `call` и возвращает промис с ответом NA.
|
|
48
|
+
*
|
|
49
|
+
* @throws Если транспорт недоступен или ответ не пришёл за {@link CALL_TIMEOUT_MS}.
|
|
50
|
+
*/
|
|
51
|
+
call(action, data) {
|
|
52
|
+
const requestId = generateRequestId();
|
|
53
|
+
const body = {
|
|
54
|
+
kind: BRIDGE_KIND_CALL,
|
|
55
|
+
action,
|
|
56
|
+
requestId,
|
|
57
|
+
data,
|
|
58
|
+
};
|
|
59
|
+
if (!this.hasTransport(BRIDGE_KIND_CALL)) {
|
|
60
|
+
this.reportNoTransport('call', action);
|
|
61
|
+
return Promise.reject(new Error(`NativeBridgeService: transport is not available for "${action}"`));
|
|
62
|
+
}
|
|
63
|
+
return new Promise((resolve, reject) => {
|
|
64
|
+
const timeoutId = setTimeout(() => {
|
|
65
|
+
this.pendingCalls.delete(requestId);
|
|
66
|
+
reject(new Error(`NativeBridgeService: request "${action}" timed out`));
|
|
67
|
+
}, exports.CALL_TIMEOUT_MS);
|
|
68
|
+
this.pendingCalls.set(requestId, {
|
|
69
|
+
resolve: resolve,
|
|
70
|
+
reject,
|
|
71
|
+
timeoutId,
|
|
72
|
+
});
|
|
73
|
+
this.dispatch(body);
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
handleCallback(requestId, payload) {
|
|
77
|
+
var _a;
|
|
78
|
+
const pending = this.pendingCalls.get(requestId);
|
|
79
|
+
if (!pending) {
|
|
80
|
+
(_a = this.savedCallback) === null || _a === void 0 ? void 0 : _a.call(this, requestId, payload);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
clearTimeout(pending.timeoutId);
|
|
84
|
+
this.pendingCalls.delete(requestId);
|
|
85
|
+
if (payload.error) {
|
|
86
|
+
const error = new Error(payload.error.message);
|
|
87
|
+
error.code = payload.error.code;
|
|
88
|
+
pending.reject(error);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
pending.resolve(payload.data);
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Проверяет доступность транспорта для указанного типа сообщения.
|
|
95
|
+
*/
|
|
96
|
+
// eslint-disable-next-line class-methods-use-this -- единая точка доступа к глобалам window.
|
|
97
|
+
hasTransport(kind) {
|
|
98
|
+
var _a, _b, _c, _d, _e;
|
|
99
|
+
return Boolean(((_c = (_b = (_a = window.webkit) === null || _a === void 0 ? void 0 : _a.messageHandlers) === null || _b === void 0 ? void 0 : _b.bridge) === null || _c === void 0 ? void 0 : _c.postMessage) ||
|
|
100
|
+
(kind === BRIDGE_KIND_CALL
|
|
101
|
+
? typeof ((_d = window.Android) === null || _d === void 0 ? void 0 : _d.call) === 'function'
|
|
102
|
+
: typeof ((_e = window.Android) === null || _e === void 0 ? void 0 : _e.send) === 'function'));
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Отправляет тело сообщения доступным транспортом.
|
|
106
|
+
*
|
|
107
|
+
* @returns `true`, если сообщение удалось передать.
|
|
108
|
+
*/
|
|
109
|
+
// eslint-disable-next-line class-methods-use-this -- единая точка доступа к глобалам window.
|
|
110
|
+
dispatch(body) {
|
|
111
|
+
var _a, _b, _c, _d, _e;
|
|
112
|
+
if ((_c = (_b = (_a = window.webkit) === null || _a === void 0 ? void 0 : _a.messageHandlers) === null || _b === void 0 ? void 0 : _b.bridge) === null || _c === void 0 ? void 0 : _c.postMessage) {
|
|
113
|
+
window.webkit.messageHandlers.bridge.postMessage(body);
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
if (body.kind === BRIDGE_KIND_CALL && typeof ((_d = window.Android) === null || _d === void 0 ? void 0 : _d.call) === 'function') {
|
|
117
|
+
window.Android.call(JSON.stringify(body));
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
if (body.kind === BRIDGE_KIND_SEND && typeof ((_e = window.Android) === null || _e === void 0 ? void 0 : _e.send) === 'function') {
|
|
121
|
+
window.Android.send(JSON.stringify(body));
|
|
122
|
+
return true;
|
|
123
|
+
}
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
reportNoTransport(kind, action) {
|
|
127
|
+
var _a;
|
|
128
|
+
const message = `NativeBridgeService: native bridge is not available, "${action}" (${kind}) was not sent`;
|
|
129
|
+
(_a = this.logError) === null || _a === void 0 ? void 0 : _a.call(this, message, { action, kind });
|
|
130
|
+
// eslint-disable-next-line no-console -- сообщаем потребителю о недоступности моста.
|
|
131
|
+
console.error(message);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
exports.NativeBridgeService = NativeBridgeService;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type Environment, type NativeFeatureKey } from '../types';
|
|
1
|
+
import { type Environment, type NativeFeatureKey, type WebFeatureAction } from '../types';
|
|
2
2
|
export declare const isValidVersionFormat: (version?: string) => version is string;
|
|
3
3
|
/**
|
|
4
4
|
* Сравнивает версии формата `x.y.z` покомпонентно, как числа.
|
|
@@ -10,3 +10,8 @@ export declare const isVersionHigherOrEqual: (version: string, versionToCompare:
|
|
|
10
10
|
* Версия в неизвестном формате считается `0.0.0`.
|
|
11
11
|
*/
|
|
12
12
|
export declare const canUseNativeFeature: (platform: Environment, appVersion: string, feature: NativeFeatureKey) => boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Проверяет, поддерживает ли NA указанной платформы и версии фичу WebFeatures.
|
|
15
|
+
* Фичи WebFeatures доступны только на iOS. Версия в неизвестном формате считается `0.0.0`.
|
|
16
|
+
*/
|
|
17
|
+
export declare const canUseWebFeature: (platform: Environment, appVersion: string, action: WebFeatureAction) => boolean;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.canUseNativeFeature = exports.isVersionHigherOrEqual = exports.isValidVersionFormat = void 0;
|
|
3
|
+
exports.canUseWebFeature = exports.canUseNativeFeature = exports.isVersionHigherOrEqual = exports.isValidVersionFormat = void 0;
|
|
4
4
|
const constants_1 = require("../constants");
|
|
5
5
|
const VERSION_FORMAT_PATTERN = /^\d+\.\d+\.\d+$/;
|
|
6
6
|
const isValidVersionFormat = (version) => Boolean(version) && VERSION_FORMAT_PATTERN.test(version);
|
|
@@ -32,3 +32,15 @@ const canUseNativeFeature = (platform, appVersion, feature) => {
|
|
|
32
32
|
return (0, exports.isVersionHigherOrEqual)((0, exports.isValidVersionFormat)(appVersion) ? appVersion : '0.0.0', fromVersion);
|
|
33
33
|
};
|
|
34
34
|
exports.canUseNativeFeature = canUseNativeFeature;
|
|
35
|
+
/**
|
|
36
|
+
* Проверяет, поддерживает ли NA указанной платформы и версии фичу WebFeatures.
|
|
37
|
+
* Фичи WebFeatures доступны только на iOS. Версия в неизвестном формате считается `0.0.0`.
|
|
38
|
+
*/
|
|
39
|
+
const canUseWebFeature = (platform, appVersion, action) => {
|
|
40
|
+
if (platform !== 'ios') {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
const { fromVersion } = constants_1.WEB_FEATURES_FROM_VERSION[action];
|
|
44
|
+
return (0, exports.isVersionHigherOrEqual)((0, exports.isValidVersionFormat)(appVersion) ? appVersion : '0.0.0', fromVersion);
|
|
45
|
+
};
|
|
46
|
+
exports.canUseWebFeature = canUseWebFeature;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { type WebFeaturesGeoConfiguration, type WebFeaturesHapticsOptions, type WebFeaturesSheetDragArea } from '../types';
|
|
2
|
+
import { type NativeBridgeService } from './native-bridge-service';
|
|
3
|
+
import { type NativeParamsService } from './native-params-service';
|
|
4
|
+
/**
|
|
5
|
+
* Доменный сервис фич WebFeatures (iOS, АМ ≥ 17.0.0).
|
|
6
|
+
*
|
|
7
|
+
* Инкапсулирует гейт доступности по платформе и версии NA и формирует
|
|
8
|
+
* данные для вызовов через {@link NativeBridgeService}.
|
|
9
|
+
*/
|
|
10
|
+
export declare class WebFeaturesService {
|
|
11
|
+
private nativeParamsService;
|
|
12
|
+
private nativeBridgeService;
|
|
13
|
+
constructor(nativeParamsService: NativeParamsService, nativeBridgeService: NativeBridgeService);
|
|
14
|
+
/**
|
|
15
|
+
* Возвращает статус доступа к геолокации и, при наличии разрешения, координаты пользователя
|
|
16
|
+
*
|
|
17
|
+
* @throws Если фича недоступна в текущем окружении или NA вернул ошибку.
|
|
18
|
+
*/
|
|
19
|
+
getGeoConfiguration(): Promise<WebFeaturesGeoConfiguration>;
|
|
20
|
+
/**
|
|
21
|
+
* Воспроизводит тактильный отклик.
|
|
22
|
+
*/
|
|
23
|
+
vibrate({ type, intensity }: WebFeaturesHapticsOptions): void;
|
|
24
|
+
/**
|
|
25
|
+
* Задаёт область шторы, за которую можно её перетаскивать.
|
|
26
|
+
*/
|
|
27
|
+
setSheetDragArea(area: WebFeaturesSheetDragArea): void;
|
|
28
|
+
/**
|
|
29
|
+
* Скрывает нативный таббар.
|
|
30
|
+
*/
|
|
31
|
+
hideTabbar(): void;
|
|
32
|
+
/**
|
|
33
|
+
* Показывает нативный таббар и, при переданном `selectedId`, выбирает вкладку.
|
|
34
|
+
*/
|
|
35
|
+
showTabbar(selectedId?: string): void;
|
|
36
|
+
private isAvailable;
|
|
37
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.WebFeaturesService = void 0;
|
|
4
|
+
const native_features_1 = require("./native-features");
|
|
5
|
+
/**
|
|
6
|
+
* Доменный сервис фич WebFeatures (iOS, АМ ≥ 17.0.0).
|
|
7
|
+
*
|
|
8
|
+
* Инкапсулирует гейт доступности по платформе и версии NA и формирует
|
|
9
|
+
* данные для вызовов через {@link NativeBridgeService}.
|
|
10
|
+
*/
|
|
11
|
+
class WebFeaturesService {
|
|
12
|
+
constructor(nativeParamsService, nativeBridgeService) {
|
|
13
|
+
this.nativeParamsService = nativeParamsService;
|
|
14
|
+
this.nativeBridgeService = nativeBridgeService;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Возвращает статус доступа к геолокации и, при наличии разрешения, координаты пользователя
|
|
18
|
+
*
|
|
19
|
+
* @throws Если фича недоступна в текущем окружении или NA вернул ошибку.
|
|
20
|
+
*/
|
|
21
|
+
getGeoConfiguration() {
|
|
22
|
+
if (!this.isAvailable('geo.configuration')) {
|
|
23
|
+
return Promise.reject(new Error('WebFeatures: geo.configuration is unavailable in this environment'));
|
|
24
|
+
}
|
|
25
|
+
return this.nativeBridgeService.call('geo.configuration', {});
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Воспроизводит тактильный отклик.
|
|
29
|
+
*/
|
|
30
|
+
vibrate({ type, intensity }) {
|
|
31
|
+
if (!this.isAvailable('haptics.vibrate')) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
this.nativeBridgeService.send('haptics.vibrate', Object.assign({ type }, (intensity === undefined ? {} : { intensity })));
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Задаёт область шторы, за которую можно её перетаскивать.
|
|
38
|
+
*/
|
|
39
|
+
setSheetDragArea(area) {
|
|
40
|
+
if (!this.isAvailable('sheet.setDragArea')) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
this.nativeBridgeService.send('sheet.setDragArea', { area });
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Скрывает нативный таббар.
|
|
47
|
+
*/
|
|
48
|
+
hideTabbar() {
|
|
49
|
+
if (!this.isAvailable('tabbar.hide')) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
this.nativeBridgeService.send('tabbar.hide', {});
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Показывает нативный таббар и, при переданном `selectedId`, выбирает вкладку.
|
|
56
|
+
*/
|
|
57
|
+
showTabbar(selectedId) {
|
|
58
|
+
if (!this.isAvailable('tabbar.show')) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
this.nativeBridgeService.send('tabbar.show', selectedId === undefined ? {} : { selectedId });
|
|
62
|
+
}
|
|
63
|
+
isAvailable(action) {
|
|
64
|
+
return (0, native_features_1.canUseWebFeature)(this.nativeParamsService.environment, this.nativeParamsService.appVersion, action);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
exports.WebFeaturesService = WebFeaturesService;
|
package/client/types.d.ts
CHANGED
|
@@ -22,4 +22,27 @@ export type NativeFeaturesFromVersion = Readonly<{
|
|
|
22
22
|
}>;
|
|
23
23
|
export type PdfType = 'pdfFile' | 'base64' | 'binary';
|
|
24
24
|
export type Theme = 'light' | 'dark';
|
|
25
|
+
export type WebFeatureAction = 'geo.configuration' | 'haptics.vibrate' | 'sheet.setDragArea' | 'tabbar.hide' | 'tabbar.show';
|
|
26
|
+
export type WebFeaturesGeoPermission = 'allowed' | 'denied' | 'notDetermined' | 'restricted';
|
|
27
|
+
export type WebFeaturesUserCoordinate = {
|
|
28
|
+
latitude: number;
|
|
29
|
+
longitude: number;
|
|
30
|
+
};
|
|
31
|
+
export type WebFeaturesGeoConfiguration = {
|
|
32
|
+
permission: WebFeaturesGeoPermission;
|
|
33
|
+
userCoordinate: WebFeaturesUserCoordinate | null;
|
|
34
|
+
};
|
|
35
|
+
export type WebFeaturesHapticsType = 'light' | 'medium' | 'heavy' | 'soft' | 'rigid' | 'success' | 'warning' | 'error' | 'selection';
|
|
36
|
+
export type WebFeaturesHapticsOptions = {
|
|
37
|
+
type: WebFeaturesHapticsType;
|
|
38
|
+
intensity?: number;
|
|
39
|
+
};
|
|
40
|
+
export type WebFeaturesSheetDragArea = 'wholeSheet' | 'navigationBar';
|
|
41
|
+
export type WebFeaturesCallbackPayload = {
|
|
42
|
+
data: unknown;
|
|
43
|
+
error: {
|
|
44
|
+
code: number;
|
|
45
|
+
message: string;
|
|
46
|
+
} | null;
|
|
47
|
+
};
|
|
25
48
|
export {};
|
package/package.json
CHANGED
|
@@ -1,127 +1,132 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
2
|
+
"name": "@alfalab/bridge-to-native",
|
|
3
|
+
"version": "1.5.2-beta.b951ff8",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"description": "Утилита для удобной работы веб приложения внутри нативного приложения и коммуникации с ним.",
|
|
6
|
+
"engines": {
|
|
7
|
+
"node": ">=20.19.2",
|
|
8
|
+
"npm": "please-use-yarn"
|
|
9
|
+
},
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/core-ds/bridge-to-native.git"
|
|
13
|
+
},
|
|
14
|
+
"exports": {
|
|
15
|
+
"./client": {
|
|
16
|
+
"import": "./client/index.js",
|
|
17
|
+
"require": "./client/index.js",
|
|
18
|
+
"types": "./client/index.d.ts"
|
|
9
19
|
},
|
|
10
|
-
"
|
|
11
|
-
|
|
12
|
-
|
|
20
|
+
"./client/primitives": {
|
|
21
|
+
"import": "./client/primitives.js",
|
|
22
|
+
"require": "./client/primitives.js",
|
|
23
|
+
"types": "./client/primitives.d.ts"
|
|
13
24
|
},
|
|
14
|
-
"
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
"
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
25
|
+
"./server": {
|
|
26
|
+
"import": "./server/index.js",
|
|
27
|
+
"require": "./server/index.js",
|
|
28
|
+
"types": "./server/index.d.ts"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"sideEffects": false,
|
|
32
|
+
"bugs": {
|
|
33
|
+
"url": "https://github.com/core-ds/bridge-to-native/issues"
|
|
34
|
+
},
|
|
35
|
+
"scripts": {
|
|
36
|
+
"build": "yarn build:clean && yarn build:ts",
|
|
37
|
+
"build:clean": "shx rm -rf .publish",
|
|
38
|
+
"build:copy-package-json": "shx cp package.json .publish/package.json",
|
|
39
|
+
"build:ts": "tsc --build",
|
|
40
|
+
"format": "arui-presets-lint format",
|
|
41
|
+
"format:check": "arui-presets-lint format:check",
|
|
42
|
+
"lint": "yarn lint:scripts && yarn format:check",
|
|
43
|
+
"lint:fix": "yarn lint:scripts --fix && yarn format",
|
|
44
|
+
"lint:scripts": "arui-presets-lint scripts",
|
|
45
|
+
"pub": "npm publish .publish --userconfig \"../.npmrc\" --tag \"$TAG\"",
|
|
46
|
+
"release": "yarn build && yarn build:copy-package-json && yarn pub",
|
|
47
|
+
"test": "arui-scripts test --silent --collect-coverage"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@happy-dom/jest-environment": "18.0.1",
|
|
51
|
+
"@types/jest": "29.5.14",
|
|
52
|
+
"@types/node": "20.19.1",
|
|
53
|
+
"arui-presets-lint": "8.7.0",
|
|
54
|
+
"arui-scripts": "19.0.7",
|
|
55
|
+
"copyfiles": "2.4.1",
|
|
56
|
+
"jest-junit": "10.0.0",
|
|
57
|
+
"lint-staged": "^12.5.0",
|
|
58
|
+
"promisify-child-process": "4.1.1",
|
|
59
|
+
"shx": "0.3.4",
|
|
60
|
+
"typescript": "5.5.4"
|
|
61
|
+
},
|
|
62
|
+
"commitlint": {
|
|
63
|
+
"extends": "./node_modules/arui-presets-lint/commitlint"
|
|
64
|
+
},
|
|
65
|
+
"eslintConfig": {
|
|
66
|
+
"extends": "./node_modules/arui-presets-lint/eslint",
|
|
67
|
+
"settings": {
|
|
68
|
+
"react": {
|
|
69
|
+
"version": "18.0.0"
|
|
70
|
+
}
|
|
48
71
|
},
|
|
49
|
-
"
|
|
50
|
-
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
|
|
55
|
-
"copyfiles": "2.4.1",
|
|
56
|
-
"jest-junit": "10.0.0",
|
|
57
|
-
"lint-staged": "^12.5.0",
|
|
58
|
-
"promisify-child-process": "4.1.1",
|
|
59
|
-
"shx": "0.3.4",
|
|
60
|
-
"typescript": "5.5.4"
|
|
61
|
-
},
|
|
62
|
-
"commitlint": {
|
|
63
|
-
"extends": "./node_modules/arui-presets-lint/commitlint"
|
|
64
|
-
},
|
|
65
|
-
"eslintConfig": {
|
|
66
|
-
"extends": "./node_modules/arui-presets-lint/eslint",
|
|
67
|
-
"parserOptions": {
|
|
68
|
-
"project": [
|
|
69
|
-
"./__tests__/tsconfig.json",
|
|
70
|
-
"./src/client/tsconfig.json",
|
|
71
|
-
"./src/server/tsconfig.json"
|
|
72
|
-
]
|
|
73
|
-
},
|
|
74
|
-
"overrides": [
|
|
75
|
-
{
|
|
76
|
-
"files": [
|
|
77
|
-
"__tests__/**/*"
|
|
78
|
-
],
|
|
79
|
-
"rules": {
|
|
80
|
-
"max-lines": "off"
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
]
|
|
72
|
+
"parserOptions": {
|
|
73
|
+
"project": [
|
|
74
|
+
"./__tests__/tsconfig.json",
|
|
75
|
+
"./src/client/tsconfig.json",
|
|
76
|
+
"./src/server/tsconfig.json"
|
|
77
|
+
]
|
|
84
78
|
},
|
|
85
|
-
"
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
"testEnvironment": "@happy-dom/jest-environment",
|
|
90
|
-
"testPathIgnorePatterns": [
|
|
91
|
-
"/__tests__/server/"
|
|
92
|
-
]
|
|
93
|
-
},
|
|
94
|
-
{
|
|
95
|
-
"displayName": "server-tests",
|
|
96
|
-
"testEnvironment": "node",
|
|
97
|
-
"testPathIgnorePatterns": [
|
|
98
|
-
"/__tests__/client/"
|
|
99
|
-
]
|
|
100
|
-
}
|
|
79
|
+
"overrides": [
|
|
80
|
+
{
|
|
81
|
+
"files": [
|
|
82
|
+
"__tests__/**/*"
|
|
101
83
|
],
|
|
102
|
-
"
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
84
|
+
"rules": {
|
|
85
|
+
"max-lines": "off"
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
]
|
|
89
|
+
},
|
|
90
|
+
"jest": {
|
|
91
|
+
"projects": [
|
|
92
|
+
{
|
|
93
|
+
"displayName": "client-tests",
|
|
94
|
+
"testEnvironment": "@happy-dom/jest-environment",
|
|
95
|
+
"testPathIgnorePatterns": [
|
|
96
|
+
"/__tests__/server/"
|
|
113
97
|
]
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
"
|
|
118
|
-
"
|
|
119
|
-
|
|
120
|
-
".yarn/releases/*"
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"displayName": "server-tests",
|
|
101
|
+
"testEnvironment": "node",
|
|
102
|
+
"testPathIgnorePatterns": [
|
|
103
|
+
"/__tests__/client/"
|
|
121
104
|
]
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
105
|
+
}
|
|
106
|
+
],
|
|
107
|
+
"testRegex": [
|
|
108
|
+
"__tests__/.*\\.test\\.ts"
|
|
109
|
+
],
|
|
110
|
+
"coveragePathIgnorePatterns": [
|
|
111
|
+
"/node_modules/",
|
|
112
|
+
"/src/(client|server)/index.ts",
|
|
113
|
+
"/src/client/primitives.ts"
|
|
114
|
+
],
|
|
115
|
+
"reporters": [
|
|
116
|
+
"default",
|
|
117
|
+
"jest-junit"
|
|
118
|
+
]
|
|
119
|
+
},
|
|
120
|
+
"prettier": "arui-presets-lint/prettier",
|
|
121
|
+
"stylelint": {
|
|
122
|
+
"extends": "arui-presets-lint/stylelint",
|
|
123
|
+
"ignoreFiles": [
|
|
124
|
+
"coverage/**/*.js",
|
|
125
|
+
".yarn/releases/*"
|
|
126
|
+
]
|
|
127
|
+
},
|
|
128
|
+
"publishConfig": {
|
|
129
|
+
"registry": "https://registry.npmjs.org"
|
|
130
|
+
},
|
|
131
|
+
"packageManager": "yarn@4.12.0"
|
|
127
132
|
}
|