Update-Check im System-Tab, Worker-Adressfeld mit Heimnetz-Warnung, Save-Knopf raus aus dem Worker-Tab
Ampel / ampel (push) Successful in 28s

1. Update-Erkennung (Commander-Frage 'wie kriegen wir Updates mit?'):
   GET /system/updates vergleicht installierte Versionen (Worker-Info) mit
   makemkv.com (Versionsnummer der Download-Seite) und der HandBrake-
   GitHub-Release-API (releases/latest), 12 h gecacht. Einstellungen ->
   System: 'Auf Updates prüfen' + fertiger Update-Befehl bei MakeMKV.
   Selbst-Update gibt es bewusst NICHT (waere Docker-Socket-Zugriff);
   dafuer ist MAKEMKV_VERSION jetzt per .env uebersteuerbar — Update ohne
   Code-Aenderung. HandBrake-Abweichung wird als Info dargestellt
   (Debian-Paket hinkt der offiziellen Version bewusst hinterher).
2. Worker-Anbindung: editierbares Adressfeld statt stillschweigend
   window.location.hostname — Befund: ueber die externe Domain kopierte
   Befehle liefen in den Reverse-Proxy (401) und Worker koennen Redis/
   Postgres eh nur im Heimnetz erreichen. Amber-Warnung bei oeffentlich
   aussehender Adresse, Anleitung ergaenzt.
3. 'Einstellungen speichern' ist im Worker-Tab ausgeblendet — dort gibt
   es nichts zu speichern, der Knopf verwirrte nur.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Hitonabi
