Skip to content

feat: 跨平台 Tauri 2 重写(macOS + Windows)#8

Merged
appergb merged 1 commit into
mainfrom
all-platform
Apr 29, 2026
Merged

feat: 跨平台 Tauri 2 重写(macOS + Windows)#8
appergb merged 1 commit into
mainfrom
all-platform

Conversation

@appergb
Copy link
Copy Markdown
Collaborator

@appergb appergb commented Apr 29, 2026

Summary

把 OpenLess 从 macOS-only Swift 应用整体重写成跨平台 Tauri 2 (Rust + React + TS) 应用。老 Swift 代码原样保留在 Sources/,不删不改,不会破坏现有 Sparkle 发版链路。

新代码全部落在 openless -all/app/,与老项目目录平级。

What's in this PR

新增模块

  • openless -all/app/src/(React + TS UI,严格按 design_handoff_openless 高保真原型 + Swift CapsuleView 实现)
  • openless -all/app/src-tauri/(Rust 后端,8 模块一一对应 Swift 库):
    • hotkey — macOS CGEventTap 原生 FFI / 其他 rdev;自动重试,Accessibility 一授权立即接管(无需重启 App)
    • recorder — cpal 16kHz Int16 PCM
    • asr — Volcengine SAUC bigmodel WebSocket(二进制帧 + 热词 context)
    • polish — OpenAI 兼容 Chat Completions(中文 prompt 一字不改自 Swift PolishPrompts.swift)
    • insertion — macOS CGEventPost 原生 FFI 模拟 Cmd+V / 其他 enigo
    • persistence~/.openless/credentials.json v1 schema(同 Swift,不走 Keychain避免 ad-hoc 签名换 hash 反复弹框)
    • coordinator — 状态机 + emit capsule:state 给胶囊窗
    • permissionsAVAudioApplication.recordPermission(同 Swift,与 cpal/AVAudioEngine 共享权限轨道)
  • .github/workflows/release-tauri.yml — 推 v*-tauri tag 触发 macOS + Windows matrix 构建,自动 GitHub Release

关键 bug 与避坑(都已写到 commit message + 代码注释)

  • rdev / enigo 在 macOS 14+ 必崩 — 它们内部同步调 TSM,后台线程会撞 dispatch_assert_queue_fail。两条路径都已用原生 CGEventTap / CGEventPost FFI 替代
  • Keychain 反复弹框 — ad-hoc 签名每次 build hash 变 → ACL 失效 → 逐账号弹。改用 JSON 文件 vault(与 Swift dev 路径一致)
  • AVCaptureDevice vs AVAudioApplication 是两个独立权限轨道 — cpal/AVAudioEngine 走的是 audio 录音权限,不是 capture session 权限。用错 API 会显示假"未授权"
  • cpal build_input_stream 不会触发 macOS 麦克风弹框 — 必须 .play() 才查 TCC

Windows 路径修复

  • credentials_path() 之前硬编码 \$HOME,Windows 没这个变量;改成 %APPDATA%\OpenLess\credentials.json
  • log_dir_path() Windows 之前落到 temp_dir()(重启清空),改成 %LOCALAPPDATA%\OpenLess\Logs

已知限制

  • macOS dmg / Windows msi/exe 都是无证书,Gatekeeper / SmartScreen 第一次都会警告
  • 没接 Tauri Updater(需要签名密钥),用户只能手动去 Release 页下载新版
  • 没在真 Windows 机上跑过,只做了代码层 cfg 分支审计;Actions matrix 出结果才能真验证 Windows 链路

Test plan

  • macOS arm64 本地构建通过(scripts/build-mac.sh)
  • cargo check on macOS target 干净
  • Onboarding 权限引导 + Accessibility 自动接管验证通过
  • 端到端语音输入链路验证(录音 → ASR → polish → 插入光标)
  • 凭据 JSON 文件读写无 Keychain 弹框
  • Windows 真机验证(等 Actions 出结果)
  • tag v1.1.0-tauri 触发完整 release 流程

How to release

merge 这个 PR 之后:
```bash
git checkout main && git pull
git tag v1.1.0-tauri
git push origin v1.1.0-tauri
```
GitHub Actions 5-10 分钟后会在 Releases 页放上 .dmg + .msi + .exe。

🤖 Generated with Claude Code

整套新代码放在 openless-all/ 目录下,与原 Swift 项目并行不冲突。

代码结构:
- openless -all/app/src/             React + TS UI(参考 design_handoff_openless 实现)
- openless -all/app/src-tauri/       Rust 后端(8 模块,与 Swift 库一一对应)
- openless -all/app/scripts/         构建脚本(macOS Info.plist 后注入 + ad-hoc 重签)
- .github/workflows/release-tauri.yml  推 v*-tauri tag 触发 macOS+Windows 矩阵构建

后端模块:
- hotkey:   macOS CGEventTap 原生 FFI / 其他 rdev;自动重试,Accessibility 一授权立即接管
- recorder: cpal 16kHz Int16 PCM
- asr:      Volcengine SAUC bigmodel WebSocket(二进制帧 + 热词 context 注入)
- polish:   OpenAI 兼容 Chat Completions(中文 prompt 一字不改自 Swift)
- insertion: macOS CGEventPost 原生 FFI 模拟 Cmd+V / 其他 enigo;不再用 enigo on macOS(TSM 主线程断言坑)
- persistence: ~/.openless/credentials.json v1 schema(同 Swift dev 路径,不走 Keychain 避免 ad-hoc 签名换 hash 反复弹框)
- coordinator: 状态机(idle/listening/processing),emit capsule:state 给胶囊窗口
- permissions: AVAudioApplication.recordPermission(同 Swift,与 cpal/AVAudioEngine 共享权限轨道)

UI:
- FloatingShell 主窗 + 5 tab(概览/历史/词汇表/风格/设置)
- Capsule 浮动胶囊(176×42 浅色磨砂 + 5 根 audio bars envelope,与 Swift CapsuleView 同源)
- 菜单栏托盘(LSUIElement = true,无 Dock 图标,关红按钮 = 隐藏)
- Onboarding 首次运行权限引导(辅助功能 + 麦克风)

跨平台已知限制:
- macOS:ad-hoc 签名,首次启动需要"右键 → 打开"或在 Gatekeeper 弹窗里点"仍要打开"
- Windows:无证书,SmartScreen 会警告
Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @appergb, your pull request is larger than the review limit of 150000 diff characters

@appergb appergb merged commit 4475a6d into main Apr 29, 2026
1 check passed
@appergb appergb deleted the all-platform branch April 30, 2026 03:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant