mirror of
https://github.com/MatrixSeven/file-transfer-go.git
synced 2026-02-21 06:05:48 +08:00
feat添加切换tab提示
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useSearchParams } from 'next/navigation';
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
||||
import { Upload, MessageSquare, Monitor, Users } from 'lucide-react';
|
||||
import Hero from '@/components/Hero';
|
||||
@@ -10,12 +9,20 @@ import { WebRTCTextImageTransfer } from '@/components/WebRTCTextImageTransfer';
|
||||
import DesktopShare from '@/components/DesktopShare';
|
||||
import WeChatGroup from '@/components/WeChatGroup';
|
||||
import { WebRTCUnsupportedModal } from '@/components/WebRTCUnsupportedModal';
|
||||
import { ConfirmDialog } from '@/components/ui/confirm-dialog';
|
||||
import { useWebRTCSupport } from '@/hooks/connection';
|
||||
import { useTabNavigation, TabType } from '@/hooks/ui';
|
||||
|
||||
export default function HomePage() {
|
||||
const searchParams = useSearchParams();
|
||||
const [activeTab, setActiveTab] = useState('webrtc');
|
||||
const [hasInitialized, setHasInitialized] = useState(false);
|
||||
// 使用tab导航hook
|
||||
const {
|
||||
activeTab,
|
||||
handleTabChange,
|
||||
getConnectionInfo,
|
||||
hasInitialized,
|
||||
confirmDialogState,
|
||||
closeConfirmDialog
|
||||
} = useTabNavigation();
|
||||
|
||||
// WebRTC 支持检测
|
||||
const {
|
||||
@@ -26,34 +33,25 @@ export default function HomePage() {
|
||||
closeUnsupportedModal,
|
||||
showUnsupportedModalManually,
|
||||
} = useWebRTCSupport();
|
||||
|
||||
// 根据URL参数设置初始标签(仅首次加载时)
|
||||
useEffect(() => {
|
||||
if (!hasInitialized) {
|
||||
const urlType = searchParams.get('type');
|
||||
|
||||
console.log('=== HomePage URL处理 ===');
|
||||
console.log('URL type参数:', urlType);
|
||||
console.log('所有搜索参数:', Object.fromEntries(searchParams.entries()));
|
||||
|
||||
// 将旧的text类型重定向到message
|
||||
if (urlType === 'text') {
|
||||
console.log('检测到text类型,重定向到message标签页');
|
||||
setActiveTab('message');
|
||||
} else if (urlType === 'webrtc') {
|
||||
// webrtc类型对应文件传输标签页
|
||||
console.log('检测到webrtc类型,切换到webrtc标签页(文件传输)');
|
||||
setActiveTab('webrtc');
|
||||
} else if (urlType && ['message', 'desktop'].includes(urlType)) {
|
||||
console.log('切换到对应标签页:', urlType);
|
||||
setActiveTab(urlType);
|
||||
} else {
|
||||
console.log('没有有效的type参数,使用默认标签页:webrtc(文件传输)');
|
||||
}
|
||||
|
||||
setHasInitialized(true);
|
||||
}
|
||||
}, [searchParams, hasInitialized]);
|
||||
|
||||
// 桌面共享功能的占位符函数(保持向后兼容)
|
||||
const handleStartSharing = async () => {
|
||||
console.log('开始桌面共享');
|
||||
};
|
||||
|
||||
const handleStopSharing = async () => {
|
||||
console.log('停止桌面共享');
|
||||
};
|
||||
|
||||
const handleJoinSharing = async (code: string) => {
|
||||
console.log('加入桌面共享:', code);
|
||||
};
|
||||
|
||||
// 处理Tabs组件的字符串参数
|
||||
const handleTabChangeWrapper = (value: string) => {
|
||||
// 类型转换并调用实际的处理函数
|
||||
handleTabChange(value as TabType);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-gradient-to-br from-slate-50 to-blue-50">
|
||||
@@ -97,7 +95,7 @@ export default function HomePage() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
<Tabs value={activeTab} onValueChange={setActiveTab} className="w-full">
|
||||
<Tabs value={activeTab} onValueChange={handleTabChangeWrapper} className="w-full">
|
||||
{/* Tabs Navigation - 横向布局 */}
|
||||
<div className="mb-6">
|
||||
<TabsList className="grid w-full grid-cols-4 max-w-2xl mx-auto h-auto bg-white/90 backdrop-blur-sm shadow-lg rounded-xl p-2 border border-slate-200">
|
||||
@@ -180,6 +178,20 @@ export default function HomePage() {
|
||||
webrtcSupport={webrtcSupport}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* 自定义确认对话框 */}
|
||||
{confirmDialogState && (
|
||||
<ConfirmDialog
|
||||
isOpen={confirmDialogState.isOpen}
|
||||
onClose={closeConfirmDialog}
|
||||
onConfirm={confirmDialogState.onConfirm}
|
||||
title={confirmDialogState.title}
|
||||
message={confirmDialogState.message}
|
||||
confirmText={confirmDialogState.confirmText}
|
||||
cancelText={confirmDialogState.cancelText}
|
||||
type={confirmDialogState.type}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
106
chuan-next/src/components/ui/confirm-dialog.tsx
Normal file
106
chuan-next/src/components/ui/confirm-dialog.tsx
Normal file
@@ -0,0 +1,106 @@
|
||||
"use client";
|
||||
|
||||
import React from 'react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { AlertTriangle, Wifi, WifiOff } from 'lucide-react';
|
||||
|
||||
interface ConfirmDialogProps {
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
onConfirm: () => void;
|
||||
title: string;
|
||||
message: string;
|
||||
confirmText?: string;
|
||||
cancelText?: string;
|
||||
type?: 'warning' | 'danger' | 'info';
|
||||
}
|
||||
|
||||
export function ConfirmDialog({
|
||||
isOpen,
|
||||
onClose,
|
||||
onConfirm,
|
||||
title,
|
||||
message,
|
||||
confirmText = '确认',
|
||||
cancelText = '取消',
|
||||
type = 'warning'
|
||||
}: ConfirmDialogProps) {
|
||||
const handleConfirm = () => {
|
||||
onConfirm();
|
||||
onClose();
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
onClose();
|
||||
};
|
||||
|
||||
const getIcon = () => {
|
||||
switch (type) {
|
||||
case 'danger':
|
||||
return <WifiOff className="w-6 h-6 text-red-500" />;
|
||||
case 'warning':
|
||||
return <AlertTriangle className="w-6 h-6 text-yellow-500" />;
|
||||
case 'info':
|
||||
return <Wifi className="w-6 h-6 text-blue-500" />;
|
||||
default:
|
||||
return <AlertTriangle className="w-6 h-6 text-yellow-500" />;
|
||||
}
|
||||
};
|
||||
|
||||
const getButtonStyles = () => {
|
||||
switch (type) {
|
||||
case 'danger':
|
||||
return 'bg-gradient-to-r from-red-500 to-red-600 hover:from-red-600 hover:to-red-700';
|
||||
case 'warning':
|
||||
return 'bg-gradient-to-r from-yellow-500 to-orange-500 hover:from-yellow-600 hover:to-orange-600';
|
||||
case 'info':
|
||||
return 'bg-gradient-to-r from-blue-500 to-indigo-500 hover:from-blue-600 hover:to-indigo-600';
|
||||
default:
|
||||
return 'bg-gradient-to-r from-yellow-500 to-orange-500 hover:from-yellow-600 hover:to-orange-600';
|
||||
}
|
||||
};
|
||||
|
||||
if (!isOpen) return null;
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 bg-black/50 backdrop-blur-sm z-50 flex items-center justify-center p-4">
|
||||
<div className="bg-white/95 backdrop-blur-md rounded-2xl shadow-2xl border border-white/20 max-w-md w-full mx-4 animate-in zoom-in-95 duration-200">
|
||||
{/* Header */}
|
||||
<div className="flex items-center space-x-4 p-6 pb-4">
|
||||
<div className="flex-shrink-0">
|
||||
{getIcon()}
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-lg font-semibold text-slate-800">
|
||||
{title}
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Content */}
|
||||
<div className="px-6 pb-6">
|
||||
<p className="text-slate-600 leading-relaxed">
|
||||
{message}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Actions */}
|
||||
<div className="flex items-center justify-end space-x-3 px-6 pb-6">
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={handleCancel}
|
||||
className="px-6 py-2 border-slate-200 text-slate-600 hover:text-slate-800 hover:border-slate-300 rounded-lg"
|
||||
>
|
||||
{cancelText}
|
||||
</Button>
|
||||
<Button
|
||||
onClick={handleConfirm}
|
||||
className={`px-6 py-2 text-white font-medium rounded-lg shadow-lg transition-all duration-200 hover:shadow-xl ${getButtonStyles()}`}
|
||||
>
|
||||
{confirmText}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
// UI状态管理相关的hooks
|
||||
export { useURLHandler } from './useURLHandler';
|
||||
export { useWebRTCStore } from './webRTCStore';
|
||||
export { useTabNavigation } from './useTabNavigation';
|
||||
export type { TabType } from './useTabNavigation';
|
||||
|
||||
52
chuan-next/src/hooks/ui/useConfirmDialog.ts
Normal file
52
chuan-next/src/hooks/ui/useConfirmDialog.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import { useState, useCallback } from 'react';
|
||||
|
||||
export interface ConfirmDialogOptions {
|
||||
title: string;
|
||||
message: string;
|
||||
confirmText?: string;
|
||||
cancelText?: string;
|
||||
type?: 'warning' | 'danger' | 'info';
|
||||
}
|
||||
|
||||
export interface ConfirmDialogState extends ConfirmDialogOptions {
|
||||
isOpen: boolean;
|
||||
onConfirm: () => void;
|
||||
onCancel: () => void;
|
||||
}
|
||||
|
||||
export const useConfirmDialog = () => {
|
||||
const [dialogState, setDialogState] = useState<ConfirmDialogState | null>(null);
|
||||
|
||||
const showConfirmDialog = useCallback((options: ConfirmDialogOptions): Promise<boolean> => {
|
||||
return new Promise((resolve) => {
|
||||
const handleConfirm = () => {
|
||||
setDialogState(null);
|
||||
resolve(true);
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
setDialogState(null);
|
||||
resolve(false);
|
||||
};
|
||||
|
||||
setDialogState({
|
||||
...options,
|
||||
isOpen: true,
|
||||
onConfirm: handleConfirm,
|
||||
onCancel: handleCancel,
|
||||
});
|
||||
});
|
||||
}, []);
|
||||
|
||||
const closeDialog = useCallback(() => {
|
||||
if (dialogState) {
|
||||
dialogState.onCancel();
|
||||
}
|
||||
}, [dialogState]);
|
||||
|
||||
return {
|
||||
dialogState,
|
||||
showConfirmDialog,
|
||||
closeDialog,
|
||||
};
|
||||
};
|
||||
171
chuan-next/src/hooks/ui/useTabNavigation.ts
Normal file
171
chuan-next/src/hooks/ui/useTabNavigation.ts
Normal file
@@ -0,0 +1,171 @@
|
||||
import { useState, useEffect, useCallback } from 'react';
|
||||
import { useSearchParams } from 'next/navigation';
|
||||
import { useURLHandler, FeatureType } from './useURLHandler';
|
||||
import { useWebRTCStore } from './webRTCStore';
|
||||
import { useConfirmDialog } from './useConfirmDialog';
|
||||
|
||||
// Tab类型定义(包括非WebRTC功能)
|
||||
export type TabType = 'webrtc' | 'message' | 'desktop' | 'wechat';
|
||||
|
||||
// Tab显示名称
|
||||
const TAB_NAMES: Record<TabType, string> = {
|
||||
webrtc: '文件传输',
|
||||
message: '文字传输',
|
||||
desktop: '桌面共享',
|
||||
wechat: '微信群'
|
||||
};
|
||||
|
||||
// WebRTC功能的映射
|
||||
const WEBRTC_FEATURES: Record<string, FeatureType> = {
|
||||
webrtc: 'webrtc',
|
||||
message: 'message',
|
||||
desktop: 'desktop'
|
||||
};
|
||||
|
||||
export const useTabNavigation = () => {
|
||||
const searchParams = useSearchParams();
|
||||
const [activeTab, setActiveTab] = useState<TabType>('webrtc');
|
||||
const [hasInitialized, setHasInitialized] = useState(false);
|
||||
const { showConfirmDialog, dialogState, closeDialog } = useConfirmDialog();
|
||||
|
||||
// 获取WebRTC全局状态
|
||||
const {
|
||||
isConnected,
|
||||
isConnecting,
|
||||
isPeerConnected,
|
||||
currentRoom,
|
||||
reset: resetWebRTCState
|
||||
} = useWebRTCStore();
|
||||
|
||||
// 创建一个通用的URL处理器(用于断开连接)
|
||||
const { hasActiveConnection } = useURLHandler({
|
||||
featureType: 'webrtc', // 默认值,实际使用时会被覆盖
|
||||
onModeChange: () => {},
|
||||
});
|
||||
|
||||
// 根据URL参数设置初始标签(仅首次加载时)
|
||||
useEffect(() => {
|
||||
if (!hasInitialized) {
|
||||
const urlType = searchParams.get('type');
|
||||
|
||||
console.log('=== HomePage URL处理 ===');
|
||||
console.log('URL type参数:', urlType);
|
||||
console.log('所有搜索参数:', Object.fromEntries(searchParams.entries()));
|
||||
|
||||
// 将旧的text类型重定向到message
|
||||
if (urlType === 'text') {
|
||||
console.log('检测到text类型,重定向到message标签页');
|
||||
setActiveTab('message');
|
||||
} else if (urlType === 'webrtc') {
|
||||
console.log('检测到webrtc类型,切换到webrtc标签页(文件传输)');
|
||||
setActiveTab('webrtc');
|
||||
} else if (urlType && ['message', 'desktop'].includes(urlType)) {
|
||||
console.log('切换到对应标签页:', urlType);
|
||||
setActiveTab(urlType as TabType);
|
||||
} else {
|
||||
console.log('没有有效的type参数,使用默认标签页:webrtc(文件传输)');
|
||||
// 保持默认的webrtc标签
|
||||
}
|
||||
|
||||
setHasInitialized(true);
|
||||
}
|
||||
}, [searchParams, hasInitialized]);
|
||||
|
||||
// 处理tab切换
|
||||
const handleTabChange = useCallback(async (newTab: TabType) => {
|
||||
console.log('=== Tab切换 ===');
|
||||
console.log('当前tab:', activeTab, '目标tab:', newTab);
|
||||
|
||||
// 如果切换到wechat tab(非WebRTC功能),可以直接切换
|
||||
if (newTab === 'wechat') {
|
||||
// 如果有活跃连接,需要确认
|
||||
if (hasActiveConnection()) {
|
||||
const currentTabName = TAB_NAMES[activeTab];
|
||||
const confirmed = await showConfirmDialog({
|
||||
title: '切换功能确认',
|
||||
message: `切换到微信群功能需要关闭当前的${currentTabName}连接,是否继续?`,
|
||||
confirmText: '确认切换',
|
||||
cancelText: '取消',
|
||||
type: 'warning'
|
||||
});
|
||||
|
||||
if (!confirmed) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 断开连接并清除状态
|
||||
resetWebRTCState();
|
||||
console.log('已清除WebRTC连接状态,切换到微信群');
|
||||
}
|
||||
|
||||
setActiveTab(newTab);
|
||||
// 清除URL参数
|
||||
const newUrl = new URL(window.location.href);
|
||||
newUrl.search = '';
|
||||
window.history.pushState({}, '', newUrl.toString());
|
||||
return true;
|
||||
}
|
||||
|
||||
// 如果有活跃连接且切换到不同的WebRTC功能,需要确认
|
||||
if (hasActiveConnection() && newTab !== activeTab && WEBRTC_FEATURES[newTab]) {
|
||||
const currentTabName = TAB_NAMES[activeTab];
|
||||
const targetTabName = TAB_NAMES[newTab];
|
||||
|
||||
const confirmed = await showConfirmDialog({
|
||||
title: '切换功能确认',
|
||||
message: `切换到${targetTabName}功能需要关闭当前的${currentTabName}连接,是否继续?`,
|
||||
confirmText: '确认切换',
|
||||
cancelText: '取消',
|
||||
type: 'warning'
|
||||
});
|
||||
|
||||
if (!confirmed) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 用户确认后,重置WebRTC状态
|
||||
resetWebRTCState();
|
||||
console.log(`已断开${currentTabName}连接,切换到${targetTabName}`);
|
||||
}
|
||||
|
||||
// 执行tab切换
|
||||
setActiveTab(newTab);
|
||||
|
||||
// 更新URL(对于WebRTC功能)
|
||||
if (WEBRTC_FEATURES[newTab]) {
|
||||
const params = new URLSearchParams();
|
||||
params.set('type', WEBRTC_FEATURES[newTab]);
|
||||
params.set('mode', 'send'); // 默认模式
|
||||
const newUrl = `?${params.toString()}`;
|
||||
window.history.pushState({}, '', newUrl);
|
||||
} else {
|
||||
// 非WebRTC功能,清除URL参数
|
||||
const newUrl = new URL(window.location.href);
|
||||
newUrl.search = '';
|
||||
window.history.pushState({}, '', newUrl.toString());
|
||||
}
|
||||
|
||||
return true;
|
||||
}, [activeTab, hasActiveConnection, resetWebRTCState]);
|
||||
|
||||
// 获取连接状态信息
|
||||
const getConnectionInfo = useCallback(() => {
|
||||
return {
|
||||
hasConnection: hasActiveConnection(),
|
||||
currentRoom: currentRoom,
|
||||
isConnected,
|
||||
isConnecting,
|
||||
isPeerConnected
|
||||
};
|
||||
}, [hasActiveConnection, currentRoom, isConnected, isConnecting, isPeerConnected]);
|
||||
|
||||
return {
|
||||
activeTab,
|
||||
handleTabChange,
|
||||
getConnectionInfo,
|
||||
hasInitialized,
|
||||
// 导出确认对话框状态
|
||||
confirmDialogState: dialogState,
|
||||
closeConfirmDialog: closeDialog
|
||||
};
|
||||
};
|
||||
@@ -1,21 +1,24 @@
|
||||
import { useState, useEffect, useRef, useCallback } from 'react';
|
||||
import { useSearchParams, useRouter } from 'next/navigation';
|
||||
import { useToast } from '@/components/ui/toast-simple';
|
||||
import { useWebRTCStore } from './webRTCStore';
|
||||
import { useConfirmDialog } from './useConfirmDialog';
|
||||
|
||||
// 支持的功能类型
|
||||
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
|
||||
// 功能类型的显示名称
|
||||
const FEATURE_NAMES: Record<FeatureType, string> = {
|
||||
webrtc: '文件传输',
|
||||
message: '文字传输',
|
||||
desktop: '桌面共享'
|
||||
};
|
||||
|
||||
interface UseURLHandlerProps<T = string> {
|
||||
featureType: FeatureType;
|
||||
onModeChange: (mode: T) => void;
|
||||
onAutoJoinRoom?: (code: string) => void;
|
||||
onDisconnect?: () => void; // 新增:断开连接的回调
|
||||
modeConverter?: {
|
||||
// 将URL模式转换为组件内部模式
|
||||
fromURL: (urlMode: 'send' | 'receive') => T;
|
||||
@@ -28,12 +31,91 @@ export const useURLHandler = <T = 'send' | 'receive'>({
|
||||
featureType,
|
||||
onModeChange,
|
||||
onAutoJoinRoom,
|
||||
onDisconnect,
|
||||
modeConverter
|
||||
}: UseURLHandlerProps<T>) => {
|
||||
const searchParams = useSearchParams();
|
||||
const router = useRouter();
|
||||
const { showToast } = useToast();
|
||||
const { showConfirmDialog, dialogState, closeDialog } = useConfirmDialog();
|
||||
const [hasProcessedInitialUrl, setHasProcessedInitialUrl] = useState(false);
|
||||
const urlProcessedRef = useRef(false);
|
||||
|
||||
// 获取WebRTC全局状态
|
||||
const {
|
||||
isConnected,
|
||||
isConnecting,
|
||||
isPeerConnected,
|
||||
currentRoom,
|
||||
reset: resetWebRTCState
|
||||
} = useWebRTCStore();
|
||||
|
||||
// 检查是否有活跃连接
|
||||
const hasActiveConnection = useCallback(() => {
|
||||
return isConnected || isConnecting || isPeerConnected;
|
||||
}, [isConnected, isConnecting, isPeerConnected]);
|
||||
|
||||
// 功能切换确认
|
||||
const switchToFeature = useCallback(async (targetFeatureType: FeatureType, mode?: 'send' | 'receive', code?: string) => {
|
||||
// 如果是同一个功能,直接切换
|
||||
if (targetFeatureType === featureType) {
|
||||
if (mode) {
|
||||
const params = new URLSearchParams(searchParams.toString());
|
||||
params.set('type', targetFeatureType);
|
||||
params.set('mode', mode);
|
||||
if (code) {
|
||||
params.set('code', code);
|
||||
} else if (mode === 'send') {
|
||||
params.delete('code');
|
||||
}
|
||||
router.push(`?${params.toString()}`, { scroll: false });
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// 如果有活跃连接,需要确认
|
||||
if (hasActiveConnection()) {
|
||||
const currentFeatureName = FEATURE_NAMES[featureType];
|
||||
const targetFeatureName = FEATURE_NAMES[targetFeatureType];
|
||||
|
||||
const confirmed = await showConfirmDialog({
|
||||
title: '切换功能确认',
|
||||
message: `切换到${targetFeatureName}功能需要关闭当前的${currentFeatureName}连接,是否继续?`,
|
||||
confirmText: '确认切换',
|
||||
cancelText: '取消',
|
||||
type: 'warning'
|
||||
});
|
||||
|
||||
if (!confirmed) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 用户确认后,断开当前连接
|
||||
try {
|
||||
if (onDisconnect) {
|
||||
await onDisconnect();
|
||||
}
|
||||
resetWebRTCState();
|
||||
showToast(`已断开${currentFeatureName}连接`, 'info');
|
||||
} catch (error) {
|
||||
console.error('断开连接时出错:', error);
|
||||
showToast('断开连接时出错,但将继续切换功能', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
// 切换到新功能
|
||||
const params = new URLSearchParams();
|
||||
params.set('type', targetFeatureType);
|
||||
if (mode) {
|
||||
params.set('mode', mode);
|
||||
}
|
||||
if (code) {
|
||||
params.set('code', code);
|
||||
}
|
||||
|
||||
router.push(`?${params.toString()}`, { scroll: false });
|
||||
return true;
|
||||
}, [featureType, hasActiveConnection, onDisconnect, resetWebRTCState, showToast, router, searchParams, showConfirmDialog]);
|
||||
|
||||
// 从URL参数中获取初始模式(仅在首次加载时处理)
|
||||
useEffect(() => {
|
||||
@@ -118,6 +200,11 @@ export const useURLHandler = <T = 'send' | 'receive'>({
|
||||
updateMode,
|
||||
updateRoomCode,
|
||||
getCurrentRoomCode,
|
||||
clearURLParams
|
||||
clearURLParams,
|
||||
switchToFeature,
|
||||
hasActiveConnection,
|
||||
// 导出对话框状态供组件使用
|
||||
confirmDialogState: dialogState,
|
||||
closeConfirmDialog: closeDialog
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user