2026-07-24 15:39:20 +02:00
parent 76b4286ad3
commit 3987c31b1e
7 changed files with 198 additions and 5 deletions
+34 -1
View File
@@ -41,9 +41,20 @@ export default function WorkerVerwaltung() {
const [workers, setWorkers] = useState<WorkerInfo[]>([])
const [kopiert, setKopiert] = useState(false)
const [variante, setVariante] = useState<'linux' | 'windows'>('linux')
const [rippyHost, setRippyHost] = useState(window.location.hostname)
const { theme } = useDarkMode()
const { toast } = useToast()
// Worker verbinden sich DIREKT mit Redis/Postgres (6379/5432) — das geht
// nur im Heimnetz. Wer das UI gerade über eine externe Domain (Reverse-
// Proxy) aufruft, würde sonst Befehle mit der falschen Adresse kopieren
// (Befund 24.07.: 401 vom Proxy statt Installer).
const siehtOeffentlichAus =
!/^(\d{1,3}\.){3}\d{1,3}$/.test(rippyHost) &&
!rippyHost.endsWith('.local') &&
rippyHost !== 'localhost' &&
rippyHost.includes('.')
const laden = (manuell = false) => {
api.get('/capabilities')
.then(r => {
@@ -59,7 +70,6 @@ export default function WorkerVerwaltung() {
return () => clearInterval(interval)
}, [])
const rippyHost = window.location.hostname
const installBefehl = variante === 'linux'
? [
`git clone <rippy-repo-url> rippy && cd rippy`,
@@ -141,6 +151,29 @@ export default function WorkerVerwaltung() {
{/* Neue Maschine anbinden — zwei Varianten */}
<div className={`rounded-lg p-4 border ${theme === 'dark' ? 'border-slate-700 bg-slate-800/50' : 'border-slate-200 bg-slate-50'}`}>
<h3 className={`font-medium mb-2 ${theme === 'dark' ? 'text-slate-100' : 'text-slate-900'}`}>Maschine als Encoding-Worker anbinden</h3>
{/* Rippy-Adresse für die Befehle: Worker reden DIREKT mit Redis/
Postgres — das geht nur im Heimnetz, nie über die externe Domain */}
<div className="mb-3">
<label className={`block text-xs font-medium mb-1 ${theme === 'dark' ? 'text-slate-400' : 'text-slate-500'}`}>
Rippy-Adresse aus Sicht des Workers (Heimnetz-IP oder -Name)
</label>
<input
value={rippyHost}
onChange={e => setRippyHost(e.target.value.trim())}
className={`w-full max-w-xs px-3 py-2 border rounded-lg text-sm font-mono focus:ring-2 focus:ring-indigo-500 focus:border-transparent ${theme === 'dark' ? 'bg-slate-800 border-slate-600 text-slate-200' : 'bg-white border-slate-300 text-slate-900'}`}
placeholder="192.168.178.162"
/>
{siehtOeffentlichAus && (
<p className={`text-xs mt-1.5 px-2.5 py-1.5 rounded-lg inline-block ${theme === 'dark' ? 'bg-amber-900/30 text-amber-300' : 'bg-amber-50 text-amber-700'}`}>
Das sieht nach einer externen Domain aus (Reverse-Proxy). Worker verbinden sich
direkt mit Redis/Postgres (Ports 6379/5432) das geht nur im Heimnetz, und der
Proxy blockt den Installer-Download (401). Hier die <strong>LAN-IP</strong> der
Rippy-Maschine eintragen, z. B. 192.168.178.162.
</p>
)}
</div>
<div className="flex gap-2 mb-3">
{([['linux', '🐧 Linux (Docker)'], ['windows', '🪟 Windows (nativ, ohne Docker)']] as const).map(([wert, label]) => (
<button
+12
View File
@@ -116,6 +116,11 @@ export default function AnleitungPage() {
danach unter ihrem Namen in der Worker-Liste auf und zieht sich Kompressions-Jobs
automatisch. Gerippt wird immer auf der Rippy-Hauptmaschine (dort hängt das Laufwerk).
</p>
<p>
<span className={fett}>Wichtig:</span> Worker verbinden sich direkt im Heimnetz in den
Befehlen immer die <span className={fett}>LAN-Adresse</span> der Rippy-Maschine verwenden,
nie eine externe Domain (die läuft über den Reverse-Proxy und blockt).
</p>
</Abschnitt>
<Abschnitt icon={Wrench} titel="MakeMKV-Beta-Key &amp; System">
@@ -125,6 +130,13 @@ export default function AnleitungPage() {
Einstellungen → System eintragen — gilt ab dem nächsten Rip, ohne Neustart. DVDs gehen
immer auch ohne Key. Dort stehen auch die Werkzeug-Versionen und der freie Speicherplatz.
</p>
<p>
<span className={fett}>Updates:</span> „Auf Updates prüfen" (ebenfalls Einstellungen
System) vergleicht die installierten Versionen mit makemkv.com und den offiziellen
HandBrake-Releases. Gibt es ein MakeMKV-Update, zeigt Rippy den fertigen
Update-Befehl an wichtig, weil neue Versionen auch die neueste
Disc-Schlüssel-Datenbank mitbringen.
</p>
</Abschnitt>
<Abschnitt icon={Download} titel="Fertige Dateien herunterladen">
+66 -1
View File
@@ -88,6 +88,25 @@ export default function SettingsPage() {
const [testBusy, setTestBusy] = useState(false)
const [quellenStatus, setQuellenStatus] = useState<Record<string, string> | null>(null)
const [quellenBusy, setQuellenBusy] = useState(false)
const [updates, setUpdates] = useState<Record<string, { installiert?: string, verfuegbar?: string, update?: boolean }> | null>(null)
const [updatesBusy, setUpdatesBusy] = useState(false)
const updatesPruefen = async () => {
setUpdatesBusy(true)
try {
const r = await api.get('/system/updates')
setUpdates(r.data)
if (r.data?.makemkv?.update) {
toast('info', `MakeMKV ${r.data.makemkv.verfuegbar} ist verfügbar (installiert: ${r.data.makemkv.installiert})`)
} else {
toast('success', 'Update-Check abgeschlossen')
}
} catch {
toast('error', 'Update-Check fehlgeschlagen (makemkv.com/GitHub nicht erreichbar?)')
} finally {
setUpdatesBusy(false)
}
}
const { theme } = useDarkMode()
const { toast } = useToast()
@@ -732,9 +751,54 @@ export default function SettingsPage() {
Rebuild: <code>docker compose build worker &amp;&amp; docker compose up -d worker</code> (siehe README).
</p>
</div>
{/* Update-Check: Rippy MELDET Updates ehrlich — selbst updaten
kann es nicht (die Versionen stecken im Worker-Image) */}
<div className={`rounded-lg p-4 mt-6 ${theme === 'dark' ? 'bg-slate-700/50' : 'bg-slate-50'}`}>
<div className="flex items-center justify-between mb-2">
<p className={`text-sm font-medium ${theme === 'dark' ? 'text-slate-200' : 'text-slate-700'}`}>Update-Check</p>
<button
onClick={updatesPruefen}
disabled={updatesBusy}
className="px-3 py-1.5 rounded-lg bg-indigo-600 text-white text-xs font-medium hover:bg-indigo-700 transition-colors disabled:opacity-40"
>
{updatesBusy ? 'Prüfe' : 'Auf Updates prüfen'}
</button>
</div>
{updates ? (
<div className="space-y-2 text-sm">
<div className={updates.makemkv?.update ? 'text-amber-500' : (theme === 'dark' ? 'text-slate-300' : 'text-slate-600')}>
<strong>MakeMKV:</strong> installiert {updates.makemkv?.installiert || ''},
aktuell {updates.makemkv?.verfuegbar || 'unbekannt'}
{updates.makemkv?.update && (
<span className="block text-xs mt-1">
Update: in der .env <code>MAKEMKV_VERSION={updates.makemkv.verfuegbar}</code> setzen,
dann auf der Rippy-Maschine <code>docker compose build worker &amp;&amp; docker compose up -d worker</code>.
Neue Version bringt auch die neueste Disc-Schlüssel-Datenbank mit.
</span>
)}
</div>
<div className={theme === 'dark' ? 'text-slate-300' : 'text-slate-600'}>
<strong>HandBrake:</strong> Docker-Worker {updates.handbrake?.installiert || ''} (Debian-Paket),
neueste offizielle Version {updates.handbrake?.verfuegbar || 'unbekannt'}
<span className={`block text-xs mt-1 ${theme === 'dark' ? 'text-slate-500' : 'text-slate-400'}`}>
Im Docker-Worker kommt HandBrake aus Debian und hinkt der offiziellen Version
bewusst hinterher (stabil, keine Eigenbauten). Der native Windows-Worker nutzt
die aktuelle Version direkt.
</span>
</div>
</div>
) : (
<p className={`text-xs ${theme === 'dark' ? 'text-slate-500' : 'text-slate-400'}`}>
Prüft gegen makemkv.com und die HandBrake-GitHub-Releases (Ergebnis wird 12 h gemerkt).
</p>
)}
</div>
</section>}
{/* Save Button */}
{/* Save Button — nicht im Worker-Tab: dort gibt es nichts zu
speichern (Liste + Anbinde-Befehle), der Knopf verwirrte nur */}
{activeTab !== 'worker' && (
<div className={`flex items-center justify-end gap-4 pt-6 transition-colors duration-300 ${theme === 'dark' ? 'border-slate-700' : 'border-slate-200'} border-t`}>
<button
onClick={handleSave}
@@ -754,6 +818,7 @@ export default function SettingsPage() {
)}
</button>
</div>
)}
</div>
</div>
</div>