build(android): cfg-gate desktop-only Tauri surfaces for android target

Phase 1 of the Android same-repo target plan: make the workspace
compilable for `aarch64-linux-android` (and the other NDK ABIs) by
removing the desktop-only crate dependencies and command bodies from the
Android build. After this commit, `tauri android init` followed by
`cargo tauri android build` is structurally unblocked — the remaining
work is the SDK/NDK toolchain (off-sandbox), the Svelte single-window
refactor, and the Phase 3 MVP feature surface.

What's gated under `cfg(not(target_os = "android"))`:

- src-tauri/Cargo.toml: `tauri = { features = ["tray-icon"] }` is now
  declared in the desktop-only target block. The `global-shortcut`,
  `window-state`, and `autostart` plugins join it — none of the three
  support Android natively. The base `tauri = "2"` plus `dialog`,
  `opener`, and `notification` plugins remain unconditional because they
  do support Android.
- src-tauri/src/lib.rs: `mod tray` declaration, the matching
  `tray::setup(app)` call, the close-to-tray `WindowEvent::CloseRequested`
  handler, and the `.plugin(tauri_plugin_global_shortcut::*)` /
  `_autostart` / `_window_state` chain are all desktop-only. The
  builder is split with a single `#[cfg(not(target_os = "android"))]`
  branch that adds the desktop plugins on top of the universal base.
- src-tauri/src/commands/tts.rs: `tts_speak` previously had three
  `#[cfg(target_os = ...)]` branches but no fallback, so on Android the
  `spawned` binding was unbound and the function failed to compile.
  Mirrored the existing `paste.rs` not-implemented fallback. Same fix
  for `list_voices_impl`. Frontend will hide the Read Page Aloud button
  on Android via `isAndroid()`.
- src-tauri/src/commands/windows.rs: all four multi-window commands
  (`open_task_window`, `open_preview_window`, `close_preview_window`,
  `open_viewer_window`) get an Android stub that returns a clear
  "Multi-window is not supported on Android" error. Tauri on Android
  is single-Activity; the previously-secondary content (preview overlay,
  transcript viewer, task float) will live as routes inside the main
  window, gated by `isAndroid()` on the frontend.

What's *not* changed:
- Top-level `identifier` in tauri.conf.json stays `uk.co.corbel.kon`.
  The Phase 10b Kon → Corbie rename sweep will land
  `corbel.technology.corbie` as part of a coherent rebrand commit
  rather than fragmenting the rename across this branch.
- `bundle.android.minSdkVersion: 24` added so a future
  `tauri android init` knows to target Android 7.0+ (Vulkan available,
  scoped storage starts at 29 — we'll surface scoped-storage paths
  via Tauri's dialog plugin on Phase 3).
- `kon-hotkey` already exports a non-Linux stub; no changes needed.
- `commands/meeting.rs` still calls `process_watch::list_running_process_names()`
  which compiles on Android but returns an empty list (SELinux blocks
  /proc walk on API 24+). Frontend will hide the toggle on Android.

Verification: 91/91 tests still pass on the buildable-in-sandbox crates
(kon-storage 60, kon-core 16, kon-mcp 9, kon-hotkey 4, kon-cloud-providers
2). svelte-check 0/0 across 3957 files. The src-tauri crate itself can't
be compiled in this sandbox (no webkit2gtk); CI's desktop builders will
exercise the desktop branch, and Jake's Android-equipped dev box will
exercise the Android branch via `tauri android init`.

https://claude.ai/code/session_0189xUb6ie6t9qHkzatGZ9Rb
This commit is contained in:
Claude
2026-04-25 12:50:33 +00:00
parent bd16c118cc
commit 4abc2356c2
4 changed files with 130 additions and 30 deletions

View File

@@ -287,6 +287,16 @@ fn list_voices_impl() -> Result<Vec<TtsVoice>, String> {
.collect())
}
// Non-desktop fallback. Android's native TextToSpeech API would need a
// JNI bridge — out of scope for v0.1-android. The frontend already hides
// the Read Page Aloud button behind a runtime detection; this stub keeps
// the command surface consistent so a stray invoke surfaces a clear
// error rather than panicking on an unbound `list_voices_impl`.
#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
fn list_voices_impl() -> Result<Vec<TtsVoice>, String> {
Ok(Vec::new())
}
// ---------- Tauri commands ----------
#[tauri::command]
@@ -310,13 +320,26 @@ pub fn tts_speak(
let spawned = spawn_macos(trimmed, rate, voice.as_deref())?;
#[cfg(target_os = "windows")]
let spawned = spawn_windows(trimmed, rate, voice.as_deref())?;
if let Some(c) = spawned {
if let Ok(mut guard) = state.child.lock() {
*guard = Some(c);
}
// No bundled TTS shim for non-desktop targets. Android has its own
// TextToSpeech APIs that would have to be reached over JNI; out of
// scope for v0.1-android. Mirrors the paste.rs not-implemented
// fallback so the command compiles cleanly across all targets and
// surfaces a clear error if the frontend tries to invoke it.
#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
{
let _ = (state, rate, voice);
return Err("TTS not implemented on this platform".into());
}
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
{
if let Some(c) = spawned {
if let Ok(mut guard) = state.child.lock() {
*guard = Some(c);
}
}
Ok(())
}
Ok(())
}
#[tauri::command]