mirror of
https://github.com/MatrixSeven/file-transfer-go.git
synced 2026-05-21 21:27:30 +08:00
feat:拆分hooks
This commit is contained in:
3
chuan-next/src/hooks/ui/index.ts
Normal file
3
chuan-next/src/hooks/ui/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
// UI状态管理相关的hooks
|
||||
export { useURLHandler } from './useURLHandler';
|
||||
export { useWebRTCStore } from './webRTCStore';
|
||||
123
chuan-next/src/hooks/ui/useURLHandler.ts
Normal file
123
chuan-next/src/hooks/ui/useURLHandler.ts
Normal file
@@ -0,0 +1,123 @@
|
||||
import { useState, useEffect, useRef, useCallback } from 'react';
|
||||
import { useSearchParams, useRouter } from 'next/navigation';
|
||||
import { useToast } from '@/components/ui/toast-simple';
|
||||
|
||||
// 支持的功能类型
|
||||
export type FeatureType = 'webrtc' | 'message' | 'desktop';
|
||||
|
||||
// 支持的模式映射
|
||||
const MODE_MAPPINGS: Record<FeatureType, { send: string; receive: string }> = {
|
||||
webrtc: { send: 'send', receive: 'receive' },
|
||||
message: { send: 'send', receive: 'receive' },
|
||||
desktop: { send: 'send', receive: 'receive' } // desktop内部可能使用 share/view,但URL统一使用send/receive
|
||||
};
|
||||
|
||||
interface UseURLHandlerProps<T = string> {
|
||||
featureType: FeatureType;
|
||||
onModeChange: (mode: T) => void;
|
||||
onAutoJoinRoom?: (code: string) => void;
|
||||
modeConverter?: {
|
||||
// 将URL模式转换为组件内部模式
|
||||
fromURL: (urlMode: 'send' | 'receive') => T;
|
||||
// 将组件内部模式转换为URL模式
|
||||
toURL: (componentMode: T) => 'send' | 'receive';
|
||||
};
|
||||
}
|
||||
|
||||
export const useURLHandler = <T = 'send' | 'receive'>({
|
||||
featureType,
|
||||
onModeChange,
|
||||
onAutoJoinRoom,
|
||||
modeConverter
|
||||
}: UseURLHandlerProps<T>) => {
|
||||
const searchParams = useSearchParams();
|
||||
const router = useRouter();
|
||||
const [hasProcessedInitialUrl, setHasProcessedInitialUrl] = useState(false);
|
||||
const urlProcessedRef = useRef(false);
|
||||
|
||||
// 从URL参数中获取初始模式(仅在首次加载时处理)
|
||||
useEffect(() => {
|
||||
// 使用 ref 确保只处理一次,避免严格模式的重复调用
|
||||
if (urlProcessedRef.current) {
|
||||
console.log('URL已处理过,跳过重复处理');
|
||||
return;
|
||||
}
|
||||
|
||||
const urlMode = searchParams.get('mode') as 'send' | 'receive';
|
||||
const type = searchParams.get('type') as FeatureType;
|
||||
const code = searchParams.get('code');
|
||||
|
||||
// 只在首次加载且URL中有对应功能类型时处理
|
||||
if (!hasProcessedInitialUrl && type === featureType && urlMode && ['send', 'receive'].includes(urlMode)) {
|
||||
console.log(`=== 处理初始URL参数 [${featureType}] ===`);
|
||||
console.log('URL模式:', urlMode, '类型:', type, '取件码:', code);
|
||||
|
||||
// 立即标记为已处理,防止重复
|
||||
urlProcessedRef.current = true;
|
||||
|
||||
// 转换模式(如果有转换器的话)
|
||||
const componentMode = modeConverter ? modeConverter.fromURL(urlMode) : urlMode as T;
|
||||
onModeChange(componentMode);
|
||||
setHasProcessedInitialUrl(true);
|
||||
|
||||
// 自动加入房间(只在receive模式且有code时)
|
||||
if (code && urlMode === 'receive' && onAutoJoinRoom) {
|
||||
console.log('URL中有取件码,自动加入房间');
|
||||
onAutoJoinRoom(code);
|
||||
}
|
||||
}
|
||||
}, [searchParams, hasProcessedInitialUrl, featureType, onModeChange, onAutoJoinRoom, modeConverter]);
|
||||
|
||||
// 更新URL参数
|
||||
const updateMode = useCallback((newMode: T) => {
|
||||
console.log(`=== 手动切换模式 [${featureType}] ===`);
|
||||
console.log('新模式:', newMode);
|
||||
|
||||
onModeChange(newMode);
|
||||
|
||||
const params = new URLSearchParams(searchParams.toString());
|
||||
params.set('type', featureType);
|
||||
|
||||
// 转换模式(如果有转换器的话)
|
||||
const urlMode = modeConverter ? modeConverter.toURL(newMode) : newMode as string;
|
||||
params.set('mode', urlMode);
|
||||
|
||||
// 如果切换到发送模式,移除code参数
|
||||
if (urlMode === 'send') {
|
||||
params.delete('code');
|
||||
}
|
||||
|
||||
router.push(`?${params.toString()}`, { scroll: false });
|
||||
}, [searchParams, router, featureType, onModeChange, modeConverter]);
|
||||
|
||||
// 更新URL中的房间代码
|
||||
const updateRoomCode = useCallback((code: string) => {
|
||||
const params = new URLSearchParams(searchParams.toString());
|
||||
params.set('type', featureType);
|
||||
params.set('code', code);
|
||||
router.push(`?${params.toString()}`, { scroll: false });
|
||||
}, [searchParams, router, featureType]);
|
||||
|
||||
// 获取当前URL中的房间代码
|
||||
const getCurrentRoomCode = useCallback(() => {
|
||||
return searchParams.get('code') || '';
|
||||
}, [searchParams]);
|
||||
|
||||
// 清除URL参数
|
||||
const clearURLParams = useCallback(() => {
|
||||
const params = new URLSearchParams(searchParams.toString());
|
||||
params.delete('type');
|
||||
params.delete('mode');
|
||||
params.delete('code');
|
||||
|
||||
const newURL = params.toString() ? `?${params.toString()}` : '/';
|
||||
router.push(newURL, { scroll: false });
|
||||
}, [searchParams, router]);
|
||||
|
||||
return {
|
||||
updateMode,
|
||||
updateRoomCode,
|
||||
getCurrentRoomCode,
|
||||
clearURLParams
|
||||
};
|
||||
};
|
||||
46
chuan-next/src/hooks/ui/webRTCStore.ts
Normal file
46
chuan-next/src/hooks/ui/webRTCStore.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import { create } from 'zustand';
|
||||
|
||||
interface WebRTCState {
|
||||
isConnected: boolean;
|
||||
isConnecting: boolean;
|
||||
isWebSocketConnected: boolean;
|
||||
isPeerConnected: boolean;
|
||||
error: string | null;
|
||||
canRetry: boolean; // 新增:是否可以重试
|
||||
currentRoom: { code: string; role: 'sender' | 'receiver' } | null;
|
||||
}
|
||||
|
||||
interface WebRTCStore extends WebRTCState {
|
||||
updateState: (updates: Partial<WebRTCState>) => void;
|
||||
setCurrentRoom: (room: { code: string; role: 'sender' | 'receiver' } | null) => void;
|
||||
reset: () => void;
|
||||
resetToInitial: () => void; // 新增:完全重置到初始状态
|
||||
}
|
||||
|
||||
const initialState: WebRTCState = {
|
||||
isConnected: false,
|
||||
isConnecting: false,
|
||||
isWebSocketConnected: false,
|
||||
isPeerConnected: false,
|
||||
error: null,
|
||||
canRetry: false, // 初始状态下不需要重试
|
||||
currentRoom: null,
|
||||
};
|
||||
|
||||
export const useWebRTCStore = create<WebRTCStore>((set) => ({
|
||||
...initialState,
|
||||
|
||||
updateState: (updates) => set((state) => ({
|
||||
...state,
|
||||
...updates,
|
||||
})),
|
||||
|
||||
setCurrentRoom: (room) => set((state) => ({
|
||||
...state,
|
||||
currentRoom: room,
|
||||
})),
|
||||
|
||||
reset: () => set(initialState),
|
||||
|
||||
resetToInitial: () => set(initialState), // 完全重置到初始状态
|
||||
}));
|
||||
Reference in New Issue
Block a user