@wowlabtech/mini-app-adapter 0.2.2 → 0.2.4
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/index.cjs +268 -49
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +38 -4
- package/dist/index.d.ts +38 -4
- package/dist/index.js +268 -49
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -479,7 +479,7 @@ async function startHtml5Qrcode() {
|
|
|
479
479
|
if (typeof document === "undefined") {
|
|
480
480
|
throw new Error("QR scanning requires a browser environment.");
|
|
481
481
|
}
|
|
482
|
-
const [{ Html5Qrcode
|
|
482
|
+
const [{ Html5Qrcode }] = await Promise.all([import("html5-qrcode")]);
|
|
483
483
|
return new Promise((resolve, reject) => {
|
|
484
484
|
const elementId = `native-shell-qr-${Date.now()}`;
|
|
485
485
|
const overlay = document.createElement("div");
|
|
@@ -516,7 +516,7 @@ async function startHtml5Qrcode() {
|
|
|
516
516
|
const previousOverflow = document.body.style.overflow;
|
|
517
517
|
document.body.style.overflow = "hidden";
|
|
518
518
|
let disposed = false;
|
|
519
|
-
const scanner = new
|
|
519
|
+
const scanner = new Html5Qrcode(elementId);
|
|
520
520
|
const cleanup = async (result, error) => {
|
|
521
521
|
if (disposed) {
|
|
522
522
|
return;
|
|
@@ -638,7 +638,8 @@ var BaseMiniAppAdapter = class {
|
|
|
638
638
|
async openExternalLink(url) {
|
|
639
639
|
window.open(url, "_blank", "noopener,noreferrer");
|
|
640
640
|
}
|
|
641
|
-
async openInternalLink(
|
|
641
|
+
async openInternalLink(url) {
|
|
642
|
+
window.open(url, "_self", "noopener,noreferrer");
|
|
642
643
|
}
|
|
643
644
|
async closeApp() {
|
|
644
645
|
if (window.history.length > 1) {
|
|
@@ -864,6 +865,10 @@ var MaxMiniAppAdapter = class extends BaseMiniAppAdapter {
|
|
|
864
865
|
return Boolean(bridge2?.BackButton?.onClick);
|
|
865
866
|
case "backButtonVisibility":
|
|
866
867
|
return Boolean(bridge2?.BackButton?.show && bridge2.BackButton.hide);
|
|
868
|
+
case "openInternalLink":
|
|
869
|
+
return typeof bridge2?.openMaxLink === "function";
|
|
870
|
+
case "downloadFile":
|
|
871
|
+
return typeof bridge2?.downloadFile === "function";
|
|
867
872
|
case "requestPhone":
|
|
868
873
|
if (!bridge2) {
|
|
869
874
|
return false;
|
|
@@ -918,6 +923,14 @@ var MaxMiniAppAdapter = class extends BaseMiniAppAdapter {
|
|
|
918
923
|
}
|
|
919
924
|
await super.openExternalLink(url);
|
|
920
925
|
}
|
|
926
|
+
async openInternalLink(url) {
|
|
927
|
+
const bridge2 = getMaxBridge();
|
|
928
|
+
if (bridge2?.openMaxLink) {
|
|
929
|
+
bridge2.openMaxLink(url);
|
|
930
|
+
return;
|
|
931
|
+
}
|
|
932
|
+
await super.openInternalLink(url);
|
|
933
|
+
}
|
|
921
934
|
async closeApp() {
|
|
922
935
|
const bridge2 = getMaxBridge();
|
|
923
936
|
if (bridge2?.close) {
|
|
@@ -1314,6 +1327,30 @@ var TelegramMiniAppAdapter = class extends BaseMiniAppAdapter {
|
|
|
1314
1327
|
return import_sdk_react.backButton.hide.isSupported();
|
|
1315
1328
|
case "bindCssVariables":
|
|
1316
1329
|
return true;
|
|
1330
|
+
case "openInternalLink":
|
|
1331
|
+
return true;
|
|
1332
|
+
case "requestFullscreen":
|
|
1333
|
+
return Boolean(
|
|
1334
|
+
typeof import_sdk.viewport.requestFullscreen === "function" || import_sdk_react.viewport.requestFullscreen?.isAvailable?.()
|
|
1335
|
+
);
|
|
1336
|
+
case "verticalSwipes":
|
|
1337
|
+
return Boolean(
|
|
1338
|
+
import_sdk.swipeBehavior.enableVertical.isAvailable() || import_sdk.swipeBehavior.disableVertical.isAvailable()
|
|
1339
|
+
);
|
|
1340
|
+
case "viewVisibility":
|
|
1341
|
+
return true;
|
|
1342
|
+
case "shareUrl":
|
|
1343
|
+
return typeof import_sdk.shareURL === "function";
|
|
1344
|
+
case "shareStory":
|
|
1345
|
+
return typeof import_sdk.shareStory === "function";
|
|
1346
|
+
case "copyTextToClipboard":
|
|
1347
|
+
return typeof import_sdk.copyTextToClipboard === "function";
|
|
1348
|
+
case "downloadFile":
|
|
1349
|
+
return typeof import_sdk.downloadFile === "function";
|
|
1350
|
+
case "addToHomeScreen":
|
|
1351
|
+
return typeof import_sdk.addToHomeScreen?.isAvailable === "function" ? import_sdk.addToHomeScreen.isAvailable() : typeof import_sdk.addToHomeScreen === "function";
|
|
1352
|
+
case "checkHomeScreenStatus":
|
|
1353
|
+
return typeof import_sdk.checkHomeScreenStatus === "function";
|
|
1317
1354
|
case "requestPhone": {
|
|
1318
1355
|
return Boolean(isFeatureAvailable(import_sdk.requestPhoneAccess) || isFeatureAvailable(import_sdk.requestContact));
|
|
1319
1356
|
}
|
|
@@ -1559,7 +1596,15 @@ var TelegramMiniAppAdapter = class extends BaseMiniAppAdapter {
|
|
|
1559
1596
|
await super.downloadFile(url, filename);
|
|
1560
1597
|
}
|
|
1561
1598
|
async shareStory(mediaUrl, options) {
|
|
1562
|
-
|
|
1599
|
+
const text = options?.telegram?.text ?? options?.text;
|
|
1600
|
+
const widgetLink = options?.telegram?.widgetLink ?? (options?.link ? {
|
|
1601
|
+
url: options.link.url,
|
|
1602
|
+
...options.link.name ? { name: options.link.name } : {}
|
|
1603
|
+
} : void 0);
|
|
1604
|
+
(0, import_sdk.shareStory)(mediaUrl, {
|
|
1605
|
+
...text ? { text } : {},
|
|
1606
|
+
...widgetLink ? { widgetLink } : {}
|
|
1607
|
+
});
|
|
1563
1608
|
}
|
|
1564
1609
|
async addToHomeScreen() {
|
|
1565
1610
|
const isAvailable = typeof import_sdk.addToHomeScreen?.isAvailable === "function" ? import_sdk.addToHomeScreen.isAvailable() : true;
|
|
@@ -1914,17 +1959,41 @@ var VKMiniAppAdapter = class extends BaseMiniAppAdapter {
|
|
|
1914
1959
|
};
|
|
1915
1960
|
}
|
|
1916
1961
|
async supports(capability) {
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1962
|
+
switch (capability) {
|
|
1963
|
+
case "haptics": {
|
|
1964
|
+
const [impact, notification, selection] = await Promise.all([
|
|
1965
|
+
this.supportsBridgeMethod("VKWebAppTapticImpactOccurred"),
|
|
1966
|
+
this.supportsBridgeMethod("VKWebAppTapticNotificationOccurred"),
|
|
1967
|
+
this.supportsBridgeMethod("VKWebAppTapticSelectionChanged")
|
|
1968
|
+
]);
|
|
1969
|
+
return impact || notification || selection;
|
|
1970
|
+
}
|
|
1971
|
+
case "qrScanner":
|
|
1972
|
+
return this.supportsBridgeMethod("VKWebAppOpenCodeReader");
|
|
1973
|
+
case "requestPhone": {
|
|
1974
|
+
const [supportsPhoneNumber, supportsPersonalCard] = await Promise.all([
|
|
1975
|
+
this.supportsBridgeMethod("VKWebAppGetPhoneNumber"),
|
|
1976
|
+
this.supportsBridgeMethod("VKWebAppGetPersonalCard")
|
|
1977
|
+
]);
|
|
1978
|
+
return supportsPhoneNumber || supportsPersonalCard;
|
|
1979
|
+
}
|
|
1980
|
+
case "notifications":
|
|
1981
|
+
return this.supportsBridgeMethod("VKWebAppAllowNotifications");
|
|
1982
|
+
case "shareUrl":
|
|
1983
|
+
return this.supportsBridgeMethod("VKWebAppShare");
|
|
1984
|
+
case "shareStory":
|
|
1985
|
+
return this.supportsBridgeMethod("VKWebAppShowStoryBox");
|
|
1986
|
+
case "downloadFile":
|
|
1987
|
+
return this.supportsBridgeMethod("VKWebAppDownloadFile");
|
|
1988
|
+
case "addToHomeScreen":
|
|
1989
|
+
return this.supportsBridgeMethod("VKWebAppAddToHomeScreen");
|
|
1990
|
+
case "denyNotifications":
|
|
1991
|
+
return this.supportsBridgeMethod("VKWebAppDenyNotifications");
|
|
1992
|
+
case "viewVisibility":
|
|
1993
|
+
return true;
|
|
1994
|
+
default:
|
|
1995
|
+
return await super.supports(capability);
|
|
1926
1996
|
}
|
|
1927
|
-
return await super.supports(capability);
|
|
1928
1997
|
}
|
|
1929
1998
|
async requestPhone() {
|
|
1930
1999
|
const [supportsPhoneNumber, supportsPersonalCard] = await Promise.all([
|
|
@@ -2026,9 +2095,34 @@ var VKMiniAppAdapter = class extends BaseMiniAppAdapter {
|
|
|
2026
2095
|
};
|
|
2027
2096
|
}
|
|
2028
2097
|
async shareStory(mediaUrl, _options) {
|
|
2098
|
+
const options = _options;
|
|
2099
|
+
const vkOptions = options?.vk;
|
|
2100
|
+
const fallbackAttachment = options?.link ? {
|
|
2101
|
+
type: "url",
|
|
2102
|
+
text: "open",
|
|
2103
|
+
url: options.link.url
|
|
2104
|
+
} : void 0;
|
|
2105
|
+
const fallbackStickers = options?.text ? [{
|
|
2106
|
+
sticker_type: "native",
|
|
2107
|
+
sticker: {
|
|
2108
|
+
action_type: "text",
|
|
2109
|
+
action: {
|
|
2110
|
+
text: options.text,
|
|
2111
|
+
style: "classic",
|
|
2112
|
+
background_style: "none"
|
|
2113
|
+
},
|
|
2114
|
+
transform: {
|
|
2115
|
+
gravity: "center_bottom",
|
|
2116
|
+
translation_y: -0.2
|
|
2117
|
+
}
|
|
2118
|
+
}
|
|
2119
|
+
}] : void 0;
|
|
2029
2120
|
const bridgeOptions = {
|
|
2030
|
-
background_type: "image",
|
|
2031
|
-
url: mediaUrl
|
|
2121
|
+
background_type: vkOptions?.backgroundType ?? "image",
|
|
2122
|
+
url: mediaUrl,
|
|
2123
|
+
locked: vkOptions?.locked ?? true,
|
|
2124
|
+
...vkOptions?.attachment ?? fallbackAttachment ? { attachment: vkOptions?.attachment ?? fallbackAttachment } : {},
|
|
2125
|
+
...vkOptions?.stickers ?? fallbackStickers ? { stickers: vkOptions?.stickers ?? fallbackStickers } : {}
|
|
2032
2126
|
};
|
|
2033
2127
|
await import_vk_bridge.default.send("VKWebAppShowStoryBox", bridgeOptions);
|
|
2034
2128
|
}
|
|
@@ -2401,7 +2495,7 @@ var VKMiniAppAdapter = class extends BaseMiniAppAdapter {
|
|
|
2401
2495
|
};
|
|
2402
2496
|
|
|
2403
2497
|
// src/adapters/webAdapter.ts
|
|
2404
|
-
var
|
|
2498
|
+
var import_jsqr = __toESM(require("jsqr"), 1);
|
|
2405
2499
|
var WebMiniAppAdapter = class extends BaseMiniAppAdapter {
|
|
2406
2500
|
constructor() {
|
|
2407
2501
|
super("web", {
|
|
@@ -2417,6 +2511,22 @@ var WebMiniAppAdapter = class extends BaseMiniAppAdapter {
|
|
|
2417
2511
|
});
|
|
2418
2512
|
}
|
|
2419
2513
|
}
|
|
2514
|
+
supports(capability) {
|
|
2515
|
+
switch (capability) {
|
|
2516
|
+
case "copyTextToClipboard":
|
|
2517
|
+
return typeof navigator !== "undefined" && Boolean(navigator.clipboard?.writeText);
|
|
2518
|
+
case "downloadFile":
|
|
2519
|
+
return typeof document !== "undefined";
|
|
2520
|
+
case "shareUrl":
|
|
2521
|
+
return typeof navigator !== "undefined" && (Boolean(navigator.share) || Boolean(navigator.clipboard?.writeText));
|
|
2522
|
+
case "addToHomeScreen":
|
|
2523
|
+
return /android/i.test(navigator.userAgent) && Boolean(this.deferredPrompt);
|
|
2524
|
+
case "checkHomeScreenStatus":
|
|
2525
|
+
return true;
|
|
2526
|
+
default:
|
|
2527
|
+
return super.supports(capability);
|
|
2528
|
+
}
|
|
2529
|
+
}
|
|
2420
2530
|
async downloadFile(url, filename) {
|
|
2421
2531
|
try {
|
|
2422
2532
|
await triggerFileDownload(url, filename, { preferBlob: true });
|
|
@@ -2471,14 +2581,31 @@ var WebMiniAppAdapter = class extends BaseMiniAppAdapter {
|
|
|
2471
2581
|
closeBtn.style.cursor = "pointer";
|
|
2472
2582
|
closeBtn.style.zIndex = "9999999999";
|
|
2473
2583
|
overlay.appendChild(closeBtn);
|
|
2584
|
+
const scanSize = Math.min(Math.floor(Math.min(window.innerWidth, window.innerHeight) * 0.72), 320);
|
|
2585
|
+
const scanBox = document.createElement("div");
|
|
2586
|
+
scanBox.style.width = `${scanSize}px`;
|
|
2587
|
+
scanBox.style.height = `${scanSize}px`;
|
|
2588
|
+
scanBox.style.position = "relative";
|
|
2589
|
+
scanBox.style.flex = "0 0 auto";
|
|
2590
|
+
scanBox.style.borderRadius = "18px";
|
|
2591
|
+
scanBox.style.overflow = "hidden";
|
|
2592
|
+
overlay.appendChild(scanBox);
|
|
2474
2593
|
const scanArea = document.createElement("div");
|
|
2475
|
-
scanArea.
|
|
2476
|
-
scanArea.style.
|
|
2477
|
-
scanArea.style.
|
|
2478
|
-
scanArea.style.
|
|
2479
|
-
scanArea
|
|
2480
|
-
|
|
2481
|
-
|
|
2594
|
+
scanArea.style.position = "absolute";
|
|
2595
|
+
scanArea.style.inset = "0";
|
|
2596
|
+
scanArea.style.zIndex = "1";
|
|
2597
|
+
scanArea.style.background = "#000";
|
|
2598
|
+
scanBox.appendChild(scanArea);
|
|
2599
|
+
const video = document.createElement("video");
|
|
2600
|
+
video.setAttribute("playsinline", "true");
|
|
2601
|
+
video.autoplay = true;
|
|
2602
|
+
video.muted = true;
|
|
2603
|
+
video.style.width = "100%";
|
|
2604
|
+
video.style.height = "100%";
|
|
2605
|
+
video.style.objectFit = "cover";
|
|
2606
|
+
video.style.position = "absolute";
|
|
2607
|
+
video.style.inset = "0";
|
|
2608
|
+
scanArea.appendChild(video);
|
|
2482
2609
|
const frame = document.createElement("div");
|
|
2483
2610
|
frame.style.position = "absolute";
|
|
2484
2611
|
frame.style.top = "0";
|
|
@@ -2488,8 +2615,8 @@ var WebMiniAppAdapter = class extends BaseMiniAppAdapter {
|
|
|
2488
2615
|
frame.style.border = "3px solid rgba(255,255,255,0.9)";
|
|
2489
2616
|
frame.style.borderRadius = "18px";
|
|
2490
2617
|
frame.style.pointerEvents = "none";
|
|
2491
|
-
frame.style.zIndex = "
|
|
2492
|
-
|
|
2618
|
+
frame.style.zIndex = "3";
|
|
2619
|
+
scanBox.appendChild(frame);
|
|
2493
2620
|
const line = document.createElement("div");
|
|
2494
2621
|
line.style.position = "absolute";
|
|
2495
2622
|
line.style.left = "0";
|
|
@@ -2498,8 +2625,8 @@ var WebMiniAppAdapter = class extends BaseMiniAppAdapter {
|
|
|
2498
2625
|
line.style.background = "rgba(255,255,255,0.85)";
|
|
2499
2626
|
line.style.borderRadius = "2px";
|
|
2500
2627
|
line.style.animation = "qr-line 2s infinite";
|
|
2501
|
-
line.style.zIndex = "
|
|
2502
|
-
|
|
2628
|
+
line.style.zIndex = "4";
|
|
2629
|
+
scanBox.appendChild(line);
|
|
2503
2630
|
const styleTag = document.createElement("style");
|
|
2504
2631
|
styleTag.innerHTML = `
|
|
2505
2632
|
@keyframes qr-line {
|
|
@@ -2516,17 +2643,26 @@ var WebMiniAppAdapter = class extends BaseMiniAppAdapter {
|
|
|
2516
2643
|
hint.style.fontSize = "17px";
|
|
2517
2644
|
hint.style.opacity = "0.9";
|
|
2518
2645
|
overlay.appendChild(hint);
|
|
2519
|
-
const
|
|
2646
|
+
const canvas = document.createElement("canvas");
|
|
2647
|
+
const context = canvas.getContext("2d", { willReadFrequently: true });
|
|
2648
|
+
let stream = null;
|
|
2649
|
+
let rafId = null;
|
|
2650
|
+
let lastScanAt = 0;
|
|
2520
2651
|
let closed = false;
|
|
2521
2652
|
const finalize = async (result) => {
|
|
2522
2653
|
if (closed) {
|
|
2523
2654
|
return;
|
|
2524
2655
|
}
|
|
2525
2656
|
closed = true;
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2657
|
+
if (rafId !== null) {
|
|
2658
|
+
cancelAnimationFrame(rafId);
|
|
2659
|
+
rafId = null;
|
|
2660
|
+
}
|
|
2661
|
+
if (stream) {
|
|
2662
|
+
stream.getTracks().forEach((track) => track.stop());
|
|
2663
|
+
stream = null;
|
|
2529
2664
|
}
|
|
2665
|
+
video.srcObject = null;
|
|
2530
2666
|
overlay.remove();
|
|
2531
2667
|
styleTag.remove();
|
|
2532
2668
|
document.body.style.overflow = prevOverflow;
|
|
@@ -2545,19 +2681,50 @@ var WebMiniAppAdapter = class extends BaseMiniAppAdapter {
|
|
|
2545
2681
|
};
|
|
2546
2682
|
closeBtn.onclick = () => closeScanner(null);
|
|
2547
2683
|
try {
|
|
2548
|
-
|
|
2549
|
-
{ facingMode: "environment" },
|
|
2550
|
-
{
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
()
|
|
2684
|
+
const constraints = [
|
|
2685
|
+
{ video: { facingMode: { ideal: "environment" } }, audio: false },
|
|
2686
|
+
{ video: { facingMode: "environment" }, audio: false },
|
|
2687
|
+
{ video: true, audio: false }
|
|
2688
|
+
];
|
|
2689
|
+
let lastError = null;
|
|
2690
|
+
for (const constraint of constraints) {
|
|
2691
|
+
try {
|
|
2692
|
+
stream = await navigator.mediaDevices.getUserMedia(constraint);
|
|
2693
|
+
break;
|
|
2694
|
+
} catch (error) {
|
|
2695
|
+
lastError = error;
|
|
2559
2696
|
}
|
|
2560
|
-
|
|
2697
|
+
}
|
|
2698
|
+
if (!stream) {
|
|
2699
|
+
throw lastError instanceof Error ? lastError : new Error("Unable to access camera");
|
|
2700
|
+
}
|
|
2701
|
+
video.srcObject = stream;
|
|
2702
|
+
await video.play();
|
|
2703
|
+
const scanFrame = (now) => {
|
|
2704
|
+
if (closed) {
|
|
2705
|
+
return;
|
|
2706
|
+
}
|
|
2707
|
+
if (now - lastScanAt >= 100 && context && video.readyState >= HTMLMediaElement.HAVE_CURRENT_DATA) {
|
|
2708
|
+
const width = video.videoWidth;
|
|
2709
|
+
const height = video.videoHeight;
|
|
2710
|
+
if (width > 0 && height > 0) {
|
|
2711
|
+
canvas.width = width;
|
|
2712
|
+
canvas.height = height;
|
|
2713
|
+
context.drawImage(video, 0, 0, width, height);
|
|
2714
|
+
const imageData = context.getImageData(0, 0, width, height);
|
|
2715
|
+
const result = (0, import_jsqr.default)(imageData.data, width, height, {
|
|
2716
|
+
inversionAttempts: "attemptBoth"
|
|
2717
|
+
});
|
|
2718
|
+
if (result?.data) {
|
|
2719
|
+
closeScanner(result.data);
|
|
2720
|
+
return;
|
|
2721
|
+
}
|
|
2722
|
+
lastScanAt = now;
|
|
2723
|
+
}
|
|
2724
|
+
}
|
|
2725
|
+
rafId = requestAnimationFrame(scanFrame);
|
|
2726
|
+
};
|
|
2727
|
+
rafId = requestAnimationFrame(scanFrame);
|
|
2561
2728
|
} catch (error) {
|
|
2562
2729
|
console.error("QR Start error", error);
|
|
2563
2730
|
closeScanner(null);
|
|
@@ -2610,6 +2777,8 @@ ${url}` : url;
|
|
|
2610
2777
|
};
|
|
2611
2778
|
|
|
2612
2779
|
// src/adapters/index.ts
|
|
2780
|
+
var CONFIRMED_PLATFORM_STORAGE_KEY = "mini-app-adapter:confirmed-platform";
|
|
2781
|
+
var CONFIRMED_PLATFORM_TTL_MS = 30 * 60 * 1e3;
|
|
2613
2782
|
function detectPlatform() {
|
|
2614
2783
|
if (typeof window === "undefined") {
|
|
2615
2784
|
return "web";
|
|
@@ -2621,30 +2790,76 @@ function detectPlatform() {
|
|
|
2621
2790
|
})();
|
|
2622
2791
|
const getParam = (name) => searchParams.get(name) ?? hashParams.get(name);
|
|
2623
2792
|
const hasParam = (...names) => names.some((name) => getParam(name));
|
|
2793
|
+
const readConfirmedPlatform = () => {
|
|
2794
|
+
try {
|
|
2795
|
+
const raw = window.sessionStorage.getItem(CONFIRMED_PLATFORM_STORAGE_KEY);
|
|
2796
|
+
if (!raw) {
|
|
2797
|
+
return null;
|
|
2798
|
+
}
|
|
2799
|
+
const parsed = JSON.parse(raw);
|
|
2800
|
+
if (!parsed?.platform || typeof parsed.ts !== "number") {
|
|
2801
|
+
return null;
|
|
2802
|
+
}
|
|
2803
|
+
if (Date.now() - parsed.ts > CONFIRMED_PLATFORM_TTL_MS) {
|
|
2804
|
+
return null;
|
|
2805
|
+
}
|
|
2806
|
+
return parsed.platform;
|
|
2807
|
+
} catch {
|
|
2808
|
+
return null;
|
|
2809
|
+
}
|
|
2810
|
+
};
|
|
2811
|
+
const persistConfirmedPlatform = (platform) => {
|
|
2812
|
+
if (platform === "web") {
|
|
2813
|
+
return;
|
|
2814
|
+
}
|
|
2815
|
+
try {
|
|
2816
|
+
window.sessionStorage.setItem(
|
|
2817
|
+
CONFIRMED_PLATFORM_STORAGE_KEY,
|
|
2818
|
+
JSON.stringify({ platform, ts: Date.now() })
|
|
2819
|
+
);
|
|
2820
|
+
} catch {
|
|
2821
|
+
}
|
|
2822
|
+
};
|
|
2624
2823
|
const shellPlatform = readShellPlatform();
|
|
2625
2824
|
if (shellPlatform) {
|
|
2825
|
+
persistConfirmedPlatform(shellPlatform);
|
|
2626
2826
|
return shellPlatform;
|
|
2627
2827
|
}
|
|
2628
2828
|
const userAgent = navigator.userAgent.toLowerCase();
|
|
2629
2829
|
const hasNativeBridge = typeof window.NativeBridge?.postMessage === "function";
|
|
2630
2830
|
if (hasNativeBridge) {
|
|
2631
2831
|
if (userAgent.includes("android")) {
|
|
2832
|
+
persistConfirmedPlatform("shell_android");
|
|
2632
2833
|
return "shell_android";
|
|
2633
2834
|
}
|
|
2835
|
+
persistConfirmedPlatform("shell_ios");
|
|
2634
2836
|
return "shell_ios";
|
|
2635
2837
|
}
|
|
2636
|
-
|
|
2838
|
+
const telegramGlobals = window;
|
|
2839
|
+
const hasTelegramGlobal = Boolean(window.Telegram?.WebApp) || typeof telegramGlobals.TelegramWebviewProxy !== "undefined" || typeof telegramGlobals.TelegramGameProxy !== "undefined";
|
|
2840
|
+
const hasTelegramParams = hasParam("tgWebAppPlatform", "tgWebAppVersion", "tgWebAppData", "tgWebAppLanguage");
|
|
2841
|
+
if (hasTelegramGlobal || hasTelegramParams || userAgent.includes("telegram")) {
|
|
2842
|
+
persistConfirmedPlatform("telegram");
|
|
2637
2843
|
return "telegram";
|
|
2638
2844
|
}
|
|
2639
2845
|
if (window.WebApp) {
|
|
2846
|
+
persistConfirmedPlatform("max");
|
|
2640
2847
|
return "max";
|
|
2641
2848
|
}
|
|
2642
2849
|
if (window.MaxMiniApp) {
|
|
2850
|
+
persistConfirmedPlatform("max");
|
|
2643
2851
|
return "max";
|
|
2644
2852
|
}
|
|
2645
|
-
|
|
2853
|
+
const hasVkParams = hasParam("vk_app_id", "vk_platform", "vk_user_id", "vk_language", "sign");
|
|
2854
|
+
const hasVkUserAgentSignal = userAgent.includes("vkclient") || userAgent.includes("vk-android") || userAgent.includes("vkontakte");
|
|
2855
|
+
if (hasVkParams || hasVkUserAgentSignal) {
|
|
2856
|
+
persistConfirmedPlatform("vk");
|
|
2646
2857
|
return "vk";
|
|
2647
2858
|
}
|
|
2859
|
+
const confirmedPlatform = readConfirmedPlatform();
|
|
2860
|
+
if (confirmedPlatform && confirmedPlatform !== "web") {
|
|
2861
|
+
return confirmedPlatform;
|
|
2862
|
+
}
|
|
2648
2863
|
return "web";
|
|
2649
2864
|
}
|
|
2650
2865
|
function createAdapter(input) {
|
|
@@ -2845,14 +3060,18 @@ var cachedPlatform = null;
|
|
|
2845
3060
|
function getPlatform() {
|
|
2846
3061
|
const adapter = getActiveAdapter();
|
|
2847
3062
|
if (adapter) {
|
|
2848
|
-
|
|
3063
|
+
if (adapter.platform !== "web") {
|
|
3064
|
+
cachedPlatform = adapter.platform;
|
|
3065
|
+
}
|
|
2849
3066
|
return adapter.platform;
|
|
2850
3067
|
}
|
|
2851
|
-
if (cachedPlatform) {
|
|
3068
|
+
if (cachedPlatform && cachedPlatform !== "web") {
|
|
2852
3069
|
return cachedPlatform;
|
|
2853
3070
|
}
|
|
2854
3071
|
const detectedPlatform = detectPlatform();
|
|
2855
|
-
|
|
3072
|
+
if (detectedPlatform !== "web") {
|
|
3073
|
+
cachedPlatform = detectedPlatform;
|
|
3074
|
+
}
|
|
2856
3075
|
return detectedPlatform;
|
|
2857
3076
|
}
|
|
2858
3077
|
|