106 lines
2.8 KiB
TypeScript
106 lines
2.8 KiB
TypeScript
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;
|
|
}
|