feat: 优化架构
This commit is contained in:
@@ -9,9 +9,9 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|||||||
import * as Notifications from 'expo-notifications';
|
import * as Notifications from 'expo-notifications';
|
||||||
import * as SystemUI from 'expo-system-ui';
|
import * as SystemUI from 'expo-system-ui';
|
||||||
|
|
||||||
import { registerNotificationPresentationHandler } from '../src/services/notificationPreferences';
|
import { registerNotificationPresentationHandler } from '@/services/notification';
|
||||||
import { api } from '../src/services/api';
|
import { api } from '@/services/core';
|
||||||
import { wsService } from '../src/services/wsService';
|
import { wsService } from '@/services/core';
|
||||||
import { EventSubscriber } from '../src/infrastructure/EventSubscriber';
|
import { EventSubscriber } from '../src/infrastructure/EventSubscriber';
|
||||||
import {
|
import {
|
||||||
ThemeBootstrap,
|
ThemeBootstrap,
|
||||||
@@ -22,9 +22,9 @@ import {
|
|||||||
import { AppBackButton } from '../src/components/common';
|
import { AppBackButton } from '../src/components/common';
|
||||||
import AppPromptBar from '../src/components/common/AppPromptBar';
|
import AppPromptBar from '../src/components/common/AppPromptBar';
|
||||||
import AppDialogHost from '../src/components/common/AppDialogHost';
|
import AppDialogHost from '../src/components/common/AppDialogHost';
|
||||||
import { installAlertOverride } from '../src/services/alertOverride';
|
import { installAlertOverride } from '@/services/ui';
|
||||||
import { useAuthStore } from '../src/stores';
|
import { useAuthStore } from '../src/stores';
|
||||||
import { checkForAPKUpdate } from '../src/services/apkUpdateService';
|
import { checkForAPKUpdate } from '@/services/platform';
|
||||||
import { CallScreen, IncomingCallModal, FloatingCallWindow } from '../src/components/call';
|
import { CallScreen, IncomingCallModal, FloatingCallWindow } from '../src/components/call';
|
||||||
|
|
||||||
registerNotificationPresentationHandler();
|
registerNotificationPresentationHandler();
|
||||||
@@ -122,11 +122,11 @@ function NotificationBootstrap() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const initNotifications = async () => {
|
const initNotifications = async () => {
|
||||||
const { loadNotificationPreferences } = await import('../src/services/notificationPreferences');
|
const { loadNotificationPreferences } = await import('@/services/notification');
|
||||||
await loadNotificationPreferences();
|
await loadNotificationPreferences();
|
||||||
const { systemNotificationService } = await import('../src/services/systemNotificationService');
|
const { systemNotificationService } = await import('@/services/notification');
|
||||||
await systemNotificationService.initialize();
|
await systemNotificationService.initialize();
|
||||||
const { initBackgroundService } = await import('../src/services/backgroundService');
|
const { initBackgroundService } = await import('@/services/background');
|
||||||
await initBackgroundService();
|
await initBackgroundService();
|
||||||
|
|
||||||
const subscription = AppState.addEventListener('change', (nextAppState) => {
|
const subscription = AppState.addEventListener('change', (nextAppState) => {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
/** @type {import('expo/metro-config').MetroConfig} */
|
/** @type {import('expo/metro-config').MetroConfig} */
|
||||||
const { getDefaultConfig } = require('expo/metro-config');
|
const { getDefaultConfig } = require('expo/metro-config');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
const config = getDefaultConfig(__dirname);
|
const config = getDefaultConfig(__dirname);
|
||||||
|
|
||||||
@@ -10,6 +11,11 @@ config.resolver.assetExts.push('wasm');
|
|||||||
// The package doesn't properly export "./index" in its exports field
|
// The package doesn't properly export "./index" in its exports field
|
||||||
config.resolver.unstable_enablePackageExports = false;
|
config.resolver.unstable_enablePackageExports = false;
|
||||||
|
|
||||||
|
// Support TypeScript path aliases (@/ -> ./src/)
|
||||||
|
config.resolver.alias = {
|
||||||
|
'@': path.resolve(__dirname, 'src'),
|
||||||
|
};
|
||||||
|
|
||||||
// NOTE: enhanceMiddleware is marked as deprecated in Metro's types,
|
// NOTE: enhanceMiddleware is marked as deprecated in Metro's types,
|
||||||
// but there's currently no official alternative for custom dev server headers.
|
// but there's currently no official alternative for custom dev server headers.
|
||||||
// For production, configure COEP/COOP headers on your hosting platform.
|
// For production, configure COEP/COOP headers on your hosting platform.
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import {
|
|||||||
import { MaterialCommunityIcons } from '@expo/vector-icons';
|
import { MaterialCommunityIcons } from '@expo/vector-icons';
|
||||||
import { useAppColors } from '../../../theme';
|
import { useAppColors } from '../../../theme';
|
||||||
import { spacing, borderRadius, fontSizes, shadows } from '../../../theme';
|
import { spacing, borderRadius, fontSizes, shadows } from '../../../theme';
|
||||||
import reportService, { ReportReason, ReportTargetType, REPORT_REASONS } from '../../../services/reportService';
|
import { reportService, ReportReason, ReportTargetType, REPORT_REASONS } from '@/services/post';
|
||||||
import { blurActiveElement } from '../../../infrastructure/platform';
|
import { blurActiveElement } from '../../../infrastructure/platform';
|
||||||
import Text from '../../common/Text';
|
import Text from '../../common/Text';
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import type { AlertButton } from 'react-native';
|
|||||||
import { MaterialCommunityIcons } from '@expo/vector-icons';
|
import { MaterialCommunityIcons } from '@expo/vector-icons';
|
||||||
import { LinearGradient } from 'expo-linear-gradient';
|
import { LinearGradient } from 'expo-linear-gradient';
|
||||||
|
|
||||||
import { bindDialogListener, DialogPayload } from '../../services/dialogService';
|
import { bindDialogListener, DialogPayload } from '@/services/ui';
|
||||||
import { borderRadius, shadows, spacing, useAppColors, type AppColors } from '../../theme';
|
import { borderRadius, shadows, spacing, useAppColors, type AppColors } from '../../theme';
|
||||||
import { blurActiveElement } from '../../infrastructure/platform';
|
import { blurActiveElement } from '../../infrastructure/platform';
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { Animated, StyleSheet, Text, TouchableOpacity, View } from 'react-native
|
|||||||
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||||
import { MaterialCommunityIcons } from '@expo/vector-icons';
|
import { MaterialCommunityIcons } from '@expo/vector-icons';
|
||||||
|
|
||||||
import { bindPromptListener, PromptPayload, PromptType } from '../../services/promptService';
|
import { bindPromptListener, PromptPayload, PromptType } from '@/services/ui';
|
||||||
import { borderRadius, shadows, spacing, useAppColors, type AppColors } from '../../theme';
|
import { borderRadius, shadows, spacing, useAppColors, type AppColors } from '../../theme';
|
||||||
|
|
||||||
interface PromptState extends PromptPayload {
|
interface PromptState extends PromptPayload {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* 封装所有 API 调用,统一错误处理和请求拦截
|
* 封装所有 API 调用,统一错误处理和请求拦截
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { api, ApiResponse, ApiError } from '../../services/api';
|
import { api, ApiResponse, ApiError } from '@/services/core';
|
||||||
import { IApiDataSource, DataSourceError } from './interfaces';
|
import { IApiDataSource, DataSourceError } from './interfaces';
|
||||||
|
|
||||||
export class ApiDataSource implements IApiDataSource {
|
export class ApiDataSource implements IApiDataSource {
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import {
|
|||||||
WSGroupTypingMessage,
|
WSGroupTypingMessage,
|
||||||
WSGroupNoticeMessage,
|
WSGroupNoticeMessage,
|
||||||
WSMessageType,
|
WSMessageType,
|
||||||
} from '../../services/wsService';
|
} from '@/services/core';
|
||||||
|
|
||||||
// 事件处理器类型
|
// 事件处理器类型
|
||||||
type EventHandler<T> = (data: T) => void;
|
type EventHandler<T> = (data: T) => void;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import type {
|
|||||||
MaterialFile,
|
MaterialFile,
|
||||||
MaterialFileType,
|
MaterialFileType,
|
||||||
} from '../../types/material';
|
} from '../../types/material';
|
||||||
import { api } from '../../services/api';
|
import { api } from '@/services/core';
|
||||||
|
|
||||||
// ==================== 接口定义 ====================
|
// ==================== 接口定义 ====================
|
||||||
|
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ import {
|
|||||||
PostBatcherOptions,
|
PostBatcherOptions,
|
||||||
createPostUpdateBatcher,
|
createPostUpdateBatcher,
|
||||||
} from '../infrastructure/diff/PostUpdateBatcher';
|
} from '../infrastructure/diff/PostUpdateBatcher';
|
||||||
import { postSyncService } from '../services/post/PostSyncService';
|
import { postSyncService } from '@/services/post';
|
||||||
import type { PostsState } from '../services/post/PostSyncService';
|
import type { PostsState } from '@/services/post';
|
||||||
import { usePostListStore } from '../stores/post/postListStore';
|
import { usePostListStore } from '../stores/post/postListStore';
|
||||||
import type { Post } from '../core/entities/Post';
|
import type { Post } from '../core/entities/Post';
|
||||||
|
|
||||||
|
|||||||
@@ -27,8 +27,8 @@ import { SafeAreaView } from 'react-native-safe-area-context';
|
|||||||
import { useRouter } from 'expo-router';
|
import { useRouter } from 'expo-router';
|
||||||
import { MaterialCommunityIcons } from '@expo/vector-icons';
|
import { MaterialCommunityIcons } from '@expo/vector-icons';
|
||||||
import { useAppColors, useResolvedColorScheme, type AppColors } from '../../theme';
|
import { useAppColors, useResolvedColorScheme, type AppColors } from '../../theme';
|
||||||
import { authService, resolveAuthApiError } from '../../services/authService';
|
import { authService, resolveAuthApiError } from '@/services/auth';
|
||||||
import { showPrompt } from '../../services/promptService';
|
import { showPrompt } from '@/services/ui';
|
||||||
|
|
||||||
export const ForgotPasswordScreen: React.FC = () => {
|
export const ForgotPasswordScreen: React.FC = () => {
|
||||||
const colors = useAppColors();
|
const colors = useAppColors();
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ import { useAppColors, useResolvedColorScheme, type AppColors } from '../../them
|
|||||||
import { useAuthStore } from '../../stores';
|
import { useAuthStore } from '../../stores';
|
||||||
import * as hrefs from '../../navigation/hrefs';
|
import * as hrefs from '../../navigation/hrefs';
|
||||||
import { useResponsive } from '../../hooks';
|
import { useResponsive } from '../../hooks';
|
||||||
import { showPrompt } from '../../services/promptService';
|
import { showPrompt } from '@/services/ui';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import {
|
|||||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||||
import { MaterialCommunityIcons } from '@expo/vector-icons';
|
import { MaterialCommunityIcons } from '@expo/vector-icons';
|
||||||
import { useRouter, useLocalSearchParams } from 'expo-router';
|
import { useRouter, useLocalSearchParams } from 'expo-router';
|
||||||
import { qrcodeApi } from '../../services/authService';
|
import { qrcodeApi } from '@/services/auth';
|
||||||
import { spacing, fontSizes, borderRadius, useAppColors, type AppColors } from '../../theme';
|
import { spacing, fontSizes, borderRadius, useAppColors, type AppColors } from '../../theme';
|
||||||
import { AppBackButton } from '../../components/common';
|
import { AppBackButton } from '../../components/common';
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ import { SafeAreaView } from 'react-native-safe-area-context';
|
|||||||
import { useRouter } from 'expo-router';
|
import { useRouter } from 'expo-router';
|
||||||
import { MaterialCommunityIcons } from '@expo/vector-icons';
|
import { MaterialCommunityIcons } from '@expo/vector-icons';
|
||||||
import { useAppColors, useResolvedColorScheme, type AppColors } from '../../theme';
|
import { useAppColors, useResolvedColorScheme, type AppColors } from '../../theme';
|
||||||
import { authService, resolveAuthApiError } from '../../services/authService';
|
import { authService, resolveAuthApiError } from '@/services/auth';
|
||||||
import { useAuthStore } from '../../stores';
|
import { useAuthStore } from '../../stores';
|
||||||
import {
|
import {
|
||||||
useRegisterStore,
|
useRegisterStore,
|
||||||
@@ -35,7 +35,7 @@ import {
|
|||||||
useRegisterCountdown,
|
useRegisterCountdown,
|
||||||
} from '../../stores/registerStore';
|
} from '../../stores/registerStore';
|
||||||
import * as hrefs from '../../navigation/hrefs';
|
import * as hrefs from '../../navigation/hrefs';
|
||||||
import { showPrompt } from '../../services/promptService';
|
import { showPrompt } from '@/services/ui';
|
||||||
import { RegisterStepIndicator } from '../../components/common';
|
import { RegisterStepIndicator } from '../../components/common';
|
||||||
import { RegisterStepProps, RegisterStep } from './types';
|
import { RegisterStepProps, RegisterStep } from './types';
|
||||||
import { RegisterStep1Email } from './RegisterStep1Email';
|
import { RegisterStep1Email } from './RegisterStep1Email';
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ import { MaterialCommunityIcons } from '@expo/vector-icons';
|
|||||||
import * as ImagePicker from 'expo-image-picker';
|
import * as ImagePicker from 'expo-image-picker';
|
||||||
import { useAppColors, type AppColors } from '../../theme';
|
import { useAppColors, type AppColors } from '../../theme';
|
||||||
import { useVerificationStore } from '../../stores/verificationStore';
|
import { useVerificationStore } from '../../stores/verificationStore';
|
||||||
import { showPrompt } from '../../services/promptService';
|
import { showPrompt } from '@/services/ui';
|
||||||
import { uploadService } from '../../services/uploadService';
|
import { uploadService } from '@/services/upload';
|
||||||
import type { UserIdentity } from '../../types/dto';
|
import type { UserIdentity } from '../../types/dto';
|
||||||
|
|
||||||
const IDENTITY_CONFIG: Record<string, { title: string; idField: string; idLabel: string }> = {
|
const IDENTITY_CONFIG: Record<string, { title: string; idField: string; idLabel: string }> = {
|
||||||
|
|||||||
@@ -35,8 +35,8 @@ import {
|
|||||||
} from '../../theme';
|
} from '../../theme';
|
||||||
import { Text, ResponsiveContainer } from '../../components/common';
|
import { Text, ResponsiveContainer } from '../../components/common';
|
||||||
import { channelService, postService, showPrompt, voteService } from '../../services';
|
import { channelService, postService, showPrompt, voteService } from '../../services';
|
||||||
import { ApiError } from '../../services/api';
|
import { ApiError } from '@/services/core';
|
||||||
import { uploadService } from '../../services/uploadService';
|
import { uploadService } from '@/services/upload';
|
||||||
import VoteEditor from '../../components/business/VoteEditor';
|
import VoteEditor from '../../components/business/VoteEditor';
|
||||||
import { useResponsive, useResponsiveValue } from '../../hooks';
|
import { useResponsive, useResponsiveValue } from '../../hooks';
|
||||||
import * as hrefs from '../../navigation/hrefs';
|
import * as hrefs from '../../navigation/hrefs';
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ import type { PostCardAction } from '../../components/business/PostCard';
|
|||||||
import { Loading, EmptyState, Text, ImageGallery, ImageGridItem, ResponsiveGrid } from '../../components/common';
|
import { Loading, EmptyState, Text, ImageGallery, ImageGridItem, ResponsiveGrid } from '../../components/common';
|
||||||
import { useResponsive, useResponsiveSpacing } from '../../hooks/useResponsive';
|
import { useResponsive, useResponsiveSpacing } from '../../hooks/useResponsive';
|
||||||
import { useDifferentialPosts } from '../../hooks/useDifferentialPosts';
|
import { useDifferentialPosts } from '../../hooks/useDifferentialPosts';
|
||||||
import { postSyncService } from '../../services/post/PostSyncService';
|
import { postSyncService } from '@/services/post';
|
||||||
import { SearchScreen } from './SearchScreen';
|
import { SearchScreen } from './SearchScreen';
|
||||||
import { CreatePostScreen } from '../create/CreatePostScreen';
|
import { CreatePostScreen } from '../create/CreatePostScreen';
|
||||||
import * as hrefs from '../../navigation/hrefs';
|
import * as hrefs from '../../navigation/hrefs';
|
||||||
|
|||||||
@@ -37,12 +37,12 @@ import { Post, Comment, VoteResultDTO, VoteOptionDTO } from '../../types';
|
|||||||
import { useUserStore } from '../../stores';
|
import { useUserStore } from '../../stores';
|
||||||
import { useCurrentUser } from '../../stores/authStore';
|
import { useCurrentUser } from '../../stores/authStore';
|
||||||
import { postService, commentService, uploadService, authService, showPrompt, voteService } from '../../services';
|
import { postService, commentService, uploadService, authService, showPrompt, voteService } from '../../services';
|
||||||
import { postSyncService } from '../../services/post/PostSyncService';
|
import { postSyncService } from '@/services/post';
|
||||||
import { useCursorPagination } from '../../hooks/useCursorPagination';
|
import { useCursorPagination } from '../../hooks/useCursorPagination';
|
||||||
import { CommentItem, VoteCard, ReportDialog } from '../../components/business';
|
import { CommentItem, VoteCard, ReportDialog } from '../../components/business';
|
||||||
import { Avatar, Button, Loading, EmptyState, Text, ImageGallery, ImageGrid, ImageGridItem, AdaptiveLayout, AppBackButton } from '../../components/common';
|
import { Avatar, Button, Loading, EmptyState, Text, ImageGallery, ImageGrid, ImageGridItem, AdaptiveLayout, AppBackButton } from '../../components/common';
|
||||||
import { useResponsive, useResponsiveValue, useResponsiveSpacing } from '../../hooks/useResponsive';
|
import { useResponsive, useResponsiveValue, useResponsiveSpacing } from '../../hooks/useResponsive';
|
||||||
import { handleError } from '../../services/errorHandler';
|
import { handleError } from '@/services/core';
|
||||||
import * as hrefs from '../../navigation/hrefs';
|
import * as hrefs from '../../navigation/hrefs';
|
||||||
|
|
||||||
function togglePostField(
|
function togglePostField(
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import { spacing, fontSizes, borderRadius, useAppColors, type AppColors } from '
|
|||||||
import { Post, User } from '../../types';
|
import { Post, User } from '../../types';
|
||||||
import { useUserStore } from '../../stores';
|
import { useUserStore } from '../../stores';
|
||||||
import { postService, authService } from '../../services';
|
import { postService, authService } from '../../services';
|
||||||
import { postSyncService } from '../../services/post/PostSyncService';
|
import { postSyncService } from '@/services/post';
|
||||||
import { PostCard, TabBar, SearchBar } from '../../components/business';
|
import { PostCard, TabBar, SearchBar } from '../../components/business';
|
||||||
import type { PostCardAction } from '../../components/business/PostCard';
|
import type { PostCardAction } from '../../components/business/PostCard';
|
||||||
import { Avatar, EmptyState, Text, ResponsiveGrid, Loading } from '../../components/common';
|
import { Avatar, EmptyState, Text, ResponsiveGrid, Loading } from '../../components/common';
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ import { MaterialCommunityIcons } from '@expo/vector-icons';
|
|||||||
import { blurActiveElement } from '../../infrastructure/platform';
|
import { blurActiveElement } from '../../infrastructure/platform';
|
||||||
import * as ImagePicker from 'expo-image-picker';
|
import * as ImagePicker from 'expo-image-picker';
|
||||||
import { spacing, fontSizes, borderRadius, shadows, useAppColors, type AppColors } from '../../theme';
|
import { spacing, fontSizes, borderRadius, shadows, useAppColors, type AppColors } from '../../theme';
|
||||||
import { groupService } from '../../services/groupService';
|
import { groupService } from '@/services/message';
|
||||||
import { uploadService } from '../../services/uploadService';
|
import { uploadService } from '@/services/upload';
|
||||||
import { Avatar, Text, Button, Loading } from '../../components/common';
|
import { Avatar, Text, Button, Loading } from '../../components/common';
|
||||||
import { User } from '../../types';
|
import { User } from '../../types';
|
||||||
import MutualFollowSelectorModal from './components/MutualFollowSelectorModal';
|
import MutualFollowSelectorModal from './components/MutualFollowSelectorModal';
|
||||||
|
|||||||
@@ -34,9 +34,9 @@ import {
|
|||||||
type AppColors,
|
type AppColors,
|
||||||
} from '../../theme';
|
} from '../../theme';
|
||||||
import { useAuthStore } from '../../stores';
|
import { useAuthStore } from '../../stores';
|
||||||
import { groupService } from '../../services/groupService';
|
import { groupService } from '@/services/message';
|
||||||
import { uploadService } from '../../services/uploadService';
|
import { uploadService } from '@/services/upload';
|
||||||
import { messageService } from '../../services/messageService';
|
import { messageService } from '@/services/message';
|
||||||
import { Avatar, Text, Button, Loading, Divider } from '../../components/common';
|
import { Avatar, Text, Button, Loading, Divider } from '../../components/common';
|
||||||
import { useResponsive, useBreakpointGTE } from '../../hooks/useResponsive';
|
import { useResponsive, useBreakpointGTE } from '../../hooks/useResponsive';
|
||||||
import {
|
import {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { MaterialCommunityIcons } from '@expo/vector-icons';
|
|||||||
import { spacing, borderRadius, fontSizes, useAppColors, type AppColors } from '../../theme';
|
import { spacing, borderRadius, fontSizes, useAppColors, type AppColors } from '../../theme';
|
||||||
import { Avatar, Text } from '../../components/common';
|
import { Avatar, Text } from '../../components/common';
|
||||||
import { routePayloadCache } from '../../stores/routePayloadCache';
|
import { routePayloadCache } from '../../stores/routePayloadCache';
|
||||||
import { groupService } from '../../services/groupService';
|
import { groupService } from '@/services/message';
|
||||||
import { groupManager } from '../../stores/groupManager';
|
import { groupManager } from '../../stores/groupManager';
|
||||||
import { GroupMemberResponse } from '../../types/dto';
|
import { GroupMemberResponse } from '../../types/dto';
|
||||||
import { GroupInfoSummaryCard, DecisionFooter } from './components/GroupRequestShared';
|
import { GroupInfoSummaryCard, DecisionFooter } from './components/GroupRequestShared';
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ import { MaterialCommunityIcons } from '@expo/vector-icons';
|
|||||||
import { blurActiveElement } from '../../infrastructure/platform';
|
import { blurActiveElement } from '../../infrastructure/platform';
|
||||||
import { spacing, fontSizes, borderRadius, useAppColors, type AppColors } from '../../theme';
|
import { spacing, fontSizes, borderRadius, useAppColors, type AppColors } from '../../theme';
|
||||||
import { useAuthStore } from '../../stores';
|
import { useAuthStore } from '../../stores';
|
||||||
import { groupService } from '../../services/groupService';
|
import { groupService } from '@/services/message';
|
||||||
import {
|
import {
|
||||||
createRemoteGroupMemberListSource,
|
createRemoteGroupMemberListSource,
|
||||||
GroupMemberListSourceKind,
|
GroupMemberListSourceKind,
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { spacing, borderRadius, shadows, useAppColors, type AppColors } from '..
|
|||||||
import { Avatar, Text } from '../../components/common';
|
import { Avatar, Text } from '../../components/common';
|
||||||
import * as hrefs from '../../navigation/hrefs';
|
import * as hrefs from '../../navigation/hrefs';
|
||||||
import { routePayloadCache } from '../../stores/routePayloadCache';
|
import { routePayloadCache } from '../../stores/routePayloadCache';
|
||||||
import { groupService } from '../../services/groupService';
|
import { groupService } from '@/services/message';
|
||||||
import { groupManager } from '../../stores/groupManager';
|
import { groupManager } from '../../stores/groupManager';
|
||||||
import { userManager } from '../../stores/userManager';
|
import { userManager } from '../../stores/userManager';
|
||||||
import { GroupInfoSummaryCard, DecisionFooter } from './components/GroupRequestShared';
|
import { GroupInfoSummaryCard, DecisionFooter } from './components/GroupRequestShared';
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import { MaterialCommunityIcons } from '@expo/vector-icons';
|
|||||||
import { spacing, borderRadius, fontSizes, useAppColors, type AppColors } from '../../theme';
|
import { spacing, borderRadius, fontSizes, useAppColors, type AppColors } from '../../theme';
|
||||||
import Avatar from '../../components/common/Avatar';
|
import Avatar from '../../components/common/Avatar';
|
||||||
import Text from '../../components/common/Text';
|
import Text from '../../components/common/Text';
|
||||||
import { groupService } from '../../services/groupService';
|
import { groupService } from '@/services/message';
|
||||||
import { groupManager } from '../../stores/groupManager';
|
import { groupManager } from '../../stores/groupManager';
|
||||||
import { GroupResponse, JoinType } from '../../types/dto';
|
import { GroupResponse, JoinType } from '../../types/dto';
|
||||||
import { useCursorPagination } from '../../hooks/useCursorPagination';
|
import { useCursorPagination } from '../../hooks/useCursorPagination';
|
||||||
|
|||||||
@@ -30,8 +30,8 @@ import { useRouter } from 'expo-router';
|
|||||||
import { MaterialCommunityIcons } from '@expo/vector-icons';
|
import { MaterialCommunityIcons } from '@expo/vector-icons';
|
||||||
import { spacing, borderRadius, useAppColors, useResolvedColorScheme, type AppColors } from '../../theme';
|
import { spacing, borderRadius, useAppColors, useResolvedColorScheme, type AppColors } from '../../theme';
|
||||||
import { SystemMessageResponse } from '../../types/dto';
|
import { SystemMessageResponse } from '../../types/dto';
|
||||||
import { messageService } from '../../services/messageService';
|
import { messageService } from '@/services/message';
|
||||||
import { commentService } from '../../services/commentService';
|
import { commentService } from '@/services/post';
|
||||||
import { SystemMessageItem } from '../../components/business';
|
import { SystemMessageItem } from '../../components/business';
|
||||||
import { Text, ResponsiveContainer } from '../../components/common';
|
import { Text, ResponsiveContainer } from '../../components/common';
|
||||||
import { useCursorPagination } from '../../hooks/useCursorPagination';
|
import { useCursorPagination } from '../../hooks/useCursorPagination';
|
||||||
|
|||||||
@@ -18,9 +18,9 @@ import { useRouter, useLocalSearchParams } from 'expo-router';
|
|||||||
import { MaterialCommunityIcons } from '@expo/vector-icons';
|
import { MaterialCommunityIcons } from '@expo/vector-icons';
|
||||||
import { spacing, borderRadius, shadows, useAppColors, type AppColors } from '../../theme';
|
import { spacing, borderRadius, shadows, useAppColors, type AppColors } from '../../theme';
|
||||||
import { useAuthStore } from '../../stores';
|
import { useAuthStore } from '../../stores';
|
||||||
import { authService } from '../../services/authService';
|
import { authService } from '@/services/auth';
|
||||||
import { messageService } from '../../services/messageService';
|
import { messageService } from '@/services/message';
|
||||||
import { ApiError } from '../../services/api';
|
import { ApiError } from '@/services/core';
|
||||||
import { messageRepository, conversationRepository } from '@/database';
|
import { messageRepository, conversationRepository } from '@/database';
|
||||||
import { messageManager } from '../../stores/messageManager';
|
import { messageManager } from '../../stores/messageManager';
|
||||||
import { userManager } from '../../stores/userManager';
|
import { userManager } from '../../stores/userManager';
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import { Text } from '../../../../components/common';
|
|||||||
import { useChatScreenStyles } from './styles';
|
import { useChatScreenStyles } from './styles';
|
||||||
import { useResponsive, useBreakpointGTE } from '../../../../hooks/useResponsive';
|
import { useResponsive, useBreakpointGTE } from '../../../../hooks/useResponsive';
|
||||||
import { EMOJIS } from './constants';
|
import { EMOJIS } from './constants';
|
||||||
import { CustomSticker, getCustomStickers, batchDeleteStickers, addStickerFromUrl } from '../../../../services/stickerService';
|
import { CustomSticker, getCustomStickers, batchDeleteStickers, addStickerFromUrl } from '@/services/message';
|
||||||
import { useAppColors, spacing } from '../../../../theme';
|
import { useAppColors, spacing } from '../../../../theme';
|
||||||
import { blurActiveElement } from '../../../../infrastructure/platform';
|
import { blurActiveElement } from '../../../../infrastructure/platform';
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import { useAppColors, spacing, fontSizes, shadows, type AppColors } from '../..
|
|||||||
import { GroupMemberResponse, GroupResponse, GroupAnnouncementResponse } from '../../../../types/dto';
|
import { GroupMemberResponse, GroupResponse, GroupAnnouncementResponse } from '../../../../types/dto';
|
||||||
import { useBreakpointGTE } from '../../../../hooks/useResponsive';
|
import { useBreakpointGTE } from '../../../../hooks/useResponsive';
|
||||||
import { groupManager } from '../../../../stores/groupManager';
|
import { groupManager } from '../../../../stores/groupManager';
|
||||||
import { groupService } from '../../../../services/groupService';
|
import { groupService } from '@/services/message';
|
||||||
|
|
||||||
const { width: screenWidth } = Dimensions.get('window');
|
const { width: screenWidth } = Dimensions.get('window');
|
||||||
const PANEL_WIDTH = 360;
|
const PANEL_WIDTH = 360;
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import { useAppColors, spacing, fontSizes, shadows, borderRadius, type AppColors
|
|||||||
import { GroupMemberResponse, GroupResponse, GroupAnnouncementResponse } from '../../../../types/dto';
|
import { GroupMemberResponse, GroupResponse, GroupAnnouncementResponse } from '../../../../types/dto';
|
||||||
import { useBreakpointGTE } from '../../../../hooks/useResponsive';
|
import { useBreakpointGTE } from '../../../../hooks/useResponsive';
|
||||||
import { groupManager } from '../../../../stores/groupManager';
|
import { groupManager } from '../../../../stores/groupManager';
|
||||||
import { groupService } from '../../../../services/groupService';
|
import { groupService } from '@/services/message';
|
||||||
|
|
||||||
const { width: screenWidth } = Dimensions.get('window');
|
const { width: screenWidth } = Dimensions.get('window');
|
||||||
const PANEL_WIDTH = 360;
|
const PANEL_WIDTH = 360;
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import { useChatScreenStyles } from './styles';
|
|||||||
import { LongPressMenuProps } from './types';
|
import { LongPressMenuProps } from './types';
|
||||||
import { RECALL_TIME_LIMIT } from './constants';
|
import { RECALL_TIME_LIMIT } from './constants';
|
||||||
import { extractTextFromSegments, ImageSegmentData } from '../../../../types/dto';
|
import { extractTextFromSegments, ImageSegmentData } from '../../../../types/dto';
|
||||||
import { isStickerExists, addStickerFromUrl } from '../../../../services/stickerService';
|
import { isStickerExists, addStickerFromUrl } from '@/services/message';
|
||||||
import { blurActiveElement } from '../../../../infrastructure/platform';
|
import { blurActiveElement } from '../../../../infrastructure/platform';
|
||||||
|
|
||||||
const { width: SCREEN_WIDTH, height: SCREEN_HEIGHT } = Dimensions.get('window');
|
const { width: SCREEN_WIDTH, height: SCREEN_HEIGHT } = Dimensions.get('window');
|
||||||
|
|||||||
@@ -22,12 +22,12 @@ import { formatDistanceToNow } from 'date-fns';
|
|||||||
import { zhCN } from 'date-fns/locale';
|
import { zhCN } from 'date-fns/locale';
|
||||||
import * as ImagePicker from 'expo-image-picker';
|
import * as ImagePicker from 'expo-image-picker';
|
||||||
import { GroupMemberResponse, MessageSegment, TextSegmentData, ImageSegmentData, AtSegmentData, ReplySegmentData, MessageStatus } from '../../../../types/dto';
|
import { GroupMemberResponse, MessageSegment, TextSegmentData, ImageSegmentData, AtSegmentData, ReplySegmentData, MessageStatus } from '../../../../types/dto';
|
||||||
import { messageService } from '../../../../services/messageService';
|
import { messageService } from '@/services/message';
|
||||||
import { uploadService } from '../../../../services/uploadService';
|
import { uploadService } from '@/services/upload';
|
||||||
import { ApiError } from '../../../../services/api';
|
import { ApiError } from '@/services/core';
|
||||||
// 【新架构】使用 MessageManager
|
// 【新架构】使用 MessageManager
|
||||||
import { useChat, useGroupTyping, useGroupMuted, messageManager, callStore } from '../../../../stores';
|
import { useChat, useGroupTyping, useGroupMuted, messageManager, callStore } from '../../../../stores';
|
||||||
import { groupService } from '../../../../services/groupService';
|
import { groupService } from '@/services/message';
|
||||||
import { userManager } from '../../../../stores/userManager';
|
import { userManager } from '../../../../stores/userManager';
|
||||||
import { groupManager } from '../../../../stores/groupManager';
|
import { groupManager } from '../../../../stores/groupManager';
|
||||||
import * as hrefs from '../../../../navigation/hrefs';
|
import * as hrefs from '../../../../navigation/hrefs';
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import {
|
|||||||
import { MaterialCommunityIcons } from '@expo/vector-icons';
|
import { MaterialCommunityIcons } from '@expo/vector-icons';
|
||||||
|
|
||||||
import { spacing, fontSizes, borderRadius, useAppColors, type AppColors } from '../../../theme';
|
import { spacing, fontSizes, borderRadius, useAppColors, type AppColors } from '../../../theme';
|
||||||
import { authService } from '../../../services/authService';
|
import { authService } from '@/services/auth';
|
||||||
import { useAuthStore } from '../../../stores';
|
import { useAuthStore } from '../../../stores';
|
||||||
import { Avatar, EmptyState, Loading, Text } from '../../../components/common';
|
import { Avatar, EmptyState, Loading, Text } from '../../../components/common';
|
||||||
import { blurActiveElement } from '../../../infrastructure/platform';
|
import { blurActiveElement } from '../../../infrastructure/platform';
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ import {
|
|||||||
} from '../../theme';
|
} from '../../theme';
|
||||||
import { Text } from '../../components/common';
|
import { Text } from '../../components/common';
|
||||||
import { useResponsive, useResponsiveSpacing } from '../../hooks';
|
import { useResponsive, useResponsiveSpacing } from '../../hooks';
|
||||||
import { checkForAPKUpdate, type VersionCheckResult } from '../../services/apkUpdateService';
|
import { checkForAPKUpdate, type VersionCheckResult } from '@/services/platform';
|
||||||
import * as hrefs from '../../navigation/hrefs';
|
import * as hrefs from '../../navigation/hrefs';
|
||||||
|
|
||||||
const CONTENT_MAX_WIDTH = 720;
|
const CONTENT_MAX_WIDTH = 720;
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ import { useResponsive, useResponsiveSpacing } from '../../hooks';
|
|||||||
// 内容最大宽度
|
// 内容最大宽度
|
||||||
const CONTENT_MAX_WIDTH = 720;
|
const CONTENT_MAX_WIDTH = 720;
|
||||||
|
|
||||||
import { authService, resolveAuthApiError } from '../../services/authService';
|
import { authService, resolveAuthApiError } from '@/services/auth';
|
||||||
import { showPrompt } from '../../services/promptService';
|
import { showPrompt } from '@/services/ui';
|
||||||
import { useAuthStore } from '../../stores';
|
import { useAuthStore } from '../../stores';
|
||||||
|
|
||||||
export const AccountSecurityScreen: React.FC = () => {
|
export const AccountSecurityScreen: React.FC = () => {
|
||||||
|
|||||||
@@ -22,9 +22,9 @@ import {
|
|||||||
setPushNotificationsPreference,
|
setPushNotificationsPreference,
|
||||||
setSoundPreference,
|
setSoundPreference,
|
||||||
setVibrationPreference,
|
setVibrationPreference,
|
||||||
} from '../../services/notificationPreferences';
|
} from '@/services/notification';
|
||||||
import { useResponsive, useResponsiveSpacing } from '../../hooks';
|
import { useResponsive, useResponsiveSpacing } from '../../hooks';
|
||||||
import { backgroundSyncManager, BackgroundSyncMode } from '../../services/BackgroundSyncManager';
|
import { backgroundSyncManager, BackgroundSyncMode } from '@/services/background';
|
||||||
|
|
||||||
// 内容最大宽度
|
// 内容最大宽度
|
||||||
const CONTENT_MAX_WIDTH = 720;
|
const CONTENT_MAX_WIDTH = 720;
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import {
|
|||||||
useVerificationStatus,
|
useVerificationStatus,
|
||||||
useVerificationLoading,
|
useVerificationLoading,
|
||||||
} from '../../stores/verificationStore';
|
} from '../../stores/verificationStore';
|
||||||
import { showPrompt } from '../../services/promptService';
|
import { showPrompt } from '@/services/ui';
|
||||||
import * as hrefs from '../../navigation/hrefs';
|
import * as hrefs from '../../navigation/hrefs';
|
||||||
|
|
||||||
const STATUS_CONFIG = {
|
const STATUS_CONFIG = {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import { Post, User } from '../../types';
|
|||||||
import { useUserStore } from '../../stores';
|
import { useUserStore } from '../../stores';
|
||||||
import { useCurrentUser } from '../../stores/authStore';
|
import { useCurrentUser } from '../../stores/authStore';
|
||||||
import { postService, authService, messageService } from '../../services';
|
import { postService, authService, messageService } from '../../services';
|
||||||
import { postSyncService } from '../../services/post/PostSyncService';
|
import { postSyncService } from '@/services/post';
|
||||||
import { userManager } from '../../stores/userManager';
|
import { userManager } from '../../stores/userManager';
|
||||||
import * as hrefs from '../../navigation/hrefs';
|
import * as hrefs from '../../navigation/hrefs';
|
||||||
import { PostCardAction } from '../../components/business/PostCard';
|
import { PostCardAction } from '../../components/business/PostCard';
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { MaterialCommunityIcons } from '@expo/vector-icons';
|
|||||||
|
|
||||||
import { spacing, borderRadius, fontSizes, shadows, useAppColors, type AppColors } from '../../theme';
|
import { spacing, borderRadius, fontSizes, shadows, useAppColors, type AppColors } from '../../theme';
|
||||||
import { routePayloadCache } from '../../stores/routePayloadCache';
|
import { routePayloadCache } from '../../stores/routePayloadCache';
|
||||||
import { scheduleService } from '../../services/scheduleService';
|
import { scheduleService } from '@/services/platform';
|
||||||
|
|
||||||
const WEEKDAY_NAMES = ['周一', '周二', '周三', '周四', '周五', '周六', '周日'];
|
const WEEKDAY_NAMES = ['周一', '周二', '周三', '周四', '周五', '周六', '周日'];
|
||||||
const getMergedSectionIndex = (section: number) => Math.ceil(section / 2);
|
const getMergedSectionIndex = (section: number) => Math.ceil(section / 2);
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ import {
|
|||||||
} from '../../types/schedule';
|
} from '../../types/schedule';
|
||||||
import * as hrefs from '../../navigation/hrefs';
|
import * as hrefs from '../../navigation/hrefs';
|
||||||
import { routePayloadCache } from '../../stores/routePayloadCache';
|
import { routePayloadCache } from '../../stores/routePayloadCache';
|
||||||
import { scheduleService } from '../../services/scheduleService';
|
import { scheduleService } from '@/services/platform';
|
||||||
|
|
||||||
const { width: SCREEN_WIDTH } = Dimensions.get('window');
|
const { width: SCREEN_WIDTH } = Dimensions.get('window');
|
||||||
|
|
||||||
|
|||||||
@@ -3,8 +3,9 @@
|
|||||||
* 处理用户登录、注册、登出等认证功能
|
* 处理用户登录、注册、登出等认证功能
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { api } from './api';
|
import { api } from '../core/api';
|
||||||
import { User } from '../types';
|
import { User } from '@/types';
|
||||||
|
import type { PrivacySettingsDTO, PrivacySettingsRequestDTO, DeletionStatusDTO } from '@/types/dto';
|
||||||
|
|
||||||
export function resolveAuthApiError(error: any, fallback = '操作失败,请稍后重试'): string {
|
export function resolveAuthApiError(error: any, fallback = '操作失败,请稍后重试'): string {
|
||||||
const code: number = error?.code ?? 0;
|
const code: number = error?.code ?? 0;
|
||||||
@@ -160,6 +161,7 @@ class AuthService {
|
|||||||
if (refreshToken) {
|
if (refreshToken) {
|
||||||
await api.setRefreshToken(refreshToken);
|
await api.setRefreshToken(refreshToken);
|
||||||
}
|
}
|
||||||
|
api.resetAuthState();
|
||||||
|
|
||||||
return response.data;
|
return response.data;
|
||||||
}
|
}
|
||||||
@@ -178,6 +180,7 @@ class AuthService {
|
|||||||
if (refreshToken) {
|
if (refreshToken) {
|
||||||
await api.setRefreshToken(refreshToken);
|
await api.setRefreshToken(refreshToken);
|
||||||
}
|
}
|
||||||
|
api.resetAuthState();
|
||||||
|
|
||||||
return response.data;
|
return response.data;
|
||||||
}
|
}
|
||||||
@@ -457,9 +460,9 @@ class AuthService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 隐私设置
|
// 隐私设置
|
||||||
async getPrivacySettings(): Promise<import('../types/dto').PrivacySettingsDTO | null> {
|
async getPrivacySettings(): Promise<PrivacySettingsDTO | null> {
|
||||||
try {
|
try {
|
||||||
const response = await api.get<import('../types/dto').PrivacySettingsDTO>('/users/me/privacy');
|
const response = await api.get<PrivacySettingsDTO>('/users/me/privacy');
|
||||||
return response.data;
|
return response.data;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('获取隐私设置失败:', error);
|
console.error('获取隐私设置失败:', error);
|
||||||
@@ -467,7 +470,7 @@ class AuthService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async updatePrivacySettings(settings: import('../types/dto').PrivacySettingsRequestDTO): Promise<boolean> {
|
async updatePrivacySettings(settings: PrivacySettingsRequestDTO): Promise<boolean> {
|
||||||
try {
|
try {
|
||||||
await api.put('/users/me/privacy', settings);
|
await api.put('/users/me/privacy', settings);
|
||||||
return true;
|
return true;
|
||||||
@@ -478,9 +481,9 @@ class AuthService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 账号注销
|
// 账号注销
|
||||||
async requestAccountDeletion(password: string): Promise<import('../types/dto').DeletionStatusDTO | null> {
|
async requestAccountDeletion(password: string): Promise<DeletionStatusDTO | null> {
|
||||||
try {
|
try {
|
||||||
const response = await api.post<import('../types/dto').DeletionStatusDTO>('/users/me/deactivate', {
|
const response = await api.post<DeletionStatusDTO>('/users/me/deactivate', {
|
||||||
password,
|
password,
|
||||||
});
|
});
|
||||||
return response.data;
|
return response.data;
|
||||||
@@ -500,9 +503,9 @@ class AuthService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getDeletionStatus(): Promise<import('../types/dto').DeletionStatusDTO | null> {
|
async getDeletionStatus(): Promise<DeletionStatusDTO | null> {
|
||||||
try {
|
try {
|
||||||
const response = await api.get<import('../types/dto').DeletionStatusDTO>('/users/me/deletion-status');
|
const response = await api.get<DeletionStatusDTO>('/users/me/deletion-status');
|
||||||
return response.data;
|
return response.data;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('获取注销状态失败:', error);
|
console.error('获取注销状态失败:', error);
|
||||||
18
src/services/auth/index.ts
Normal file
18
src/services/auth/index.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
export { authService, resolveAuthApiError, qrcodeApi } from './authService';
|
||||||
|
export type {
|
||||||
|
LoginRequest,
|
||||||
|
RegisterRequest,
|
||||||
|
SendEmailCodeRequest,
|
||||||
|
ResetPasswordRequest,
|
||||||
|
VerifyCurrentUserEmailRequest,
|
||||||
|
AuthResponse,
|
||||||
|
RefreshTokenResponse,
|
||||||
|
UpdateUserRequest,
|
||||||
|
BlockedUserListResponse,
|
||||||
|
BlockStatusResponse,
|
||||||
|
QRCodeSession,
|
||||||
|
ScanResponse,
|
||||||
|
} from './authService';
|
||||||
|
|
||||||
|
export { verificationService } from './verificationService';
|
||||||
|
export type { SubmitVerificationResponse } from './verificationService';
|
||||||
@@ -3,13 +3,13 @@
|
|||||||
* 处理用户身份认证申请、状态查询等功能
|
* 处理用户身份认证申请、状态查询等功能
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { api } from './api';
|
import { api } from '../core/api';
|
||||||
import {
|
import {
|
||||||
VerificationStatusDTO,
|
VerificationStatusDTO,
|
||||||
VerificationRecordDTO,
|
VerificationRecordDTO,
|
||||||
SubmitVerificationRequest,
|
SubmitVerificationRequest,
|
||||||
PaginatedData,
|
PaginatedData,
|
||||||
} from '../types/dto';
|
} from '@/types/dto';
|
||||||
|
|
||||||
// 提交认证响应
|
// 提交认证响应
|
||||||
export interface SubmitVerificationResponse {
|
export interface SubmitVerificationResponse {
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
import { AppState, AppStateStatus, Platform } from 'react-native';
|
import { AppState, AppStateStatus, Platform } from 'react-native';
|
||||||
import { ForegroundServiceModule } from './ForegroundServiceModule';
|
import { ForegroundServiceModule } from './ForegroundServiceModule';
|
||||||
import { wsService } from './wsService';
|
import { wsService } from '../core/wsService';
|
||||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -15,8 +15,8 @@ import {
|
|||||||
backgroundSyncManager,
|
backgroundSyncManager,
|
||||||
BackgroundSyncMode,
|
BackgroundSyncMode,
|
||||||
} from './BackgroundSyncManager';
|
} from './BackgroundSyncManager';
|
||||||
import { messageService } from './messageService';
|
import { messageService } from '../message/messageService';
|
||||||
import { api } from './api';
|
import { api } from '../core/api';
|
||||||
|
|
||||||
// 后台任务名称
|
// 后台任务名称
|
||||||
const BACKGROUND_SYNC_TASK = 'background-sync-task';
|
const BACKGROUND_SYNC_TASK = 'background-sync-task';
|
||||||
@@ -215,7 +215,7 @@ export {
|
|||||||
setVibrationConfig,
|
setVibrationConfig,
|
||||||
getVibrationConfig,
|
getVibrationConfig,
|
||||||
setVibrationEnabled,
|
setVibrationEnabled,
|
||||||
} from './messageVibrationService';
|
} from '../platform/messageVibrationService';
|
||||||
|
|
||||||
// 重新导出类型
|
// 重新导出类型
|
||||||
export { BackgroundSyncMode };
|
export { BackgroundSyncMode };
|
||||||
@@ -230,7 +230,7 @@ export const backgroundService = {
|
|||||||
checkStatus: checkBackgroundStatus,
|
checkStatus: checkBackgroundStatus,
|
||||||
// 震动相关
|
// 震动相关
|
||||||
vibrate: async () => {
|
vibrate: async () => {
|
||||||
const { triggerVibration } = await import('./messageVibrationService');
|
const { triggerVibration } = await import('../platform/messageVibrationService');
|
||||||
triggerVibration();
|
triggerVibration();
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
19
src/services/background/index.ts
Normal file
19
src/services/background/index.ts
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
export {
|
||||||
|
backgroundService,
|
||||||
|
initBackgroundService,
|
||||||
|
stopBackgroundService,
|
||||||
|
triggerVibration,
|
||||||
|
vibrateOnMessage,
|
||||||
|
setVibrationConfig,
|
||||||
|
getVibrationConfig,
|
||||||
|
setVibrationEnabled,
|
||||||
|
checkBackgroundStatus,
|
||||||
|
setBackgroundSyncMode,
|
||||||
|
getBackgroundSyncMode,
|
||||||
|
syncNow,
|
||||||
|
} from './backgroundService';
|
||||||
|
|
||||||
|
export { BackgroundSyncMode, backgroundSyncManager } from './BackgroundSyncManager';
|
||||||
|
|
||||||
|
export { ForegroundServiceModule } from './ForegroundServiceModule';
|
||||||
|
export type { ForegroundServiceOptions } from './ForegroundServiceModule';
|
||||||
@@ -75,6 +75,7 @@ class ApiClient {
|
|||||||
private baseUrl: string;
|
private baseUrl: string;
|
||||||
private verificationModalShown = false;
|
private verificationModalShown = false;
|
||||||
private refreshLock: Promise<boolean> | null = null;
|
private refreshLock: Promise<boolean> | null = null;
|
||||||
|
private isAuthFailed = false; // 全局认证失败标志,防止无限重试
|
||||||
|
|
||||||
constructor(baseUrl: string) {
|
constructor(baseUrl: string) {
|
||||||
this.baseUrl = baseUrl;
|
this.baseUrl = baseUrl;
|
||||||
@@ -90,10 +91,17 @@ class ApiClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private navigateToLogin() {
|
private navigateToLogin() {
|
||||||
|
this.isAuthFailed = true; // 设置全局失败标志
|
||||||
eventBus.emit({ type: 'NAVIGATE', payload: { path: '/(auth)/login' } });
|
eventBus.emit({ type: 'NAVIGATE', payload: { path: '/(auth)/login' } });
|
||||||
eventBus.emit({ type: 'AUTH_LOGOUT' });
|
eventBus.emit({ type: 'AUTH_LOGOUT' });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 重置认证状态(登录成功后调用)
|
||||||
|
resetAuthState() {
|
||||||
|
this.isAuthFailed = false;
|
||||||
|
this.refreshLock = null;
|
||||||
|
}
|
||||||
|
|
||||||
private parseJwt(token: string): JwtPayload | null {
|
private parseJwt(token: string): JwtPayload | null {
|
||||||
try {
|
try {
|
||||||
const parts = token.split('.');
|
const parts = token.split('.');
|
||||||
@@ -167,13 +175,22 @@ class ApiClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 不需要认证的路径前缀
|
||||||
|
private static PUBLIC_PATHS = ['/auth/login', '/auth/register', '/auth/password/', '/auth/check-username', '/auth/qrcode', '/auth/refresh'];
|
||||||
|
|
||||||
// 统一请求方法
|
// 统一请求方法
|
||||||
private async request<T>(
|
private async request<T>(
|
||||||
method: string,
|
method: string,
|
||||||
path: string,
|
path: string,
|
||||||
params?: Record<string, any>,
|
params?: Record<string, any>,
|
||||||
body?: any
|
body?: any,
|
||||||
|
_retryCount = 0,
|
||||||
): Promise<ApiResponse<T>> {
|
): Promise<ApiResponse<T>> {
|
||||||
|
// 认证已失败,仅放行公开路径(登录、注册等)
|
||||||
|
if (this.isAuthFailed && !ApiClient.PUBLIC_PATHS.some(p => path.startsWith(p))) {
|
||||||
|
throw new ApiError(401, '登录已过期,请重新登录');
|
||||||
|
}
|
||||||
|
|
||||||
const url = new URL(`${this.baseUrl}${path}`);
|
const url = new URL(`${this.baseUrl}${path}`);
|
||||||
|
|
||||||
// 添加查询参数
|
// 添加查询参数
|
||||||
@@ -226,6 +243,11 @@ class ApiClient {
|
|||||||
|
|
||||||
// 处理 401 未授权
|
// 处理 401 未授权
|
||||||
if (response.status === 401) {
|
if (response.status === 401) {
|
||||||
|
if (_retryCount >= 1) {
|
||||||
|
await this.clearToken();
|
||||||
|
this.navigateToLogin();
|
||||||
|
throw new ApiError(401, '登录已过期,请重新登录');
|
||||||
|
}
|
||||||
const refreshed = await this.refreshToken();
|
const refreshed = await this.refreshToken();
|
||||||
if (!refreshed) {
|
if (!refreshed) {
|
||||||
await this.clearToken();
|
await this.clearToken();
|
||||||
@@ -233,7 +255,7 @@ class ApiClient {
|
|||||||
throw new ApiError(401, '登录已过期,请重新登录');
|
throw new ApiError(401, '登录已过期,请重新登录');
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.request(method, path, params, body);
|
return this.request(method, path, params, body, _retryCount + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 解析响应(兼容非 JSON 返回,避免 SyntaxError 被误判为网络错误)
|
// 解析响应(兼容非 JSON 返回,避免 SyntaxError 被误判为网络错误)
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
* 替代散落在代码中的 console.error + 手动 Alert 模式
|
* 替代散落在代码中的 console.error + 手动 Alert 模式
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { showPrompt } from './promptService';
|
import { showPrompt } from '../ui/promptService';
|
||||||
|
|
||||||
export enum AppErrorCode {
|
export enum AppErrorCode {
|
||||||
NETWORK_ERROR = 'NETWORK_ERROR',
|
NETWORK_ERROR = 'NETWORK_ERROR',
|
||||||
39
src/services/core/index.ts
Normal file
39
src/services/core/index.ts
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
export { api, WS_URL, TOKEN_KEY, REFRESH_TOKEN_KEY } from './api';
|
||||||
|
export { ApiError } from './api';
|
||||||
|
export type { ApiResponse, PaginatedData } from './api';
|
||||||
|
|
||||||
|
export { wsService } from './wsService';
|
||||||
|
export type {
|
||||||
|
WSMessage,
|
||||||
|
WSMessageType,
|
||||||
|
WSChatMessage,
|
||||||
|
WSReadMessage,
|
||||||
|
WSTypingMessage,
|
||||||
|
WSRecallMessage,
|
||||||
|
WSNotificationMessage,
|
||||||
|
WSAnnouncementMessage,
|
||||||
|
WSGroupChatMessage,
|
||||||
|
WSGroupTypingMessage,
|
||||||
|
GroupNoticeType,
|
||||||
|
WSGroupNoticeMessage,
|
||||||
|
WSGroupMentionMessage,
|
||||||
|
WSGroupReadMessage,
|
||||||
|
WSGroupRecallMessage,
|
||||||
|
WSCallIncomingMessage,
|
||||||
|
WSCallAcceptedMessage,
|
||||||
|
WSCallRejectedMessage,
|
||||||
|
WSCallBusyMessage,
|
||||||
|
WSCallEndedMessage,
|
||||||
|
WSCallSDPMessage,
|
||||||
|
WSCallICEMessage,
|
||||||
|
WSCallPeerMutedMessage,
|
||||||
|
WSCallInvitedMessage,
|
||||||
|
WSCallAnsweredElsewhereMessage,
|
||||||
|
WSErrorMessage,
|
||||||
|
WSServerMessage,
|
||||||
|
ICEServerConfig,
|
||||||
|
} from './wsService';
|
||||||
|
|
||||||
|
export { handleError, createErrorHandler, safeAsync, createAppError } from './errorHandler';
|
||||||
|
export type { AppError, ErrorHandlerOptions } from './errorHandler';
|
||||||
|
export { AppErrorCode } from './errorHandler';
|
||||||
@@ -2,8 +2,8 @@ import { AppState, AppStateStatus } from 'react-native';
|
|||||||
|
|
||||||
import { api, WS_URL } from './api';
|
import { api, WS_URL } from './api';
|
||||||
import { eventBus } from '@/core/events/EventBus';
|
import { eventBus } from '@/core/events/EventBus';
|
||||||
import { MessageCategory, SystemMessageType, SystemMessageExtraData, MessageSegment } from '../types/dto';
|
import { MessageCategory, SystemMessageType, SystemMessageExtraData, MessageSegment } from '@/types/dto';
|
||||||
import { systemNotificationService } from './systemNotificationService';
|
import { systemNotificationService } from '../notification/systemNotificationService';
|
||||||
|
|
||||||
export type WSMessageType =
|
export type WSMessageType =
|
||||||
| 'chat'
|
| 'chat'
|
||||||
@@ -1,54 +1,6 @@
|
|||||||
/**
|
export { api, WS_URL, TOKEN_KEY, REFRESH_TOKEN_KEY, ApiError } from './core';
|
||||||
* 服务导出
|
export type { ApiResponse, PaginatedData } from './core';
|
||||||
* 统一导出所有API服务
|
export { wsService } from './core';
|
||||||
*/
|
|
||||||
|
|
||||||
// API 客户端
|
|
||||||
export { api, WS_URL, TOKEN_KEY, REFRESH_TOKEN_KEY } from './api';
|
|
||||||
export type { ApiResponse, PaginatedData, ApiError } from './api';
|
|
||||||
|
|
||||||
// 认证服务
|
|
||||||
export { authService } from './authService';
|
|
||||||
export { resolveAuthApiError } from './authService';
|
|
||||||
export type {
|
|
||||||
LoginRequest,
|
|
||||||
RegisterRequest,
|
|
||||||
SendEmailCodeRequest,
|
|
||||||
ResetPasswordRequest,
|
|
||||||
VerifyCurrentUserEmailRequest,
|
|
||||||
AuthResponse,
|
|
||||||
RefreshTokenResponse,
|
|
||||||
UpdateUserRequest,
|
|
||||||
BlockedUserListResponse,
|
|
||||||
BlockStatusResponse,
|
|
||||||
} from './authService';
|
|
||||||
|
|
||||||
// 帖子服务
|
|
||||||
export { postService } from './postService';
|
|
||||||
|
|
||||||
// 评论服务
|
|
||||||
export { commentService } from './commentService';
|
|
||||||
|
|
||||||
// 消息服务
|
|
||||||
export { messageService } from './messageService';
|
|
||||||
|
|
||||||
// 通知服务
|
|
||||||
export { notificationService } from './notificationService';
|
|
||||||
|
|
||||||
// 文件上传服务
|
|
||||||
export { uploadService } from './uploadService';
|
|
||||||
export type { UploadResponse } from './uploadService';
|
|
||||||
|
|
||||||
// 推送服务
|
|
||||||
export { pushService, registerDevice, getDevices, unregisterDevice, updateDeviceToken, getPushRecords } from './pushService';
|
|
||||||
|
|
||||||
// 投票服务
|
|
||||||
export { voteService } from './voteService';
|
|
||||||
export { channelService } from './channelService';
|
|
||||||
export type { ChannelItem } from './channelService';
|
|
||||||
|
|
||||||
// WebSocket 实时服务
|
|
||||||
export { wsService } from './wsService';
|
|
||||||
export type {
|
export type {
|
||||||
WSMessage,
|
WSMessage,
|
||||||
WSMessageType,
|
WSMessageType,
|
||||||
@@ -64,15 +16,32 @@ export type {
|
|||||||
WSGroupNoticeMessage,
|
WSGroupNoticeMessage,
|
||||||
WSGroupMentionMessage,
|
WSGroupMentionMessage,
|
||||||
WSGroupReadMessage,
|
WSGroupReadMessage,
|
||||||
WSGroupRecallMessage
|
WSGroupRecallMessage,
|
||||||
} from './wsService';
|
} from './core';
|
||||||
|
export { handleError, createErrorHandler, safeAsync, createAppError, AppErrorCode } from './core';
|
||||||
|
export type { AppError, ErrorHandlerOptions } from './core';
|
||||||
|
|
||||||
// 系统通知服务
|
export { authService, resolveAuthApiError } from './auth';
|
||||||
export { systemNotificationService, getNotificationTitle } from './systemNotificationService';
|
export type {
|
||||||
export type { AppNotificationType } from './systemNotificationService';
|
LoginRequest,
|
||||||
|
RegisterRequest,
|
||||||
|
SendEmailCodeRequest,
|
||||||
|
ResetPasswordRequest,
|
||||||
|
VerifyCurrentUserEmailRequest,
|
||||||
|
AuthResponse,
|
||||||
|
RefreshTokenResponse,
|
||||||
|
UpdateUserRequest,
|
||||||
|
BlockedUserListResponse,
|
||||||
|
BlockStatusResponse,
|
||||||
|
} from './auth';
|
||||||
|
export { verificationService } from './auth';
|
||||||
|
export type { SubmitVerificationResponse } from './auth';
|
||||||
|
|
||||||
// 群组服务
|
export { postService, commentService, voteService, channelService, reportService } from './post';
|
||||||
export { groupService } from './groupService';
|
export type { ChannelItem } from './post';
|
||||||
|
|
||||||
|
export { messageService } from './message';
|
||||||
|
export { groupService } from './message';
|
||||||
export type {
|
export type {
|
||||||
GroupResponse,
|
GroupResponse,
|
||||||
GroupMemberResponse,
|
GroupMemberResponse,
|
||||||
@@ -88,13 +57,16 @@ export type {
|
|||||||
SetMuteAllRequest,
|
SetMuteAllRequest,
|
||||||
SetJoinTypeRequest,
|
SetJoinTypeRequest,
|
||||||
CreateAnnouncementRequest,
|
CreateAnnouncementRequest,
|
||||||
} from './groupService';
|
} from './message';
|
||||||
|
|
||||||
// 课表服务
|
export { notificationService } from './notification';
|
||||||
export { scheduleService } from './scheduleService';
|
export { systemNotificationService, getNotificationTitle } from './notification';
|
||||||
export type { CreateScheduleCourseRequest } from './scheduleService';
|
export type { AppNotificationType } from './notification';
|
||||||
|
export { pushService, registerDevice, getDevices, unregisterDevice, updateDeviceToken, getPushRecords } from './notification';
|
||||||
|
|
||||||
|
export { uploadService } from './upload';
|
||||||
|
export type { UploadResponse } from './upload';
|
||||||
|
|
||||||
// 后台保活服务
|
|
||||||
export {
|
export {
|
||||||
backgroundService,
|
backgroundService,
|
||||||
initBackgroundService,
|
initBackgroundService,
|
||||||
@@ -105,21 +77,12 @@ export {
|
|||||||
getVibrationConfig,
|
getVibrationConfig,
|
||||||
setVibrationEnabled,
|
setVibrationEnabled,
|
||||||
checkBackgroundStatus,
|
checkBackgroundStatus,
|
||||||
} from './backgroundService';
|
} from './background';
|
||||||
|
|
||||||
// 统一提示/弹窗服务
|
export { showPrompt } from './ui';
|
||||||
export { showPrompt } from './promptService';
|
export { showConfirm } from './ui';
|
||||||
export { showConfirm } from './dialogService';
|
|
||||||
|
|
||||||
// 统一错误处理服务
|
export { apkUpdateService, checkForAPKUpdate, manualCheckForUpdate } from './platform';
|
||||||
export { handleError, createErrorHandler, safeAsync, createAppError } from './errorHandler';
|
export type { APKVersionInfo, VersionCheckResult } from './platform';
|
||||||
export type { AppError, ErrorHandlerOptions } from './errorHandler';
|
export { scheduleService } from './platform';
|
||||||
export { AppErrorCode } from './errorHandler';
|
export type { CreateScheduleCourseRequest } from './platform';
|
||||||
|
|
||||||
// APK 更新检查服务
|
|
||||||
export { apkUpdateService, checkForAPKUpdate, manualCheckForUpdate } from './apkUpdateService';
|
|
||||||
export type { APKVersionInfo, VersionCheckResult } from './apkUpdateService';
|
|
||||||
|
|
||||||
// 身份认证服务
|
|
||||||
export { verificationService } from './verificationService';
|
|
||||||
export type { SubmitVerificationResponse } from './verificationService';
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
* 使用 RESTful API: /api/v1/groups
|
* 使用 RESTful API: /api/v1/groups
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { api } from './api';
|
import { api } from '../core/api';
|
||||||
import {
|
import {
|
||||||
GroupResponse,
|
GroupResponse,
|
||||||
GroupMemberResponse,
|
GroupMemberResponse,
|
||||||
@@ -25,7 +25,7 @@ import {
|
|||||||
HandleGroupRequestAction,
|
HandleGroupRequestAction,
|
||||||
CursorPaginationRequest,
|
CursorPaginationRequest,
|
||||||
CursorPaginationResponse,
|
CursorPaginationResponse,
|
||||||
} from '../types/dto';
|
} from '@/types/dto';
|
||||||
|
|
||||||
function asGroupId(raw: unknown): string {
|
function asGroupId(raw: unknown): string {
|
||||||
return String(raw);
|
return String(raw);
|
||||||
42
src/services/message/index.ts
Normal file
42
src/services/message/index.ts
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
export { messageService } from './messageService';
|
||||||
|
export type { RemoteConversationListPageResult } from './messageService';
|
||||||
|
export type {
|
||||||
|
ConversationListResponse,
|
||||||
|
ConversationResponse,
|
||||||
|
ConversationDetailResponse,
|
||||||
|
MessageListResponse,
|
||||||
|
MessageResponse,
|
||||||
|
SendMessageRequest,
|
||||||
|
UnreadCountResponse,
|
||||||
|
ConversationUnreadCountResponse,
|
||||||
|
SystemMessageListResponse,
|
||||||
|
SystemUnreadCountResponse,
|
||||||
|
} from './messageService';
|
||||||
|
|
||||||
|
export { groupService } from './groupService';
|
||||||
|
export type {
|
||||||
|
GroupResponse,
|
||||||
|
GroupMemberResponse,
|
||||||
|
GroupAnnouncementResponse,
|
||||||
|
GroupListResponse,
|
||||||
|
GroupMemberListResponse,
|
||||||
|
GroupAnnouncementListResponse,
|
||||||
|
CreateGroupRequest,
|
||||||
|
InviteMembersRequest,
|
||||||
|
TransferOwnerRequest,
|
||||||
|
SetRoleRequest,
|
||||||
|
SetNicknameRequest,
|
||||||
|
SetMuteAllRequest,
|
||||||
|
SetJoinTypeRequest,
|
||||||
|
CreateAnnouncementRequest,
|
||||||
|
} from './groupService';
|
||||||
|
|
||||||
|
export type { CustomSticker } from './stickerService';
|
||||||
|
export {
|
||||||
|
getCustomStickers,
|
||||||
|
addStickerFromUrl,
|
||||||
|
deleteSticker,
|
||||||
|
isStickerExists,
|
||||||
|
reorderStickers,
|
||||||
|
batchDeleteStickers,
|
||||||
|
} from './stickerService';
|
||||||
@@ -4,8 +4,8 @@
|
|||||||
* 使用新的 API 接口: /api/v1/conversations (RESTful action 风格)
|
* 使用新的 API 接口: /api/v1/conversations (RESTful action 风格)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { api } from './api';
|
import { api } from '../core/api';
|
||||||
import { wsService } from './wsService';
|
import { wsService } from '../core/wsService';
|
||||||
import {
|
import {
|
||||||
ConversationListResponse,
|
ConversationListResponse,
|
||||||
ConversationResponse,
|
ConversationResponse,
|
||||||
@@ -21,7 +21,7 @@ import {
|
|||||||
MessageSegment,
|
MessageSegment,
|
||||||
CursorPaginationRequest,
|
CursorPaginationRequest,
|
||||||
CursorPaginationResponse,
|
CursorPaginationResponse,
|
||||||
} from '../types/dto';
|
} from '@/types/dto';
|
||||||
import { conversationRepository, userCacheRepository } from '@/database';
|
import { conversationRepository, userCacheRepository } from '@/database';
|
||||||
|
|
||||||
/** 远端会话列表分页(offset / cursor)统一结果:拉取成功后均已执行本地缓存同步 */
|
/** 远端会话列表分页(offset / cursor)统一结果:拉取成功后均已执行本地缓存同步 */
|
||||||
@@ -3,8 +3,8 @@
|
|||||||
* 管理用户自定义添加的表情包(云端存储)
|
* 管理用户自定义添加的表情包(云端存储)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { api } from './api';
|
import { api } from '../core/api';
|
||||||
import { uploadService } from './uploadService';
|
import { uploadService } from '../upload/uploadService';
|
||||||
|
|
||||||
// 自定义表情类型
|
// 自定义表情类型
|
||||||
export interface CustomSticker {
|
export interface CustomSticker {
|
||||||
17
src/services/notification/index.ts
Normal file
17
src/services/notification/index.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
export { notificationService } from './notificationService';
|
||||||
|
|
||||||
|
export { systemNotificationService, getNotificationTitle } from './systemNotificationService';
|
||||||
|
export type { AppNotificationType } from './systemNotificationService';
|
||||||
|
|
||||||
|
export {
|
||||||
|
NOTIFICATION_PREF_KEYS,
|
||||||
|
getNotificationPreferencesSync,
|
||||||
|
loadNotificationPreferences,
|
||||||
|
setVibrationPreference,
|
||||||
|
setPushNotificationsPreference,
|
||||||
|
setSoundPreference,
|
||||||
|
registerNotificationPresentationHandler,
|
||||||
|
} from './notificationPreferences';
|
||||||
|
export type { NotificationPrefs } from './notificationPreferences';
|
||||||
|
|
||||||
|
export { pushService, registerDevice, getDevices, unregisterDevice, updateDeviceToken, getPushRecords } from './pushService';
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||||
import * as Notifications from 'expo-notifications';
|
import * as Notifications from 'expo-notifications';
|
||||||
import { setVibrationEnabled } from './messageVibrationService';
|
import { setVibrationEnabled } from '../platform/messageVibrationService';
|
||||||
|
|
||||||
export const NOTIFICATION_PREF_KEYS = {
|
export const NOTIFICATION_PREF_KEYS = {
|
||||||
/** 与历史版本保持一致 */
|
/** 与历史版本保持一致 */
|
||||||
@@ -3,9 +3,9 @@
|
|||||||
* 处理系统通知、互动通知等功能
|
* 处理系统通知、互动通知等功能
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { api, PaginatedData } from './api';
|
import { api, PaginatedData } from '../core/api';
|
||||||
import { Notification, NotificationBadge, NotificationType } from '../types';
|
import { Notification, NotificationBadge, NotificationType } from '@/types';
|
||||||
import { CursorPaginationRequest, CursorPaginationResponse } from '../types/dto';
|
import { CursorPaginationRequest, CursorPaginationResponse } from '@/types/dto';
|
||||||
|
|
||||||
// 通知列表响应
|
// 通知列表响应
|
||||||
interface NotificationListResponse {
|
interface NotificationListResponse {
|
||||||
@@ -2,12 +2,12 @@
|
|||||||
* 推送服务 - 管理设备Token和推送记录
|
* 推送服务 - 管理设备Token和推送记录
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { api } from './api';
|
import { api } from '../core/api';
|
||||||
import {
|
import {
|
||||||
DeviceTokenResponse,
|
DeviceTokenResponse,
|
||||||
RegisterDeviceRequest,
|
RegisterDeviceRequest,
|
||||||
PushRecordResponse
|
PushRecordResponse
|
||||||
} from '../types/dto';
|
} from '@/types/dto';
|
||||||
|
|
||||||
// 推送服务类
|
// 推送服务类
|
||||||
class PushService {
|
class PushService {
|
||||||
@@ -6,10 +6,10 @@
|
|||||||
|
|
||||||
import * as Notifications from 'expo-notifications';
|
import * as Notifications from 'expo-notifications';
|
||||||
import { Platform, AppState, AppStateStatus } from 'react-native';
|
import { Platform, AppState, AppStateStatus } from 'react-native';
|
||||||
import type { WSChatMessage, WSNotificationMessage, WSAnnouncementMessage } from './wsService';
|
import type { WSChatMessage, WSNotificationMessage, WSAnnouncementMessage } from '../core/wsService';
|
||||||
import { extractTextFromSegments } from '../types/dto';
|
import { extractTextFromSegments } from '@/types/dto';
|
||||||
import { getNotificationPreferencesSync } from './notificationPreferences';
|
import { getNotificationPreferencesSync } from './notificationPreferences';
|
||||||
import { vibrateOnMessage } from './messageVibrationService';
|
import { vibrateOnMessage } from '../platform/messageVibrationService';
|
||||||
|
|
||||||
// 通知渠道配置
|
// 通知渠道配置
|
||||||
const CHANNEL_ID = 'default';
|
const CHANNEL_ID = 'default';
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
import { Platform, Linking, Alert } from 'react-native';
|
import { Platform, Linking, Alert } from 'react-native';
|
||||||
import Constants from 'expo-constants';
|
import Constants from 'expo-constants';
|
||||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||||
import { showConfirm } from './dialogService';
|
import { showConfirm } from '../ui/dialogService';
|
||||||
|
|
||||||
// 条件导入原生模块(仅在 Android 上可用)
|
// 条件导入原生模块(仅在 Android 上可用)
|
||||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
13
src/services/platform/index.ts
Normal file
13
src/services/platform/index.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
export { apkUpdateService, checkForAPKUpdate, manualCheckForUpdate } from './apkUpdateService';
|
||||||
|
export type { APKVersionInfo, VersionCheckResult } from './apkUpdateService';
|
||||||
|
|
||||||
|
export { scheduleService } from './scheduleService';
|
||||||
|
export type { CreateScheduleCourseRequest, SyncScheduleRequest } from './scheduleService';
|
||||||
|
|
||||||
|
export {
|
||||||
|
triggerVibration,
|
||||||
|
vibrateOnMessage,
|
||||||
|
setVibrationConfig,
|
||||||
|
getVibrationConfig,
|
||||||
|
setVibrationEnabled,
|
||||||
|
} from './messageVibrationService';
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { api } from './api';
|
import { api } from '../core/api';
|
||||||
import { Course } from '../types/schedule';
|
import { Course } from '@/types/schedule';
|
||||||
|
|
||||||
interface ScheduleCourseDTO {
|
interface ScheduleCourseDTO {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { api } from './api';
|
import { api } from '../core/api';
|
||||||
|
|
||||||
export interface ChannelItem {
|
export interface ChannelItem {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -3,9 +3,9 @@
|
|||||||
* 处理评论的增删改查、点赞等功能
|
* 处理评论的增删改查、点赞等功能
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { api, PaginatedData } from './api';
|
import { api, PaginatedData } from '../core/api';
|
||||||
import { Comment, CreateCommentInput } from '../types';
|
import { Comment, CreateCommentInput } from '@/types';
|
||||||
import { CursorPaginationRequest, CursorPaginationResponse, CommentDTO } from '../types/dto';
|
import { CursorPaginationRequest, CursorPaginationResponse, CommentDTO } from '@/types/dto';
|
||||||
|
|
||||||
// 评论列表响应
|
// 评论列表响应
|
||||||
interface CommentListResponse {
|
interface CommentListResponse {
|
||||||
15
src/services/post/index.ts
Normal file
15
src/services/post/index.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
export { postService } from './postService';
|
||||||
|
|
||||||
|
export { commentService } from './commentService';
|
||||||
|
|
||||||
|
export { voteService } from './voteService';
|
||||||
|
|
||||||
|
export { channelService } from './channelService';
|
||||||
|
export type { ChannelItem } from './channelService';
|
||||||
|
|
||||||
|
export { reportService, REPORT_REASONS } from './reportService';
|
||||||
|
export type { ReportReason, ReportTargetType, ReportResponse } from './reportService';
|
||||||
|
|
||||||
|
export { postSyncService } from './PostSyncService';
|
||||||
|
export type { PostDetailState, PostsState } from './PostSyncService';
|
||||||
|
export { mergePostListWithFastPath, mergeRefreshWindow } from './postMerge';
|
||||||
@@ -3,9 +3,9 @@
|
|||||||
* 互动操作(点赞、收藏)请使用 postSyncService
|
* 互动操作(点赞、收藏)请使用 postSyncService
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { api, PaginatedData } from './api';
|
import { api, PaginatedData } from '../core/api';
|
||||||
import { Post, CreatePostInput } from '../types';
|
import { Post, CreatePostInput } from '@/types';
|
||||||
import { CursorPaginationRequest, CursorPaginationResponse } from '../types/dto';
|
import { CursorPaginationRequest, CursorPaginationResponse } from '@/types/dto';
|
||||||
|
|
||||||
// 帖子列表响应
|
// 帖子列表响应
|
||||||
interface PostListResponse {
|
interface PostListResponse {
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
* 处理帖子、评论、消息的举报功能
|
* 处理帖子、评论、消息的举报功能
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { api } from './api';
|
import { api } from '../core/api';
|
||||||
|
|
||||||
// 举报原因类型
|
// 举报原因类型
|
||||||
export type ReportReason = 'spam' | 'inappropriate' | 'harassment' | 'misinformation' | 'other';
|
export type ReportReason = 'spam' | 'inappropriate' | 'harassment' | 'misinformation' | 'other';
|
||||||
@@ -3,8 +3,8 @@
|
|||||||
* 处理投票相关的API调用
|
* 处理投票相关的API调用
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { api } from './api';
|
import { api } from '../core/api';
|
||||||
import { Post, VoteResultDTO, CreateVotePostRequest } from '../types';
|
import { Post, VoteResultDTO, CreateVotePostRequest } from '@/types';
|
||||||
|
|
||||||
// 投票响应
|
// 投票响应
|
||||||
interface VoteResponse {
|
interface VoteResponse {
|
||||||
16
src/services/ui/index.ts
Normal file
16
src/services/ui/index.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
export {
|
||||||
|
showPrompt,
|
||||||
|
bindPromptListener,
|
||||||
|
PromptType,
|
||||||
|
PromptPayload,
|
||||||
|
} from './promptService';
|
||||||
|
|
||||||
|
export {
|
||||||
|
showDialog,
|
||||||
|
bindDialogListener,
|
||||||
|
showConfirm,
|
||||||
|
DialogPayload,
|
||||||
|
ConfirmOptions,
|
||||||
|
} from './dialogService';
|
||||||
|
|
||||||
|
export { installAlertOverride } from './alertOverride';
|
||||||
2
src/services/upload/index.ts
Normal file
2
src/services/upload/index.ts
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
export { uploadService } from './uploadService';
|
||||||
|
export type { UploadResponse } from './uploadService';
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
* 处理图片、视频等文件上传功能
|
* 处理图片、视频等文件上传功能
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { api } from './api';
|
import { api } from '../core/api';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据 URI 扩展名和 mimeType 推断正确的文件信息
|
* 根据 URI 扩展名和 mimeType 推断正确的文件信息
|
||||||
@@ -14,7 +14,7 @@ import AsyncStorage from '@react-native-async-storage/async-storage';
|
|||||||
import { create } from 'zustand';
|
import { create } from 'zustand';
|
||||||
import { User } from '../types';
|
import { User } from '../types';
|
||||||
import { authService, resolveAuthApiError, LoginRequest, RegisterRequest } from '../services';
|
import { authService, resolveAuthApiError, LoginRequest, RegisterRequest } from '../services';
|
||||||
import { wsService } from '../services/wsService';
|
import { wsService } from '@/services/core';
|
||||||
import { callStore } from './callStore';
|
import { callStore } from './callStore';
|
||||||
import { useSessionStore } from './sessionStore';
|
import { useSessionStore } from './sessionStore';
|
||||||
import {
|
import {
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import {
|
|||||||
WSCallSDPMessage,
|
WSCallSDPMessage,
|
||||||
WSCallICEMessage,
|
WSCallICEMessage,
|
||||||
WSErrorMessage,
|
WSErrorMessage,
|
||||||
} from '../services/wsService';
|
} from '@/services/core';
|
||||||
import { webrtcManager, ICEServer } from '../services/webrtc';
|
import { webrtcManager, ICEServer } from '@/services/webrtc';
|
||||||
import { getCurrentUserId } from './sessionStore';
|
import { getCurrentUserId } from './sessionStore';
|
||||||
import { useUserStore } from './userStore';
|
import { useUserStore } from './userStore';
|
||||||
import { userManager } from './userManager';
|
import { userManager } from './userManager';
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { ConversationResponse } from '../types/dto';
|
import { ConversationResponse } from '../types/dto';
|
||||||
import { messageService } from '../services/messageService';
|
import { messageService } from '@/services/message';
|
||||||
import { conversationRepository } from '@/database';
|
import { conversationRepository } from '@/database';
|
||||||
|
|
||||||
export const CONVERSATION_LIST_PAGE_SIZE = 20;
|
export const CONVERSATION_LIST_PAGE_SIZE = 20;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import type {
|
|||||||
GroupMemberResponse,
|
GroupMemberResponse,
|
||||||
GroupResponse,
|
GroupResponse,
|
||||||
} from '../../types/dto';
|
} from '../../types/dto';
|
||||||
import { groupService } from '../../services/groupService';
|
import { groupService } from '@/services/message';
|
||||||
import { groupCacheRepository, userCacheRepository } from '@/database';
|
import { groupCacheRepository, userCacheRepository } from '@/database';
|
||||||
import { useGroupManagerStore } from './groupStore';
|
import { useGroupManagerStore } from './groupStore';
|
||||||
import { createCacheEntry, isCacheExpired, DEFAULT_TTL } from '../utils/cache';
|
import { createCacheEntry, isCacheExpired, DEFAULT_TTL } from '../utils/cache';
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import {
|
|||||||
GroupMemberListResponse,
|
GroupMemberListResponse,
|
||||||
CursorPaginationRequest,
|
CursorPaginationRequest,
|
||||||
} from '../types/dto';
|
} from '../types/dto';
|
||||||
import { groupService } from '../services/groupService';
|
import { groupService } from '@/services/message';
|
||||||
import { groupCacheRepository } from '@/database';
|
import { groupCacheRepository } from '@/database';
|
||||||
|
|
||||||
export const GROUP_LIST_PAGE_SIZE = 20;
|
export const GROUP_LIST_PAGE_SIZE = 20;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { groupService } from '../services/groupService';
|
import { groupService } from '@/services/message';
|
||||||
import { CursorPaginationResponse, GroupMemberResponse } from '../types/dto';
|
import { CursorPaginationResponse, GroupMemberResponse } from '../types/dto';
|
||||||
|
|
||||||
export const GROUP_MEMBER_LIST_PAGE_SIZE = 50;
|
export const GROUP_MEMBER_LIST_PAGE_SIZE = 50;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import type { ConversationResponse } from '../../../types/dto';
|
import type { ConversationResponse } from '../../../types/dto';
|
||||||
import { messageService } from '../../../services/messageService';
|
import { messageService } from '@/services/message';
|
||||||
import { conversationRepository } from '@/database';
|
import { conversationRepository } from '@/database';
|
||||||
import type { IConversationOperations } from '../types';
|
import type { IConversationOperations } from '../types';
|
||||||
import { useMessageStore, normalizeConversationId } from '../store';
|
import { useMessageStore, normalizeConversationId } from '../store';
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import type { MessageResponse, MessageSegment, ConversationResponse } from '../../../types/dto';
|
import type { MessageResponse, MessageSegment, ConversationResponse } from '../../../types/dto';
|
||||||
import { messageService } from '../../../services/messageService';
|
import { messageService } from '@/services/message';
|
||||||
import { messageRepository } from '@/database';
|
import { messageRepository } from '@/database';
|
||||||
import type { IMessageSendService } from '../types';
|
import type { IMessageSendService } from '../types';
|
||||||
import { useMessageStore, mergeMessagesById } from '../store';
|
import { useMessageStore, mergeMessagesById } from '../store';
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import type { ConversationResponse, MessageResponse } from '../../../types/dto';
|
import type { ConversationResponse, MessageResponse } from '../../../types/dto';
|
||||||
import { messageService } from '../../../services/messageService';
|
import { messageService } from '@/services/message';
|
||||||
import { messageRepository, conversationRepository } from '@/database';
|
import { messageRepository, conversationRepository } from '@/database';
|
||||||
import { MessageMapper } from '@/data/mappers';
|
import { MessageMapper } from '@/data/mappers';
|
||||||
import {
|
import {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import type { ConversationResponse } from '../../../types/dto';
|
import type { ConversationResponse } from '../../../types/dto';
|
||||||
import { messageService } from '../../../services/messageService';
|
import { messageService } from '@/services/message';
|
||||||
import { messageRepository, conversationRepository } from '@/database';
|
import { messageRepository, conversationRepository } from '@/database';
|
||||||
import type { ReadStateRecord, IReadReceiptManager } from '../types';
|
import type { ReadStateRecord, IReadReceiptManager } from '../types';
|
||||||
import { READ_STATE_PROTECTION_DELAY } from '../constants';
|
import { READ_STATE_PROTECTION_DELAY } from '../constants';
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import type { MessageResponse, UserDTO } from '../../../types/dto';
|
import type { MessageResponse, UserDTO } from '../../../types/dto';
|
||||||
import { api } from '../../../services/api';
|
import { api } from '@/services/core';
|
||||||
import { userCacheRepository } from '@/database';
|
import { userCacheRepository } from '@/database';
|
||||||
import type { IUserCacheService } from '../types';
|
import type { IUserCacheService } from '../types';
|
||||||
|
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ import type {
|
|||||||
WSGroupRecallMessage,
|
WSGroupRecallMessage,
|
||||||
WSGroupTypingMessage,
|
WSGroupTypingMessage,
|
||||||
WSGroupNoticeMessage,
|
WSGroupNoticeMessage,
|
||||||
} from '../../../services/wsService';
|
} from '@/services/core';
|
||||||
import { wsService, GroupNoticeType } from '../../../services/wsService';
|
import { wsService, GroupNoticeType } from '@/services/core';
|
||||||
import { eventBus } from '@/core/events/EventBus';
|
import { eventBus } from '@/core/events/EventBus';
|
||||||
import { messageRepository } from '@/database';
|
import { messageRepository } from '@/database';
|
||||||
import type { MessageResponse, ConversationResponse } from '../../../types/dto';
|
import type { MessageResponse, ConversationResponse } from '../../../types/dto';
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import type { Post } from '../../types';
|
import type { Post } from '../../types';
|
||||||
import { postService } from '../../services/postService';
|
import { postService } from '@/services/post';
|
||||||
import { usePostManagerStore } from './postStore';
|
import { usePostManagerStore } from './postStore';
|
||||||
import { createCacheEntry, isCacheExpired, DEFAULT_TTL } from '../utils/cache';
|
import { createCacheEntry, isCacheExpired, DEFAULT_TTL } from '../utils/cache';
|
||||||
import { createDedupe } from '../utils/requestDedupe';
|
import { createDedupe } from '../utils/requestDedupe';
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Post } from '../types';
|
import { Post } from '../types';
|
||||||
import { postService } from '../services/postService';
|
import { postService } from '@/services/post';
|
||||||
import type { CursorPaginationRequest } from '../types/dto';
|
import type { CursorPaginationRequest } from '../types/dto';
|
||||||
|
|
||||||
export const POST_LIST_PAGE_SIZE = 20;
|
export const POST_LIST_PAGE_SIZE = 20;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import type { UserDTO } from '../../types/dto';
|
import type { UserDTO } from '../../types/dto';
|
||||||
import { authService } from '../../services/authService';
|
import { authService } from '@/services/auth';
|
||||||
import { userCacheRepository } from '@/database';
|
import { userCacheRepository } from '@/database';
|
||||||
import { useUserManagerStore } from './userStore';
|
import { useUserManagerStore } from './userStore';
|
||||||
import { createCacheEntry, isCacheExpired, DEFAULT_TTL } from '../utils/cache';
|
import { createCacheEntry, isCacheExpired, DEFAULT_TTL } from '../utils/cache';
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
import { create } from 'zustand';
|
import { create } from 'zustand';
|
||||||
import { User, Post, Notification, NotificationBadge } from '../types';
|
import { User, Post, Notification, NotificationBadge } from '../types';
|
||||||
import { PaginatedData } from '../services/api';
|
import { PaginatedData } from '@/services/core';
|
||||||
import {
|
import {
|
||||||
authService,
|
authService,
|
||||||
postService,
|
postService,
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { create } from 'zustand';
|
import { create } from 'zustand';
|
||||||
import { verificationService } from '../services/verificationService';
|
import { verificationService } from '@/services/auth';
|
||||||
import {
|
import {
|
||||||
VerificationStatusDTO,
|
VerificationStatusDTO,
|
||||||
VerificationRecordDTO,
|
VerificationRecordDTO,
|
||||||
|
|||||||
Reference in New Issue
Block a user