fix(chat): restore Facebook keyboard avoidance

This commit is contained in:
2026-07-16 16:28:10 +08:00
parent 9d04176e90
commit 54b9031622
10 changed files with 642 additions and 121 deletions
@@ -0,0 +1,88 @@
export const CHAT_KEYBOARD_VISIBLE_THRESHOLD_PX = 80;
export const CHAT_KEYBOARD_ZOOM_THRESHOLD = 1.05;
export const CHAT_KEYBOARD_FALLBACK_RATIO = 0.42;
export const CHAT_KEYBOARD_FALLBACK_MIN_PX = 260;
export const CHAT_KEYBOARD_FALLBACK_MAX_PX = 380;
const CHAT_KEYBOARD_MAX_INSET_RATIO = 0.55;
export interface ChatKeyboardViewportBaseline {
layoutHeight: number;
visualHeight: number;
}
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)),
source:
virtualKeyboardHeight >= visualViewportHeight
? "virtual-keyboard"
: "visual-viewport",
};
}
export function resolveChatKeyboardFallbackInset(
layoutHeight: number,
): number {
return Math.min(
CHAT_KEYBOARD_FALLBACK_MAX_PX,
Math.max(
CHAT_KEYBOARD_FALLBACK_MIN_PX,
Math.round(layoutHeight * CHAT_KEYBOARD_FALLBACK_RATIO),
),
);
}