Commit Graph

47 Commits

Author SHA1 Message Date
be-nj
73f6dbba75 Surface failed refreshes instead of swallowing them
All checks were successful
Build TV app / build (push) Successful in 2m54s
Favourites and stream profiles were refreshed inside a bare runCatching,
so when they failed nothing was logged and the app just showed a stale
cached list. An expired login now always raises the re-login screen, even
when cached channels could still be displayed, and the settings gained a
"Senderliste neu laden" row for a manual retry.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
v0.10.6
2026-08-26 03:59:25 +02:00
be-nj
f6f6a2499f Stop the CI from re-fetching crests, cache their URLs instead
All checks were successful
Build TV app / build (push) Successful in 2m49s
Fetching 56 images on every run earned nothing but rate limits, and the
CI artefact is a test build that does not need the badges — the shield
fallback covers it. The resolved image URLs are cached in
tools/crest-sources.json, which is plain text and safe to commit, so a
local run needs one request per club instead of two and can resume after
a rate limit. The artwork itself stays out of the repository.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-26 03:42:49 +02:00
be-nj
8aa3a4da02 Ship the real club crests in the APK, and fix the CI licence step
All checks were successful
Build TV app / build (push) Successful in 4m15s
Resolving crests from Wikipedia at runtime never produced a visible badge
on the TV and left nothing in the log to debug, so the shield fallback was
all anyone ever saw. They are now downloaded once at build time by
tools/fetch-crests.py into assets/crests (git-ignored, so no trademarked
artwork is committed) and loaded from there — instant, and independent of
the network.

CI: accepting SDK licences by piping "yes" into sdkmanager died of SIGPIPE
(exit 141) under pipefail; the licence hashes are written directly now.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
v0.10.5
2026-08-26 03:31:06 +02:00
be-nj
b7ee0523d1 CI: build without marketplace actions
Some checks failed
Build TV app / build (push) Failing after 21s
The runner resolves bare action names against this Gitea, and even with
full GitHub URLs it fails on annotated tags (unsupported object type).
The image also ships neither a JDK nor an Android SDK, so the job never
had a chance. Everything is plain shell now: shallow checkout, JDK 17,
command-line SDK tools, tests, debug APK.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-26 03:10:43 +02:00
be-nj
a3105925bb Make a waiting update visible instead of hiding it in the settings
Some checks failed
Build TV app / build (push) Failing after 5s
The start-up check already ran, but its result only showed as a badge for
whoever happened to open the settings. A chip in the top bar now says
"Update <version>" and leads straight there, and the check repeats every
six hours because a TV keeps the same process alive for days.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
v0.10.3
2026-08-26 03:07:12 +02:00
be-nj
7f1dff5661 Real club crests, and no more crash on "Verein hinzufügen"
Some checks failed
Build TV app / build (push) Failing after 5s
Crests are resolved from the German Wikipedia page summary at runtime and
cached per device, so nothing copyrighted is stored in the repository. The
coloured shield remains as the fallback while the badge loads or when a
club has none.

The add dialog crashed for the same reason the rail did: it focused a row
that only exists when something is preselected, and adding a club has no
preselection. It now also scrolls, which 56 clubs rather need.

CI: this Gitea resolves bare action names against itself, so the workflow
now uses full GitHub URLs, and it runs the unit tests too.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
v0.10.2
2026-08-26 02:59:23 +02:00
be-nj
869060c56f Pick clubs from the top three divisions, and stop the rail from crashing
Some checks failed
Build TV app / build (push) Failing after 2s
The club shortcut now offers every club of the first three German
divisions instead of two hard-coded ones. Up to three can be active at
once; benjamin and tobiasb still start with Hansa and the VfB switched on.

Also fixes a crash on the left jump out of the channel list: the jump
targeted a FocusRequester bound to the selected rail row, and a row that
is scrolled out of a LazyColumn is not composed, so requesting focus on it
threw. Jumps are now attempted and fall back to normal focus movement.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
v0.10.1
2026-08-26 02:54:04 +02:00
be-nj
7ad7f5172e Club shortcut: a rail group for "where is my club on tonight"
Some checks failed
Build TV app / build (push) Failing after 2s
Adds an optional rail entry per club that lists every channel whose EPG
mentions the club within the next three hours, with the matching kick-off
instead of the usual Now/Next. Only sport and free-to-air groups are
scanned (NFL excluded), so the scan stays cheap and quiet.

Which clubs appear is a per-TV setting: the signed-in viewer's own club is
on by default, and every club can be switched on or off under Einstellungen
-> Vereinsmenüs, so a household can follow more than one.

