// TypeScript types for garbo-web-app.js, version 1.0 — https://developers.garbo.ph
// Copy this file into your project (or reference it with /// ) to get
// window.Garbo.WebApp typed. The names follow Telegram's Telegram.WebApp where they mean the same.
export {};
declare global {
interface Window {
Garbo: { WebApp: GarboWebApp; WebView: GarboWebView };
}
}
/** The person as your app sees them (only what they allowed; `id` is made for your app only). */
export interface GarboWebAppUser {
/** A number made for your app only: the same person has another id in every other app. */
id: number;
language_code: string;
/** Allowed "Nickname, picture and profile link". */
username?: string;
profile_url?: string;
photo_url?: string;
/** The Official badge's name, for official accounts. */
official_name?: string;
/** Allowed "Full name". */
first_name?: string;
last_name?: string;
/** Allowed "Town and province" (town_code is the PSGC code). */
town?: string;
town_code?: string;
province?: string;
/** Allowed "Gender". */
gender?: 'male' | 'female' | 'prefer_not_to_say';
/** Allowed "When you joined Garbo": "YYYY-MM". */
joined_month?: string;
}
export interface GarboInitDataUnsafe {
app_id?: string;
auth_date?: number;
start_param?: string;
/** Absent for a visitor (nobody logged in). */
user?: GarboWebAppUser | null;
signature?: string;
hash?: string;
}
export interface GarboThemeParams {
bg_color?: string;
text_color?: string;
hint_color?: string;
link_color?: string;
button_color?: string;
button_text_color?: string;
secondary_bg_color?: string;
header_bg_color?: string;
bottom_bar_bg_color?: string;
accent_text_color?: string;
section_bg_color?: string;
section_header_text_color?: string;
section_separator_color?: string;
subtitle_text_color?: string;
destructive_text_color?: string;
}
export interface GarboInsets {
top: number;
bottom: number;
left: number;
right: number;
}
export interface GarboTopButton {
readonly isVisible: boolean;
show(): GarboTopButton;
hide(): GarboTopButton;
onClick(callback: () => void): GarboTopButton;
offClick(callback: () => void): GarboTopButton;
}
export interface GarboBottomButtonParams {
text?: string;
color?: string | null;
text_color?: string | null;
is_visible?: boolean;
is_active?: boolean;
has_shine_effect?: boolean;
/** Secondary button only. */
position?: 'left' | 'right' | 'top' | 'bottom';
}
export interface GarboBottomButton {
readonly type: 'main' | 'secondary';
text: string;
color: string;
textColor: string;
isVisible: boolean;
isActive: boolean;
readonly isProgressVisible: boolean;
hasShineEffect: boolean;
/** Secondary button only. */
position?: 'left' | 'right' | 'top' | 'bottom';
setText(text: string): GarboBottomButton;
setParams(params: GarboBottomButtonParams): GarboBottomButton;
onClick(callback: () => void): GarboBottomButton;
offClick(callback: () => void): GarboBottomButton;
show(): GarboBottomButton;
hide(): GarboBottomButton;
enable(): GarboBottomButton;
disable(): GarboBottomButton;
showProgress(leaveActive?: boolean): GarboBottomButton;
hideProgress(): GarboBottomButton;
}
export interface GarboHapticFeedback {
impactOccurred(style: 'light' | 'medium' | 'heavy' | 'rigid' | 'soft'): GarboHapticFeedback;
notificationOccurred(type: 'error' | 'success' | 'warning'): GarboHapticFeedback;
selectionChanged(): GarboHapticFeedback;
}
export interface GarboPopupButton {
id?: string;
type?: 'default' | 'ok' | 'close' | 'cancel' | 'destructive';
/** Needed for default and destructive buttons. */
text?: string;
}
export interface GarboPopupParams {
title?: string;
message: string;
buttons?: GarboPopupButton[];
}
type Callback = (error: Error | null, result?: T) => void;
export interface GarboCloudStorage {
setItem(key: string, value: string, callback?: Callback): GarboCloudStorage;
getItem(key: string, callback: Callback): GarboCloudStorage;
getItems(keys: string[], callback: Callback>): GarboCloudStorage;
removeItem(key: string, callback?: Callback): GarboCloudStorage;
removeItems(keys: string[], callback?: Callback): GarboCloudStorage;
getKeys(callback: Callback): GarboCloudStorage;
}
export interface GarboDeviceStorage {
setItem(key: string, value: string, callback?: Callback): GarboDeviceStorage;
getItem(key: string, callback: Callback): GarboDeviceStorage;
removeItem(key: string, callback?: Callback): GarboDeviceStorage;
clear(callback?: Callback): GarboDeviceStorage;
}
export interface GarboSecureStorage {
setItem(key: string, value: string, callback?: Callback): GarboSecureStorage;
getItem(key: string, callback: (error: Error | null, value?: string | null, canRestore?: boolean) => void): GarboSecureStorage;
/** Always fails in Garbo (values never leave the phone). */
restoreItem(key: string, callback?: Callback): GarboSecureStorage;
removeItem(key: string, callback?: Callback): GarboSecureStorage;
clear(callback?: Callback): GarboSecureStorage;
}
/** A signed answer: check `response` on your server like initData. */
export interface GarboContactAnswer {
status: 'sent' | 'cancelled';
response?: string;
responseUnsafe?: { contact: { user_id: number; phone_number?: string; email?: string }; auth_date: number };
}
export type GarboEventName =
| 'activated'
| 'deactivated'
| 'themeChanged'
| 'viewportChanged'
| 'safeAreaChanged'
| 'contentSafeAreaChanged'
| 'mainButtonClicked'
| 'secondaryButtonClicked'
| 'backButtonClicked'
| 'settingsButtonClicked'
| 'popupClosed'
| 'homeScreenAdded'
| 'homeScreenFailed'
| 'homeScreenChecked'
| 'profileAccessRequested'
| 'contactRequested'
| 'emailRequested'
| 'fileDownloadRequested'
| 'shareClosed';
export interface GarboWebApp {
readonly initData: string;
readonly initDataUnsafe: GarboInitDataUnsafe;
readonly version: string;
readonly platform: 'ios' | 'android' | 'web' | 'unknown';
readonly colorScheme: 'light' | 'dark';
readonly themeParams: GarboThemeParams;
readonly isActive: boolean;
readonly isExpanded: boolean;
readonly viewportHeight: number;
readonly viewportStableHeight: number;
readonly safeAreaInset: GarboInsets;
readonly contentSafeAreaInset: GarboInsets;
headerColor: string;
backgroundColor: string;
bottomBarColor: string;
isClosingConfirmationEnabled: boolean;
BackButton: GarboTopButton;
SettingsButton: GarboTopButton;
MainButton: GarboBottomButton;
SecondaryButton: GarboBottomButton;
HapticFeedback: GarboHapticFeedback;
CloudStorage: GarboCloudStorage;
DeviceStorage: GarboDeviceStorage;
SecureStorage: GarboSecureStorage;
isVersionAtLeast(version: string): boolean;
setHeaderColor(color: 'bg_color' | 'secondary_bg_color' | string): void;
setBackgroundColor(color: 'bg_color' | 'secondary_bg_color' | string): void;
setBottomBarColor(color: 'bg_color' | 'secondary_bg_color' | 'bottom_bar_bg_color' | string): void;
enableClosingConfirmation(): void;
disableClosingConfirmation(): void;
onEvent(eventType: GarboEventName, handler: (params?: any) => void): void;
offEvent(eventType: GarboEventName, handler: (params?: any) => void): void;
openLink(url: string): void;
/** A Garbo page: https://garbo.ph/app/?start=…, /people/, /news/post/, /search?q=… */
openGarboLink(url: string): void;
showPopup(params: GarboPopupParams, callback?: (buttonId: string | null) => void): void;
showAlert(message: string, callback?: () => void): void;
showConfirm(message: string, callback?: (ok: boolean) => void): void;
ready(): void;
expand(): void;
close(): void;
hideKeyboard(): void;
addToHomeScreen(): void;
checkHomeScreenStatus(callback?: (status: 'added' | 'missed' | 'unknown' | 'unsupported') => void): void;
/** Garbo only: asks again for what your app asks to know; initData is updated when allowed. */
requestProfileAccess(callback?: (allowed: boolean) => void): void;
/** Garbo only: opens Garbo's Login; your page reloads once the person is logged in. */
requestLogin(): void;
requestContact(callback?: (shared: boolean, answer: GarboContactAnswer) => void): void;
/** Garbo only: the person's confirmed email, asked each time. */
requestEmail(callback?: (shared: boolean, answer: GarboContactAnswer) => void): void;
downloadFile(params: { url: string; file_name: string }, callback?: (accepted: boolean) => void): void;
/** Garbo only: in a Garbo post or the phone's share sheet. */
share(params: { text?: string; url?: string }, callback?: (status: 'garbo_post' | 'phone' | 'cancelled') => void): void;
}
export interface GarboWebView {
readonly initParams: Record;
readonly isIframe: boolean;
postEvent(eventType: string, eventData?: unknown): boolean;
receiveEvent(eventType: string, eventData?: unknown): void;
onEvent(eventType: string, handler: (eventType: string, eventData: unknown) => void): void;
offEvent(eventType: string, handler: (eventType: string, eventData: unknown) => void): void;
}