feat(telegram): native SettingsButton opens our Settings screen
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Has been skipped
CI / integration (pull_request) Has been skipped
CI / ui (pull_request) Successful in 55s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m16s
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Has been skipped
CI / integration (pull_request) Has been skipped
CI / ui (pull_request) Successful in 55s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m16s
Inside the Mini App, reveal Telegram's native Settings button (Bot API 7.0) and route its taps to the Settings screen — the standard Mini App affordance. The in-app gear entry stays the primary path (two entry points by design). No-op outside Telegram or on a client predating the button.
This commit is contained in:
@@ -22,6 +22,7 @@ import {
|
|||||||
telegramContentSafeAreaTop,
|
telegramContentSafeAreaTop,
|
||||||
telegramSafeAreaInset,
|
telegramSafeAreaInset,
|
||||||
telegramDisableVerticalSwipes,
|
telegramDisableVerticalSwipes,
|
||||||
|
telegramShowSettingsButton,
|
||||||
telegramHaptic,
|
telegramHaptic,
|
||||||
telegramLaunch,
|
telegramLaunch,
|
||||||
type TelegramLaunch,
|
type TelegramLaunch,
|
||||||
@@ -647,6 +648,9 @@ export async function bootstrap(): Promise<void> {
|
|||||||
telegramOnEvent('fullscreenChanged', syncTelegramSafeArea);
|
telegramOnEvent('fullscreenChanged', syncTelegramSafeArea);
|
||||||
// Re-apply the theme live when the user switches Telegram's light/dark mode while the app is open.
|
// Re-apply the theme live when the user switches Telegram's light/dark mode while the app is open.
|
||||||
telegramOnEvent('themeChanged', () => syncTelegramTheme());
|
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);
|
await bootTelegram(launch);
|
||||||
app.ready = true;
|
app.ready = true;
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import {
|
|||||||
telegramOpenExternalLink,
|
telegramOpenExternalLink,
|
||||||
telegramThemeParams,
|
telegramThemeParams,
|
||||||
telegramSafeAreaInset,
|
telegramSafeAreaInset,
|
||||||
|
telegramShowSettingsButton,
|
||||||
} from './telegram';
|
} from './telegram';
|
||||||
|
|
||||||
function stubWebApp(initData: string, startParam?: string) {
|
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', () => {
|
describe('routeExternalLinkInTelegram', () => {
|
||||||
afterEach(() => vi.unstubAllGlobals());
|
afterEach(() => vi.unstubAllGlobals());
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,12 @@ interface TelegramWebApp {
|
|||||||
onClick?: (cb: () => void) => void;
|
onClick?: (cb: () => void) => void;
|
||||||
offClick?: (cb: () => void) => void;
|
offClick?: (cb: () => void) => void;
|
||||||
};
|
};
|
||||||
|
SettingsButton?: {
|
||||||
|
show?: () => void;
|
||||||
|
hide?: () => void;
|
||||||
|
onClick?: (cb: () => void) => void;
|
||||||
|
offClick?: (cb: () => void) => void;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function webApp(): TelegramWebApp | undefined {
|
function webApp(): TelegramWebApp | undefined {
|
||||||
@@ -293,6 +299,19 @@ export function telegramDisableVerticalSwipes(): void {
|
|||||||
webApp()?.disableVerticalSwipes?.();
|
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. */
|
/** Haptic is the set of feedbacks the app triggers. */
|
||||||
export type Haptic = 'select' | 'success' | 'error' | 'warning' | 'light' | 'medium' | 'heavy';
|
export type Haptic = 'select' | 'success' | 'error' | 'warning' | 'light' | 'medium' | 'heavy';
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user