export const CHAT_KEYBOARD_VISIBLE_THRESHOLD_PX = 80; export const CHAT_KEYBOARD_ZOOM_THRESHOLD = 1.05; export const CHAT_KEYBOARD_TARGET_GAP_PX = 16; export const CHAT_KEYBOARD_FALLBACK_WIDTH_RATIO = 0.84; export const CHAT_KEYBOARD_FALLBACK_HEIGHT_RATIO = 0.43; export const CHAT_KEYBOARD_FALLBACK_MIN_PX = 240; export const CHAT_KEYBOARD_FALLBACK_MAX_PX = 340; const CHAT_KEYBOARD_MAX_INSET_RATIO = 0.55; export interface ChatKeyboardViewportBaseline { layoutHeight: number; layoutWidth: number; visualHeight: number; } export type ChatKeyboardFallbackViewport = Pick< ChatKeyboardViewportBaseline, "layoutHeight" | "layoutWidth" >; export interface ChatKeyboardViewportSnapshot { layoutHeight: number; visualHeight: number; visualScale: number; virtualKeyboardHeight: number; } export type ChatKeyboardInsetSource = | "content-resize" | "visual-viewport" | "virtual-keyboard" | "none"; export interface ChatKeyboardInsetResolution { keyboardVisible: boolean; bottomInset: number; source: ChatKeyboardInsetSource; } export function resolveChatKeyboardInset( baseline: ChatKeyboardViewportBaseline, snapshot: ChatKeyboardViewportSnapshot, ): ChatKeyboardInsetResolution { const contentResize = baseline.layoutHeight - snapshot.layoutHeight; if (contentResize > CHAT_KEYBOARD_VISIBLE_THRESHOLD_PX) { return { keyboardVisible: true, bottomInset: 0, source: "content-resize", }; } const virtualKeyboardHeight = Math.max(0, snapshot.virtualKeyboardHeight); const visualViewportHeight = snapshot.visualScale <= CHAT_KEYBOARD_ZOOM_THRESHOLD ? Math.max(0, baseline.visualHeight - snapshot.visualHeight) : 0; const occludedHeight = Math.max( virtualKeyboardHeight, visualViewportHeight, ); if (occludedHeight <= CHAT_KEYBOARD_VISIBLE_THRESHOLD_PX) { return { keyboardVisible: false, bottomInset: 0, source: "none", }; } const maxInset = Math.round( baseline.layoutHeight * CHAT_KEYBOARD_MAX_INSET_RATIO, ); return { keyboardVisible: true, bottomInset: Math.min( maxInset, Math.round(occludedHeight + CHAT_KEYBOARD_TARGET_GAP_PX), ), source: virtualKeyboardHeight >= visualViewportHeight ? "virtual-keyboard" : "visual-viewport", }; } export function resolveChatKeyboardFallbackInset( viewport: ChatKeyboardFallbackViewport, ): number { const widthEstimate = viewport.layoutWidth * CHAT_KEYBOARD_FALLBACK_WIDTH_RATIO; const heightLimit = viewport.layoutHeight * CHAT_KEYBOARD_FALLBACK_HEIGHT_RATIO; const estimatedKeyboardHeight = Math.min( CHAT_KEYBOARD_FALLBACK_MAX_PX, Math.max( CHAT_KEYBOARD_FALLBACK_MIN_PX, Math.round(Math.min(widthEstimate, heightLimit)), ), ); return estimatedKeyboardHeight + CHAT_KEYBOARD_TARGET_GAP_PX; }