# API 文档

本文档详细介绍 Flash Send 的 Tauri 命令 API 和事件系统。

## Tauri 命令

所有命令通过 `@tauri-apps/api/core` 的 `invoke` 函数调用。

### 设备发现

#### start_discovery

启动设备发现服务，开始广播本机信息并监听其他设备。

```typescript
invoke('start_discovery')
```

**返回**: `Promise<void>`

---

#### stop_discovery

停止设备发现服务。

```typescript
invoke('stop_discovery')
```

**返回**: `Promise<void>`

---

#### get_online_devices

获取当前在线的设备列表。

```typescript
invoke<DeviceInfo[]>('get_online_devices')
```

**返回**: `Promise<DeviceInfo[]>`

```typescript
interface DeviceInfo {
  deviceId: string      // 设备唯一标识
  deviceName: string    // 设备名称
  ip: string            // IP 地址
  wsPort: number        // WebSocket 端口
  httpPort: number      // HTTP 端口
  lastSeen: number      // 最后在线时间戳
}
```

---

#### get_local_device

获取本机设备信息。

```typescript
invoke<DeviceInfo>('get_local_device')
```

**返回**: `Promise<DeviceInfo>`

---

### 聊天通信

#### start_ws_server

启动 WebSocket 服务端，接收其他设备的连接。

```typescript
invoke('start_ws_server')
```

**返回**: `Promise<void>`

---

#### connect_to_device

连接到指定设备的 WebSocket 服务。

```typescript
invoke('connect_to_device', { deviceId: string })
```

**参数**:
| 参数 | 类型 | 说明 |
|------|------|------|
| deviceId | string | 目标设备 ID |

**返回**: `Promise<void>`

---

#### send_chat_message

发送聊天消息。

```typescript
invoke<ChatMessage>('send_chat_message', {
  deviceId: string,
  content: string,
  messageType?: string
})
```

**参数**:
| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| deviceId | string | - | 目标设备 ID |
| content | string | - | 消息内容 |
| messageType | string | 'text' | 消息类型：text/image/file |

**返回**: `Promise<ChatMessage>`

```typescript
interface ChatMessage {
  id: string
  fromDevice: string
  toDevice: string
  content: string
  messageType: 'text' | 'image' | 'file' | 'system'
  timestamp: number
  isRead: boolean
}
```

---

#### get_chat_history

获取与指定设备的聊天历史。

```typescript
invoke<ChatMessage[]>('get_chat_history', {
  deviceId: string,
  limit?: number,
  offset?: number
})
```

**参数**:
| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| deviceId | string | - | 目标设备 ID |
| limit | number | 50 | 返回条数限制 |
| offset | number | 0 | 偏移量 |

**返回**: `Promise<ChatMessage[]>`

---

#### delete_chat_history

删除与指定设备的聊天历史。

```typescript
invoke('delete_chat_history', { deviceId: string })
```

**参数**:
| 参数 | 类型 | 说明 |
|------|------|------|
| deviceId | string | 目标设备 ID |

**返回**: `Promise<void>`

---

### 文件传输

#### start_http_server

启动 HTTPS 文件服务，接收文件上传。

```typescript
invoke('start_http_server')
```

**返回**: `Promise<void>`

---

#### select_file

打开文件选择对话框。

```typescript
invoke<FileMetadata | null>('select_file')
```

**返回**: `Promise<FileMetadata | null>`

```typescript
interface FileMetadata {
  name: string      // 文件名
  path: string      // 文件完整路径
  size: number      // 文件大小（字节）
  mimeType?: string // MIME 类型
}
```

---

#### send_file

发送文件到指定设备。

```typescript
invoke<FileTransfer>('send_file', {
  deviceId: string,
  fileId: string,
  filePath: string
})
```

**参数**:
| 参数 | 类型 | 说明 |
|------|------|------|
| deviceId | string | 目标设备 ID |
| fileId | string | 文件传输 ID（UUID） |
| filePath | string | 本地文件路径 |

**返回**: `Promise<FileTransfer>`

```typescript
interface FileTransfer {
  fileId: string
  name: string
  size: number
  progress: number           // 0.0 - 1.0
  status: TransferStatus
  mimeType?: string
  fromDevice: string
  toDevice: string
  localPath?: string
  createdAt: number
  completedAt?: number
  transferredBytes: number
}

type TransferStatus = 'pending' | 'transferring' | 'completed' | 'failed' | 'cancelled'
```

---

#### cancel_transfer

取消文件传输。

```typescript
invoke('cancel_transfer', { fileId: string })
```

**参数**:
| 参数 | 类型 | 说明 |
|------|------|------|
| fileId | string | 传输 ID |

**返回**: `Promise<void>`

---

#### get_transfer_history

获取与指定设备的文件传输历史。

```typescript
invoke<FileTransfer[]>('get_transfer_history', {
  deviceId: string,
  limit?: number
})
```

**参数**:
| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| deviceId | string | - | 目标设备 ID |
| limit | number | 50 | 返回条数限制 |

**返回**: `Promise<FileTransfer[]>`

---

#### open_file_location

在系统文件管理器中打开文件所在位置。

```typescript
invoke('open_file_location', { path: string })
```

**参数**:
| 参数 | 类型 | 说明 |
|------|------|------|
| path | string | 文件路径 |

