Commit Graph
35 Commits
Author SHA1 Message Date
edde746 69fadc220d chore: clean up code comments 2026-08-10 20:28:41 +02:00
edde746 369c6279d6 fix(i18n): translate the player, downloads and server-setup text left in English
A Portuguese user reported "Skip Intro" rendering in English on Android TV.
The locale files were not the problem - all 22 were structurally complete.
skip_marker_button.dart simply never imported strings.g.dart and assigned
'Skip Intro' / 'Skip Credits' / 'Next Episode' as plain literals. An audit of
lib/ found ~120 more sites in the same state, in four shapes that need
different fixes:

A literal in a file that never imported the i18n layer is the easy one -
skip_marker_button, performance_stats, track_label_builder and codec_utils all
render text with no `t` in the file at all. TrackLabelBuilder._compose now takes
a fallbackLabel builder instead of an English fallbackPrefix, so the caller
supplies t.audioTracks.track / t.videoControls.subtitleTrack and every unnamed
audio and subtitle row in the track menus is localized.

English reaching the user through an exception message is the widest one, and
it needs care: MediaServerException.message feeds both toString() - logs and
Sentry grouping - and verbatim UI display. Localizing it in place would make
bug-report logs follow the user's locale and split one Sentry issue into 22.
The MediaServer and Seerr families instead gain a nullable `display` alongside
the English `message`, and the six screens that print these errors read
`display ?? message`. PlaybackException keeps the opposite rule, because it
already carries a PlaybackFailureReason for logic and classifyPlaybackFailure
already builds it from t.messages: its stragglers are localized at the throw
site. That also removes the literal "Exception: " prefix Live TV users saw on
a tune failure, since PlaybackException.toString() returns the bare message.

Localized parts hand-concatenated with bare English are the shape no search for
Text('...') can find: '${t.common.pause} auto-scroll' on the home carousel,
'${day} at ${time}' on the Live TV schedule row, and an actor-screen count that
hand-rolled its plural as `n == 1 ? 'title' : 'titles'` - wrong for ru and pl
regardless of translation, now a real Slang plural.

Finally a literal assigned to provider state that a widget renders later:
DownloadProgress.errorMessage, and the four background_downloader notification
bodies, which sit inside a plugin config call where no widget-shaped search
reaches them.

Two things surfaced while converting. track_chapter_controls compared a track
label against 'Audio Track N' to swap in a localized version; once the builder
localized its own fallback that branch became unreachable, so it and the
orphaned _joinTrackLabel are gone. And discovery_view's PeerError fallback arm
looks like a leak but is not - its producers already localize, and a test says
so - so it stays as it is.

All 21 non-base locales are translated, including the 21 keys left empty by
earlier commits that were falling back to English. No locale has an empty value.

scripts/check_hardcoded_strings.py guards the three shapes a structural check
can see, and runs in ci_checks.sh after translation hygiene. Its first draft
passed its own tests while missing this very bug, because 'Skip Intro' is bound
to a local rather than handed to Text(); the name-bound rule that closes that
gap is restricted to phrase-shaped literals, or it cannot tell copy from the
identifiers this codebase binds constantly ('cast_row', 'auto', 'liveTv'). It
cannot see English inside a throw or assigned to a provider field - neither is
distinguishable from a log message without dataflow analysis - and the docstring
says so. label: and actionLabel: are deliberately unscanned: here they name a
diagnostic operation, and a check that is chronically red is a check that gets
switched off.

One commit rather than one per area: the keys, the 22 locale files and the
generated output are a single unit, and any partial split fails the repo's own
unused-key scan on the way through.

close #1856
2026-08-10 15:32:43 +02:00
edde746 352b88109b refactor: extract shared mixins and helpers, drop dead abstractions
Introduces shared seams for paginated views, D-pad reorder, media control
routing, async singletons and the device method channel, then points the
open-coded copies at them.

