diff --git a/app/composables/useTauri.ts b/app/composables/useTauri.ts new file mode 100644 index 0000000..de08d8e --- /dev/null +++ b/app/composables/useTauri.ts @@ -0,0 +1,273 @@ +import { invoke } from '@tauri-apps/api/core' +import { listen, type UnlistenFn } from '@tauri-apps/api/event' + +// 类型定义,对应 Rust 端的结构 +export interface ConnectionConfig { + host: string + port: number + timeout: number + autoReconnect: boolean + reconnectInterval: number +} + +export interface VideoInfo { + path: string + title: string + duration?: number + size?: number + format?: string +} + +export interface PlayerState { + connectionStatus: 'connected' | 'connecting' | 'disconnected' | { error: string } + playbackStatus: 'playing' | 'paused' | 'stopped' | 'loading' + currentVideo?: VideoInfo + position: number + duration: number + volume: number + isLooping: boolean + isFullscreen: boolean + playlist: VideoInfo[] + currentPlaylistIndex?: number +} + +export interface ApiResponse { + success: boolean + data?: T + message?: string + error?: string +} + +export type PlaybackCommand = + | 'play' + | 'pause' + | 'stop' + | { seek: { position: number } } + | { setVolume: { volume: number } } + | { setLoop: { enabled: boolean } } + | 'toggleFullscreen' + | { loadVideo: { path: string } } + | { setPlaylist: { videos: string[] } } + | { playFromPlaylist: { index: number } } + +export interface AppSettings { + connection: ConnectionConfig + defaultVolume: number + defaultLoop: boolean + autoFullscreen: boolean + playbackEndBehavior: 'stop' | 'next' | 'repeat' + theme: string + language: string + showNotifications: boolean + debugMode: boolean + cacheSize: number + proxy?: string +} + +/** + * Tauri API composable + * 提供与 Tauri 后端通信的方法 + */ +export function useTauri() { + const toast = useToast() + + /** + * 安全地调用 Tauri API + */ + async function safeInvoke(command: string, args?: any): Promise { + try { + const result = await invoke(command, args) + return result + } catch (error) { + console.error(`Tauri invoke error (${command}):`, error) + toast.add({ + title: '操作失败', + description: `调用 ${command} 失败: ${error}`, + color: 'error' + }) + return null + } + } + + /** + * 连接到视频播放器 + */ + async function connectToPlayer(config: ConnectionConfig): Promise { + const response = await safeInvoke>('connect_to_player', { config }) + if (response?.success && response.data) { + toast.add({ + title: '连接成功', + description: response.message || '已成功连接到视频播放器', + color: 'success' + }) + return response.data + } + const host = config?.host || '127.0.0.1' + const port = config?.port || 6666 + const reason = response?.error || '无法连接到视频播放器,请检查地址与端口是否正确,以及播放器是否已启动' + toast.add({ + title: '连接失败', + description: `${reason}(目标:${host}:${port})`, + color: 'error' + }) + return null + } + + /** + * 断开与视频播放器的连接 + */ + async function disconnectFromPlayer(): Promise { + const response = await safeInvoke>('disconnect_from_player') + if (response?.success) { + toast.add({ + title: '已断开连接', + description: response.message || '已断开与视频播放器的连接', + color: 'warning' + }) + return true + } + return false + } + + /** + * 获取连接状态 + */ + async function getConnectionStatus(): Promise { + const response = await safeInvoke>('get_connection_status') + return response?.success && response.data ? response.data : null + } + + /** + * 发送播放控制命令 + */ + async function sendPlaybackCommand(command: PlaybackCommand): Promise { + const response = await safeInvoke>('send_playback_command', { command }) + if (response?.success) { + // 不显示成功消息,避免过多通知 + return true + } + return false + } + + /** + * 更新连接配置 + */ + async function updateConnectionConfig(config: ConnectionConfig): Promise { + const response = await safeInvoke>('update_connection_config', { config }) + if (response?.success) { + toast.add({ + title: '配置更新成功', + description: response.message || '连接配置已更新', + color: 'success' + }) + return true + } + return false + } + + /** + * 获取应用设置 + */ + async function getSettings(): Promise { + const response = await safeInvoke>('get_settings') + return response?.success && response.data ? response.data : null + } + + /** + * 保存应用设置 + */ + async function saveSettings(settings: AppSettings): Promise { + const response = await safeInvoke>('save_settings', { settings }) + if (response?.success) { + toast.add({ + title: '设置保存成功', + description: response.message || '应用设置已保存', + color: 'success' + }) + return true + } + return false + } + + /** + * 选择文件 + */ + async function selectFile(): Promise { + const response = await safeInvoke>('select_file') + return response?.success && response.data ? response.data : null + } + + /** + * 选择多个文件 + */ + async function selectFiles(): Promise { + const response = await safeInvoke>('select_files') + return response?.success && response.data ? response.data : null + } + + /** + * 监听播放器状态更新事件 + */ + async function listenPlayerStateUpdate(callback: (state: PlayerState) => void): Promise { + try { + return await listen('player-state-update', (event) => { + callback(event.payload) + }) + } catch (error) { + console.error('监听播放器状态更新失败:', error) + return null + } + } + + /** + * 监听播放命令发送事件 + */ + async function listenPlaybackCommandSent(callback: (command: PlaybackCommand) => void): Promise { + try { + return await listen('playback-command-sent', (event) => { + callback(event.payload) + }) + } catch (error) { + console.error('监听播放命令发送失败:', error) + return null + } + } + + /** + * 监听连接状态变化事件 + */ + async function listenConnectionStatusChange(callback: (status: string) => void): Promise { + try { + return await listen('connection-status-change', (event) => { + callback(event.payload) + }) + } catch (error) { + console.error('监听连接状态变化失败:', error) + return null + } + } + + return { + // 连接管理 + connectToPlayer, + disconnectFromPlayer, + getConnectionStatus, + updateConnectionConfig, + + // 播放控制 + sendPlaybackCommand, + + // 设置管理 + getSettings, + saveSettings, + + // 文件操作 + selectFile, + selectFiles, + + // 事件监听 + listenPlayerStateUpdate, + listenPlaybackCommandSent, + listenConnectionStatusChange, + } +} diff --git a/app/pages/index.vue b/app/pages/index.vue index 2934361..fcb8d95 100644 --- a/app/pages/index.vue +++ b/app/pages/index.vue @@ -157,6 +157,9 @@