Skip to content

did lots of updates backend and frontend, i loved your design but qml frontend was the best option for performance - #21

Open
neur0map wants to merge 193 commits into
ashmitvoid:mainfrom
Ryoku-dev:main
Open

neur0map wants to merge 193 commits into
ashmitvoid:mainfrom
Ryoku-dev:main

Conversation

@neur0map

@neur0map neur0map commented Sep 8, 2026

Copy link
Copy Markdown

your design was good but it really was causing a lot of ram spikes and issues with audio.. if you want deeper description of what i did let me know.

neur0map and others added 30 commits September 2, 2026 23:09
Three interlocking causes made each track start refetch the 2.9 MB player.js
and spawn a fresh hidden WebKit process:

- the cipher and PoToken webviews were torn down 15 s after use, which any
  song outlives; keep them while media is loaded and release after 5 min idle
- the player hash was re-read from iframe_api on every resolve because
  current_hash.txt was written but never read; pin it for the cache TTL
- a WEB_REMIX HEAD 403, routine on capped videos, ran the full self-heal
  (delete player.js, drop the bridge and the PoToken session) each time;
  allow one heal per ten minutes

Measured on a Ryoku desktop: six consecutive track changes with no fetch and
no webview build, where before each one paid ~1.2 s and a WebProcess.
mpv titled the stream by its URL, so the PipeWire node carried the full
signed googlevideo link. Pass a per-file force-media-title (Artist - Title)
through loadfile's options, quoted for the command parser and
length-prefixed for the option parser so any title round-trips verbatim.
Includes a probe example that asserts the round trip.
The reveal was gated on the Ryoku token IPC and retried for ~1.85 s against a
1.5 s native failsafe, so a cold WebKit mount was routinely revealed natively
and unstyled. Race the palette against 250 ms; the native failsafe moved to
4 s in the previous commit's lib.rs change.
Tauri sets cfg(dev) whenever custom-protocol is absent, so the source
PKGBUILD's plain cargo build produced a binary that opened build.devUrl.
Default the feature on; cargo tauri dev still passes --no-default-features.
Locale::default() is hard-coded to US/en, so every InnerTube request
announces English even when the system language and the signed-in
account are French; the API's hl/gl context wins over account
preferences and the UI never switches.

Add Locale::from_env(), which reads LC_ALL/LANG, parses
lang_TERRITORY and maps the compound tags YouTube localises
(zh-CN/TW/HK, pt-BR/PT, es-419/es-US, en-GB, fr-CA), falling back
to US/en when nothing parseable is set. The session bootstrap now
uses it instead of Locale::default().
InnerTube content is now localised by the backend locale (hl/gl), but the
app-owned chrome (context menus, settings, dialogs, status text) is
hard-coded English in the Svelte UI. Add a small reactive i18n module
(t() with a fr dictionary keyed by the exact English source string,
locale detected from navigator.language) and wrap every static UI
string in it. Unknown keys fall back to English, so missing
translations degrade gracefully. Covers 36 components/routes (~490
strings), including ternary display branches and aria labels; dynamic
API-driven text is untouched.
Both seek sliders hold the dragged value locally and commit it on the
input's change event. Release the thumb outside the window (the bar sits
on the bottom edge) and WebKitGTK delivers neither change nor pointerup;
the local value then shadowed every later position tick and the timeline
sat frozen for the rest of the session while playback carried on.
Reproduced by dragging past the window edge: MPRIS kept ticking, the bar
did not. A shared guard now commits the pending drag on pointerup,
pointercancel, lostpointercapture, window blur, or the first pointer
movement with no button held, and a track change ends a drag outright.
Home toggled ryo-is-scrolling on <main> on each scroll event and again
110 ms after the last one, and the queue/lyrics wheel helper did the same
on its scroller. Rules keyed on that class matched every <img> and every
promoted .ryo-art-wash layer, so each toggle was a full style recalc plus
compositing-layer churn, twice per wheel notch. Scrolling is otherwise
paint-bound in WebKitGTK (measured the same 60% of a core with and
without the toggle), so the class and its rules go rather than get
cheaper.
WebKitGTK 2.42's feature API can flip compositing borders and repaint
counters on, which is how to see what a scroll actually repaints; the
webkit2gtk crate does not bind it yet, so the five calls are declared
here and gated on an env var that is normally unset.
The cold-start reveal failsafe grew to 4000 ms in 531c2b5 but the
invariant still asked for 1500; the private-path scan matched the .git
file of a git worktree; two files had drifted from rustfmt.
The host calls lastfm::spawn from Tauri's synchronous setup closure, on
the main thread with no ambient Tokio context; the tokio::spawn that
replaced tauri::async_runtime::spawn panicked there at startup. Take the
runtime handle explicitly (the daemon will pass its own) and format the
files the extraction left unformatted.
neur0map and others added 30 commits September 24, 2026 22:38
The embedded webview capture could not survive captchas or IdP popups, so
users reported never getting signed in. Connect now imports the session
straight from the browser's cookie stores (Gecko plaintext, Chromium v10
AES-CBC), default profile first, proving the bearer against /me before
persisting it; when no session exists it opens soundcloud.com and polls
the stores (mtime-guarded) until the sign-in lands or five minutes pass.
The client mirrors the new waiting/expired states.
install_update left 'quit and reopen' as the user's chore. The client now
spawns a detached helper that flock-waits for the old daemon's socket lock
to release, then execs the launcher (socket-activating the new daemon and
opening the new client), and asks the daemon to quit. The manual guidance
stays as the fallback text if the helper fails.
mpv's demuxer cache drains the Spotify FIFO, so librespot decodes a whole
track within seconds and then idles in EndOfTrack with its sink still
open. mpv never saw EOF, so playback hung at the end of every Spotify
track, and seeks went to librespot, which rejects them in that state.

Close the pipe when the stream handle sees its own EndOfTrack so mpv
plays out its cache and EOFs into the normal queue advance, and seek
Spotify tracks in mpv's cache like any other track. That retires the
FIFO reload on seek and the position base it needed.
…er back to zero

Superseded by #3, which seeks inside mpv's cache and closes the pipe at the stream's own end of track; the tree keeps #3's version.
…nstead of reloading its pipe

Superseded by #3, which seeks inside mpv's cache and closes the pipe at the stream's own end of track; the tree keeps #3's version.
…done so the queue advances

Superseded by #3, which seeks inside mpv's cache and closes the pipe at the stream's own end of track; the tree keeps #3's version.
…e the UI chrome into French

# Conflicts:
#	ui/src/lib/components/MiniPlayer.svelte
#	ui/src/lib/components/PlayerBar.svelte
#	ui/src/lib/components/SettingsDialog.svelte
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.

3 participants