Also removes unused models and duplicated provider/server plumbing, folds
the twice-implemented artifact store in the server, and factors the
repeated Flutter toolchain prologue in CI into a composite action.
2026-07-26 06:09:48 +02:00
edde746 764345f021 feat(music): audio downloads and music home rows
Album/artist downloads expand to tracks with pinned parent metadata,
aggregate progress, container deletes with reference-counted album
covers, and a Music tab on the downloads screen with fully offline
album playback. Home rows include music libraries (fixes plex hub
items being filtered to video types) and audio playlists join
download/sync rules.
2026-07-05 21:51:37 +02:00
edde746 cceba28d0a fix(i18n): request localized Plex labels
close #1311
2026-06-12 07:59:35 +02:00
edde746 38616770e5 fix(i18n): localize season & episode labels in downloads tree 2026-06-07 21:46:44 +02:00
edde746 74b8dc4561 refactor: type server identifiers 2026-06-01 11:06:03 +02:00
edde746 5a68711f7b feat(ui): add pointer cursors to clickable controls
close #1068
2026-05-18 15:56:41 +02:00
edde746 31d2d9dc98 feat: jellyfin 2026-05-01 01:20:36 +02:00
edde746 ee020d81bd refactor: trakt/download hardening and cleanup sweep 2026-04-21 13:57:03 +02:00
edde746 3da51f9d64 chore: pre-commit ci hook, dart format 2026-04-18 12:40:35 +02:00
edde746 771c431188 fix: treat 500 as permanent failure, show error in UI 2026-04-14 22:29:05 +02:00
edde746 f7e3408c86 fix: guard empty list access in alpha jump bar and download tree 2026-04-13 22:07:21 +02:00
edde746 d3602201c6 refactor: remove dead code 2026-03-27 17:39:43 +01:00
edde746 a05efef3c8 fix: guard download action button focus node access 2026-03-27 10:39:50 +01:00
edde746 4f736c555b fix: make PlexMetadata type/key/title nullable for folder items
Plex API returns Directory entries without type field, causing
TypeError crash in fromJson. Made fields nullable and migrated
callers to use mediaType enum and displayTitle getter instead
of raw string access.
2026-03-14 05:40:14 +01:00
edde746 166e73cdaa fix: sync button focus nodes with actual action count 2026-03-10 06:08:55 +01:00
edde746 04438c8e45 refactor: code quality & format 2026-02-15 04:07:09 +01:00
edde746 1c7303d095 fix: download queue status 2026-02-14 22:22:50 +01:00
edde746 d986f0d2ea feat: migrate downloads to background_downloader
close #454
2026-02-14 18:02:49 +01:00
edde746 6e9b78e5b5 fix: missing translations, simplify translations 2026-02-10 21:37:27 +01:00
edde746 038ec52e00 fix: add confirm dialog to download delete buttons 2026-02-08 10:04:23 +01:00
edde746 87fa2d765b fix warnings 2026-02-03 02:16:04 +01:00
edde746 2e15d2b4e9 fix: downloads not being tappable
close #355
2026-01-31 10:06:52 +01:00
edde746 a3b5dfecfb refactor: clean up 2026-01-28 05:22:56 +01:00
edde746 27e88207fa fix: misc focus
close #266
2026-01-25 18:16:23 +01:00
edde746 84c255b917 refactor: deduplicate logic 2025-12-21 13:19:21 +01:00
edde746 3c89d0eba8 refactor: update formatting 2025-12-15 02:29:03 +01:00
edde746 fb17600bb0 refactor: consolidate 2025-12-15 01:16:22 +01:00
edde746 5f78bbe93a refactor: deduplicate 2025-12-14 20:18:36 +01:00
edde746 867992e96b refactor: fix warnings 2025-12-13 15:37:55 +01:00
edde746 0eb84dc7d2 refactor: deduplicate 2025-12-12 18:00:34 +01:00
edde746 11461eefe5 refactor: format 2025-12-12 17:05:26 +01:00
edde746 263eddbdba refactor: new icons 2025-12-12 15:57:22 +01:00
edde746 dc44354036 feat: downloads 2025-12-12 02:59:27 +01:00