refactor(platform): extract blurActiveElement to infrastructure module
- Centralize duplicated Platform.OS === 'web' blur logic across 16 components - Add blurActiveElement utility to src/infrastructure/platform module - Optimize MessageBubble and ImageSegment with React.memo custom comparators - Add useMemo for computed values in MessageSegmentsRenderer - Update DTO types with is_system_notice and notice_content fields - Fix keyboard dismissal order in useChatScreen handleDismiss - Simplify userStore follow/unfollow state updates - Remove unnecessary TypeScript type assertions throughout codebase
This commit is contained in:
83
src/infrastructure/platform/domUtils.ts
Normal file
83
src/infrastructure/platform/domUtils.ts
Normal file
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* Web Platform DOM Utilities
|
||||
*
|
||||
* 提供Web平台特定的DOM操作工具函数
|
||||
* 解决跨平台代码中需要访问Web DOM的补丁问题
|
||||
*/
|
||||
|
||||
import { Platform, Keyboard } from 'react-native';
|
||||
|
||||
/**
|
||||
* Blur当前激活的DOM元素(Web)并收起键盘(移动端)
|
||||
*
|
||||
* - Web: blur DOM active element
|
||||
* - iOS/Android: Keyboard.dismiss()
|
||||
*
|
||||
* 替代散落在多个文件中的重复代码
|
||||
*/
|
||||
export function blurActiveElement(): void {
|
||||
if (Platform.OS === 'web') {
|
||||
try {
|
||||
const activeElement = (globalThis as any)?.document?.activeElement as
|
||||
{ blur?: () => void } | undefined;
|
||||
|
||||
if (activeElement?.blur) {
|
||||
activeElement.blur();
|
||||
}
|
||||
} catch {
|
||||
// 安全忽略:某些环境下document可能不可访问
|
||||
}
|
||||
} else {
|
||||
Keyboard.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查当前是否有激活的DOM元素(仅Web平台)
|
||||
*/
|
||||
export function hasActiveElement(): boolean {
|
||||
if (Platform.OS !== 'web') return false;
|
||||
|
||||
try {
|
||||
const doc = (globalThis as any)?.document;
|
||||
return !!doc?.activeElement && doc.activeElement !== doc.body;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前激活元素的类型(仅Web平台)
|
||||
* 用于判断是否需要特殊处理(如输入框)
|
||||
*/
|
||||
export function getActiveElementType(): string | null {
|
||||
if (Platform.OS !== 'web') return null;
|
||||
|
||||
try {
|
||||
const activeElement = (globalThis as any)?.document?.activeElement as
|
||||
{ tagName?: string; type?: string } | undefined;
|
||||
|
||||
if (!activeElement) return null;
|
||||
|
||||
const tagName = activeElement.tagName?.toLowerCase();
|
||||
const type = activeElement.type?.toLowerCase();
|
||||
|
||||
return tagName === 'input' ? `input:${type || 'text'}` : tagName || null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断当前激活元素是否为输入类型
|
||||
*/
|
||||
export function isInputFocused(): boolean {
|
||||
const elementType = getActiveElementType();
|
||||
if (!elementType) return false;
|
||||
|
||||
return (
|
||||
elementType.startsWith('input:') ||
|
||||
elementType === 'textarea' ||
|
||||
elementType === 'select'
|
||||
);
|
||||
}
|
||||
12
src/infrastructure/platform/index.ts
Normal file
12
src/infrastructure/platform/index.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* Platform Infrastructure
|
||||
*
|
||||
* 平台相关的基础设施代码
|
||||
*/
|
||||
|
||||
export {
|
||||
blurActiveElement,
|
||||
hasActiveElement,
|
||||
getActiveElementType,
|
||||
isInputFocused,
|
||||
} from './domUtils';
|
||||
Reference in New Issue
Block a user