refactor: project architecture refactor, container splitting
This commit is contained in:
@@ -0,0 +1,169 @@
|
||||
export function readTelegramMiniAppInitDataFromLocation() {
|
||||
if (typeof window === "undefined") return "";
|
||||
const queryText = window.location.search.replace(/^\?/, "");
|
||||
const hashText = window.location.hash.replace(/^#/, "");
|
||||
for (const text of [queryText, hashText]) {
|
||||
if (!text) continue;
|
||||
const params = new URLSearchParams(text);
|
||||
const initData = params.get("tgWebAppData");
|
||||
if (initData) return initData;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
export function createTelegramSdk({
|
||||
scriptUrl,
|
||||
bootTimeoutMs,
|
||||
actionTimeoutMs,
|
||||
miniAppAuthTimeoutMs,
|
||||
onStatusChange = () => {},
|
||||
onInitDataChange = () => {},
|
||||
} = {}) {
|
||||
let tg = resolve();
|
||||
let sdkPromise = null;
|
||||
let launchParamsDetected = false;
|
||||
let initData = tg?.initData || readTelegramMiniAppInitDataFromLocation();
|
||||
if (initData) launchParamsDetected = true;
|
||||
|
||||
function resolve() {
|
||||
return window.Telegram?.WebApp || null;
|
||||
}
|
||||
|
||||
function setStatus(status) {
|
||||
onStatusChange(status);
|
||||
}
|
||||
|
||||
function refresh() {
|
||||
tg = resolve();
|
||||
if (tg) setStatus("ready");
|
||||
initData = tg?.initData || readTelegramMiniAppInitDataFromLocation();
|
||||
onInitDataChange(initData);
|
||||
if (initData) launchParamsDetected = true;
|
||||
return tg;
|
||||
}
|
||||
|
||||
function hasLaunchParams() {
|
||||
refresh();
|
||||
if (launchParamsDetected || initData) {
|
||||
launchParamsDetected = true;
|
||||
return true;
|
||||
}
|
||||
const queryText = window.location.search.replace(/^\?/, "");
|
||||
const hashText = window.location.hash.replace(/^#/, "");
|
||||
const detected = [queryText, hashText].some((text) => {
|
||||
if (!text) return false;
|
||||
const params = new URLSearchParams(text);
|
||||
return ["tgWebAppData", "tgWebAppVersion", "tgWebAppPlatform", "tgWebAppThemeParams"].some(
|
||||
(key) => params.has(key)
|
||||
);
|
||||
});
|
||||
if (detected) launchParamsDetected = true;
|
||||
return detected;
|
||||
}
|
||||
|
||||
function load(timeoutMs = bootTimeoutMs) {
|
||||
if (refresh()) return Promise.resolve(tg);
|
||||
if (sdkPromise) return sdkPromise;
|
||||
if (typeof document === "undefined") return Promise.resolve(null);
|
||||
|
||||
setStatus("loading");
|
||||
sdkPromise = new Promise((resolvePromise) => {
|
||||
const existingScript = document.querySelector("script[data-rw-telegram-web-app-sdk]");
|
||||
const script = existingScript || document.createElement("script");
|
||||
let resolved = false;
|
||||
let timeoutId = null;
|
||||
|
||||
const resolveOnce = (value) => {
|
||||
if (resolved) return;
|
||||
resolved = true;
|
||||
if (timeoutId) window.clearTimeout(timeoutId);
|
||||
resolvePromise(value);
|
||||
};
|
||||
|
||||
const refreshFromScript = () => {
|
||||
tg = resolve();
|
||||
setStatus(tg ? "ready" : "unavailable");
|
||||
return tg;
|
||||
};
|
||||
|
||||
script.addEventListener("load", () => resolveOnce(refreshFromScript()), { once: true });
|
||||
script.addEventListener(
|
||||
"error",
|
||||
() => {
|
||||
setStatus("unavailable");
|
||||
resolveOnce(null);
|
||||
},
|
||||
{ once: true }
|
||||
);
|
||||
|
||||
if (!existingScript) {
|
||||
script.src = scriptUrl;
|
||||
script.async = true;
|
||||
script.defer = true;
|
||||
script.dataset.rwTelegramWebAppSdk = "1";
|
||||
document.head.appendChild(script);
|
||||
}
|
||||
|
||||
timeoutId = window.setTimeout(() => {
|
||||
if (!tg) setStatus("unavailable");
|
||||
resolveOnce(tg);
|
||||
}, timeoutMs);
|
||||
}).finally(() => {
|
||||
sdkPromise = null;
|
||||
});
|
||||
return sdkPromise;
|
||||
}
|
||||
|
||||
async function ensureForAction() {
|
||||
if (refresh()) return tg;
|
||||
return await load(actionTimeoutMs);
|
||||
}
|
||||
|
||||
function createMiniAppAuthTimeout() {
|
||||
const controller = typeof AbortController === "undefined" ? null : new AbortController();
|
||||
let timedOut = false;
|
||||
let timeoutId = null;
|
||||
let timeoutPromise = new Promise(() => {});
|
||||
|
||||
if (typeof window !== "undefined") {
|
||||
timeoutPromise = new Promise((_, reject) => {
|
||||
timeoutId = window.setTimeout(() => {
|
||||
timedOut = true;
|
||||
controller?.abort();
|
||||
const error = new Error("telegram_mini_app_auth_timeout");
|
||||
error.name = "AbortError";
|
||||
reject(error);
|
||||
}, miniAppAuthTimeoutMs);
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
promise: timeoutPromise,
|
||||
get signal() {
|
||||
return controller?.signal;
|
||||
},
|
||||
get timedOut() {
|
||||
return timedOut;
|
||||
},
|
||||
clear() {
|
||||
if (timeoutId) window.clearTimeout(timeoutId);
|
||||
timeoutId = null;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
get tg() {
|
||||
return tg;
|
||||
},
|
||||
get initData() {
|
||||
return initData;
|
||||
},
|
||||
refresh,
|
||||
hasLaunchParams,
|
||||
load,
|
||||
ensureForAction,
|
||||
createMiniAppAuthTimeout,
|
||||
readInitDataFromLocation: readTelegramMiniAppInitDataFromLocation,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user