28 Commits

Author SHA1 Message Date
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>
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>
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>
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>
2026-08-26 02:14:48 +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>
2026-08-26 01:32:34 +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>
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>
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>
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
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
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
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>
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
4f508e9e9a Version 0.2.0
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 18:30:23 +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