@lingxia/bridge 0.5.0 → 0.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/bridge-runtime.es2020.js +1 -0
- package/dist/bridge-runtime.es5.js +1 -0
- package/dist/bridge.d.ts +5 -2
- package/dist/es2020/boot.js +34 -0
- package/dist/es2020/bridge.js +1597 -0
- package/dist/es2020/error.js +89 -0
- package/dist/es2020/image-proxy.js +82 -0
- package/dist/es2020/index.js +19 -0
- package/dist/es2020/invocation.js +77 -0
- package/dist/es2020/nativecomponents/coverage-monitor.js +159 -0
- package/dist/es2020/runtime-env.js +31 -0
- package/dist/es2020/types.js +16 -0
- package/dist/es2020/ui/action-sheet.js +138 -0
- package/dist/es2020/ui/index.js +10 -0
- package/dist/es2020/ui/modal.js +170 -0
- package/dist/es2020/ui/toast.js +145 -0
- package/dist/es5/boot.js +34 -0
- package/dist/es5/bridge.js +1930 -0
- package/dist/es5/error.js +35 -0
- package/dist/es5/image-proxy.js +83 -0
- package/dist/es5/index.js +19 -0
- package/dist/es5/invocation.js +103 -0
- package/dist/es5/nativecomponents/coverage-monitor.js +219 -0
- package/dist/es5/runtime-env.js +32 -0
- package/dist/es5/types.js +16 -0
- package/dist/es5/ui/action-sheet.js +82 -0
- package/dist/es5/ui/index.js +10 -0
- package/dist/es5/ui/modal.js +84 -0
- package/dist/es5/ui/toast.js +102 -0
- package/dist/index.d.ts +3 -2
- package/dist/invocation.d.ts +14 -0
- package/dist/types.d.ts +42 -15
- package/package.json +21 -9
- package/dist/runtime.es2020.js +0 -1663
- package/dist/runtime.es5.js +0 -1
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
var ERROR_STYLES = "\n* { margin: 0; padding: 0; box-sizing: border-box; }\nbody {\n font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Segoe UI', Roboto, sans-serif;\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 100vh;\n background: #f5f5f7;\n color: #1d1d1f;\n padding: 20px;\n -webkit-font-smoothing: antialiased;\n}\n.lx-error {\n text-align: center;\n max-width: 400px;\n}\n.lx-error-code {\n font-size: 120px;\n font-weight: 700;\n color: #d1d1d6;\n line-height: 1;\n letter-spacing: -4px;\n}\n.lx-error-title {\n font-size: 21px;\n font-weight: 600;\n margin: 16px 0 8px;\n color: #1d1d1f;\n}\n.lx-error-desc {\n font-size: 15px;\n color: #86868b;\n line-height: 1.5;\n}\n.lx-error-path {\n display: inline-block;\n margin-top: 20px;\n padding: 10px 16px;\n background: rgba(0,0,0,0.04);\n border-radius: 8px;\n font-family: 'SF Mono', ui-monospace, Menlo, Monaco, monospace;\n font-size: 13px;\n color: #1d1d1f;\n word-break: break-all;\n max-width: 100%;\n}\n@media (prefers-color-scheme: dark) {\n body { background: #000; color: #f5f5f7; }\n .lx-error-code { color: #3a3a3c; }\n .lx-error-title { color: #f5f5f7; }\n .lx-error-desc { color: #86868b; }\n .lx-error-path { background: rgba(255,255,255,0.08); color: #f5f5f7; }\n}\n";
|
|
2
|
+
function escapeHtml(str) {
|
|
3
|
+
var div = document.createElement('div');
|
|
4
|
+
div.textContent = str;
|
|
5
|
+
return div.innerHTML;
|
|
6
|
+
}
|
|
7
|
+
export function renderErrorUI(errorInfo) {
|
|
8
|
+
var failedPath = errorInfo.failedPath, reason = errorInfo.reason;
|
|
9
|
+
var styleEl = document.createElement('style');
|
|
10
|
+
styleEl.textContent = ERROR_STYLES;
|
|
11
|
+
document.head.appendChild(styleEl);
|
|
12
|
+
document.body.innerHTML = '';
|
|
13
|
+
document.body.style.cssText = '';
|
|
14
|
+
var container = document.createElement('div');
|
|
15
|
+
container.className = 'lx-error';
|
|
16
|
+
var html = '<div class="lx-error-code">404</div>';
|
|
17
|
+
html += '<h1 class="lx-error-title">Page Not Found</h1>';
|
|
18
|
+
html += '<p class="lx-error-desc">The page you\'re looking for doesn\'t exist.</p>';
|
|
19
|
+
if (failedPath) {
|
|
20
|
+
html += "<div class=\"lx-error-path\">".concat(escapeHtml(failedPath), "</div>");
|
|
21
|
+
}
|
|
22
|
+
if (reason) {
|
|
23
|
+
html += "<p class=\"lx-error-desc\" style=\"margin-top:12px\">".concat(escapeHtml(reason), "</p>");
|
|
24
|
+
}
|
|
25
|
+
container.innerHTML = html;
|
|
26
|
+
document.body.appendChild(container);
|
|
27
|
+
}
|
|
28
|
+
export function hasError() {
|
|
29
|
+
var config = window.__LX_RUNTIME_CONFIG;
|
|
30
|
+
return !!(config && config.error);
|
|
31
|
+
}
|
|
32
|
+
export function getErrorInfo() {
|
|
33
|
+
var config = window.__LX_RUNTIME_CONFIG;
|
|
34
|
+
return (config === null || config === void 0 ? void 0 : config.error) || null;
|
|
35
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { getPlatformOS } from './runtime-env';
|
|
2
|
+
var PROXY_PREFIX = 'lx://proxy/';
|
|
3
|
+
function shouldProxyImageUrl(trimmed) {
|
|
4
|
+
if (trimmed.length === 0) {
|
|
5
|
+
return false;
|
|
6
|
+
}
|
|
7
|
+
if (trimmed.startsWith('lx://') ||
|
|
8
|
+
trimmed.startsWith('data:') ||
|
|
9
|
+
trimmed.startsWith('blob:') ||
|
|
10
|
+
trimmed.startsWith('file:')) {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
return trimmed.startsWith('http://') || trimmed.startsWith('https://');
|
|
14
|
+
}
|
|
15
|
+
function toProxyUrl(url) {
|
|
16
|
+
var b64 = btoa(url);
|
|
17
|
+
var urlSafe = b64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/g, '');
|
|
18
|
+
return "".concat(PROXY_PREFIX).concat(urlSafe);
|
|
19
|
+
}
|
|
20
|
+
function proxyImageUrl(url) {
|
|
21
|
+
var trimmed = url.trim();
|
|
22
|
+
if (!shouldProxyImageUrl(trimmed))
|
|
23
|
+
return url;
|
|
24
|
+
return toProxyUrl(trimmed);
|
|
25
|
+
}
|
|
26
|
+
export function setupImageProxy() {
|
|
27
|
+
var os = getPlatformOS();
|
|
28
|
+
if (os !== 'iOS' && os !== 'macOS')
|
|
29
|
+
return;
|
|
30
|
+
if (typeof window === 'undefined' || typeof document === 'undefined')
|
|
31
|
+
return;
|
|
32
|
+
if (typeof HTMLImageElement === 'undefined')
|
|
33
|
+
return;
|
|
34
|
+
var proto = HTMLImageElement.prototype;
|
|
35
|
+
if (proto.__lxProxyPatched)
|
|
36
|
+
return;
|
|
37
|
+
proto.__lxProxyPatched = true;
|
|
38
|
+
var originalSetAttribute = proto.setAttribute;
|
|
39
|
+
proto.setAttribute = function (name, value) {
|
|
40
|
+
if (typeof name === 'string' && name.toLowerCase() === 'src' && typeof value === 'string') {
|
|
41
|
+
return originalSetAttribute.call(this, name, proxyImageUrl(value));
|
|
42
|
+
}
|
|
43
|
+
return originalSetAttribute.call(this, name, value);
|
|
44
|
+
};
|
|
45
|
+
var srcDescriptor = Object.getOwnPropertyDescriptor(proto, 'src');
|
|
46
|
+
if (srcDescriptor === null || srcDescriptor === void 0 ? void 0 : srcDescriptor.set) {
|
|
47
|
+
Object.defineProperty(proto, 'src', {
|
|
48
|
+
configurable: srcDescriptor.configurable,
|
|
49
|
+
enumerable: srcDescriptor.enumerable,
|
|
50
|
+
get: srcDescriptor.get,
|
|
51
|
+
set: function (value) {
|
|
52
|
+
var _a, _b;
|
|
53
|
+
if (typeof value === 'string') {
|
|
54
|
+
(_a = srcDescriptor.set) === null || _a === void 0 ? void 0 : _a.call(this, proxyImageUrl(value));
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
(_b = srcDescriptor.set) === null || _b === void 0 ? void 0 : _b.call(this, value);
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
var rewriteExisting = function () {
|
|
63
|
+
var imgs = document.querySelectorAll('img[src]');
|
|
64
|
+
imgs.forEach(function (img) {
|
|
65
|
+
var src = img.getAttribute('src');
|
|
66
|
+
if (!src)
|
|
67
|
+
return;
|
|
68
|
+
var proxied = proxyImageUrl(src);
|
|
69
|
+
if (proxied !== src) {
|
|
70
|
+
originalSetAttribute.call(img, 'src', proxied);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
};
|
|
74
|
+
var domReadyListener = {
|
|
75
|
+
handleEvent: function () { return rewriteExisting(); },
|
|
76
|
+
};
|
|
77
|
+
if (document.readyState === 'loading') {
|
|
78
|
+
document.addEventListener('DOMContentLoaded', domReadyListener);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
rewriteExisting();
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LingXia Web Runtime
|
|
3
|
+
*
|
|
4
|
+
* Injected into SPA HTML to handle:
|
|
5
|
+
* - Bridge initialization for native communication
|
|
6
|
+
* - Error UI rendering when page cannot be loaded
|
|
7
|
+
*/
|
|
8
|
+
export { LingXiaBridge, channel, initBridge, invoke, notify, stream, } from './bridge';
|
|
9
|
+
export { isNativeError } from './invocation';
|
|
10
|
+
export { renderErrorUI, hasError, getErrorInfo } from './error';
|
|
11
|
+
export { boot, bootWhenReady } from './boot';
|
|
12
|
+
import { bootWhenReady } from './boot';
|
|
13
|
+
import { setupImageProxy } from './image-proxy';
|
|
14
|
+
import { registerUIHandlers } from './ui';
|
|
15
|
+
if (__LX_RUNTIME_PLATFORM__ === 'all' || __LX_RUNTIME_PLATFORM__ === 'desktop') {
|
|
16
|
+
registerUIHandlers();
|
|
17
|
+
}
|
|
18
|
+
setupImageProxy();
|
|
19
|
+
bootWhenReady();
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
var __extends = (this && this.__extends) || (function () {
|
|
2
|
+
var extendStatics = function (d, b) {
|
|
3
|
+
extendStatics = Object.setPrototypeOf ||
|
|
4
|
+
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
5
|
+
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
|
6
|
+
return extendStatics(d, b);
|
|
7
|
+
};
|
|
8
|
+
return function (d, b) {
|
|
9
|
+
if (typeof b !== "function" && b !== null)
|
|
10
|
+
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
|
11
|
+
extendStatics(d, b);
|
|
12
|
+
function __() { this.constructor = d; }
|
|
13
|
+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
14
|
+
};
|
|
15
|
+
})();
|
|
16
|
+
var __assign = (this && this.__assign) || function () {
|
|
17
|
+
__assign = Object.assign || function(t) {
|
|
18
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
19
|
+
s = arguments[i];
|
|
20
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
21
|
+
t[p] = s[p];
|
|
22
|
+
}
|
|
23
|
+
return t;
|
|
24
|
+
};
|
|
25
|
+
return __assign.apply(this, arguments);
|
|
26
|
+
};
|
|
27
|
+
import { BRIDGE_ERROR } from "./types";
|
|
28
|
+
var BridgeInvocationError = /** @class */ (function (_super) {
|
|
29
|
+
__extends(BridgeInvocationError, _super);
|
|
30
|
+
function BridgeInvocationError(code, message, data) {
|
|
31
|
+
var _this = _super.call(this, message) || this;
|
|
32
|
+
_this.name = "BridgeInvocationError";
|
|
33
|
+
_this.code = code;
|
|
34
|
+
_this.data = data;
|
|
35
|
+
return _this;
|
|
36
|
+
}
|
|
37
|
+
return BridgeInvocationError;
|
|
38
|
+
}(Error));
|
|
39
|
+
export function toBridgeError(err) {
|
|
40
|
+
if (err instanceof BridgeInvocationError)
|
|
41
|
+
return err;
|
|
42
|
+
if (err && typeof err === "object") {
|
|
43
|
+
var source = err;
|
|
44
|
+
var code = BRIDGE_ERROR.INTERNAL_ERROR;
|
|
45
|
+
if (typeof source.code === "string" && source.code.trim() !== "") {
|
|
46
|
+
code = source.code;
|
|
47
|
+
}
|
|
48
|
+
else if (typeof source.code === "number" && Number.isFinite(source.code)) {
|
|
49
|
+
code = source.code;
|
|
50
|
+
}
|
|
51
|
+
var message_1 = typeof source.message === "string" && source.message.trim() !== ""
|
|
52
|
+
? source.message
|
|
53
|
+
: "Unknown error";
|
|
54
|
+
return new BridgeInvocationError(code, message_1, "data" in source ? source.data : undefined);
|
|
55
|
+
}
|
|
56
|
+
var message = err instanceof Error ? err.message : typeof err === "string" ? err : "Unknown error";
|
|
57
|
+
return new BridgeInvocationError(BRIDGE_ERROR.INTERNAL_ERROR, message);
|
|
58
|
+
}
|
|
59
|
+
export function toNativeError(err) {
|
|
60
|
+
var bridgeError = toBridgeError(err);
|
|
61
|
+
return __assign({ code: String(bridgeError.code || BRIDGE_ERROR.INTERNAL_ERROR), message: typeof bridgeError.message === "string" && bridgeError.message.trim() !== ""
|
|
62
|
+
? bridgeError.message
|
|
63
|
+
: "Unknown error" }, (bridgeError.data === undefined ? {} : { data: bridgeError.data }));
|
|
64
|
+
}
|
|
65
|
+
export function isNativeError(error, code) {
|
|
66
|
+
if (!error || typeof error !== "object")
|
|
67
|
+
return false;
|
|
68
|
+
var candidate = error;
|
|
69
|
+
if (typeof candidate.code !== "string" || candidate.code.trim() === "")
|
|
70
|
+
return false;
|
|
71
|
+
if (typeof candidate.message !== "string")
|
|
72
|
+
return false;
|
|
73
|
+
return code === undefined || candidate.code === code;
|
|
74
|
+
}
|
|
75
|
+
export function resolveParams(source) {
|
|
76
|
+
if (typeof source === "function") {
|
|
77
|
+
return source();
|
|
78
|
+
}
|
|
79
|
+
return source;
|
|
80
|
+
}
|
|
81
|
+
export function stableParamKey(value) {
|
|
82
|
+
var _a;
|
|
83
|
+
if (value === undefined)
|
|
84
|
+
return "undefined";
|
|
85
|
+
try {
|
|
86
|
+
return (_a = JSON.stringify(value)) !== null && _a !== void 0 ? _a : "undefined";
|
|
87
|
+
}
|
|
88
|
+
catch (_b) {
|
|
89
|
+
return String(value);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
export function invokeMethod(method, params) {
|
|
93
|
+
if (params === undefined) {
|
|
94
|
+
return method();
|
|
95
|
+
}
|
|
96
|
+
return method(params);
|
|
97
|
+
}
|
|
98
|
+
export function getMethodKey(method) {
|
|
99
|
+
if (typeof method !== "function")
|
|
100
|
+
return undefined;
|
|
101
|
+
var candidate = method.__funcName;
|
|
102
|
+
return typeof candidate === "string" && candidate !== "" ? candidate : undefined;
|
|
103
|
+
}
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
var __values = (this && this.__values) || function(o) {
|
|
2
|
+
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
|
|
3
|
+
if (m) return m.call(o);
|
|
4
|
+
if (o && typeof o.length === "number") return {
|
|
5
|
+
next: function () {
|
|
6
|
+
if (o && i >= o.length) o = void 0;
|
|
7
|
+
return { value: o && o[i++], done: !o };
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
|
11
|
+
};
|
|
12
|
+
var __read = (this && this.__read) || function (o, n) {
|
|
13
|
+
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
|
14
|
+
if (!m) return o;
|
|
15
|
+
var i = m.call(o), r, ar = [], e;
|
|
16
|
+
try {
|
|
17
|
+
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
|
18
|
+
}
|
|
19
|
+
catch (error) { e = { error: error }; }
|
|
20
|
+
finally {
|
|
21
|
+
try {
|
|
22
|
+
if (r && !r.done && (m = i["return"])) m.call(i);
|
|
23
|
+
}
|
|
24
|
+
finally { if (e) throw e.error; }
|
|
25
|
+
}
|
|
26
|
+
return ar;
|
|
27
|
+
};
|
|
28
|
+
export function installNativeComponentCoverageMonitor(_a) {
|
|
29
|
+
var os = _a.os, send = _a.send;
|
|
30
|
+
if (typeof window === 'undefined')
|
|
31
|
+
return;
|
|
32
|
+
if (typeof document === 'undefined')
|
|
33
|
+
return;
|
|
34
|
+
var isIOS = os === 'iOS';
|
|
35
|
+
var isAndroid = os === 'Android';
|
|
36
|
+
if (!isIOS && !isAndroid)
|
|
37
|
+
return;
|
|
38
|
+
var key = Symbol.for('LingXia.NativeComponentCoverageMonitor');
|
|
39
|
+
var existing = window[key];
|
|
40
|
+
if (existing === null || existing === void 0 ? void 0 : existing.installed)
|
|
41
|
+
return;
|
|
42
|
+
var state = {
|
|
43
|
+
installed: true,
|
|
44
|
+
coveredById: new Map(),
|
|
45
|
+
coveredCount: 0,
|
|
46
|
+
anyCovered: false,
|
|
47
|
+
scheduled: false,
|
|
48
|
+
hasAnyVideo: false,
|
|
49
|
+
scrollLocked: false,
|
|
50
|
+
scrollY: 0,
|
|
51
|
+
htmlOverflow: '',
|
|
52
|
+
bodyOverflow: '',
|
|
53
|
+
bodyPosition: '',
|
|
54
|
+
bodyTop: '',
|
|
55
|
+
bodyWidth: '',
|
|
56
|
+
};
|
|
57
|
+
window[key] = state;
|
|
58
|
+
function lockScroll() {
|
|
59
|
+
if (!isIOS)
|
|
60
|
+
return;
|
|
61
|
+
if (state.scrollLocked)
|
|
62
|
+
return;
|
|
63
|
+
var html = document.documentElement;
|
|
64
|
+
var body = document.body;
|
|
65
|
+
if (!html || !body)
|
|
66
|
+
return;
|
|
67
|
+
state.scrollLocked = true;
|
|
68
|
+
state.scrollY = window.scrollY || html.scrollTop || 0;
|
|
69
|
+
state.htmlOverflow = html.style.overflow || '';
|
|
70
|
+
state.bodyOverflow = body.style.overflow || '';
|
|
71
|
+
state.bodyPosition = body.style.position || '';
|
|
72
|
+
state.bodyTop = body.style.top || '';
|
|
73
|
+
state.bodyWidth = body.style.width || '';
|
|
74
|
+
html.style.overflow = 'hidden';
|
|
75
|
+
body.style.overflow = 'hidden';
|
|
76
|
+
body.style.position = 'fixed';
|
|
77
|
+
body.style.top = "".concat(-state.scrollY, "px");
|
|
78
|
+
body.style.width = '100%';
|
|
79
|
+
}
|
|
80
|
+
function unlockScroll() {
|
|
81
|
+
if (!isIOS)
|
|
82
|
+
return;
|
|
83
|
+
if (!state.scrollLocked)
|
|
84
|
+
return;
|
|
85
|
+
var html = document.documentElement;
|
|
86
|
+
var body = document.body;
|
|
87
|
+
if (!html || !body)
|
|
88
|
+
return;
|
|
89
|
+
state.scrollLocked = false;
|
|
90
|
+
html.style.overflow = state.htmlOverflow;
|
|
91
|
+
body.style.overflow = state.bodyOverflow;
|
|
92
|
+
body.style.position = state.bodyPosition;
|
|
93
|
+
body.style.top = state.bodyTop;
|
|
94
|
+
body.style.width = state.bodyWidth;
|
|
95
|
+
window.scrollTo(0, state.scrollY);
|
|
96
|
+
}
|
|
97
|
+
function isElementCovered(el) {
|
|
98
|
+
var _a, _b, _c;
|
|
99
|
+
var rect = (_b = (_a = el).getBoundingClientRect) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
100
|
+
if (!rect)
|
|
101
|
+
return false;
|
|
102
|
+
if (rect.width < 2 || rect.height < 2)
|
|
103
|
+
return false;
|
|
104
|
+
var x = rect.left + rect.width / 2;
|
|
105
|
+
var y = rect.top + rect.height / 2;
|
|
106
|
+
if (x < 0 || y < 0 || x >= window.innerWidth || y >= window.innerHeight)
|
|
107
|
+
return false;
|
|
108
|
+
var top = (_c = document.elementFromPoint) === null || _c === void 0 ? void 0 : _c.call(document, x, y);
|
|
109
|
+
if (!top)
|
|
110
|
+
return false;
|
|
111
|
+
if (top === document.documentElement || top === document.body)
|
|
112
|
+
return false;
|
|
113
|
+
return !(top === el || el.contains(top));
|
|
114
|
+
}
|
|
115
|
+
function check() {
|
|
116
|
+
var e_1, _a, e_2, _b, e_3, _c;
|
|
117
|
+
state.scheduled = false;
|
|
118
|
+
var nodes = document.querySelectorAll('lx-video[id]');
|
|
119
|
+
state.hasAnyVideo = nodes.length > 0;
|
|
120
|
+
if (!state.hasAnyVideo && state.coveredById.size === 0 && !state.anyCovered) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
var seenIds = new Set();
|
|
124
|
+
try {
|
|
125
|
+
for (var _d = __values(Array.from(nodes)), _e = _d.next(); !_e.done; _e = _d.next()) {
|
|
126
|
+
var node = _e.value;
|
|
127
|
+
var id = node.id;
|
|
128
|
+
if (!id)
|
|
129
|
+
continue;
|
|
130
|
+
seenIds.add(id);
|
|
131
|
+
var covered = isElementCovered(node);
|
|
132
|
+
var prev = state.coveredById.get(id);
|
|
133
|
+
if (prev === covered)
|
|
134
|
+
continue;
|
|
135
|
+
if (prev === true)
|
|
136
|
+
state.coveredCount -= 1;
|
|
137
|
+
if (covered === true)
|
|
138
|
+
state.coveredCount += 1;
|
|
139
|
+
state.coveredById.set(id, covered);
|
|
140
|
+
send({ id: id, action: 'component.coverage', covered: covered });
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
144
|
+
finally {
|
|
145
|
+
try {
|
|
146
|
+
if (_e && !_e.done && (_a = _d.return)) _a.call(_d);
|
|
147
|
+
}
|
|
148
|
+
finally { if (e_1) throw e_1.error; }
|
|
149
|
+
}
|
|
150
|
+
var staleIds = [];
|
|
151
|
+
try {
|
|
152
|
+
for (var _f = __values(state.coveredById.entries()), _g = _f.next(); !_g.done; _g = _f.next()) {
|
|
153
|
+
var _h = __read(_g.value, 2), id = _h[0], covered = _h[1];
|
|
154
|
+
if (seenIds.has(id))
|
|
155
|
+
continue;
|
|
156
|
+
staleIds.push(id);
|
|
157
|
+
if (covered === true)
|
|
158
|
+
state.coveredCount -= 1;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
162
|
+
finally {
|
|
163
|
+
try {
|
|
164
|
+
if (_g && !_g.done && (_b = _f.return)) _b.call(_f);
|
|
165
|
+
}
|
|
166
|
+
finally { if (e_2) throw e_2.error; }
|
|
167
|
+
}
|
|
168
|
+
try {
|
|
169
|
+
for (var staleIds_1 = __values(staleIds), staleIds_1_1 = staleIds_1.next(); !staleIds_1_1.done; staleIds_1_1 = staleIds_1.next()) {
|
|
170
|
+
var id = staleIds_1_1.value;
|
|
171
|
+
state.coveredById.delete(id);
|
|
172
|
+
send({ id: id, action: 'component.coverage', covered: false });
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
catch (e_3_1) { e_3 = { error: e_3_1 }; }
|
|
176
|
+
finally {
|
|
177
|
+
try {
|
|
178
|
+
if (staleIds_1_1 && !staleIds_1_1.done && (_c = staleIds_1.return)) _c.call(staleIds_1);
|
|
179
|
+
}
|
|
180
|
+
finally { if (e_3) throw e_3.error; }
|
|
181
|
+
}
|
|
182
|
+
var anyCovered = state.coveredCount > 0;
|
|
183
|
+
if (anyCovered !== state.anyCovered) {
|
|
184
|
+
state.anyCovered = anyCovered;
|
|
185
|
+
if (isIOS) {
|
|
186
|
+
if (anyCovered)
|
|
187
|
+
lockScroll();
|
|
188
|
+
else
|
|
189
|
+
unlockScroll();
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
function schedule() {
|
|
194
|
+
if (state.scheduled)
|
|
195
|
+
return;
|
|
196
|
+
state.scheduled = true;
|
|
197
|
+
requestAnimationFrame(check);
|
|
198
|
+
}
|
|
199
|
+
function onScroll() {
|
|
200
|
+
if (!state.hasAnyVideo && state.coveredById.size === 0)
|
|
201
|
+
return;
|
|
202
|
+
schedule();
|
|
203
|
+
}
|
|
204
|
+
var observer = new MutationObserver(schedule);
|
|
205
|
+
observer.observe(document.documentElement, {
|
|
206
|
+
subtree: true,
|
|
207
|
+
childList: true,
|
|
208
|
+
attributes: true,
|
|
209
|
+
});
|
|
210
|
+
var scrollListener = {
|
|
211
|
+
handleEvent: function () { return onScroll(); },
|
|
212
|
+
};
|
|
213
|
+
var resizeListener = {
|
|
214
|
+
handleEvent: function () { return schedule(); },
|
|
215
|
+
};
|
|
216
|
+
window.addEventListener('scroll', scrollListener, { capture: true, passive: true });
|
|
217
|
+
window.addEventListener('resize', resizeListener);
|
|
218
|
+
schedule();
|
|
219
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export var BRIDGE_CONFIG = (typeof window !== 'undefined' && window.__LX_BRIDGE_CFG) || {};
|
|
2
|
+
export function getPlatformOS() {
|
|
3
|
+
return BRIDGE_CONFIG.os || 'unknown';
|
|
4
|
+
}
|
|
5
|
+
export function isHarmony() {
|
|
6
|
+
return BRIDGE_CONFIG.os === 'Harmony';
|
|
7
|
+
}
|
|
8
|
+
export function isIOS() {
|
|
9
|
+
return BRIDGE_CONFIG.os === 'iOS';
|
|
10
|
+
}
|
|
11
|
+
export function isAndroid() {
|
|
12
|
+
return BRIDGE_CONFIG.os === 'Android';
|
|
13
|
+
}
|
|
14
|
+
export function isMacOS() {
|
|
15
|
+
return BRIDGE_CONFIG.os === 'macOS';
|
|
16
|
+
}
|
|
17
|
+
export function isDesktop() {
|
|
18
|
+
return isMacOS();
|
|
19
|
+
}
|
|
20
|
+
export function getCommunicationMethod() {
|
|
21
|
+
var _a, _b;
|
|
22
|
+
if (BRIDGE_CONFIG.os === 'iOS' || BRIDGE_CONFIG.os === 'macOS')
|
|
23
|
+
return 'webkit';
|
|
24
|
+
if (BRIDGE_CONFIG.os === 'Harmony')
|
|
25
|
+
return 'messageport';
|
|
26
|
+
if (BRIDGE_CONFIG.os === 'Android') {
|
|
27
|
+
if ((_b = (_a = window.LingXiaProxy) === null || _a === void 0 ? void 0 : _a.supportsMessagePort) === null || _b === void 0 ? void 0 : _b.call(_a))
|
|
28
|
+
return 'messageport';
|
|
29
|
+
return 'jsinterface';
|
|
30
|
+
}
|
|
31
|
+
return 'unknown';
|
|
32
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// V2 Error Codes (stable)
|
|
2
|
+
export var BRIDGE_ERROR = {
|
|
3
|
+
NOT_READY: 'BRIDGE_NOT_READY',
|
|
4
|
+
TIMEOUT: 'BRIDGE_TIMEOUT',
|
|
5
|
+
CANCELED: 'BRIDGE_CANCELED',
|
|
6
|
+
PROTOCOL_MISMATCH: 'BRIDGE_PROTOCOL_MISMATCH',
|
|
7
|
+
HANDSHAKE_FAILED: 'BRIDGE_HANDSHAKE_FAILED',
|
|
8
|
+
MALFORMED_MESSAGE: 'BRIDGE_MALFORMED_MESSAGE',
|
|
9
|
+
METHOD_NOT_FOUND: 'BRIDGE_METHOD_NOT_FOUND',
|
|
10
|
+
TOPIC_NOT_FOUND: 'BRIDGE_TOPIC_NOT_FOUND',
|
|
11
|
+
CAPABILITY_DENIED: 'BRIDGE_CAPABILITY_DENIED',
|
|
12
|
+
INTERNAL_ERROR: 'BRIDGE_INTERNAL_ERROR',
|
|
13
|
+
OUTBOX_FULL: 'BRIDGE_OUTBOX_FULL',
|
|
14
|
+
STREAM_OVERFLOW: 'BRIDGE_STREAM_OVERFLOW',
|
|
15
|
+
STREAM_CLOSED: 'BRIDGE_STREAM_CLOSED',
|
|
16
|
+
};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { getPlatformOS } from '../runtime-env';
|
|
2
|
+
var ANIMATION_MS = 300;
|
|
3
|
+
var STYLE_ID = 'lx-action-sheet-style';
|
|
4
|
+
var activeSheet = null;
|
|
5
|
+
function isDesktopMode() {
|
|
6
|
+
return getPlatformOS() === 'macOS';
|
|
7
|
+
}
|
|
8
|
+
function ensureActionSheetStyle() {
|
|
9
|
+
if (document.getElementById(STYLE_ID))
|
|
10
|
+
return;
|
|
11
|
+
var style = document.createElement('style');
|
|
12
|
+
style.id = STYLE_ID;
|
|
13
|
+
style.textContent = "\n.lx-as-backdrop {\n position: fixed; inset: 0; z-index: 99999;\n background: rgba(0,0,0,0.4);\n opacity: 0; transition: opacity ".concat(ANIMATION_MS, "ms ease;\n}\n.lx-as-backdrop.lx-as-visible { opacity: 1; }\n\n.lx-as-sheet {\n position: fixed; left: 0; right: 0; bottom: 0; z-index: 100000;\n transform: translateY(100%);\n transition: transform ").concat(ANIMATION_MS, "ms ease;\n font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Segoe UI', Roboto, sans-serif;\n -webkit-font-smoothing: antialiased;\n}\n.lx-as-sheet.lx-as-visible { transform: translateY(0); }\n.lx-as-sheet.lx-as-desktop {\n left: 50%;\n right: auto;\n bottom: auto;\n top: 50%;\n width: min(92vw, 460px);\n transform: translate(-50%, calc(-50% + 16px));\n}\n.lx-as-sheet.lx-as-desktop.lx-as-visible { transform: translate(-50%, -50%); }\n\n.lx-as-container {\n background: #fff;\n border-radius: 16px 16px 0 0;\n overflow: hidden;\n}\n.lx-as-container.lx-as-desktop {\n border-radius: 16px;\n}\n\n.lx-as-item {\n display: block; width: 100%;\n height: 56px;\n line-height: 56px;\n padding: 0;\n border: none; background: none;\n font-size: 18px; font-weight: 400;\n text-align: center;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n position: relative;\n}\n.lx-as-item:active { background: rgba(0,0,0,0.08); }\n.lx-as-item + .lx-as-item::before {\n content: ''; position: absolute; top: 0; left: 0; right: 0;\n height: 1px; background: #E0E0E0;\n}\n.lx-as-separator {\n height: 8px;\n background: #F2F2F2;\n}\n.lx-as-cancel-btn { font-weight: 500; color: #000; }\n");
|
|
14
|
+
document.head.appendChild(style);
|
|
15
|
+
}
|
|
16
|
+
export function showActionSheet(params) {
|
|
17
|
+
var _a, _b, _c;
|
|
18
|
+
var p = params;
|
|
19
|
+
var items = (_a = p === null || p === void 0 ? void 0 : p.itemList) !== null && _a !== void 0 ? _a : [];
|
|
20
|
+
var cancelText = (_b = p === null || p === void 0 ? void 0 : p.cancelText) !== null && _b !== void 0 ? _b : 'Cancel';
|
|
21
|
+
var itemColor = (_c = p === null || p === void 0 ? void 0 : p.itemColor) !== null && _c !== void 0 ? _c : '#007AFF';
|
|
22
|
+
var task = (activeSheet !== null && activeSheet !== void 0 ? activeSheet : Promise.resolve()).then(function () { return renderSheet(items, cancelText, itemColor); }, function () { return renderSheet(items, cancelText, itemColor); });
|
|
23
|
+
activeSheet = task;
|
|
24
|
+
return task;
|
|
25
|
+
}
|
|
26
|
+
function renderSheet(items, cancelText, itemColor) {
|
|
27
|
+
return new Promise(function (resolve) {
|
|
28
|
+
var dismissed = false;
|
|
29
|
+
var desktopMode = isDesktopMode();
|
|
30
|
+
ensureActionSheetStyle();
|
|
31
|
+
// --- DOM ---
|
|
32
|
+
var backdrop = document.createElement('div');
|
|
33
|
+
backdrop.className = 'lx-as-backdrop';
|
|
34
|
+
var sheet = document.createElement('div');
|
|
35
|
+
sheet.className = 'lx-as-sheet';
|
|
36
|
+
if (desktopMode) {
|
|
37
|
+
sheet.classList.add('lx-as-desktop');
|
|
38
|
+
}
|
|
39
|
+
var container = document.createElement('div');
|
|
40
|
+
container.className = 'lx-as-container';
|
|
41
|
+
if (desktopMode) {
|
|
42
|
+
container.classList.add('lx-as-desktop');
|
|
43
|
+
}
|
|
44
|
+
items.forEach(function (text, index) {
|
|
45
|
+
var btn = document.createElement('button');
|
|
46
|
+
btn.className = 'lx-as-item';
|
|
47
|
+
btn.textContent = text;
|
|
48
|
+
btn.style.color = itemColor;
|
|
49
|
+
btn.addEventListener('click', function () { return dismiss(index); });
|
|
50
|
+
container.appendChild(btn);
|
|
51
|
+
});
|
|
52
|
+
var separator = document.createElement('div');
|
|
53
|
+
separator.className = 'lx-as-separator';
|
|
54
|
+
container.appendChild(separator);
|
|
55
|
+
var cancelBtn = document.createElement('button');
|
|
56
|
+
cancelBtn.className = 'lx-as-item lx-as-cancel-btn';
|
|
57
|
+
cancelBtn.textContent = cancelText;
|
|
58
|
+
cancelBtn.addEventListener('click', function () { return dismiss(-1); });
|
|
59
|
+
container.appendChild(cancelBtn);
|
|
60
|
+
sheet.appendChild(container);
|
|
61
|
+
document.body.appendChild(backdrop);
|
|
62
|
+
document.body.appendChild(sheet);
|
|
63
|
+
// Trigger enter animation on next frame
|
|
64
|
+
requestAnimationFrame(function () {
|
|
65
|
+
backdrop.classList.add('lx-as-visible');
|
|
66
|
+
sheet.classList.add('lx-as-visible');
|
|
67
|
+
});
|
|
68
|
+
backdrop.addEventListener('click', function () { return dismiss(-1); });
|
|
69
|
+
function dismiss(tapIndex) {
|
|
70
|
+
if (dismissed)
|
|
71
|
+
return;
|
|
72
|
+
dismissed = true;
|
|
73
|
+
backdrop.classList.remove('lx-as-visible');
|
|
74
|
+
sheet.classList.remove('lx-as-visible');
|
|
75
|
+
setTimeout(function () {
|
|
76
|
+
backdrop.remove();
|
|
77
|
+
sheet.remove();
|
|
78
|
+
resolve({ tapIndex: tapIndex });
|
|
79
|
+
}, ANIMATION_MS);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { registerViewMethodHandler } from '../bridge';
|
|
2
|
+
import { showActionSheet } from './action-sheet';
|
|
3
|
+
import { showModal } from './modal';
|
|
4
|
+
import { showToast, hideToast } from './toast';
|
|
5
|
+
export function registerUIHandlers() {
|
|
6
|
+
registerViewMethodHandler('ui.showActionSheet', showActionSheet);
|
|
7
|
+
registerViewMethodHandler('ui.showModal', showModal);
|
|
8
|
+
registerViewMethodHandler('ui.showToast', showToast);
|
|
9
|
+
registerViewMethodHandler('ui.hideToast', hideToast);
|
|
10
|
+
}
|