round12: FritzBox-Merge-Bug vor Doppel-Ausloesung fixen, Scan-Meldungen entschaerfen, Dienstname-Fallback aus Hostname statt IP

This commit is contained in:
2026-07-22 23:01:01 +02:00
parent 54f224b650
commit 1f8218dff1
7 changed files with 129 additions and 20 deletions

View File

@@ -338,8 +338,10 @@ function DeviceRow({ device }: { device: DeviceWithServices }) {
mutationFn: () => scanDevice(device.id),
onSuccess: (result) => {
const portsText = result.ports.length > 0 ? result.ports.join(", ") : "keine";
const pending = result.nameChanges.length + result.staleServices.length;
setScanMessage(
`Ports offen: ${portsText} · ${result.created} neu · ${result.updated} aktualisiert`
`Ports offen: ${portsText} · ${result.created} neu` +
(pending > 0 ? ` · ${pending} Änderung(en) warten auf Bestätigung` : "")
);
setStaleServices(result.staleServices);
setNameChanges(result.nameChanges);

View File

@@ -356,10 +356,19 @@ export function ScannerPage() {
}
}
// "updated" zählt jeden bereits bekannten Dienst, dessen Favicon/Beschreibung
// aufgefrischt wurde - das ist normal und keine "Änderung" im Sinne von
// Namens-/Kategorie-Anpassungen. Deshalb hier NICHT mit anzeigen, um nicht
// den Eindruck zu erwecken, es sei bereits etwas Wichtiges verändert
// worden. Echte Änderungen/verschwundene Dienste stehen explizit unten in
// den Listen und müssen einzeln bestätigt werden.
void updated;
const pending = allNameChanges.length + allStale.length;
setBulkStatus(
`Fertig: ${devices.length} Gerät(e) gescannt, ${created} neue Dienste, ${updated} aktualisiert${
allStale.length > 0 ? `, ${allStale.length} nicht mehr gefunden` : ""
}${allNameChanges.length > 0 ? `, ${allNameChanges.length} Namensänderung(en) vorgeschlagen` : ""} (siehe unten).`
`Fertig: ${devices.length} Gerät(e) gescannt, ${created} neue(r) Dienst(e) gefunden.` +
(pending > 0
? ` ${pending} Änderung(en) warten unten auf deine Bestätigung.`
: " Keine Änderungen an bestehenden Diensten vorgeschlagen.")
);
setBulkStaleServices(allStale);
setBulkNameChanges(allNameChanges);

View File

@@ -240,6 +240,7 @@ function ServiceRow({
service,
deviceMac,
deviceIp,
deviceHostname,
draggable,
onDragStart,
onDragOver,
@@ -249,6 +250,7 @@ function ServiceRow({
service: Service;
deviceMac: string | null;
deviceIp: string | null;
deviceHostname: string | null;
draggable: boolean;
onDragStart: (e: DragEvent<HTMLTableRowElement>) => void;
onDragOver: (e: DragEvent<HTMLTableRowElement>) => void;
@@ -328,7 +330,16 @@ function ServiceRow({
</div>
</td>
<td className="px-4 py-3 font-mono text-xs text-black/60 dark:text-white/60">
{service.hostname}
{/* Der gespeicherte Hostname ist oft nur die IP (wenn DNS nichts
Besseres auflösen konnte) - dann lieber den bekannten Gerätenamen
zeigen statt der IP doppelt (die steht schon in der Spalte
daneben). Der technische Wert bleibt beim Bearbeiten unverändert
editierbar/verwendbar, hier geht es nur um die Anzeige. */}
{service.hostname === deviceIp && deviceHostname ? (
<span title={`Technisch: ${service.hostname}`}>{deviceHostname}</span>
) : (
service.hostname
)}
</td>
<td className="px-4 py-3 font-mono text-xs text-black/60 dark:text-white/60">
{deviceIp ?? ""}
@@ -428,6 +439,12 @@ export function ServicesPage() {
return map;
}, [devices]);
const hostnameByDeviceId = useMemo(() => {
const map: Record<string, string | null> = {};
for (const d of devices ?? []) map[d.id] = d.hostname;
return map;
}, [devices]);
const reorderMutation = useMutation({
mutationFn: reorderServicesRequest,
onSuccess: () => {
@@ -569,6 +586,7 @@ export function ServicesPage() {
service={service}
deviceMac={macByDeviceId[service.deviceId] ?? null}
deviceIp={ipByDeviceId[service.deviceId] ?? null}
deviceHostname={hostnameByDeviceId[service.deviceId] ?? null}
draggable={dragEnabled}
isDragging={draggedId === service.id}
onDragStart={handleDragStart(service.id)}