@de./sdk 2.4.3 → 2.6.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/dist/allend/MSI/native.d.ts +26 -0
- package/dist/allend/MSI/native.js +95 -4
- package/dist/allend/MSI/native.js.map +1 -1
- package/dist/react-native.d.ts +1 -1
- package/dist/react-native.js.map +1 -1
- package/package.json +1 -1
- package/src/allend/MSI/native.tsx +121 -1
- package/src/react-native.ts +3 -1
|
@@ -8,10 +8,36 @@ export interface MSIInterface {
|
|
|
8
8
|
handles: Handles;
|
|
9
9
|
plugins: Plugins;
|
|
10
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* A position as the browser's Geolocation API reports it, which is also what
|
|
13
|
+
* expo-location's `getCurrentPositionAsync` and `watchPositionAsync` give.
|
|
14
|
+
*/
|
|
15
|
+
export type HostPosition = {
|
|
16
|
+
coords: {
|
|
17
|
+
latitude: number;
|
|
18
|
+
longitude: number;
|
|
19
|
+
accuracy?: number | null;
|
|
20
|
+
altitude?: number | null;
|
|
21
|
+
altitudeAccuracy?: number | null;
|
|
22
|
+
heading?: number | null;
|
|
23
|
+
speed?: number | null;
|
|
24
|
+
};
|
|
25
|
+
timestamp: number;
|
|
26
|
+
};
|
|
27
|
+
export interface HostGeolocation {
|
|
28
|
+
getCurrentPosition: () => Promise<HostPosition>;
|
|
29
|
+
/** Calls back on every fix; returns what stops it */
|
|
30
|
+
watchPosition: (onPosition: (position: HostPosition) => void) => () => void;
|
|
31
|
+
}
|
|
11
32
|
export interface MSIProps extends MapOptions {
|
|
12
33
|
onReady?: () => void;
|
|
13
34
|
onError?: (error: Error) => void;
|
|
14
35
|
onLoaded?: (msi: MSIInterface) => void;
|
|
36
|
+
/**
|
|
37
|
+
* The app's own location, for the map to use instead of asking the WebView.
|
|
38
|
+
* Leave it out and iOS prompts in the gateway's name on every launch.
|
|
39
|
+
*/
|
|
40
|
+
geolocation?: HostGeolocation;
|
|
15
41
|
style?: any;
|
|
16
42
|
}
|
|
17
43
|
export interface MSIRef extends Partial<MSIInterface> {
|
|
@@ -68,6 +68,57 @@ function injectedConsole() {
|
|
|
68
68
|
})();
|
|
69
69
|
`;
|
|
70
70
|
}
|
|
71
|
+
/**
|
|
72
|
+
* Answer the page's `navigator.geolocation` from the host app.
|
|
73
|
+
*
|
|
74
|
+
* iOS treats the gateway page as a website: asked for the position there, it
|
|
75
|
+
* prompts again in the page's name (the gateway's host) on every launch, though
|
|
76
|
+
* the app holds location already, and the app has no public way to answer it.
|
|
77
|
+
* With this in place before the page loads, the page asks the app instead and
|
|
78
|
+
* WebKit never prompts. Replies come back through `window.__deGeo`.
|
|
79
|
+
*/
|
|
80
|
+
function injectedGeolocation() {
|
|
81
|
+
return `
|
|
82
|
+
(function(){
|
|
83
|
+
var seq = 0, calls = {}
|
|
84
|
+
var ask = function( kind, id ){
|
|
85
|
+
window.ReactNativeWebView.postMessage( JSON.stringify({ type: '__geo', kind: kind, id: id }) )
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
window.__deGeo = function( reply ){
|
|
89
|
+
var call = calls[ reply.id ]
|
|
90
|
+
if( !call ) return
|
|
91
|
+
if( !call.watch ) delete calls[ reply.id ]
|
|
92
|
+
|
|
93
|
+
reply.error
|
|
94
|
+
? call.fail && call.fail({ code: 2, message: reply.error, PERMISSION_DENIED: 1, POSITION_UNAVAILABLE: 2, TIMEOUT: 3 })
|
|
95
|
+
: call.ok( reply.position )
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
Object.defineProperty( navigator, 'geolocation', {
|
|
99
|
+
configurable: true,
|
|
100
|
+
value: {
|
|
101
|
+
getCurrentPosition: function( ok, fail ){
|
|
102
|
+
var id = ++seq
|
|
103
|
+
calls[ id ] = { ok: ok, fail: fail }
|
|
104
|
+
ask('get', id )
|
|
105
|
+
},
|
|
106
|
+
watchPosition: function( ok, fail ){
|
|
107
|
+
var id = ++seq
|
|
108
|
+
calls[ id ] = { ok: ok, fail: fail, watch: true }
|
|
109
|
+
ask('watch', id )
|
|
110
|
+
return id
|
|
111
|
+
},
|
|
112
|
+
clearWatch: function( id ){
|
|
113
|
+
if( !calls[ id ] ) return
|
|
114
|
+
delete calls[ id ]
|
|
115
|
+
ask('clear', id )
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
})
|
|
119
|
+
})();
|
|
120
|
+
`;
|
|
121
|
+
}
|
|
71
122
|
/**
|
|
72
123
|
* Resolve the gateway host for the running platform.
|
|
73
124
|
*
|
|
@@ -102,7 +153,9 @@ exports.default = (0, react_1.forwardRef)((props, ref) => {
|
|
|
102
153
|
* the callbacks: a host passing inline handlers had the mount-time ones
|
|
103
154
|
* called forever.
|
|
104
155
|
*/
|
|
105
|
-
propsRef = (0, react_1.useRef)(props),
|
|
156
|
+
propsRef = (0, react_1.useRef)(props),
|
|
157
|
+
/** The page's position watches, by the id the page gave them */
|
|
158
|
+
watchesRef = (0, react_1.useRef)(new Map()), [isConnected, setIsConnected] = (0, react_1.useState)(false), [isReady, setIsReady] = (0, react_1.useState)(false),
|
|
106
159
|
/** Pages loaded: every load is a new page, with nothing the last one drew */
|
|
107
160
|
[loads, setLoads] = (0, react_1.useState)(0), baseURL = gatewayURL(props),
|
|
108
161
|
/**
|
|
@@ -168,7 +221,7 @@ exports.default = (0, react_1.forwardRef)((props, ref) => {
|
|
|
168
221
|
* Resolve the token here rather than at mount, so a reconnect after a
|
|
169
222
|
* backgrounded app or a dropped bridge binds with a current token.
|
|
170
223
|
*/
|
|
171
|
-
const { getAccessToken, onReady, onError, onLoaded, style, ...config } = propsRef.current;
|
|
224
|
+
const { getAccessToken, onReady, onError, onLoaded, geolocation, style, ...config } = propsRef.current;
|
|
172
225
|
await wio.emitAsync('bind', {
|
|
173
226
|
...config,
|
|
174
227
|
accessToken: (0, token_1.default)(propsRef.current),
|
|
@@ -221,6 +274,7 @@ exports.default = (0, react_1.forwardRef)((props, ref) => {
|
|
|
221
274
|
return () => {
|
|
222
275
|
subscription.remove();
|
|
223
276
|
wio.disconnect();
|
|
277
|
+
stopWatches();
|
|
224
278
|
apiRef.current = null;
|
|
225
279
|
builtForRef.current = 0;
|
|
226
280
|
};
|
|
@@ -251,11 +305,48 @@ exports.default = (0, react_1.forwardRef)((props, ref) => {
|
|
|
251
305
|
setLoads(n => n + 1);
|
|
252
306
|
initializeConnection();
|
|
253
307
|
};
|
|
308
|
+
/**
|
|
309
|
+
* Answer the page's position requests from the host -- see
|
|
310
|
+
* `injectedGeolocation`.
|
|
311
|
+
*/
|
|
312
|
+
const answer = (reply) => {
|
|
313
|
+
var _a;
|
|
314
|
+
(_a = webViewRef.current) === null || _a === void 0 ? void 0 : _a.injectJavaScript(`window.__deGeo && window.__deGeo(${JSON.stringify(reply)}); true;`);
|
|
315
|
+
};
|
|
316
|
+
const locate = (kind, id) => {
|
|
317
|
+
var _a;
|
|
318
|
+
const { geolocation } = propsRef.current;
|
|
319
|
+
if (!geolocation)
|
|
320
|
+
return;
|
|
321
|
+
switch (kind) {
|
|
322
|
+
case 'get':
|
|
323
|
+
geolocation.getCurrentPosition()
|
|
324
|
+
.then(position => answer({ id, position }))
|
|
325
|
+
.catch((error) => answer({ id, error: String((error === null || error === void 0 ? void 0 : error.message) || error) }));
|
|
326
|
+
break;
|
|
327
|
+
case 'watch':
|
|
328
|
+
watchesRef.current.set(id, geolocation.watchPosition(position => answer({ id, position })));
|
|
329
|
+
break;
|
|
330
|
+
case 'clear':
|
|
331
|
+
(_a = watchesRef.current.get(id)) === null || _a === void 0 ? void 0 : _a();
|
|
332
|
+
watchesRef.current.delete(id);
|
|
333
|
+
break;
|
|
334
|
+
}
|
|
335
|
+
};
|
|
336
|
+
// A new page starts with no watches of its own; the last page's are dead
|
|
337
|
+
function stopWatches() {
|
|
338
|
+
watchesRef.current.forEach(stop => stop());
|
|
339
|
+
watchesRef.current.clear();
|
|
340
|
+
}
|
|
254
341
|
const onMessage = (event) => {
|
|
255
342
|
var _a;
|
|
256
343
|
// Console forwarding rides the same bridge; peel it off before WIO sees it
|
|
257
344
|
try {
|
|
258
345
|
const data = JSON.parse(event.nativeEvent.data);
|
|
346
|
+
if ((data === null || data === void 0 ? void 0 : data.type) === '__geo') {
|
|
347
|
+
locate(data.kind, data.id);
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
259
350
|
if ((data === null || data === void 0 ? void 0 : data.type) === '__console') {
|
|
260
351
|
const message = `[MSI gateway] ${data.message}`;
|
|
261
352
|
switch (data.level) {
|
|
@@ -275,14 +366,14 @@ exports.default = (0, react_1.forwardRef)((props, ref) => {
|
|
|
275
366
|
}
|
|
276
367
|
(_a = wioRef.current) === null || _a === void 0 ? void 0 : _a.handleMessage(event);
|
|
277
368
|
};
|
|
278
|
-
return ((0, jsx_runtime_1.jsx)(react_native_1.View, { style: [styles.container, props.style], children: (0, jsx_runtime_1.jsx)(react_native_webview_1.WebView, { ref: webViewRef, source: { uri: baseURL }, style: styles.webview, injectedJavaScript: `
|
|
369
|
+
return ((0, jsx_runtime_1.jsx)(react_native_1.View, { style: [styles.container, props.style], children: (0, jsx_runtime_1.jsx)(react_native_webview_1.WebView, { ref: webViewRef, source: { uri: baseURL }, style: styles.webview, injectedJavaScriptBeforeContentLoaded: props.geolocation ? injectedGeolocation() : undefined, injectedJavaScript: `
|
|
279
370
|
${props.env === 'dev' ? injectedConsole() : ''}
|
|
280
371
|
${injectedBridge}
|
|
281
372
|
`, javaScriptEnabled: true, domStorageEnabled: true, geolocationEnabled: true, allowsInlineMediaPlayback: true,
|
|
282
373
|
// The host app owns the status bar. Left on, the WebView restores the
|
|
283
374
|
// style it saw at creation whenever any window shows or hides — the
|
|
284
375
|
// keyboard included — overriding whatever screen is now on top.
|
|
285
|
-
autoManageStatusBarEnabled: false, cacheEnabled: props.env !== 'dev', incognito: props.env === 'dev', androidLayerType: "hardware", allowsBackForwardNavigationGestures: false, bounces: false, scrollEnabled: false, originWhitelist: [baseURL], onShouldStartLoadWithRequest: ({ url }) => isGatewayURL(url), onMessage: onMessage, onLoadEnd: onLoadEnd,
|
|
376
|
+
autoManageStatusBarEnabled: false, cacheEnabled: props.env !== 'dev', incognito: props.env === 'dev', androidLayerType: "hardware", allowsBackForwardNavigationGestures: false, bounces: false, scrollEnabled: false, originWhitelist: [baseURL], onShouldStartLoadWithRequest: ({ url }) => isGatewayURL(url), onMessage: onMessage, onLoadStart: stopWatches, onLoadEnd: onLoadEnd,
|
|
286
377
|
// iOS kills a WebView's content process under memory pressure and
|
|
287
378
|
// leaves the view blank: load the page again rather than show nothing
|
|
288
379
|
onContentProcessDidTerminate: () => { var _a; return (_a = webViewRef.current) === null || _a === void 0 ? void 0 : _a.reload(); }, onError: ({ nativeEvent }) => reportError(new Error((nativeEvent === null || nativeEvent === void 0 ? void 0 : nativeEvent.description) || 'WebView error')) }) }));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"native.js","sourceRoot":"","sources":["../../../src/allend/MSI/native.tsx"],"names":[],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"native.js","sourceRoot":"","sources":["../../../src/allend/MSI/native.tsx"],"names":[],"mappings":"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"}
|
package/dist/react-native.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export * from './core';
|
|
2
|
-
export { default as MSI, plugin, type MSIInterface, type MSIProps, type MSIRef } from './allend/MSI/native';
|
|
2
|
+
export { default as MSI, plugin, type MSIInterface, type MSIProps, type MSIRef, type HostGeolocation, type HostPosition } from './allend/MSI/native';
|
|
3
3
|
declare const De: {
|
|
4
4
|
MSI: import("react").ForwardRefExoticComponent<import("./allend/MSI/native").MSIProps & import("react").RefAttributes<import("./allend/MSI/native").MSIRef>>;
|
|
5
5
|
Auth: typeof import("./core").Auth;
|
package/dist/react-native.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react-native.js","sourceRoot":"","sources":["../src/react-native.ts"],"names":[],"mappings":";AAAA,iFAAiF;AACjF,EAAE;AACF,gFAAgF;AAChF,EAAE;AACF,gFAAgF;AAChF,8EAA8E;AAC9E,gFAAgF;AAChF,eAAe;AACf,EAAE;AACF,oDAAoD;AACpD,EAAE;AACF,SAAS;AACT,gBAAgB;AAChB,mCAAmC;AACnC,8CAA8C;AAC9C,OAAO;AACP,EAAE;AACF,8EAA8E;AAC9E,gFAAgF;AAChF,kBAAkB;AAClB,EAAE;AACF,gFAAgF;;;;;;;;;;;;;;;;;;;;AAEhF,yCAAsB;AAEtB,2DAA2D;AAC3D,
|
|
1
|
+
{"version":3,"file":"react-native.js","sourceRoot":"","sources":["../src/react-native.ts"],"names":[],"mappings":";AAAA,iFAAiF;AACjF,EAAE;AACF,gFAAgF;AAChF,EAAE;AACF,gFAAgF;AAChF,8EAA8E;AAC9E,gFAAgF;AAChF,eAAe;AACf,EAAE;AACF,oDAAoD;AACpD,EAAE;AACF,SAAS;AACT,gBAAgB;AAChB,mCAAmC;AACnC,8CAA8C;AAC9C,OAAO;AACP,EAAE;AACF,8EAA8E;AAC9E,gFAAgF;AAChF,kBAAkB;AAClB,EAAE;AACF,gFAAgF;;;;;;;;;;;;;;;;;;;;AAEhF,yCAAsB;AAEtB,2DAA2D;AAC3D,8CAQ4B;AAP3B,8GAAA,OAAO,OAAO;AACd,gGAAA,MAAM,OAAA;AAQP,iEAAqC;AACrC,iCAA6B;AAE7B,MAAM,EAAE,GAAG;IACV,GAAG,WAAI;IACP,GAAG,EAAH,gBAAG;CACH,CAAA;AAED,kBAAe,EAAE,CAAA"}
|
package/package.json
CHANGED
|
@@ -75,6 +75,81 @@ function injectedConsole(): string {
|
|
|
75
75
|
`
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
/**
|
|
79
|
+
* Answer the page's `navigator.geolocation` from the host app.
|
|
80
|
+
*
|
|
81
|
+
* iOS treats the gateway page as a website: asked for the position there, it
|
|
82
|
+
* prompts again in the page's name (the gateway's host) on every launch, though
|
|
83
|
+
* the app holds location already, and the app has no public way to answer it.
|
|
84
|
+
* With this in place before the page loads, the page asks the app instead and
|
|
85
|
+
* WebKit never prompts. Replies come back through `window.__deGeo`.
|
|
86
|
+
*/
|
|
87
|
+
function injectedGeolocation(): string {
|
|
88
|
+
return `
|
|
89
|
+
(function(){
|
|
90
|
+
var seq = 0, calls = {}
|
|
91
|
+
var ask = function( kind, id ){
|
|
92
|
+
window.ReactNativeWebView.postMessage( JSON.stringify({ type: '__geo', kind: kind, id: id }) )
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
window.__deGeo = function( reply ){
|
|
96
|
+
var call = calls[ reply.id ]
|
|
97
|
+
if( !call ) return
|
|
98
|
+
if( !call.watch ) delete calls[ reply.id ]
|
|
99
|
+
|
|
100
|
+
reply.error
|
|
101
|
+
? call.fail && call.fail({ code: 2, message: reply.error, PERMISSION_DENIED: 1, POSITION_UNAVAILABLE: 2, TIMEOUT: 3 })
|
|
102
|
+
: call.ok( reply.position )
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
Object.defineProperty( navigator, 'geolocation', {
|
|
106
|
+
configurable: true,
|
|
107
|
+
value: {
|
|
108
|
+
getCurrentPosition: function( ok, fail ){
|
|
109
|
+
var id = ++seq
|
|
110
|
+
calls[ id ] = { ok: ok, fail: fail }
|
|
111
|
+
ask('get', id )
|
|
112
|
+
},
|
|
113
|
+
watchPosition: function( ok, fail ){
|
|
114
|
+
var id = ++seq
|
|
115
|
+
calls[ id ] = { ok: ok, fail: fail, watch: true }
|
|
116
|
+
ask('watch', id )
|
|
117
|
+
return id
|
|
118
|
+
},
|
|
119
|
+
clearWatch: function( id ){
|
|
120
|
+
if( !calls[ id ] ) return
|
|
121
|
+
delete calls[ id ]
|
|
122
|
+
ask('clear', id )
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
})
|
|
126
|
+
})();
|
|
127
|
+
`
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* A position as the browser's Geolocation API reports it, which is also what
|
|
132
|
+
* expo-location's `getCurrentPositionAsync` and `watchPositionAsync` give.
|
|
133
|
+
*/
|
|
134
|
+
export type HostPosition = {
|
|
135
|
+
coords: {
|
|
136
|
+
latitude: number
|
|
137
|
+
longitude: number
|
|
138
|
+
accuracy?: number | null
|
|
139
|
+
altitude?: number | null
|
|
140
|
+
altitudeAccuracy?: number | null
|
|
141
|
+
heading?: number | null
|
|
142
|
+
speed?: number | null
|
|
143
|
+
}
|
|
144
|
+
timestamp: number
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export interface HostGeolocation {
|
|
148
|
+
getCurrentPosition: () => Promise<HostPosition>
|
|
149
|
+
/** Calls back on every fix; returns what stops it */
|
|
150
|
+
watchPosition: ( onPosition: ( position: HostPosition ) => void ) => () => void
|
|
151
|
+
}
|
|
152
|
+
|
|
78
153
|
/**
|
|
79
154
|
* Resolve the gateway host for the running platform.
|
|
80
155
|
*
|
|
@@ -95,6 +170,11 @@ export interface MSIProps extends MapOptions {
|
|
|
95
170
|
onReady?: () => void
|
|
96
171
|
onError?: ( error: Error ) => void
|
|
97
172
|
onLoaded?: ( msi: MSIInterface ) => void
|
|
173
|
+
/**
|
|
174
|
+
* The app's own location, for the map to use instead of asking the WebView.
|
|
175
|
+
* Leave it out and iOS prompts in the gateway's name on every launch.
|
|
176
|
+
*/
|
|
177
|
+
geolocation?: HostGeolocation
|
|
98
178
|
style?: any
|
|
99
179
|
}
|
|
100
180
|
|
|
@@ -128,6 +208,8 @@ export default forwardRef<MSIRef, MSIProps>( ( props, ref ) => {
|
|
|
128
208
|
* called forever.
|
|
129
209
|
*/
|
|
130
210
|
propsRef = useRef( props ),
|
|
211
|
+
/** The page's position watches, by the id the page gave them */
|
|
212
|
+
watchesRef = useRef( new Map<number, () => void>() ),
|
|
131
213
|
|
|
132
214
|
[ isConnected, setIsConnected ] = useState( false ),
|
|
133
215
|
[ isReady, setIsReady ] = useState( false ),
|
|
@@ -207,7 +289,7 @@ export default forwardRef<MSIRef, MSIProps>( ( props, ref ) => {
|
|
|
207
289
|
* Resolve the token here rather than at mount, so a reconnect after a
|
|
208
290
|
* backgrounded app or a dropped bridge binds with a current token.
|
|
209
291
|
*/
|
|
210
|
-
const { getAccessToken, onReady, onError, onLoaded, style, ...config } = propsRef.current
|
|
292
|
+
const { getAccessToken, onReady, onError, onLoaded, geolocation, style, ...config } = propsRef.current
|
|
211
293
|
|
|
212
294
|
await wio.emitAsync('bind', {
|
|
213
295
|
...config,
|
|
@@ -260,6 +342,7 @@ export default forwardRef<MSIRef, MSIProps>( ( props, ref ) => {
|
|
|
260
342
|
return () => {
|
|
261
343
|
subscription.remove()
|
|
262
344
|
wio.disconnect()
|
|
345
|
+
stopWatches()
|
|
263
346
|
|
|
264
347
|
apiRef.current = null
|
|
265
348
|
builtForRef.current = 0
|
|
@@ -300,10 +383,45 @@ export default forwardRef<MSIRef, MSIProps>( ( props, ref ) => {
|
|
|
300
383
|
initializeConnection()
|
|
301
384
|
}
|
|
302
385
|
|
|
386
|
+
/**
|
|
387
|
+
* Answer the page's position requests from the host -- see
|
|
388
|
+
* `injectedGeolocation`.
|
|
389
|
+
*/
|
|
390
|
+
const answer = ( reply: object ) => {
|
|
391
|
+
webViewRef.current?.injectJavaScript(`window.__deGeo && window.__deGeo(${JSON.stringify( reply )}); true;`)
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
const locate = ( kind: string, id: number ) => {
|
|
395
|
+
const { geolocation } = propsRef.current
|
|
396
|
+
if( !geolocation ) return
|
|
397
|
+
|
|
398
|
+
switch( kind ){
|
|
399
|
+
case 'get': geolocation.getCurrentPosition()
|
|
400
|
+
.then( position => answer({ id, position }) )
|
|
401
|
+
.catch( ( error: any ) => answer({ id, error: String( error?.message || error ) }) ); break
|
|
402
|
+
|
|
403
|
+
case 'watch': watchesRef.current.set( id, geolocation.watchPosition( position => answer({ id, position }) ) ); break
|
|
404
|
+
|
|
405
|
+
case 'clear': watchesRef.current.get( id )?.()
|
|
406
|
+
watchesRef.current.delete( id ); break
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
// A new page starts with no watches of its own; the last page's are dead
|
|
411
|
+
function stopWatches(){
|
|
412
|
+
watchesRef.current.forEach( stop => stop() )
|
|
413
|
+
watchesRef.current.clear()
|
|
414
|
+
}
|
|
415
|
+
|
|
303
416
|
const onMessage = ( event: any ) => {
|
|
304
417
|
// Console forwarding rides the same bridge; peel it off before WIO sees it
|
|
305
418
|
try {
|
|
306
419
|
const data = JSON.parse( event.nativeEvent.data )
|
|
420
|
+
if( data?.type === '__geo' ){
|
|
421
|
+
locate( data.kind, data.id )
|
|
422
|
+
return
|
|
423
|
+
}
|
|
424
|
+
|
|
307
425
|
if( data?.type === '__console' ){
|
|
308
426
|
const message = `[MSI gateway] ${data.message}`
|
|
309
427
|
|
|
@@ -329,6 +447,7 @@ export default forwardRef<MSIRef, MSIProps>( ( props, ref ) => {
|
|
|
329
447
|
ref={webViewRef}
|
|
330
448
|
source={{ uri: baseURL }}
|
|
331
449
|
style={styles.webview}
|
|
450
|
+
injectedJavaScriptBeforeContentLoaded={props.geolocation ? injectedGeolocation() : undefined}
|
|
332
451
|
injectedJavaScript={`
|
|
333
452
|
${props.env === 'dev' ? injectedConsole() : ''}
|
|
334
453
|
${injectedBridge}
|
|
@@ -350,6 +469,7 @@ export default forwardRef<MSIRef, MSIProps>( ( props, ref ) => {
|
|
|
350
469
|
originWhitelist={[ baseURL ]}
|
|
351
470
|
onShouldStartLoadWithRequest={( { url }: any ) => isGatewayURL( url )}
|
|
352
471
|
onMessage={onMessage}
|
|
472
|
+
onLoadStart={stopWatches}
|
|
353
473
|
onLoadEnd={onLoadEnd}
|
|
354
474
|
// iOS kills a WebView's content process under memory pressure and
|
|
355
475
|
// leaves the view blank: load the page again rather than show nothing
|