Skip to content

2.0.6 - #276

Merged
BartolomeoRusso9 merged 39 commits into
mainfrom
2.0.6
Nov 12, 2026
Merged

2.0.6#276
BartolomeoRusso9 merged 39 commits into
mainfrom
2.0.6

Conversation

@BartolomeoRusso9

Copy link
Copy Markdown
Collaborator

No description provided.

…translation

Brings the main features of the mobile app to the desktop app.

Player
- New "Player" section: opens a folder, scans only tags and durations (no
  Spotify lookup), lists tracks with lazily loaded covers, search and sort.
  Play all, Shuffle (every track once per round, the chosen one first) and
  Repeat off/all/one, remembered between sessions. Recent folders as chips.
- Playback never lowers quality. Files the web view can decode (FLAC, MP3,
  WAV, Ogg, Opus, AAC) are streamed untouched. Others (ALAC, AIFF, WavPack,
  TTA, APE, WMA...) are decoded once to a cached lossless FLAC copy with the
  same sample rate and bit depth. core/playback.py decides; core/media_server.py
  is a loopback-only, token-protected HTTP server with Range support for the
  desktop window; /api/media does the same in web mode.
- Full-screen Now Playing view: cover, tinted background, quality line,
  controls, queue in play order, volume. Lyrics come from a .lrc next to the
  file or the file's own tag, in any LRC flavour: line-synced, enhanced
  word-by-word (<mm:ss.xx> tags, v1:/v2: singers, [bg:] backing vocals,
  [x-translation:]/[x-romaji:] lines). Word fill with a soft edge, lift and
  glow on held words, intro/instrumental dots, right-aligned second singer.
  Scroll and defocus follow the mobile lyrics screen: focus anchored near the
  top, critically damped spring with trailing rows, defocus by distance,
  4 s pause after a manual scroll.

Fix Local Files
- Convert dialog (all targets of core/transcode, bitrate and bit-depth /
  sample-rate caps); a lossless target on a lossy source is refused.
- Tag editor: edits only the typed fields, keeps every other tag, cover and
  lyrics, backs up the file and restores it if the write fails. Fixes FLAC
  covers surviving a replace/remove (mutagen's delete() leaves pictures).
- Audio analysis: technical details and a spectrogram drawn by ffmpeg.
- Library reorganiser: moves files into folders built from their tags after a
  dry-run preview; never overwrites, never leaves the chosen folder.

Following
- "New this week": releases of followed artists from the discography
  listings, no track fetches, cached for 30 minutes. Release now carries its
  full date.
- Concerts reported by an extension (same contract as the mobile app) show on
  the artist card with venue-local times and an .ics download. The metadata
  merge no longer drops the extension's extras when the built-in answer has
  none.

Lyrics translation
- OpenAI, OpenRouter, Gemini, Anthropic or any OpenAI-compatible server with
  the user's own key, stored in a private file and never sent back to the
  page. Line by line, so timestamps survive; save as <name>.<lang>.lrc.

Other
- The folder picker is shared by Fix Local Files and the Player, and starts
  from the path in the field instead of "/", which the web build refuses.
- index.html loads styles.css, toast-system.js and app.js with a timestamp
  instead of a hand-kept ?v= suffix; webapp.py injects the browser shim at an
  explicit marker instead of matching a script tag.
- Checkboxes inside modals keep their own size.
Comment thread mornye/core/media_server.py Fixed
Comment thread mornye/core/media_server.py Fixed
Comment thread mornye/core/media_server.py Fixed
Comment thread mornye/core/media_server.py Fixed
Comment thread mornye/webapp.py Fixed
Comment thread mornye/core/media_server.py Fixed
Comment thread mornye/core/media_server.py Fixed
Comment thread mornye/webapp.py Fixed
Comment thread mornye/webapp.py Fixed
Fails when the markup loses an element the script looks up, when an inline
handler names an undefined function, or when the script selects a class
nothing produces. A frozen inventory covers ids reached indirectly.
tests/visual/capture_tui.py draws the twelve panels at 80x24 and 120x40
in both Mornye themes, against an empty throw-away home, and can compare
a fresh capture with the committed baseline.
A per-extension 'Allow local network access' switch in Settings ->
Extensions. When on, the hosts of the URLs in that extension's non-secret
text settings get past the network guard, so a Jellyfin server on
192.168.x.x works without MORNYE_EXT_ALLOW_PRIVATE_NETWORK opening the
whole local network to every extension. Stored by the host, admin-only
over the web.
An installed extension of type lyrics_provider that defines fetchLyrics
(Jellyfin, Apple Music) is now a provider named ext:<name>, ranked with the
built-in ones. The GUI and TUI add them to their provider lists, off by
default, and --lyrics-providers accepts ext:<name>. Line-synced answers
become LRC, unsynced ones stay plain text.
Explore gets a Feed picker: Spotify, as before, or any installed extension
declaring capabilities.homeFeed (Jellyfin, Apple Music, YouTube Music...).
Each item gets an open_url the URL box can open: the item's own web link,
the manifest's share template, or for a self-hosted source the configured
server plus its fragment link.
A setting with a long description squeezed its text field to 25px, so
Jellyfin's Server URL could not be read or edited. The fields keep at
least 200px and the description wraps instead.
A link to a source with no built-in client, such as a Jellyfin server's
.../web/#/details?id=..., was handed to the Spotify client and could only
fail. It now goes to the extension whose urlHandler claims it, and its
tracks remember that extension. A track from an extension declaring
skipBuiltInFallback is downloaded by that extension alone, and one from an
extension declaring skipMetadataEnrichment keeps its own tags.
A line timed as one piece ('<00:51.00>I don't know how ... stay') drew
its lit copy on a single row: it ran off the right edge ('...you to
trea') while the dim copy underneath wrapped and stayed grey. Every
piece is now split into words, its time shared out by length, and a
piece with no end of its own lasts about a third of a second a word,
never past the next line.
tests/visual/capture_gui.py starts mornye --web on an empty throw-away
data folder and saves the ten views, dark and light, at desktop, 768 and
375 wide, through Playwright and the installed Chrome. The URL box's
typing animation is frozen, and --compare ignores anti-aliasing noise.
Playwright is an optional 'visual' extra.
164 of the 217 style="" attributes become u-* utility classes at the end
of styles.css, one declaration each, so a new stylesheet can reach every
look decision. What stays inline is what app.js clears at runtime
(display, opacity...) and eleven declarations an id or attribute rule
would otherwise override. Every element's computed style is unchanged
(1472 elements, desktop and phone, dark and light, compared before and
after), and the GUI screenshots match the baseline. A test keeps new
inline styles out.
The style="" attributes in the markup app.js builds become the same u-*
utilities as index.html's. Colours that carry a meaning become a
data-tone (muted, ok, warn, error) instead of a colour string: the
animated-artwork check, extension health, signed sessions and conflicting
reorganise rows; the Save button's border follows data-dirty. Fixed
padding and grid values set from JS become classes. What is still written
inline is computed or behaviour: shown/hidden, progress widths, lyric
motion, cover images.

Computed styles of every element in every view and settings tab, desktop
and phone, are unchanged; the GUI screenshots match the baseline. The
screenshot diff now ignores up to 20 stray anti-aliased pixels.
Now Playing's white-on-artwork ink and its tints, a barcode's black on
white, the glyphs on a status dot and on the player's main button become
theme-independent tokens (branding_tokens.FIXED), declared once in :root;
translucent shades use channel tokens, rgba(var(--media-ink-rgb), .62).
The toasts lose fallbacks that could never apply. Masks keep their black,
which is an alpha channel. New tests: the fixed tokens match the module
and the light theme leaves them alone, and no declaration names a raw
colour. Computed styles are unchanged everywhere.
Static pages in docs/mocks on one stylesheet that holds the proposed
token v2 values (graphite surfaces, amber signal, state colours), with
the three signature elements: the quality readout, the segment meter and
the legend set in a panel's border. The TUI mock is generated at 120x40
by make_tui_mock.py. For approval before token v2 (voce 8).
@BartolomeoRusso9
BartolomeoRusso9 merged commit dcff676 into main Nov 12, 2026
11 checks passed
@BartolomeoRusso9
BartolomeoRusso9 deleted the 2.0.6 branch November 12, 2026 16:20
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.

2 participants