fix: tg safe area
All checks were successful
Deploy to VPS (dist) / deploy (push) Successful in 2m10s

This commit is contained in:
Hewston Fox
2026-03-18 23:06:36 +02:00
parent 43e52e7585
commit a1f6c57901
4 changed files with 51 additions and 27 deletions

View File

@@ -1,9 +1,10 @@
:root {
--header-height: 90px;
--header-total: calc(
var(--header-height) + var(--tg-safe-area-inset-top, 0px) +
var(--tg-content-safe-area-inset-top, 0px)
--header-padding: calc(
var(--tg-viewport-safe-area-inset-top, 0px) +
var(--tg-viewport-content-safe-area-inset-top, 0px)
);
--header-total: calc(var(--header-height) + var(--header-padding));
}
@layer base {
@@ -14,9 +15,7 @@
left: 0;
z-index: 10;
height: var(--header-total);
padding-top: calc(
var(--tg-safe-area-inset-top, 0px) + var(--tg-content-safe-area-inset-top, 0px)
);
padding-top: var(--header-padding);
background: rgb(59 130 246 / 0.3);
}
}

View File

@@ -1,6 +1,7 @@
:root {
--navigation-height: 74px;
--navigation-total: calc(var(--navigation-height) + var(--tg-safe-area-inset-bottom, 0px));
--navigation-padding: var(--tg-viewport-safe-area-inset-bottom, 0px);
--navigation-total: calc(var(--navigation-height) + var(--navigation-padding));
}
@layer base {
@@ -33,7 +34,7 @@
flex-direction: column;
align-items: center;
justify-content: flex-start;
padding-bottom: var(--tg-safe-area-inset-bottom, 0px);
padding-bottom: var(--navigation-padding);
}
.barActive {

View File

@@ -7,6 +7,7 @@ import { useEffect } from "react";
import { Route as GameRoute } from "./game";
import Header from "./-/Header";
import Navigation from "./-/Navigation";
import tg from "@/tg";
function AppLayout() {
return (
@@ -22,6 +23,17 @@ function AppLayout() {
);
}
tg.storage.setItem("authToken", "123");
tg.storage
.getItem("authToken")
.then((value) => {
console.log("Success", `$${value}$`);
})
.catch((error) => {
console.error("Error", error);
});
export const Route = createRootRoute({
notFoundComponent: () => {
const navigate = useNavigate();

View File

@@ -5,9 +5,7 @@ export const STORAGE_KEYS = {
} as const;
export type StorageKey = (typeof STORAGE_KEYS)[keyof typeof STORAGE_KEYS];
type WithChecks<Result> = {
ifAvailable: (...args: any[]) => { ok: true; data: Result } | { ok: false };
};
type TgResult<T> = { ok: true; data: T } | { ok: false };
const isPromise = <T>(value: T | Promise<T>): value is Promise<T> =>
value && typeof value === "object" && "then" in value && typeof value.then === "function";
@@ -16,26 +14,30 @@ const promisify = <T>(value: T | Promise<T>): Promise<T> =>
isPromise(value) ? value : Promise.resolve(value);
const fallbackImplementation = <
T extends ((...args: any) => any) & WithChecks<any>,
Async extends boolean,
Params extends Parameters<T>,
Result extends T extends WithChecks<infer Result> ? Result : never,
F extends (...args: Params) => Async extends true ? Result | Awaited<Result> : Result,
TMain extends (...args: any) => TgResult<any>,
Async extends Extract<ReturnType<TMain>, { ok: true }>["data"] extends Promise<any>
? true
: false,
Params extends Parameters<TMain>,
Result extends Awaited<Extract<ReturnType<TMain>, { ok: true }>["data"]>,
TFallback extends (...args: Params) => Async extends true ? Result | Awaited<Result> : Result,
>(
async: Async,
args: Params,
cb: T,
onErr: F,
cb: TMain,
onErr: TFallback,
): Async extends true ? Promise<Result> : Awaited<Result> => {
const res = cb.ifAvailable.apply(null, args);
const returnValue = (res.ok ? res.data : onErr.apply(null, args)) as Result;
const res = cb.apply(null, args);
const returnValue = (
res.ok && !import.meta.env.DEV ? res.data : onErr.apply(null, args)
) as Result;
if (!async) return returnValue as Async extends true ? Promise<Result> : Awaited<Result>;
return promisify(returnValue).catch(() => onErr.apply(null, args)) as Async extends true
? Promise<Result>
: Awaited<Result>;
};
export default {
const externalTgApi = {
init: () => {
tg.setDebug(import.meta.env.DEV);
@@ -134,13 +136,18 @@ export default {
initData: tg.initData,
storage: {
async clear() {
return fallbackImplementation(true, [], tg.cloudStorage.clear, localStorage.clear);
return fallbackImplementation(
true,
[],
() => tg.cloudStorage.clear.ifAvailable(),
() => Object.values(STORAGE_KEYS).forEach((key) => localStorage.removeItem(key)),
);
},
async getItem(key: StorageKey, options?: tg.InvokeCustomMethodFpOptions) {
return fallbackImplementation(
true,
[key, options],
tg.cloudStorage.getItem,
(key, options) => tg.cloudStorage.getItem.ifAvailable(key, options),
(key) => localStorage.getItem(key) ?? "",
);
},
@@ -148,17 +155,22 @@ export default {
return fallbackImplementation(
true,
[key, value, options],
tg.cloudStorage.setItem,
localStorage.setItem,
(key, value, options) => tg.cloudStorage.setItem.ifAvailable(key, value, options),
(key, value) => localStorage.setItem(key, value),
);
},
async deleteItem(key: StorageKey, options?: tg.InvokeCustomMethodFpOptions) {
return fallbackImplementation(
true,
[key, options],
tg.cloudStorage.deleteItem,
localStorage.removeItem as typeof tg.cloudStorage.deleteItem,
(key, options) => tg.cloudStorage.deleteItem.ifAvailable(key, options),
(key) => localStorage.removeItem(key as string),
);
},
},
};
export default externalTgApi;
// @ts-expect-error
window.TG = externalTgApi;