feat: migrate to Next.js for Mini App and enhance project structure
- Replaced the previous webapp with a new Mini App built using Next.js, improving performance and maintainability. - Updated the `.gitignore` to exclude Next.js build artifacts and node modules. - Revised documentation in `AGENTS.md`, `README.md`, and `architecture.md` to reflect the new Mini App structure and technology stack. - Enhanced Dockerfile to support the new build process for the Next.js application. - Updated CI workflow to build and test the Next.js application. - Added new configuration options for the Mini App, including `MINI_APP_SHORT_NAME` for improved deep linking. - Refactored frontend testing setup to accommodate the new structure and testing framework. - Removed legacy webapp files and dependencies to streamline the project.
This commit is contained in:
89
webapp-next/src/hooks/use-telegram-theme.ts
Normal file
89
webapp-next/src/hooks/use-telegram-theme.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect } from "react";
|
||||
import {
|
||||
useSignal,
|
||||
isThemeParamsDark,
|
||||
setMiniAppBackgroundColor,
|
||||
setMiniAppHeaderColor,
|
||||
} from "@telegram-apps/sdk-react";
|
||||
|
||||
/**
|
||||
* Resolves color scheme when Telegram theme is not available (SSR or non-TWA).
|
||||
* Uses --tg-color-scheme (if set by Telegram) then prefers-color-scheme.
|
||||
*/
|
||||
export function getFallbackScheme(): "dark" | "light" {
|
||||
if (typeof window === "undefined") return "dark";
|
||||
try {
|
||||
const cssScheme = getComputedStyle(document.documentElement)
|
||||
.getPropertyValue("--tg-color-scheme")
|
||||
.trim();
|
||||
if (cssScheme === "light" || cssScheme === "dark") return cssScheme;
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
if (window.matchMedia("(prefers-color-scheme: dark)").matches) return "dark";
|
||||
return "light";
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure --surface differs from --bg so cards/cells are visible.
|
||||
* iOS OLED sends secondary_bg === bg (#000000) while section_bg differs;
|
||||
* PC desktop sends section_bg === bg (#17212b) while secondary_bg differs.
|
||||
* When the CSS-resolved --surface equals --bg, override with whichever
|
||||
* Telegram color provides contrast, or a synthesized lighter fallback.
|
||||
*/
|
||||
export function fixSurfaceContrast(): void {
|
||||
const root = document.documentElement;
|
||||
const cs = getComputedStyle(root);
|
||||
const bg = cs.getPropertyValue("--bg").trim();
|
||||
const surface = cs.getPropertyValue("--surface").trim();
|
||||
if (!bg || !surface || bg !== surface) return;
|
||||
const sectionBg = cs.getPropertyValue("--tg-theme-section-bg-color").trim();
|
||||
if (sectionBg && sectionBg !== bg) {
|
||||
root.style.setProperty("--surface", sectionBg);
|
||||
return;
|
||||
}
|
||||
const secondaryBg = cs.getPropertyValue("--tg-theme-secondary-bg-color").trim();
|
||||
if (secondaryBg && secondaryBg !== bg) {
|
||||
root.style.setProperty("--surface", secondaryBg);
|
||||
return;
|
||||
}
|
||||
root.style.setProperty("--surface", `color-mix(in srgb, ${bg}, white 8%)`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies theme: sets data-theme, forces reflow, fixes surface contrast,
|
||||
* then Mini App background/header.
|
||||
* Shared by TelegramProvider (initial + delayed) and useTelegramTheme.
|
||||
* @param scheme - If provided, use it; otherwise resolve via getFallbackScheme().
|
||||
*/
|
||||
export function applyTheme(scheme?: "dark" | "light"): void {
|
||||
const resolved = scheme ?? getFallbackScheme();
|
||||
document.documentElement.setAttribute("data-theme", resolved);
|
||||
void document.documentElement.offsetHeight; // force reflow so WebView repaints
|
||||
fixSurfaceContrast();
|
||||
if (setMiniAppBackgroundColor.isAvailable()) {
|
||||
setMiniAppBackgroundColor("bg_color");
|
||||
}
|
||||
if (setMiniAppHeaderColor.isAvailable()) {
|
||||
setMiniAppHeaderColor("bg_color");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps Telegram theme params to data-theme and Mini App background/header.
|
||||
* Subscribes to theme changes via SDK signals.
|
||||
* Ported from webapp/js/theme.js applyTheme / initTheme.
|
||||
*/
|
||||
export function useTelegramTheme(): "dark" | "light" {
|
||||
const signalDark = useSignal(isThemeParamsDark);
|
||||
const isDark =
|
||||
typeof signalDark === "boolean" ? signalDark : getFallbackScheme() === "dark";
|
||||
|
||||
useEffect(() => {
|
||||
applyTheme(isDark ? "dark" : "light");
|
||||
}, [isDark]);
|
||||
|
||||
return isDark ? "dark" : "light";
|
||||
}
|
||||
Reference in New Issue
Block a user