Files
ForbiddenStarsApp/frontend/src/components/TelegramLoginButton.tsx
T

60 lines
2.0 KiB
TypeScript

import { useEffect, useRef } from "react";
interface TelegramUser {
id: number;
first_name?: string;
last_name?: string;
username?: string;
photo_url?: string;
auth_date: number;
hash: string;
}
declare global {
interface Window {
__fsTelegramAuth?: (user: TelegramUser) => void;
}
}
/**
* Официальный Telegram Login Widget. Требует бота (@BotFather) и /setdomain
* на текущий HTTPS-домен. botUsername — без «@».
*/
export function TelegramLoginButton({
botUsername,
onAuth,
}: {
botUsername: string;
onAuth: (user: TelegramUser) => void;
}) {
const ref = useRef<HTMLDivElement>(null);
// onAuth держим в ref, чтобы он НЕ был в зависимостях эффекта: иначе новая инлайн-
// функция на каждый рендер пересоздавала бы виджет (а cleanup сносит его innerHTML
// в момент отрисовки — в dev со StrictMode кнопка из-за этого не появлялась).
const onAuthRef = useRef(onAuth);
onAuthRef.current = onAuth;
useEffect(() => {
window.__fsTelegramAuth = (user) => onAuthRef.current(user);
const node = ref.current;
if (!node) return;
node.innerHTML = ""; // на случай повторного монтирования (StrictMode)
const script = document.createElement("script");
script.src = "https://telegram.org/js/telegram-widget.js?22";
script.async = true;
script.setAttribute("data-telegram-login", botUsername);
script.setAttribute("data-size", "large");
script.setAttribute("data-userpic", "false");
script.setAttribute("data-request-access", "write");
script.setAttribute("data-onauth", "__fsTelegramAuth(user)");
node.appendChild(script);
return () => {
node.innerHTML = "";
};
}, [botUsername]); // только смена бота пересоздаёт виджет
return <div ref={ref} />;
}