android: the phone, on the real core — the mockup shell, playback, the media card, the catalog, the resolver, Save, the dev flavour

The same Tauri 2 project builds for Android: mobile.html as a third Vite
entry (src/mobile/, the mockup on real data), tauri.android.conf.json, the
mobile stubs (updater, lyric alignment, vocal separation), rustls reqwest
on Android, the AAudio buffer, and a hand-driven detour build
(src-tauri/android/{env,build,deploy,dev}.sh) while Developer Mode is off.
ANDROID.md is the recipe.

Playback: the media-session plugin crate (lock-screen card, MediaStyle
notification, audio focus, headset buttons, a foreground service that
promotes itself first — Android 14 kills the app otherwise), session
restore across reload and restart, solid chrome after measuring the
backdrop-filter lag.

The catalog: Search is the desktop's top bar (the top-result rule, artist
cards), the artist page and the record page are the desktop's, Home is the
desktop's landing page, Gaps per followed shelf. Playing goes through the
desktop's own source rules, moved verbatim from state.svelte.js into
src/lib/sources.js so both apps share one resolver; the phone readies the
next three tracks and crosses boundaries gapless. Save fetches a record or
a track into the library by the download rules; Transfers shows the
burst. The raw Soulseek search stays, offered on request, a peer's copy
streaming with the lane rising as the bytes arrive. Community is the
Soulseek side (rooms, chat, buddies); the private layer waits.

The opener and storage plugins (social links, the picked library folder,
all-files access), the volume normalization switch, and the harness:
tests/mobile/smoke.mjs walks the mock (a fake network behind
src/lib/events.js) and the real phone over CDP, perf.mjs measures frames.
This commit is contained in:
KeelrLeek committed 2026-09-13 09:30:06 -05:00
1 parent 972dd103cb
commit bb828ff2dc
102 files changed
+12258 -830

No files matched your search

+31
View File
@@ -1,3 +1,7 @@
/// Publishes the JavaVM and the app Context to the `ndk-context` crate at
/// library load, which cpal's AAudio backend needs and tao 0.35 does not do.
#[cfg(target_os = "android")]
mod android_glue;
mod commands;
mod community;
mod config;
@@ -12,6 +16,12 @@ mod inbox;
mod ledger;
mod hero_detector;
mod loudness;
/// The CTC aligner and the vocal separator run through Windows ML; off
/// Windows their stand-ins keep the names and answer "not here" honestly.
#[cfg(windows)]
mod lyric_align;
#[cfg(not(windows))]
#[path = "lyric_align_stub.rs"]
mod lyric_align;
mod lyric_prep;
mod lyrics;
@@ -34,7 +44,17 @@ mod overlap;
mod holdings;
mod state;
mod thumbbar;
/// Release checks and in-place installs are a desktop story; the phone's
/// stand-in keeps the same names so nothing else needs a cfg.
#[cfg(desktop)]
mod updater;
#[cfg(mobile)]
#[path = "updater_mobile.rs"]
mod updater;
#[cfg(windows)]
mod vocal_sep;
#[cfg(not(windows))]
#[path = "vocal_sep_stub.rs"]
mod vocal_sep;
mod youtube_playlist;
mod youtube_setlist;
@@ -56,9 +76,19 @@ pub fn run() {
.build(),
)?;
app.handle().plugin(tauri_plugin_dialog::init())?;
app.handle().plugin(tauri_plugin_media_session::init())?;
// Links out of the app (an artist's socials on the phone): the
// official opener — an Android intent there, the desktop's own
// `open_external` stays for the desktop views.
app.handle().plugin(tauri_plugin_opener::init())?;
// The library folder on the phone: the picker and all-files access.
app.handle().plugin(tauri_plugin_storage::init())?;
#[cfg(desktop)]
app.handle().plugin(tauri_plugin_updater::Builder::new().build())?;
// Must run before anything touches the app-data dir.
config::migrate_app_data(app.handle());
// The phone keeps its secrets in the app data dir; the helpers need its path.
config::remember_secrets_dir(app.handle());
// Prepare the small local vision model while the user is still on
// the app shell, so a first artist visit pays only warm inference.
hero_detector::warm_up(app.handle().clone());
@@ -245,6 +275,7 @@ pub fn run() {
ytdlp::deno_download,
playlists::playlist_export,
playlists::library_track_search,
playlists::library_track_index,
lyrics::lyrics_get,
lyrics::lyrics_search,
lyrics::lyrics_select,