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>
This commit is contained in:
be-nj
2026-08-25 23:37:15 +02:00
parent 1015a98acb
commit 487ad1254d
20 changed files with 940 additions and 313 deletions

View File

@@ -129,6 +129,8 @@
/* --- Pairing --- */
#view-pair { justify-content: center; align-items: center; gap: 26px; padding: 24px; text-align: center; }
#view-setup { justify-content: center; align-items: center; gap: 18px; padding: 24px; }
#setup-url:focus { border-color: #5fd4c4; }
#view-pair h1 { font-size: 24px; font-weight: 500; }
#view-pair p { font-size: 14px; color: #9aa0a8; font-weight: 300; max-width: 280px; line-height: 1.5; }
#code-input { background: #0a0b0d; border: 1px solid #1e2126; border-radius: 12px; height: 56px;
@@ -164,6 +166,20 @@
<div id="pair-error"></div>
</section>
<!-- TV-Einrichtung (Onboarding) -->
<section class="view" id="view-setup">
<h1 style="font-size:24px;font-weight:500;text-align:center">TV einrichten</h1>
<p style="font-size:14px;color:#9aa0a8;font-weight:300;max-width:300px;line-height:1.5;text-align:center">
Gib die Adresse deines TV-Servers an — den Rest erledigt die Anmeldung.
</p>
<input id="setup-url" type="url" placeholder="https://tv.example.com" autocapitalize="off" autocorrect="off"
style="background:#0a0b0d;border:1px solid #1e2126;border-radius:12px;height:52px;width:280px;padding:0 14px;font-size:15px;outline:none;text-align:center">
<button class="btn-accent" id="setup-send" style="width:280px">Verbinden</button>
<a id="setup-login" target="_blank" rel="noopener" class="btn-accent"
style="display:none;width:280px;text-align:center;line-height:46px;text-decoration:none">Jetzt anmelden</a>
<div id="setup-status" style="color:#9aa0a8;font-size:13px;min-height:18px;text-align:center"></div>
</section>
<!-- Steuerung -->
<section class="view" id="view-remote">
<div class="nowcard" id="nowcard">
@@ -319,7 +335,15 @@
if (msg.extras) { state.extras = msg.extras; }
state.playlistUrl = msg.playlistUrl || '';
$('pair-error').textContent = '';
showView('view-remote');
state.setupMode = !!msg.setup;
if (state.setupMode) {
$('setup-url').value = localStorage.getItem('castarr_server_url') || '';
$('setup-login').style.display = 'none';
$('setup-status').textContent = '';
showView('view-setup');
} else {
showView('view-remote');
}
renderAll();
break;
case 'status':
@@ -335,6 +359,21 @@
break;
case 'toast':
toast(msg.message);
if (state.setupMode) { $('setup-status').textContent = msg.message; $('setup-send').disabled = false; }
break;
case 'login_link': {
const link = $('setup-login');
link.href = msg.url;
link.style.display = 'block';
$('setup-status').textContent = 'Code: ' + (msg.code || '') + ' — nach der Anmeldung geht es hier automatisch weiter.';
showView('view-setup');
break;
}
case 'setup_done':
state.setupMode = false;
localStorage.setItem('castarr_server_url', $('setup-url').value.trim());
toast('Fertig! Der Fernseher ist eingerichtet.');
showView('view-remote');
break;
case 'error':
if (msg.error === 'bad_code' || msg.error === 'rate_limited') {
@@ -512,6 +551,14 @@
renderChannels();
});
$('setup-send').addEventListener('click', () => {
const url = $('setup-url').value.trim();
if (!url) { $('setup-status').textContent = 'Bitte Server-Adresse angeben.'; return; }
$('setup-send').disabled = true;
$('setup-status').textContent = 'Verbinde mit Server…';
send({ type: 'configure_server', url });
});
$('pair-btn').addEventListener('click', () => {
const code = $('code-input').value.trim();
if (code.length !== 4) { $('pair-error').textContent = 'Bitte 4 Ziffern eingeben.'; return; }