**返回**: `Promise<void>`

**平台行为**:
- **Windows**: `explorer /select, <path>`
- **macOS**: `open -R <path>`
- **Linux**: `xdg-open <dir>`

---

### 配置管理

#### get_app_config

获取应用配置。

```typescript
invoke<AppConfig>('get_app_config')
```

**返回**: `Promise<AppConfig>`

```typescript
interface AppConfig {
  deviceId: string      // 本机设备 ID
  deviceName: string    // 设备名称
  downloadDir: string   // 下载目录
  wsPort: number        // WebSocket 端口
  httpPort: number      // HTTP 端口
}
```

---

#### update_device_name

更新设备名称。

```typescript
invoke('update_device_name', { name: string })
```

**参数**:
| 参数 | 类型 | 说明 |
|------|------|------|
| name | string | 新的设备名称 |

**返回**: `Promise<void>`

---

#### update_download_dir

更新文件下载目录。

```typescript
invoke('update_download_dir', { path: string })
```

**参数**:
| 参数 | 类型 | 说明 |
|------|------|------|
| path | string | 新的下载目录路径 |

**返回**: `Promise<void>`

---

## 事件系统

通过 `@tauri-apps/api/event` 的 `listen` 函数监听后端事件。

### device:found

发现新设备时触发。

```typescript
import { listen } from '@tauri-apps/api/event'

listen<DeviceInfo>('device:found', (event) => {
  console.log('发现设备:', event.payload)
})
```

**Payload**: `DeviceInfo`

---

### device:lost

设备离线时触发。

```typescript
listen<string>('device:lost', (event) => {
  console.log('设备离线:', event.payload)  // device_id
})
```

**Payload**: `string` (device_id)

---

### chat:message

收到聊天消息时触发。

```typescript
listen<ChatMessage>('chat:message', (event) => {
  console.log('收到消息:', event.payload)
})
```

**Payload**: `ChatMessage`

---

### file:progress

文件传输进度更新时触发。

```typescript
listen<TransferProgressEvent>('file:progress', (event) => {
  console.log('传输进度:', event.payload)
})
```

**Payload**: `TransferProgressEvent`

```typescript
interface TransferProgressEvent {
  fileId: string           // 传输 ID
  progress: number         // 进度 0.0 - 1.0
  transferredBytes: number // 已传输字节数
  totalBytes: number       // 总字节数
  status: TransferStatus   // 传输状态
  fileName?: string        // 文件名（接收方）
  localPath?: string       // 本地路径（接收方）
}
```

---

## 错误处理

所有命令在出错时会抛出 `CommandError`：

```typescript
interface CommandError {
  code: string     // 错误代码
  message: string  // 错误信息
}
```

**常见错误代码**:

| 代码 | 说明 |
|------|------|
| `DB_ERROR` | 数据库操作错误 |
| `IO_ERROR` | 文件 IO 错误 |
| `WS_ERROR` | WebSocket 错误 |
| `DEVICE_NOT_FOUND` | 设备不存在 |
| `NOT_CONNECTED` | 未建立连接 |
| `TRANSFER_ERROR` | 传输错误 |

**使用示例**：

```typescript
try {
  await invoke('send_chat_message', { deviceId, content })
} catch (error) {
  const err = error as CommandError
  if (err.code === 'NOT_CONNECTED') {
    // 尝试重新连接
    await invoke('connect_to_device', { deviceId })
  }
}
```

---

## 完整示例

### 设备发现与聊天

```typescript
import { invoke } from '@tauri-apps/api/core'
import { listen } from '@tauri-apps/api/event'

// 1. 监听设备发现事件
const unlistenDevice = await listen<DeviceInfo>('device:found', (event) => {
  console.log('发现设备:', event.payload.deviceName)
})

// 2. 监听消息事件
const unlistenMessage = await listen<ChatMessage>('chat:message', (event) => {
  console.log('收到消息:', event.payload.content)
})

// 3. 启动服务
await invoke('start_ws_server')
await invoke('start_discovery')

// 4. 获取在线设备
const devices = await invoke<DeviceInfo[]>('get_online_devices')

// 5. 连接设备并发送消息
if (devices.length > 0) {
  const device = devices[0]
  await invoke('connect_to_device', { deviceId: device.deviceId })
  await invoke('send_chat_message', {
    deviceId: device.deviceId,
    content: 'Hello!'
  })
}

// 清理
unlistenDevice()
unlistenMessage()
await invoke('stop_discovery')
```

### 文件传输

```typescript
import { invoke } from '@tauri-apps/api/core'
import { listen } from '@tauri-apps/api/event'

// 1. 监听传输进度
const unlisten = await listen<TransferProgressEvent>('file:progress', (event) => {
  const { fileId, progress, status } = event.payload
  console.log(`${fileId}: ${(progress * 100).toFixed(1)}% - ${status}`)
})

// 2. 启动文件服务
await invoke('start_http_server')

// 3. 选择文件
const file = await invoke<FileMetadata | null>('select_file')
if (!file) return

// 4. 发送文件
const fileId = crypto.randomUUID()
const transfer = await invoke<FileTransfer>('send_file', {
  deviceId: targetDeviceId,
  fileId,
  filePath: file.path
})

console.log('开始传输:', transfer.name)

// 清理
unlisten()
```