Crests are trademarks, so the icon is a plain shield in the club colours.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
v0.10.0
2026-08-26 02:47:06 +02:00
be-nj
753ab3a3ab Follow the repo move to the be-nj organisation
Some checks failed
Build TV app / build (push) Failing after 2s
Updater and README point at the new path. The old one redirects, but the
updater should not depend on that. Also drops a stale GitHub-specific
Accept header.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
v0.9.2
2026-08-26 02:33:47 +02:00
be-nj
f157323626 fix(live): returning from playback keeps the group you were in
Some checks failed
Build TV app / build (push) Failing after 2s
The rail opens whatever gets focused, so when the player closed and focus
landed on "Alle Sender", the view silently switched away from the group
the viewer had been browsing. A restore flag now suppresses that
auto-select until focus has been placed on the channel that was watched.

Completes #13.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
v0.9.1
2026-08-26 02:20:17 +02:00
be-nj
c0adce2b09 Resolve the full review backlog (issues #1-#13)
Some checks failed
Build TV app / build (push) Failing after 2s
Control server security and robustness:
- Socket read timeout, handshake deadline and a client cap so an idle or
  hostile connection can no longer pin threads forever (#1)
- Per-address rate limiting that counts every failed hello, Origin
  checking on the upgrade, and a separate revocable session token for
  code-authenticated clients so the guessable path no longer yields the
  QR credential (#2)
- Credentials excluded from cloud backup and device transfer, constant
  time comparisons, and a pairing reset in the settings (#3)
- Playlist fetches restricted to http(s), capped at 24 MB and bounded by
  an overall transfer deadline (#4)
- Port conflicts and MediaSession id collisions no longer crash the app;
  the remote degrades to unavailable with a plain-language note (#11)

Player:
- Seeking no longer collapses to position 0 when the duration is unknown
  (#5)
- Pause acts on playWhenReady, so pausing during a stall works and
  playback cannot resume in the background after leaving the app (#6)
- Playback failures stay on screen with a retry action instead of
  silently dropping back to the list (#7)
- Reconnects are spaced 1s/3s/8s and re-entering the channel just closed
  waits out a short grace period, which is what the provider needs to
  release the previous session (#12)

Channel list and remote:
- Leaving playback returns to the channel the viewer came from (#13)
- The remote only rebuilds its list when the data changed, never
  overwrites a focused input and carries indices instead of scanning (#8)
- Pairing retry reconnects properly, resets its backoff and validates the
  code before spending an attempt (#9)
- M3U parsing keeps commas in names, strips a BOM and rejects payloads
  that are not playlists, covered by unit tests under tests/ (#10)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
v0.9.0
2026-08-26 02:14:48 +02:00
be-nj
7abd4b2a48 README: generic group names in screenshots, consistent captions
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-26 01:55:15 +02:00
be-nj
f69ae2f437 README: screenshots as 2x2 grid
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-26 01:43:14 +02:00
be-nj
01a76bffcd README: welcome screen screenshot (QR and LAN address pixelated)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-26 01:42:49 +02:00
be-nj
13352994e4 README: all screenshots full width
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-26 01:42:05 +02:00
be-nj
6acbe77200 README: overlay screenshot (scene pick)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-26 01:41:16 +02:00
be-nj
7da6f5c69f README: brighter player screenshot
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-26 01:36:11 +02:00
be-nj
e66c8a863b Overlay readability on bright video: brighter times, translucent progress track
Some checks failed
Build TV app / build (push) Failing after 2s
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
v0.8.6
2026-08-26 01:32:34 +02:00
be-nj
ca401e8ca3 README for humans: German, screenshots, install guide
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-26 01:30:29 +02:00
be-nj
844ea928ef Channel number in the player overlay (inline before the name)
Some checks failed
Build TV app / build (push) Failing after 3s
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
v0.8.5
2026-08-26 01:27:50 +02:00
be-nj
95f8793938 Bare, larger channel logos (no tile box)
Some checks failed
Build TV app / build (push) Failing after 2s
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
v0.8.4
2026-08-26 01:20:22 +02:00
be-nj
1757d8015d Move update source to Gitea (git.beckm4nn.net)
Some checks failed
Build TV app / build (push) Failing after 3s
Releases API for the version check; the APK itself is served from the
orphan 'apk' branch of the public repo (asset uploads need a token,
raw files do not). Transitional GitHub release carries this change so
existing installs hop over.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
v0.8.3
2026-08-26 01:16:38 +02:00
be-nj
7c1f8d2c8b Channel rows with real logos (Entwurf A), no focus scale clipping
- Rows carry the Dispatcharr channel logo in a small tile (initials as
  fallback), sit on a surface instead of transparent black, and get the
  accent focus border; the group subline is gone — the logo carries
  channel identity.
- Focus scale disabled on settings rows, picker options, rail items and
  channel rows: the grown surface got clipped by its parent.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-26 01:12:07 +02:00
be-nj
3068eaea19 Picker with fullscreen scrim, framed QR tile
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-26 01:07:11 +02:00
be-nj
5b6cebd041 Settings: Wiedergabe card + picker dialogs instead of chip walls
- Quelle and Stream-Qualität move out of Konto into their own
  Wiedergabe card; Konto is account + Abmelden only.
- Choices open a TV-style picker dialog (focus starts on the current
  value, Back closes) with the current value + drawn caret shown at
  the row's trailing edge.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-26 01:01:38 +02:00
be-nj
5de71193ad fix: settings option chips (blob layout), real gear icon, overlay EPG filter, installer on main thread
- SegmentedRow lays label above wrapping option chips instead of
  squeezing them into the trailing slot (long profile names collapsed
  the label and blew the pill up into a blob).
- Gear icon: thick ring + stubby teeth instead of sun rays.
- Player overlay filters EPG placeholders and next==now duplicates
  like the channel list.
- Updater: startActivity from Dispatchers.Main — firing it from the IO
  dispatcher stalled the first install attempt.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-26 00:55:47 +02:00
be-nj
deca5bd0cb fix(live): left lands on the selected group, right enters a fresh group at the top
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-26 00:50:36 +02:00
be-nj
a4391740ec Settings redesign: cards with focusable rows, segmented controls, gear button
- Settings page follows the Google TV pattern: Konto / App / Handy-
  Fernbedienung cards, each row a full-width focus target with label,
  subtitle and trailing value.
- Quelle and Stream-Qualität are segmented controls switched with
  left/right inside the focused row (click cycles).
- Account row with initial avatar, Abmelden as red row, update row
  with version badge; Update installieren only when one is available.
- Top bar: drawn gear icon button replaces the text pill.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-26 00:48:14 +02:00
be-nj
11a8056ce2 fix(player): opening key-up no longer clicks the freshly focused pause button
The key-down that opens the overlay is consumed by the activity, but its
key-up arrived after the play button grabbed focus and clicked it —
instant pause right after the overlay appeared. The overlay now swallows
select-releases whose press it never saw.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-26 00:32:22 +02:00
be-nj
d98f277ec4 Channel numbers on the remote pad, EPG column redesign, calmer overlay
- Number keys type the stable channel number (position in Alle Sender,
  shown identically in every view) with a live feedback badge; commits
  after a short pause or as soon as no longer number can match.
- EPG cell is a left-aligned column with a fixed leading edge: title +
  time range, progress under the title, next line only when it differs;
  placeholder programmes (kein Programm / no information) count as no
  EPG data. Star hidden in the favorites view.
- Player overlay: no LIVE dot (reads as recording) and no status word
  while playing; state text only for paused/buffering/error.
- Settings pill gets a resting surface so it reads as a target.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-26 00:27:55 +02:00
be-nj
8d6958536d Icon-only transport buttons (play/pause/stop need no labels)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-26 00:17:39 +02:00
be-nj
ee721708dc Drawn transport icons instead of glyphs (Android renders those as emoji)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-26 00:10:05 +02:00
be-nj
b04240ffde Live screen: group rail layout, exclusive filtering, cleaner top bar
- Groups live in a scrollable rail on the left (Alle Sender, Favoriten,
  then Dispatcharr groups with counts); focusing one opens it like a
  menu — filters no longer stack additively.
- Channel list sits right of the rail with Now/Next and progress;
  group subline only shown in the Alle view.
- Top bar: wordmark plus one context pill (Einstellungen / Zurück zu
  Live) instead of two text tabs; Back returns to Live instead of
  quitting the app.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-26 00:07:23 +02:00
be-nj
00762b6cbb Player overlay: real transport buttons (pause/stop/audio), OK opens controls
OK now opens the overlay like every TV player; its buttons are ordinary
focusable pills (play/pause, stop, audio-track cycle). Back closes the
overlay first, then stops. Auto-hide timer restarts on any interaction.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-26 00:05:25 +02:00
be-nj
b12bfdf6e8 Key-hint row in player overlay instead of on-screen buttons
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 23:59:11 +02:00
be-nj
0410eda9c9 Player overlay v2: now/next with programme progress, audio track switching
- Overlay shows current programme (title, time range, EPG progress) and
  what's next; resurfaces briefly on programme change, hides after 5s.
- Audio tracks: listed from the stream, switchable via D-pad left/right
  on live streams (seek keeps left/right on seekable media), via chips
  in the overlay and from the phone remote (set_audio message).
- Main UI font switches to Inter; Space Grotesk stays for the wordmark.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 23:54:02 +02:00
be-nj
e69c79061f Version 0.3.1 2026-08-25 23:42:16 +02:00
be-nj
487ad1254d 0.2.2 + 0.3.0: remote threading fix, phone-first onboarding, ten-foot settings, self-healing errors, in-app updater, group filter
Some checks failed
Build TV app / build (push) Failing after 2s
Squashed history rewrite: earlier revisions of the docs carried private
hostnames; placeholders throughout history now.

- Fix phone remote threading (welcome/get_state/broadcast) — remote connects
  and mirrors channels, Now/Next, favorites
- Phone-first onboarding (ADR-0007): one QR, server URL + IdP login on the
  phone (closes #11)
- Ten-foot settings + Erweitert sub-screen (closes #14), TvTextField D-pad
  focus fix (closes #9)
- EPG grid envelope parsing, Now/Next live (closes #10)
- Self-healing error states (closes #13), in-app updater (closes #12)
- Channel group filter chips fed by Dispatcharr groups

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
v0.2.2 v0.3.0
2026-08-25 23:37:15 +02:00
be-nj
1015a98acb Version 0.2.1 2026-08-25 21:21:56 +02:00
be-nj
8c4857576b Fix Dispatcharr playback: stream URLs must use the channel UUID
The live proxy resolves /proxy/ts/stream/<key> by channel uuid (or stream
hash) — integer ids 404, so every Dispatcharr channel failed to play.
Streams now use the uuid, channels use effective_name/effective_tvg_id and
skip hidden_from_output entries.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 21:20:50 +02:00
be-nj
4f508e9e9a Version 0.2.0
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 18:30:23 +02:00
be-nj
b9195e8658 docs: README reflects the actual feature set 2026-08-25 01:48:48 +02:00
be-nj
0cf22204d3 Compose for TV UI, generic + Dispatcharr sources, device-flow login, favorites, stream profiles, richer remote
- Compose for TV scaffold: D-pad app shell (Live/Einstellungen), channel list
  with focus handling, fullscreen player with auto-hiding overlay; zapping via
  channel/D-pad keys (closes #2)
- Generic source end-to-end: M3U + XMLTV configurable on the TV, Now/Next with
  progress in the list, channel cache (closes #3)
- OIDC device-flow login: server URL is the only input, issuer/client id come
  from the fork's status endpoint; QR + user code screen, silent refresh,
  logout (closes #4)
- Dispatcharr source via Bearer API: channels, groups, EPG grid; switchable
  against the generic source (closes #5)
- Per-user favorites: star via long-press, favorites filter, backend-synced
  (closes #6)
- Stream profile selection (Standard/Passthrough/audiofix/720p from the
  backend profile list), applied per stream URL (closes #7)
- Phone remote: Now/Next lines, favorites star + filter over the WebSocket
  protocol (closes #8)

Device verification pending (TV currently in use).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 01:35:48 +02:00
be-nj
358b4c6a47 Fix startup crash: listener methods collided with Activity lifecycle
ControlServer.Listener declared onPause()/onResume(); implementing them in
MainActivity overrode Activity.onPause/onResume without super calls, so the
first resume died with SuperNotCalledException. Renamed to onPauseCast/
onResumeCast (matching onStopCast). Also drop R8 optimize variant.
Verified on a Sony Bravia (Android TV 14). Version 0.1.1.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 00:48:39 +02:00
be-nj
26cb823508 Release signing from env, version 0.1.0, minSdk 26
Signed with the local release keystore when CASTARR_STORE_* env vars are
set; minSdk raised to 26 to match the adaptive-icon-only resources.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 00:34:45 +02:00
be-nj
e2822d6f6f Rename app to Castarr (dev.castarr.tv), add JDK toolchain resolution
Package/applicationId com.nodecast.tv -> dev.castarr.tv, all branding in app
and remote page renamed, remote localStorage key changed. Foojay toolchain
resolver + jvmToolchain(17) so hosts with only a JRE can build.

Closes #1

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 00:17:59 +02:00
be-nj
a11b5a68c0 Bootstrap Castarr from NodeCast prototype
Imported the native TV app (Kotlin, ExoPlayer, embedded remote server, QR
pairing) plus CONTEXT.md and ADRs 0001-0005. Rename, Compose for TV UI and
the Dispatcharr integration follow as tracked issues.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 00:09:00 +02:00