refactor: restructure core architecture and responsive system
This commit implements a major architectural refactor to improve modularity, type safety, and maintainability across the codebase.
Key changes include:
- **Responsive System Refactor**: Migrated from a monolithic `useResponsive` hook to a set of specialized, granular hooks (`useBreakpoint`, `useOrientation`, `usePlatform`, etc.) located in `src/presentation/hooks/responsive`. This reduces unnecessary re-renders and improves developer experience.
- **Core Service Restructuring**: Introduced a new directory structure for services, including dedicated folders for `datasources`, `mappers`, and domain-specific types (`message`, `post`).
- **Data Layer Improvements**:
- Centralized JSON parsing logic in `src/database/core/jsonUtils.ts`.
- Cleaned up repository implementations by removing redundant local utility functions.
- Refactored `MessageMapper` to use the new centralized JSON utility.
- **Type System Cleanup**:
- Decomposed the large `src/types/dto.ts` into a modular `src/types/dto/` directory.
- Simplified `src/types/index.ts` and introduced backward-compatible aliases for core entities.
- **Utility Consolidation**:
- Created a centralized `src/utils/formatTime.ts` to replace fragmented date formatting logic across various screens and components.
- Removed deprecated responsive utility files in favor of the new hook-based system.
- **Service Logic Refinement**: Refactored `ApiClient` and `WebSocketService` to use a centralized `showVerificationModal` service, removing duplicated state management for verification prompts.
This commit is contained in:
@@ -37,7 +37,7 @@ import { Text, ImageGallery, ImageGridItem } from '../../components/common';
|
||||
import { useAppColors, useResolvedColorScheme } from '../../theme';
|
||||
import * as hrefs from '../../navigation/hrefs';
|
||||
import { messageManager, callStore } from '../../stores';
|
||||
import { useBreakpointGTE } from '../../hooks/useResponsive';
|
||||
import { useBreakpointGTE } from '../../hooks';
|
||||
import {
|
||||
useChatScreen,
|
||||
useChatScreenStyles,
|
||||
|
||||
@@ -38,7 +38,7 @@ import { groupService } from '@/services/message';
|
||||
import { uploadService } from '@/services/upload';
|
||||
import { messageService } from '@/services/message';
|
||||
import { Avatar, Text, Button, Loading, Divider } from '../../components/common';
|
||||
import { useResponsive, useBreakpointGTE } from '../../hooks/useResponsive';
|
||||
import { useResponsive, useBreakpointGTE } from '../../hooks';
|
||||
import {
|
||||
GroupResponse,
|
||||
GroupMemberResponse,
|
||||
|
||||
@@ -34,7 +34,7 @@ import {
|
||||
} from '../../stores/group';
|
||||
import { enrichGroupMembersWithUserProfiles } from '../../stores/group';
|
||||
import { Avatar, Text, Button, Loading, EmptyState, Divider, ResponsiveContainer, AppBackButton } from '../../components/common';
|
||||
import { useResponsive, useBreakpointGTE } from '../../hooks/useResponsive';
|
||||
import { useResponsive, useBreakpointGTE } from '../../hooks';
|
||||
import { useCursorPagination } from '../../hooks/useCursorPagination';
|
||||
import {
|
||||
GroupMemberResponse,
|
||||
|
||||
@@ -38,6 +38,7 @@ import {
|
||||
type AppColors,
|
||||
} from '../../theme';
|
||||
import { ConversationResponse, UserDTO, MessageResponse, extractTextFromSegments } from '../../types/dto';
|
||||
import { formatTime as formatTimeUtil } from '../../utils/formatTime';
|
||||
import { authService } from '../../services';
|
||||
import { blurActiveElement } from '../../infrastructure/platform';
|
||||
import { useUserStore, useAuthStore } from '../../stores';
|
||||
@@ -52,7 +53,7 @@ import {
|
||||
useMessageStore,
|
||||
} from '../../stores';
|
||||
import { Avatar, Text, EmptyState, ResponsiveContainer, AppBackButton } from '../../components/common';
|
||||
import { useResponsive, useBreakpointGTE } from '../../hooks/useResponsive';
|
||||
import { useResponsive, useBreakpointGTE } from '../../hooks';
|
||||
import * as hrefs from '../../navigation/hrefs';
|
||||
// 导入 ChatScreen 组件用于桌面端双栏布局
|
||||
import { ChatScreen } from './ChatScreen';
|
||||
@@ -245,32 +246,7 @@ export const MessageListScreen: React.FC = () => {
|
||||
|
||||
// 格式化时间(稳定引用,配合会话行 memo)
|
||||
const formatTime = useCallback((dateString: string): string => {
|
||||
if (!dateString) return '';
|
||||
try {
|
||||
const date = new Date(dateString);
|
||||
if (Number.isNaN(date.getTime())) return '';
|
||||
const now = new Date();
|
||||
const diffInHours = (now.getTime() - date.getTime()) / (1000 * 60 * 60);
|
||||
|
||||
if (diffInHours < 24 && date.getDate() === now.getDate()) {
|
||||
return date.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' });
|
||||
}
|
||||
|
||||
const yesterday = new Date(now);
|
||||
yesterday.setDate(yesterday.getDate() - 1);
|
||||
if (date.getDate() === yesterday.getDate()) {
|
||||
return '昨天';
|
||||
}
|
||||
|
||||
if (diffInHours < 24 * 7) {
|
||||
const days = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
|
||||
return days[date.getDay()];
|
||||
}
|
||||
|
||||
return `${date.getMonth() + 1}/${date.getDate()}`;
|
||||
} catch {
|
||||
return '';
|
||||
}
|
||||
return formatTimeUtil(dateString);
|
||||
}, []);
|
||||
|
||||
// 跳转到聊天页
|
||||
|
||||
@@ -10,7 +10,7 @@ import { MaterialCommunityIcons } from '@expo/vector-icons';
|
||||
import { Avatar, Text } from '../../../../components/common';
|
||||
import { useAppColors, spacing } from '../../../../theme';
|
||||
import { useChatScreenStyles, useChatDynamicStyles } from './styles';
|
||||
import { useBreakpointGTE } from '../../../../hooks/useResponsive';
|
||||
import { useBreakpointGTE } from '../../../../hooks';
|
||||
import { ChatHeaderProps } from './types';
|
||||
|
||||
export const ChatHeader: React.FC<ChatHeaderProps> = ({
|
||||
|
||||
@@ -10,7 +10,7 @@ import { MaterialCommunityIcons } from '@expo/vector-icons';
|
||||
import { Text } from '../../../../components/common';
|
||||
import { useAppColors } from '../../../../theme';
|
||||
import { useChatScreenStyles, useChatDynamicStyles } from './styles';
|
||||
import { useBreakpointGTE } from '../../../../hooks/useResponsive';
|
||||
import { useBreakpointGTE } from '../../../../hooks';
|
||||
import { ChatInputProps, GroupMessage, SenderInfo } from './types';
|
||||
import { extractTextFromSegments } from '../../../../types/dto';
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import { MaterialCommunityIcons } from '@expo/vector-icons';
|
||||
import * as ImagePicker from 'expo-image-picker';
|
||||
import { Text } from '../../../../components/common';
|
||||
import { useChatScreenStyles } from './styles';
|
||||
import { useResponsive, useBreakpointGTE } from '../../../../hooks/useResponsive';
|
||||
import { useResponsive, useBreakpointGTE } from '../../../../hooks';
|
||||
import { EMOJIS } from './constants';
|
||||
import { CustomSticker, getCustomStickers, batchDeleteStickers, addStickerFromUrl } from '@/services/message';
|
||||
import { useAppColors, spacing } from '../../../../theme';
|
||||
|
||||
@@ -19,7 +19,7 @@ import { MaterialCommunityIcons } from '@expo/vector-icons';
|
||||
import { Avatar, Text } from '../../../../components/common';
|
||||
import { useAppColors, spacing, fontSizes, shadows, type AppColors } from '../../../../theme';
|
||||
import { GroupMemberResponse, GroupResponse, GroupAnnouncementResponse } from '../../../../types/dto';
|
||||
import { useBreakpointGTE } from '../../../../hooks/useResponsive';
|
||||
import { useBreakpointGTE } from '../../../../hooks';
|
||||
import { groupManager } from '../../../../stores/group';
|
||||
import { groupService } from '@/services/message';
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ import { MaterialCommunityIcons } from '@expo/vector-icons';
|
||||
import { Avatar, Text } from '../../../../components/common';
|
||||
import { useAppColors, spacing, fontSizes, shadows, borderRadius, type AppColors } from '../../../../theme';
|
||||
import { GroupMemberResponse, GroupResponse, GroupAnnouncementResponse } from '../../../../types/dto';
|
||||
import { useBreakpointGTE } from '../../../../hooks/useResponsive';
|
||||
import { useBreakpointGTE } from '../../../../hooks';
|
||||
import { groupManager } from '../../../../stores/group';
|
||||
import { groupService } from '@/services/message';
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ import {
|
||||
import { MaterialCommunityIcons } from '@expo/vector-icons';
|
||||
import { Avatar, Text, ImageGridItem } from '../../../../components/common';
|
||||
import { useChatScreenStyles } from './styles';
|
||||
import { useResponsive, useBreakpointGTE } from '../../../../hooks/useResponsive';
|
||||
import { useResponsive, useBreakpointGTE } from '../../../../hooks';
|
||||
import { MessageBubbleProps, SenderInfo, MenuPosition, GroupMessage } from './types';
|
||||
import { MessageSegmentsRenderer } from './SegmentRenderer';
|
||||
import { MessageSegment, ImageSegmentData, extractTextFromSegments } from '../../../../types/dto';
|
||||
|
||||
@@ -18,8 +18,7 @@ import {
|
||||
Alert,
|
||||
} from 'react-native';
|
||||
import { useLocalSearchParams, router } from 'expo-router';
|
||||
import { formatDistanceToNow } from 'date-fns';
|
||||
import { zhCN } from 'date-fns/locale';
|
||||
import { formatChatTime } from '@/utils/formatTime';
|
||||
import * as ImagePicker from 'expo-image-picker';
|
||||
import { GroupMemberResponse, MessageSegment, TextSegmentData, ImageSegmentData, AtSegmentData, ReplySegmentData, MessageStatus } from '../../../../types/dto';
|
||||
import { messageService } from '@/services/message';
|
||||
@@ -707,24 +706,7 @@ export const useChatScreen = (props?: ChatScreenProps) => {
|
||||
|
||||
// 格式化时间
|
||||
const formatTime = useCallback((dateString: string): string => {
|
||||
if (!dateString) return '';
|
||||
try {
|
||||
const date = new Date(dateString);
|
||||
if (Number.isNaN(date.getTime())) return '';
|
||||
const now = new Date();
|
||||
const diffInHours = (now.getTime() - date.getTime()) / (1000 * 60 * 60);
|
||||
|
||||
if (diffInHours < 24 && date.getDate() === now.getDate()) {
|
||||
return date.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' });
|
||||
}
|
||||
|
||||
return formatDistanceToNow(date, {
|
||||
addSuffix: true,
|
||||
locale: zhCN,
|
||||
});
|
||||
} catch {
|
||||
return '';
|
||||
}
|
||||
return formatChatTime(dateString);
|
||||
}, []);
|
||||
|
||||
// 检查是否需要显示时间分隔
|
||||
|
||||
Reference in New Issue
Block a user