Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ jobs:
runs-on: windows-latest
defaults:
run:
working-directory: openless -all/app
working-directory: openless-all/app
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: "22"
cache: npm
cache-dependency-path: openless -all/app/package-lock.json
cache-dependency-path: openless-all/app/package-lock.json

- uses: dtolnay/rust-toolchain@stable

Expand Down
30 changes: 15 additions & 15 deletions .github/workflows/release-tauri.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ jobs:
with:
node-version: 20
cache: npm
cache-dependency-path: 'openless -all/app/package-lock.json'
cache-dependency-path: 'openless-all/app/package-lock.json'

- uses: dtolnay/rust-toolchain@stable
with:
Expand All @@ -44,7 +44,7 @@ jobs:
- name: Cache Cargo
uses: swatinem/rust-cache@v2
with:
workspaces: 'openless -all/app/src-tauri -> target'
workspaces: 'openless-all/app/src-tauri -> target'

- name: Install Linux bundle deps
if: matrix.platform == 'ubuntu-22.04'
Expand All @@ -66,17 +66,17 @@ jobs:
wget

- name: Install npm deps
working-directory: 'openless -all/app'
working-directory: 'openless-all/app'
run: npm ci

- name: Build (Windows)
if: matrix.platform == 'windows-latest'
working-directory: 'openless -all/app'
working-directory: 'openless-all/app'
run: npm run tauri build

- name: Build (Linux)
if: matrix.platform == 'ubuntu-22.04'
working-directory: 'openless -all/app'
working-directory: 'openless-all/app'
run: npm run tauri -- build --bundles deb,rpm,appimage

