Files
video-tool/app/composables/useTauri.ts
2025-08-18 08:46:39 +08:00

274 lines
7.1 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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<T> {
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<T>(command: string, args?: any): Promise<T | null> {
try {
const result = await invoke<T>(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<PlayerState | null> {
const response = await safeInvoke<ApiResponse<PlayerState>>('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<boolean> {
const response = await safeInvoke<ApiResponse<void>>('disconnect_from_player')
if (response?.success) {
toast.add({
title: '已断开连接',
description: response.message || '已断开与视频播放器的连接',
color: 'warning'
})
return true
}
return false
}
/**
* 获取连接状态
*/
async function getConnectionStatus(): Promise<PlayerState | null> {
const response = await safeInvoke<ApiResponse<PlayerState>>('get_connection_status')
return response?.success && response.data ? response.data : null
}
/**
* 发送播放控制命令
*/
async function sendPlaybackCommand(command: PlaybackCommand): Promise<boolean> {
const response = await safeInvoke<ApiResponse<void>>('send_playback_command', { command })
if (response?.success) {
// 不显示成功消息,避免过多通知
return true
}
return false
}
/**
* 更新连接配置
*/
async function updateConnectionConfig(config: ConnectionConfig): Promise<boolean> {
const response = await safeInvoke<ApiResponse<void>>('update_connection_config', { config })
if (response?.success) {
toast.add({
title: '配置更新成功',
description: response.message || '连接配置已更新',
color: 'success'
})
return true
}
return false
}
/**
* 获取应用设置
*/
async function getSettings(): Promise<AppSettings | null> {
const response = await safeInvoke<ApiResponse<AppSettings>>('get_settings')
return response?.success && response.data ? response.data : null
}
/**
* 保存应用设置
*/
async function saveSettings(settings: AppSettings): Promise<boolean> {
const response = await safeInvoke<ApiResponse<void>>('save_settings', { settings })
if (response?.success) {
toast.add({
title: '设置保存成功',
description: response.message || '应用设置已保存',
color: 'success'
})
return true
}
return false
}
/**
* 选择文件
*/
async function selectFile(): Promise<string | null> {
const response = await safeInvoke<ApiResponse<string>>('select_file')
return response?.success && response.data ? response.data : null
}
/**
* 选择多个文件
*/
async function selectFiles(): Promise<string[] | null> {
const response = await safeInvoke<ApiResponse<string[]>>('select_files')
return response?.success && response.data ? response.data : null
}
/**
* 监听播放器状态更新事件
*/
async function listenPlayerStateUpdate(callback: (state: PlayerState) => void): Promise<UnlistenFn | null> {
try {
return await listen<PlayerState>('player-state-update', (event) => {
callback(event.payload)
})
} catch (error) {
console.error('监听播放器状态更新失败:', error)
return null
}
}
/**
* 监听播放命令发送事件
*/
async function listenPlaybackCommandSent(callback: (command: PlaybackCommand) => void): Promise<UnlistenFn | null> {
try {
return await listen<PlaybackCommand>('playback-command-sent', (event) => {
callback(event.payload)
})
} catch (error) {
console.error('监听播放命令发送失败:', error)
return null
}
}
/**
* 监听连接状态变化事件
*/
async function listenConnectionStatusChange(callback: (status: string) => void): Promise<UnlistenFn | null> {
try {
return await listen<string>('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,
}
}