// 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; }