@nihinmedia/medgen-react-native 1.0.12

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.
@@ -0,0 +1,204 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+
7
+ var _exportNames = {
8
+ MedGen: true,
9
+ MedGenHost: true,
10
+ MedGenSurface: true,
11
+ SDK_VERSION: true
12
+ };
13
+
14
+ exports.MedGenSurface = exports.MedGenHost = exports.MedGen = void 0;
15
+
16
+ Object.defineProperty(exports, "SDK_VERSION", {
17
+ enumerable: true,
18
+ get: function() {
19
+ return _client.SDK_VERSION;
20
+ }
21
+ });
22
+
23
+ var _react = _interopRequireWildcard(require("react"));
24
+
25
+ var _reactNative = require("react-native");
26
+
27
+ var _client = require("./client");
28
+
29
+ var _MedGenWebView = require("./MedGenWebView");
30
+
31
+ var _types = require("./types");
32
+
33
+ Object.keys(_types).forEach(function(key) {
34
+ if (key === "default" || key === "__esModule") return;
35
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
36
+ if (key in exports && exports[key] === _types[key]) return;
37
+ Object.defineProperty(exports, key, {
38
+ enumerable: true,
39
+ get: function() {
40
+ return _types[key];
41
+ }
42
+ });
43
+ });
44
+
45
+ function _interopRequireWildcard(e, t) {
46
+ if ("function" == typeof WeakMap) var r = new WeakMap, n = new WeakMap;
47
+ return (_interopRequireWildcard = function(e, t) {
48
+ if (!t && e && e.__esModule) return e;
49
+ var o, i, f = {
50
+ __proto__: null,
51
+ default: e
52
+ };
53
+ if (null === e || "object" != typeof e && "function" != typeof e) return f;
54
+ if (o = t ? n : r) {
55
+ if (o.has(e)) return o.get(e);
56
+ o.set(e, f);
57
+ }
58
+ for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]);
59
+ return f;
60
+ })(e, t);
61
+ }
62
+
63
+ const hostRef = {
64
+ current: null
65
+ };
66
+
67
+ const teardowns = new Set;
68
+
69
+ const MedGen = exports.MedGen = {
70
+ initialize(config) {
71
+ if (!config.assertionProvider && !config.assertion) {
72
+ throw new _types.MedGenError("NOT_INITIALIZED", "MedGen.initialize() needs assertionProvider (or, to try the SDK once, assertion)");
73
+ }
74
+ if (!config.assertionProvider && config.assertion) {
75
+ if (typeof __DEV__ !== "undefined" && !__DEV__) {
76
+ throw new _types.MedGenError("NOT_INITIALIZED", "A static `assertion` cannot be used in a release build — it is " + "single-use and cannot be refreshed. Set `assertionProvider`.");
77
+ }
78
+ console.warn("[MedGen] Using a static `assertion`. It is single-use and expires " + "after 120s, so only the first present() will succeed. Set " + "`assertionProvider` before shipping.");
79
+ }
80
+ (0, _client.configure)(config);
81
+ },
82
+ async present(options) {
83
+ if (!hostRef.current) {
84
+ throw new _types.MedGenError("NOT_INITIALIZED", "Mount <MedGenHost /> near the root of your app");
85
+ }
86
+ await hostRef.current(options);
87
+ },
88
+ async signOut() {
89
+ teardowns.forEach(fn => {
90
+ try {
91
+ fn();
92
+ } catch {}
93
+ });
94
+ await (0, _client.clearCredentials)();
95
+ }
96
+ };
97
+
98
+ const MedGenHost = () => {
99
+ const [url, setUrl] = (0, _react.useState)(null);
100
+ const [capabilities, setCapabilities] = (0, _react.useState)(null);
101
+ const present = (0, _react.useCallback)(async options => {
102
+ const result = await (0, _client.exchange)();
103
+ setCapabilities(result.capabilities);
104
+ setUrl((0, _client.buildEmbedUrl)(result.handoffCode, options?.entryQuestion, result.capabilities));
105
+ (0, _client.emit)("surface.opened");
106
+ }, []);
107
+ (0, _react.useEffect)(() => {
108
+ hostRef.current = present;
109
+ return () => {
110
+ if (hostRef.current === present) hostRef.current = null;
111
+ };
112
+ }, [ present ]);
113
+ const close = (0, _react.useCallback)(() => {
114
+ setUrl(null);
115
+ setCapabilities(null);
116
+ (0, _client.emit)("surface.closed");
117
+ }, []);
118
+ (0, _react.useEffect)(() => {
119
+ teardowns.add(close);
120
+ return () => {
121
+ teardowns.delete(close);
122
+ };
123
+ }, [ close ]);
124
+ return _react.default.createElement(_reactNative.Modal, {
125
+ visible: url !== null,
126
+ animationType: "slide",
127
+ presentationStyle: "fullScreen",
128
+ onRequestClose: close
129
+ }, _react.default.createElement(_reactNative.SafeAreaView, {
130
+ style: styles.container
131
+ }, url && capabilities ? _react.default.createElement(_MedGenWebView.MedGenWebView, {
132
+ url: url,
133
+ handlers: (0, _client.requireConfig)().nativeHandlers ?? {},
134
+ capabilities: capabilities,
135
+ onClose: close
136
+ }) : null));
137
+ };
138
+
139
+ exports.MedGenHost = MedGenHost;
140
+
141
+ const MedGenSurface = ({visible: visible = true, options: options, onError: onError, onClose: onClose}) => {
142
+ const [url, setUrl] = (0, _react.useState)(null);
143
+ const [capabilities, setCapabilities] = (0, _react.useState)(null);
144
+ const [loading, setLoading] = (0, _react.useState)(false);
145
+ const started = (0, _react.useRef)(false);
146
+ (0, _react.useEffect)(() => {
147
+ if (!visible || started.current) return;
148
+ started.current = true;
149
+ setLoading(true);
150
+ (0, _client.exchange)().then(result => {
151
+ setCapabilities(result.capabilities);
152
+ setUrl((0, _client.buildEmbedUrl)(result.handoffCode, options?.entryQuestion, result.capabilities));
153
+ (0, _client.emit)("surface.opened");
154
+ }).catch(e => {
155
+ started.current = false;
156
+ onError?.(e);
157
+ }).finally(() => setLoading(false));
158
+ }, [ visible, options, onError ]);
159
+ (0, _react.useEffect)(() => {
160
+ const reset = () => {
161
+ setUrl(null);
162
+ setCapabilities(null);
163
+ started.current = false;
164
+ };
165
+ teardowns.add(reset);
166
+ return () => {
167
+ teardowns.delete(reset);
168
+ };
169
+ }, []);
170
+ return _react.default.createElement(_reactNative.View, {
171
+ style: [ styles.container, !visible && styles.hidden ],
172
+ pointerEvents: visible ? "auto" : "none"
173
+ }, url && capabilities ? _react.default.createElement(_MedGenWebView.MedGenWebView, {
174
+ url: url,
175
+ handlers: (0, _client.requireConfig)().nativeHandlers ?? {},
176
+ capabilities: capabilities,
177
+ onClose: () => {
178
+ setUrl(null);
179
+ setCapabilities(null);
180
+ started.current = false;
181
+ onClose?.();
182
+ }
183
+ }) : _react.default.createElement(_reactNative.View, {
184
+ style: styles.loading
185
+ }, loading ? _react.default.createElement(_reactNative.ActivityIndicator, {
186
+ size: "large"
187
+ }) : null));
188
+ };
189
+
190
+ exports.MedGenSurface = MedGenSurface;
191
+
192
+ const styles = _reactNative.StyleSheet.create({
193
+ container: {
194
+ flex: 1
195
+ },
196
+ hidden: {
197
+ display: "none"
198
+ },
199
+ loading: {
200
+ flex: 1,
201
+ alignItems: "center",
202
+ justifyContent: "center"
203
+ }
204
+ });
@@ -0,0 +1,201 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+
7
+ exports.writeClipboard = exports.shareText = exports.shareFile = exports.saveToDownloads = exports.renderPdf = exports.registerNativeModules = exports.ensureStoragePermission = exports.canShareText = exports.canSaveToDownloads = exports.canRenderPdf = exports.canCopy = void 0;
8
+
9
+ var _reactNative = require("react-native");
10
+
11
+ var _pdfLinks = require("./pdfLinks");
12
+
13
+ let registry = {};
14
+
15
+ const registerNativeModules = mods => {
16
+ registry = {
17
+ ...registry,
18
+ ...mods
19
+ };
20
+ };
21
+
22
+ exports.registerNativeModules = registerNativeModules;
23
+
24
+ const unwrap = mod => mod?.default ?? mod;
25
+
26
+ const fromRegistry = key => {
27
+ const mod = registry[key];
28
+ return mod ? unwrap(mod) : null;
29
+ };
30
+
31
+ const loadClipboard = () => fromRegistry("clipboard");
32
+
33
+ const loadShare = () => fromRegistry("share");
34
+
35
+ const loadHtmlToPdf = () => fromRegistry("htmlToPdf");
36
+
37
+ const loadBlobUtil = () => fromRegistry("blobUtil");
38
+
39
+ const ensureStoragePermission = async () => {
40
+ if (_reactNative.Platform.OS !== "android") return true;
41
+ if (typeof _reactNative.Platform.Version === "number" && _reactNative.Platform.Version >= 29) return true;
42
+ const permission = _reactNative.PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE;
43
+ if (!permission) return false;
44
+ try {
45
+ const granted = await _reactNative.PermissionsAndroid.request(permission, {
46
+ title: "Save to your device",
47
+ message: "MedGen needs permission to save this document.",
48
+ buttonPositive: "Allow"
49
+ });
50
+ return granted === _reactNative.PermissionsAndroid.RESULTS.GRANTED;
51
+ } catch {
52
+ return false;
53
+ }
54
+ };
55
+
56
+ exports.ensureStoragePermission = ensureStoragePermission;
57
+
58
+ const writeClipboard = async (text, html) => {
59
+ const Clipboard = loadClipboard();
60
+ if (!Clipboard) return false;
61
+ try {
62
+ if (html && typeof Clipboard.setStringHTML === "function") {
63
+ Clipboard.setStringHTML(html, text);
64
+ } else {
65
+ Clipboard.setString(text);
66
+ }
67
+ return true;
68
+ } catch {
69
+ return false;
70
+ }
71
+ };
72
+
73
+ exports.writeClipboard = writeClipboard;
74
+
75
+ const canShareText = () => true;
76
+
77
+ exports.canShareText = canShareText;
78
+
79
+ const canCopy = () => loadClipboard() !== null;
80
+
81
+ exports.canCopy = canCopy;
82
+
83
+ const canRenderPdf = () => loadHtmlToPdf() !== null;
84
+
85
+ exports.canRenderPdf = canRenderPdf;
86
+
87
+ const canSaveToDownloads = () => _reactNative.Platform.OS === "android" && loadBlobUtil() !== null;
88
+
89
+ exports.canSaveToDownloads = canSaveToDownloads;
90
+
91
+ const shareText = async text => {
92
+ try {
93
+ const result = await _reactNative.Share.share({
94
+ message: text
95
+ });
96
+ return result.action !== _reactNative.Share.dismissedAction;
97
+ } catch {
98
+ return false;
99
+ }
100
+ };
101
+
102
+ exports.shareText = shareText;
103
+
104
+ const shareFile = async (uri, mimeType = "application/pdf", fileName) => {
105
+ const RNShare = loadShare();
106
+ if (!RNShare) return {
107
+ saved: false,
108
+ reason: "no_module"
109
+ };
110
+ try {
111
+ await RNShare.open({
112
+ url: uri.startsWith("file://") ? uri : `file://${uri}`,
113
+ type: mimeType,
114
+ filename: fileName,
115
+ failOnCancel: false
116
+ });
117
+ return {
118
+ saved: true,
119
+ uri: uri
120
+ };
121
+ } catch (e) {
122
+ const msg = e instanceof Error ? e.message : "";
123
+ return {
124
+ saved: false,
125
+ reason: /cancel/i.test(msg) ? "cancelled" : "failed"
126
+ };
127
+ }
128
+ };
129
+
130
+ exports.shareFile = shareFile;
131
+
132
+ const renderPdf = async (html, fileName, links = []) => {
133
+ const HtmlToPdf = loadHtmlToPdf();
134
+ if (!HtmlToPdf) return null;
135
+ const withLinks = _reactNative.Platform.OS === "ios" && links.length > 0;
136
+ try {
137
+ const {filePath: filePath, base64: base64} = await HtmlToPdf.convert({
138
+ html: html,
139
+ fileName: fileName.replace(/\.pdf$/i, ""),
140
+ directory: "Documents",
141
+ base64: withLinks
142
+ });
143
+ if (filePath && withLinks && base64) await writeLinks(filePath, base64, links);
144
+ return filePath ?? null;
145
+ } catch {
146
+ return null;
147
+ }
148
+ };
149
+
150
+ exports.renderPdf = renderPdf;
151
+
152
+ const writeLinks = async (filePath, base64, links) => {
153
+ const Blob = loadBlobUtil();
154
+ if (!Blob?.fs?.writeFile) return;
155
+ try {
156
+ const linked = await (0, _pdfLinks.addPdfLinks)(base64, links);
157
+ await Blob.fs.writeFile(filePath, linked, "base64");
158
+ } catch {}
159
+ };
160
+
161
+ const saveToDownloads = async (sourcePath, fileName) => {
162
+ const Blob = loadBlobUtil();
163
+ if (_reactNative.Platform.OS !== "android") return {
164
+ saved: false,
165
+ reason: "no_module"
166
+ };
167
+ if (!Blob) return {
168
+ saved: false,
169
+ reason: "no_module"
170
+ };
171
+ if (!await ensureStoragePermission()) {
172
+ return {
173
+ saved: false,
174
+ reason: "permission_denied"
175
+ };
176
+ }
177
+ try {
178
+ const target = `${Blob.fs.dirs.DownloadDir}/${fileName}`;
179
+ await Blob.fs.cp(sourcePath.replace("file://", ""), target);
180
+ if (_reactNative.Platform.OS === "android" && Blob.android?.addCompleteDownload) {
181
+ Blob.android.addCompleteDownload({
182
+ title: fileName,
183
+ description: "MedGen document",
184
+ mime: "application/pdf",
185
+ path: target,
186
+ showNotification: true
187
+ });
188
+ }
189
+ return {
190
+ saved: true,
191
+ uri: target
192
+ };
193
+ } catch {
194
+ return {
195
+ saved: false,
196
+ reason: "failed"
197
+ };
198
+ }
199
+ };
200
+
201
+ exports.saveToDownloads = saveToDownloads;
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+
7
+ exports.sanitizeLinks = exports.addPdfLinks = void 0;
8
+
9
+ var _pdfLib = require("pdf-lib");
10
+
11
+ const MAX_LINKS = 2e3;
12
+
13
+ const isFiniteNumber = n => typeof n === "number" && Number.isFinite(n);
14
+
15
+ const sanitizeLinks = raw => {
16
+ if (!Array.isArray(raw)) return [];
17
+ return raw.slice(0, MAX_LINKS).filter(l => {
18
+ const link = l;
19
+ return !!link && Number.isInteger(link.page) && link.page >= 0 && [ link.x, link.y, link.width, link.height ].every(isFiniteNumber) && link.width > 0 && link.height > 0 && typeof link.url === "string" && /^https?:\/\/[^\s]+$/i.test(link.url);
20
+ });
21
+ };
22
+
23
+ exports.sanitizeLinks = sanitizeLinks;
24
+
25
+ const pdfLiteral = url => url.replace(/[^\x20-\x7E]/g, c => encodeURIComponent(c)).replace(/[\\()]/g, c => `\\${c}`);
26
+
27
+ const addPdfLinks = async (base64, links) => {
28
+ const doc = await _pdfLib.PDFDocument.load(base64);
29
+ const pages = doc.getPages();
30
+ for (const link of links) {
31
+ const page = pages[link.page];
32
+ if (!page) continue;
33
+ const {width: pw, height: ph} = page.getSize();
34
+ const left = Math.max(0, link.x);
35
+ const right = Math.min(pw, link.x + link.width);
36
+ const top = Math.min(ph, ph - link.y);
37
+ const bottom = Math.max(0, ph - link.y - link.height);
38
+ if (right <= left || top <= bottom) continue;
39
+ const annot = doc.context.obj({
40
+ Type: "Annot",
41
+ Subtype: "Link",
42
+ Rect: [ left, bottom, right, top ],
43
+ Border: [ 0, 0, 0 ],
44
+ A: {
45
+ Type: "Action",
46
+ S: "URI",
47
+ URI: _pdfLib.PDFString.of(pdfLiteral(link.url))
48
+ }
49
+ });
50
+ page.node.addAnnot(doc.context.register(annot));
51
+ }
52
+ return doc.saveAsBase64({
53
+ useObjectStreams: false
54
+ });
55
+ };
56
+
57
+ exports.addPdfLinks = addPdfLinks;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+
7
+ exports.MedGenError = exports.MedGenEnvironment = void 0;
8
+
9
+ let MedGenEnvironment = exports.MedGenEnvironment = function(MedGenEnvironment) {
10
+ MedGenEnvironment["Development"] = "development";
11
+ MedGenEnvironment["Staging"] = "staging";
12
+ MedGenEnvironment["Production"] = "production";
13
+ return MedGenEnvironment;
14
+ }({});
15
+
16
+ class MedGenError extends Error {
17
+ constructor(code, message, retryable = false, supportReference) {
18
+ super(message);
19
+ this.name = "MedGenError";
20
+ this.code = code;
21
+ this.retryable = retryable;
22
+ this.supportReference = supportReference;
23
+ Object.setPrototypeOf(this, MedGenError.prototype);
24
+ }
25
+ }
26
+
27
+ exports.MedGenError = MedGenError;
@@ -0,0 +1,166 @@
1
+ import React, { useCallback, useMemo, useRef } from "react";
2
+
3
+ import { ActivityIndicator, Linking, StyleSheet, View } from "react-native";
4
+
5
+ import { WebView as RNWebView } from "react-native-webview";
6
+
7
+ const WebView = RNWebView;
8
+
9
+ import { handleBridgeMessage } from "./bridge";
10
+
11
+ import { embedBase, emit, SDK_VERSION } from "./client";
12
+
13
+ export const originOf = u => {
14
+ const m = /^[a-z][a-z0-9+.-]*:\/\/[^/?#]+/i.exec(u);
15
+ return m ? m[0].toLowerCase() : "";
16
+ };
17
+
18
+ export const decideNavigation = (url, base, isTopFrame) => {
19
+ if (isSameOrigin(url, base)) return "load";
20
+ if (isTopFrame === false) return "block";
21
+ if (/^(mailto|tel|sms):/i.test(url)) return "external";
22
+ if (!/^https?:\/\//i.test(url)) return "block";
23
+ return "external";
24
+ };
25
+
26
+ const openExternally = async url => {
27
+ try {
28
+ if (!await Linking.canOpenURL(url)) {
29
+ emit("surface.externalLinkFailed", {
30
+ url: url,
31
+ reason: "unsupported"
32
+ });
33
+ return false;
34
+ }
35
+ await Linking.openURL(url);
36
+ emit("surface.externalLinkOpened", {
37
+ url: url
38
+ });
39
+ return true;
40
+ } catch (error) {
41
+ emit("surface.externalLinkFailed", {
42
+ url: url,
43
+ reason: error instanceof Error ? error.message : "unknown"
44
+ });
45
+ return false;
46
+ }
47
+ };
48
+
49
+ const makeNonce = () => `${Date.now().toString(36)}.${Math.random().toString(36).slice(2)}${Math.random().toString(36).slice(2)}`;
50
+
51
+ export const isSameOrigin = (target, base) => {
52
+ if (target === "about:blank") return true;
53
+ const b = originOf(base);
54
+ return b !== "" && originOf(target) === b;
55
+ };
56
+
57
+ export const MedGenWebView = ({url: url, handlers: handlers, capabilities: capabilities, onClose: onClose}) => {
58
+ const ref = useRef(null);
59
+ const nonce = useMemo(() => makeNonce(), [ url ]);
60
+ const isMedGenOrigin = useCallback(target => isSameOrigin(target, embedBase()), []);
61
+ const onShouldStartLoadWithRequest = useCallback(req => {
62
+ const decision = decideNavigation(req.url, embedBase(), req.isTopFrame);
63
+ if (decision === "load") return true;
64
+ if (decision === "external") void openExternally(req.url);
65
+ return false;
66
+ }, [ isMedGenOrigin ]);
67
+ const onMessage = useCallback(event => {
68
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
69
+ try {
70
+ const probe = JSON.parse(event.nativeEvent.data);
71
+ if (probe?.__medgenLog) {
72
+ const {level: level = "log", args: args = []} = probe.__medgenLog;
73
+ console[level === "error" ? "error" : "warn"]("[MedGen surface]", ...args);
74
+ return;
75
+ }
76
+ } catch {}
77
+ }
78
+ if (!isMedGenOrigin(event.nativeEvent.url)) {
79
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
80
+ console.warn("[MedGen] message rejected — origin not allowed:", event.nativeEvent.url);
81
+ }
82
+ return;
83
+ }
84
+ void handleBridgeMessage(event.nativeEvent.data, replyJson => {
85
+ const safe = JSON.stringify(replyJson).replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
86
+ ref.current?.injectJavaScript(`window.__medgen && window.__medgen.receive(${safe}); true;`);
87
+ }, {
88
+ handlers: handlers,
89
+ capabilities: capabilities,
90
+ onClose: onClose,
91
+ nonce: nonce
92
+ });
93
+ }, [ isMedGenOrigin, handlers, capabilities, onClose, nonce ]);
94
+ return React.createElement(WebView, {
95
+ ref: ref,
96
+ source: {
97
+ uri: url
98
+ },
99
+ style: styles.web,
100
+ injectedJavaScriptBeforeContentLoaded: `window.__medgenNonce=${JSON.stringify(nonce)};` + (typeof __DEV__ !== "undefined" && __DEV__ ? `(function(){var p=window.ReactNativeWebView&&window.ReactNativeWebView.postMessage;` + `if(!p)return;['log','warn','error'].forEach(function(l){var o=console[l];` + `console[l]=function(){try{p.call(window.ReactNativeWebView,JSON.stringify(` + `{__medgenLog:{level:l,args:Array.prototype.slice.call(arguments).map(String)}}));}` + `catch(e){}o&&o.apply(console,arguments);};});})();` : "") + `true;`,
101
+ injectedJavaScriptBeforeContentLoadedForMainFrameOnly: true,
102
+ originWhitelist: [ originOf(embedBase()) ],
103
+ onShouldStartLoadWithRequest: onShouldStartLoadWithRequest,
104
+ onMessage: onMessage,
105
+ allowFileAccess: false,
106
+ allowUniversalAccessFromFileURLs: false,
107
+ mixedContentMode: "never",
108
+ javaScriptCanOpenWindowsAutomatically: false,
109
+ setSupportMultipleWindows: false,
110
+ onOpenWindow: event => {
111
+ const url = event?.nativeEvent?.targetUrl;
112
+ if (!url) return;
113
+ const decision = decideNavigation(url, embedBase(), true);
114
+ if (decision === "load") {
115
+ ref.current?.injectJavaScript(`window.location.assign(${JSON.stringify(url)});true;`);
116
+ } else if (decision === "external") {
117
+ void openExternally(url);
118
+ }
119
+ },
120
+ onError: event => {
121
+ emit("surface.loadFailed", {
122
+ description: event?.nativeEvent?.description,
123
+ code: event?.nativeEvent?.code
124
+ });
125
+ },
126
+ onHttpError: event => {
127
+ emit("surface.loadFailed", {
128
+ statusCode: event?.nativeEvent?.statusCode
129
+ });
130
+ },
131
+ automaticallyAdjustContentInsets: false,
132
+ contentInsetAdjustmentBehavior: "never",
133
+ keyboardDisplayRequiresUserAction: false,
134
+ androidLayerType: "hardware",
135
+ onContentProcessDidTerminate: () => {
136
+ emit("surface.loadFailed", {
137
+ reason: "content_process_terminated"
138
+ });
139
+ ref.current?.reload();
140
+ },
141
+ allowsInlineMediaPlayback: true,
142
+ allowsLinkPreview: false,
143
+ applicationNameForUserAgent: `MedGenSDK/${SDK_VERSION}`,
144
+ sharedCookiesEnabled: true,
145
+ thirdPartyCookiesEnabled: false,
146
+ startInLoadingState: true,
147
+ renderLoading: () => React.createElement(View, {
148
+ style: styles.loading
149
+ }, React.createElement(ActivityIndicator, {
150
+ size: "large"
151
+ })),
152
+ bounces: false,
153
+ overScrollMode: "never"
154
+ });
155
+ };
156
+
157
+ const styles = StyleSheet.create({
158
+ web: {
159
+ flex: 1
160
+ },
161
+ loading: {
162
+ ...StyleSheet.absoluteFillObject,
163
+ alignItems: "center",
164
+ justifyContent: "center"
165
+ }
166
+ });