- name: Upload Windows artifacts
Expand All @@ -85,8 +85,8 @@ jobs:
with:
name: openless-windows-x64
path: |
openless -all/app/src-tauri/target/release/bundle/nsis/*.exe
openless -all/app/src-tauri/target/release/bundle/msi/*.msi
openless-all/app/src-tauri/target/release/bundle/nsis/*.exe
openless-all/app/src-tauri/target/release/bundle/msi/*.msi
if-no-files-found: error

- name: Upload Linux artifacts
Expand All @@ -95,9 +95,9 @@ jobs:
with:
name: openless-linux-x64
path: |
openless -all/app/src-tauri/target/release/bundle/deb/*.deb
openless -all/app/src-tauri/target/release/bundle/rpm/*.rpm
openless -all/app/src-tauri/target/release/bundle/appimage/*.AppImage
openless-all/app/src-tauri/target/release/bundle/deb/*.deb
openless-all/app/src-tauri/target/release/bundle/rpm/*.rpm
openless-all/app/src-tauri/target/release/bundle/appimage/*.AppImage
if-no-files-found: error

# ── tag 推送时上传到 GitHub Release(macOS DMG 由本地手动上传)──
Expand All @@ -111,8 +111,8 @@ jobs:
prerelease: false
generate_release_notes: true
files: |
openless -all/app/src-tauri/target/release/bundle/nsis/*.exe
openless -all/app/src-tauri/target/release/bundle/msi/*.msi
openless -all/app/src-tauri/target/release/bundle/deb/*.deb
openless -all/app/src-tauri/target/release/bundle/rpm/*.rpm
openless -all/app/src-tauri/target/release/bundle/appimage/*.AppImage
openless-all/app/src-tauri/target/release/bundle/nsis/*.exe
openless-all/app/src-tauri/target/release/bundle/msi/*.msi
openless-all/app/src-tauri/target/release/bundle/deb/*.deb
openless-all/app/src-tauri/target/release/bundle/rpm/*.rpm
openless-all/app/src-tauri/target/release/bundle/appimage/*.AppImage
22 changes: 11 additions & 11 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,16 @@ The repository contains **two parallel implementations** of the same product:
| Path | Stack | Status |
| --- | --- | --- |
| `Sources/`, `Tests/`, `Package.swift`, `scripts/`, `appcast.xml` | SwiftPM macOS-only (macOS 15+, Swift 5.9) | Legacy. Still ships Sparkle updates for `v*` tags so old users keep auto-updating. |
| `openless -all/app/` (note the space) | Tauri 2 + Rust backend + React/TS frontend, macOS 12+ and Windows | **Active**. All current development happens here. |
| `openless-all/app/` (no space) | Tauri 2 + Rust backend + React/TS frontend, macOS 12+ and Windows | **Active**. All current development happens here. |

The Tauri port is a faithful module-for-module rewrite of the Swift app. **The Swift original is the behavior authority — when Rust and TS disagree, Swift wins.** When porting, open the Rust file and the matching `Sources/OpenLess<X>/...` Swift file side by side. UI must match `openless -all/design_handoff_openless/*.jsx` pixel-for-pixel; the JSX is reference-only, never imported.
The Tauri port is a faithful module-for-module rewrite of the Swift app. **The Swift original is the behavior authority — when Rust and TS disagree, Swift wins.** When porting, open the Rust file and the matching `Sources/OpenLess<X>/...` Swift file side by side. UI must match `openless-all/design_handoff_openless/*.jsx` pixel-for-pixel; the JSX is reference-only, never imported.

## Build, Run, Test

### Tauri (current — start here)

```bash
cd "openless -all/app"
cd "openless-all/app"
npm ci

# Dev: vite at :1420 + tauri shell
Expand Down Expand Up @@ -49,8 +49,8 @@ cargo check --manifest-path src-tauri/Cargo.toml
```

Generated artifacts:
- `openless -all/app/src-tauri/target/release/bundle/macos/OpenLess.app`
- `openless -all/app/src-tauri/target/release/bundle/dmg/OpenLess_<version>_aarch64.dmg`
- `openless-all/app/src-tauri/target/release/bundle/macos/OpenLess.app`
- `openless-all/app/src-tauri/target/release/bundle/dmg/OpenLess_<version>_aarch64.dmg`

Logs: `~/Library/Logs/OpenLess/openless.log` (macOS) / `%LOCALAPPDATA%\OpenLess\Logs\openless.log` (Windows).

Expand All @@ -75,7 +75,7 @@ Logs: `~/Library/Logs/OpenLess/OpenLess.log`.
`DictationCoordinator` (Swift) / `coordinator::Coordinator` (Rust) is the **single owner of session state**. Hotkey edges drive a small phase enum (`Idle → Starting → Listening → Processing`); recorder, ASR, polish, insertion, and history are wired here and nowhere else. Library/module code never calls across modules — they each depend only on shared types.

```
Swift (Sources/OpenLess*) Rust (openless -all/app/src-tauri/src) Purpose
Swift (Sources/OpenLess*) Rust (openless-all/app/src-tauri/src) Purpose
───────────────────────── ────────────────────────────────────── ────────────────────────────────
OpenLessCore types.rs Pure value types: DictationSession, PolishMode, HotkeyBinding, errors
OpenLessHotkey hotkey.rs Global hotkey monitor (modifier-key edges)
Expand Down Expand Up @@ -107,8 +107,8 @@ Invariants:

### Permissions, credentials, on-disk state

- **Bundle ID `com.openless.app`** is shared between Swift and Tauri builds (hard-coded in `scripts/build-app.sh`, `openless -all/app/src-tauri/tauri.conf.json`, and `CredentialsVault.serviceName`). Changing it breaks Keychain lookups *and* every existing TCC grant.
- **TCC**: Microphone + Accessibility + AppleEvents. Both apps declare `NSMicrophoneUsageDescription` / `NSAccessibilityUsageDescription` / `NSAppleEventsUsageDescription` in their Info.plist. Tauri's lives at `openless -all/app/src-tauri/Info.plist`. After a fresh build that resets TCC, the app must be **fully quit and relaunched** after granting Accessibility before the global hotkey tap installs.
- **Bundle ID `com.openless.app`** is shared between Swift and Tauri builds (hard-coded in `scripts/build-app.sh`, `openless-all/app/src-tauri/tauri.conf.json`, and `CredentialsVault.serviceName`). Changing it breaks Keychain lookups *and* every existing TCC grant.
- **TCC**: Microphone + Accessibility + AppleEvents. Both apps declare `NSMicrophoneUsageDescription` / `NSAccessibilityUsageDescription` / `NSAppleEventsUsageDescription` in their Info.plist. Tauri's lives at `openless-all/app/src-tauri/Info.plist`. After a fresh build that resets TCC, the app must be **fully quit and relaunched** after granting Accessibility before the global hotkey tap installs.
- **Credentials** live in Keychain under accounts in `CredentialAccount` (`volcengine.app_key`, `volcengine.access_key`, `volcengine.resource_id`, `ark.api_key`, `ark.model_id`, `ark.endpoint`). The Rust port additionally reads the legacy plaintext fallback at `~/.openless/credentials.json` so users who configured the Swift app keep their creds without re-entering. Never hard-code keys.
- **Per-user data**:
- macOS: `~/Library/Application Support/OpenLess/{history.json, preferences.json, dictionary.json}` — same paths as the Swift app, capped at 200 history entries. **Do not rename `dictionary.json` to `vocab.json`** (drops user data).
Expand All @@ -122,7 +122,7 @@ Two separate flows, by design:
- **Swift (Sparkle, old users):** `scripts/release.sh <version>` bumps `build-app.sh`, builds the `.app`, ditto-zips it, signs with Sparkle EdDSA private key (Keychain item, not in repo), appends `<item>` to `appcast.xml`, commits, tags `v<version>`, pushes, and creates the GitHub Release. The public EdDSA key in `build-app.sh` (`SPARKLE_PUBLIC_KEY`) and the appcast URL `https://raw.githubusercontent.com/appergb/openless/main/appcast.xml` are baked into shipped clients — changing either strands existing users.
- **Tauri (cross-platform):** push a `v*-tauri` tag → `.github/workflows/release-tauri.yml` builds macOS arm64 `.dmg` and Windows x64 `.msi`. macOS Developer ID signing + notarization runs only when `APPLE_CERTIFICATE` / `APPLE_CERTIFICATE_PASSWORD` / `APPLE_ID` / `APPLE_PASSWORD` / `APPLE_TEAM_ID` secrets are set; otherwise it falls back to ad-hoc signing with a CI warning. Tauri tags use `-tauri` suffix specifically to not collide with Swift `vX.Y.Z` tags.

When bumping versions, update **both** `version` fields: `openless -all/app/package.json` and `openless -all/app/src-tauri/tauri.conf.json` (and `Cargo.toml`). For Swift releases, bump `APP_VERSION` *and* `BUILD_NUMBER` in `scripts/build-app.sh`.
When bumping versions, update **both** `version` fields: `openless-all/app/package.json` and `openless-all/app/src-tauri/tauri.conf.json` (and `Cargo.toml`). For Swift releases, bump `APP_VERSION` *and* `BUILD_NUMBER` in `scripts/build-app.sh`.

## Repo conventions

Expand All @@ -135,10 +135,10 @@ When bumping versions, update **both** `version` fields: `openless -all/app/pack
### Adding a new module

Tauri (preferred):
1. Add a `<name>.rs` (or directory) under `openless -all/app/src-tauri/src/`, importing only from `types`.
1. Add a `<name>.rs` (or directory) under `openless-all/app/src-tauri/src/`, importing only from `types`.
2. Register it in `lib.rs` (`mod <name>;`).
3. Wire it into `coordinator.rs` and expose any frontend-callable surface via `commands.rs` + `invoke_handler!`.
4. Add the matching TS wrapper in `openless -all/app/src/lib/ipc.ts` (with a mock branch for browser dev).
4. Add the matching TS wrapper in `openless-all/app/src/lib/ipc.ts` (with a mock branch for browser dev).

Swift (only if also patching the legacy app):
1. Add target in `Package.swift` under `Sources/OpenLess<Name>`, depending only on `OpenLessCore`.
Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,10 @@ Full end-user walkthrough: [USAGE.md](USAGE.md).

## Build from source (developers)

The active codebase is in `openless -all/app/` (Tauri 2 + Rust + React/TS).
The active codebase is in `openless-all/app/` (Tauri 2 + Rust + React/TS).

```bash
cd "openless -all/app"
cd "openless-all/app"
npm ci

# Dev: Vite at :1420 + Tauri shell
Expand All @@ -145,7 +145,7 @@ npm run build

Logs: `~/Library/Logs/OpenLess/openless.log` (macOS) / `%LOCALAPPDATA%\OpenLess\Logs\openless.log` (Windows).

**Windows build** — see [`openless -all/README.md`](openless%20-all/README.md) for MSVC vs GNU/MinGW routes.
**Windows build** — see [`openless-all/README.md`](openless-all/README.md) for MSVC vs GNU/MinGW routes.

**Swift (legacy, Sparkle updates only):**

Expand Down Expand Up @@ -197,7 +197,7 @@ The main window is organized as Home / History / Dictionary / Settings. The Dict

## Architecture

The active implementation is Tauri 2 (`openless -all/app/`). The Swift/SwiftPM codebase under `Sources/` is legacy and still serves Sparkle auto-updates for existing users.
The active implementation is Tauri 2 (`openless-all/app/`). The Swift/SwiftPM codebase under `Sources/` is legacy and still serves Sparkle auto-updates for existing users.

**Tauri backend (Rust)** — each module depends only on `types.rs`:

Expand Down Expand Up @@ -232,7 +232,7 @@ Planned but not yet shipped:

## Maintainer release checklist

- Bump version in `openless -all/app/package.json`, `src-tauri/tauri.conf.json`, and `src-tauri/Cargo.toml`.
- Bump version in `openless-all/app/package.json`, `src-tauri/tauri.conf.json`, and `src-tauri/Cargo.toml`.
- Run `INSTALL=0 ./scripts/build-mac.sh` and confirm the `.app` launches.
- Verify on a clean macOS box: permission flow, hotkey, recording, ASR, polish, insertion, clipboard fallback.
- Push a `v<version>-tauri` tag — CI builds and signs the macOS `.dmg` + Windows `.msi`.
Expand Down
10 changes: 5 additions & 5 deletions README.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,10 @@ OpenLess 只做一件事:**把语音变成可用的书面文字(尤其是 AI

## 从源码构建(开发者)

当前活跃代码库在 `openless -all/app/`(Tauri 2 + Rust + React/TS)。
当前活跃代码库在 `openless-all/app/`(Tauri 2 + Rust + React/TS)。

```bash
cd "openless -all/app"
cd "openless-all/app"
npm ci

# 开发模式:Vite at :1420 + Tauri shell
Expand All @@ -145,7 +145,7 @@ npm run build

日志路径:`~/Library/Logs/OpenLess/openless.log`(macOS)/ `%LOCALAPPDATA%\OpenLess\Logs\openless.log`(Windows)。

**Windows 构建** — MSVC 和 GNU/MinGW 两种路线详见 [`openless -all/README.md`](openless%20-all/README.md)。
**Windows 构建** — MSVC 和 GNU/MinGW 两种路线详见 [`openless-all/README.md`](openless-all/README.md)。

**Swift(仅用于 Sparkle 遗留版本发布):**

Expand Down Expand Up @@ -201,7 +201,7 @@ OpenLess 的润色模型只做文本整理,不做问答、不做任务执行

## 架构概览

当前活跃实现是 Tauri 2(`openless -all/app/`)。`Sources/` 下的 Swift/SwiftPM 代码是遗留版本,仍为老用户提供 Sparkle 自动更新。
当前活跃实现是 Tauri 2(`openless-all/app/`)。`Sources/` 下的 Swift/SwiftPM 代码是遗留版本,仍为老用户提供 Sparkle 自动更新。

**Tauri 后端(Rust)** — 各模块只依赖 `types.rs`:

Expand Down Expand Up @@ -236,7 +236,7 @@ commands.rs Tauri IPC 接口

## 维护者:发布检查

- 同步更新 `openless -all/app/package.json`、`src-tauri/tauri.conf.json`、`src-tauri/Cargo.toml` 中的版本号。
- 同步更新 `openless-all/app/package.json`、`src-tauri/tauri.conf.json`、`src-tauri/Cargo.toml` 中的版本号。
- 运行 `INSTALL=0 ./scripts/build-mac.sh`,确认 `.app` 可启动。
- 在干净 macOS 机器上验证:权限引导、快捷键、录音、ASR、润色、插入、剪贴板兜底。
- 推送 `v<version>-tauri` tag → CI 构建并签名 macOS `.dmg` + Windows `.msi`。
Expand Down
8 changes: 4 additions & 4 deletions openless -all/README.md → openless-all/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,10 @@ powershell -ExecutionPolicy Bypass -File .\scripts\windows-preflight.ps1 -Toolch

### GNU / MinGW Route

Use this route when MSVC/Windows SDK is unavailable. The current repository path
contains a space in `openless -all`, and GNU/MinGW tooling can fail from paths
with spaces while generating import libraries. Use the helper script; it mirrors
the app to a no-space temporary directory before building.
Use this route when MSVC/Windows SDK is unavailable. The app now lives under
the no-space `openless-all` directory to avoid GNU/MinGW path quoting issues
while generating import libraries. Use the helper script to keep the GNU build
environment and target setup consistent.

```powershell
cd app
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -248,8 +248,7 @@ function ProvidersSection() {
await setActiveAsrProvider(id);
if (prefs) {
const next = { ...prefs, activeAsrProvider: id };
setPrefsState(next);
await setSettings(next);
await updatePrefs(next);
}
};

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loading