feat(telegram): Mini App embedding enhancements #136

Merged
developer merged 7 commits from feature/telegram-embedding into development 2026-06-24 11:41:15 +00:00
3 changed files with 42 additions and 0 deletions
Showing only changes of commit ea931c6680 - Show all commits
+4
View File
@@ -22,6 +22,7 @@ import {
telegramContentSafeAreaTop,
telegramSafeAreaInset,
telegramDisableVerticalSwipes,
telegramShowSettingsButton,
telegramHaptic,
telegramLaunch,
type TelegramLaunch,
@@ -647,6 +648,9 @@ export async function bootstrap(): Promise<void> {
telegramOnEvent('fullscreenChanged', syncTelegramSafeArea);
// Re-apply the theme live when the user switches Telegram's light/dark mode while the app is open.
telegramOnEvent('themeChanged', () => syncTelegramTheme());
// Telegram's native Settings button (Bot API 7.0) opens our Settings screen; the in-app gear
// entry stays the primary path. No-op on clients predating the button.
telegramShowSettingsButton(() => navigate('/settings'));
await bootTelegram(launch);
app.ready = true;
return;
+19
View File
@@ -9,6 +9,7 @@ import {
telegramOpenExternalLink,
telegramThemeParams,
telegramSafeAreaInset,
telegramShowSettingsButton,
} from './telegram';
function stubWebApp(initData: string, startParam?: string) {
@@ -77,6 +78,24 @@ describe('telegramOpenExternalLink', () => {
});
});
describe('telegramShowSettingsButton', () => {
afterEach(() => vi.unstubAllGlobals());
it('shows the native Settings button and wires its click inside Telegram', () => {
const onClick = vi.fn();
const show = vi.fn();
const handler = vi.fn();
vi.stubGlobal('window', { Telegram: { WebApp: { SettingsButton: { onClick, show } } } });
telegramShowSettingsButton(handler);
expect(onClick).toHaveBeenCalledWith(handler);
expect(show).toHaveBeenCalled();
});
it('is a no-op without the SDK button (older client / outside Telegram)', () => {
expect(() => telegramShowSettingsButton(() => {})).not.toThrow();
});
});
describe('routeExternalLinkInTelegram', () => {
afterEach(() => vi.unstubAllGlobals());
+19
View File
@@ -41,6 +41,12 @@ interface TelegramWebApp {
onClick?: (cb: () => void) => void;
offClick?: (cb: () => void) => void;
};
SettingsButton?: {
show?: () => void;
hide?: () => void;
onClick?: (cb: () => void) => void;
offClick?: (cb: () => void) => void;
};
}
function webApp(): TelegramWebApp | undefined {
@@ -293,6 +299,19 @@ export function telegramDisableVerticalSwipes(): void {
webApp()?.disableVerticalSwipes?.();
}
/**
* telegramShowSettingsButton reveals Telegram's native Settings button (in the Mini App's ⋮ menu,
* Bot API 7.0) and routes its taps to handler. A no-op outside Telegram or on a client predating
* the button, so the app's own in-app settings entry stays the primary path. The app registers it
* once per launch (Telegram hides the button when the Mini App closes), so there is no offClick.
*/
export function telegramShowSettingsButton(handler: () => void): void {
const b = webApp()?.SettingsButton;
if (!b?.show) return;
b.onClick?.(handler);
b.show();
}
/** Haptic is the set of feedbacks the app triggers. */
export type Haptic = 'select' | 'success' | 'error' | 'warning' | 'light' | 'medium' | 'heavy';