generated from Dicken/dickendock
round36: Bestaetigte Scan-Ergebnisse erscheinen nach Neuladen der Seite nicht mehr erneut (betraf alle drei Scanner)
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import { useState, useEffect, useRef } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||||
import { Link } from "@tanstack/react-router";
|
import { Link } from "@tanstack/react-router";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
@@ -71,6 +71,35 @@ function nameChangeKey(c: ScanNameChange): string {
|
|||||||
return `${c.serviceId}:${c.field}`;
|
return `${c.serviceId}:${c.field}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merkt sich (dauerhaft über sessionStorage, NICHT über React-State), welches
|
||||||
|
* Backend-Scan-Ergebnis (identifiziert über seinen startedAt-Zeitstempel)
|
||||||
|
* bereits in die lokale Anzeige übernommen wurde. Bewusst kein
|
||||||
|
* usePersistedState/useState hier: der Poll-Callback läuft in einem
|
||||||
|
* setInterval, das nur einmal erzeugt wird (leeres deps-Array) - ein
|
||||||
|
* React-State-Wert wäre in diesem Callback für immer auf seinem Anfangswert
|
||||||
|
* eingefroren (stale closure). Gleichzeitig darf der Wert NICHT nur im
|
||||||
|
* Speicher (useRef) leben, sonst würde ein Neuladen der Seite ihn auf null
|
||||||
|
* zurücksetzen und dieselbe Meldung (inkl. bereits bestätigter Einträge)
|
||||||
|
* einfach erneut aus dem immer noch unveränderten Backend-Ergebnis
|
||||||
|
* importieren - genau das gemeldete Problem.
|
||||||
|
*/
|
||||||
|
function getHandledResultId(key: string): string | null {
|
||||||
|
try {
|
||||||
|
return sessionStorage.getItem(`launchpad:${key}`);
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function setHandledResultId(key: string, value: string): void {
|
||||||
|
try {
|
||||||
|
sessionStorage.setItem(`launchpad:${key}`, value);
|
||||||
|
} catch {
|
||||||
|
// Speicher evtl. nicht verfügbar (Privatmodus o. ä.) - dann greift die
|
||||||
|
// Deduplizierung für die aktuelle Sitzung eben nicht, kein Absturz nötig.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Übernimmt einen Namens-/Kategorie-Vorschlag des Scanners. Setzt dabei
|
* Übernimmt einen Namens-/Kategorie-Vorschlag des Scanners. Setzt dabei
|
||||||
* explizit die *EditedManually-Flag auf false zurück, damit der Dienst
|
* explizit die *EditedManually-Flag auf false zurück, damit der Dienst
|
||||||
@@ -311,8 +340,6 @@ function ApiScannerCard() {
|
|||||||
const [lastNewFindings, setLastNewFindings] = usePersistedState<
|
const [lastNewFindings, setLastNewFindings] = usePersistedState<
|
||||||
{ serviceId: string; serviceName: string; apis: DetectedApiEntry[] }[]
|
{ serviceId: string; serviceName: string; apis: DetectedApiEntry[] }[]
|
||||||
>("scanner:apiNewFindings", []);
|
>("scanner:apiNewFindings", []);
|
||||||
const lastHandledStartedAt = useRef<string | null>(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let cancelled = false;
|
let cancelled = false;
|
||||||
|
|
||||||
@@ -328,8 +355,8 @@ function ApiScannerCard() {
|
|||||||
setStatus(
|
setStatus(
|
||||||
`Prüfe ${s.progress.currentLabel ?? "…"} (${s.progress.current + 1} von ${s.progress.total})`
|
`Prüfe ${s.progress.currentLabel ?? "…"} (${s.progress.current + 1} von ${s.progress.total})`
|
||||||
);
|
);
|
||||||
} else if (s.lastResult && s.startedAt !== lastHandledStartedAt.current) {
|
} else if (s.lastResult && s.startedAt !== getHandledResultId("scanner:apiLastHandledAt")) {
|
||||||
lastHandledStartedAt.current = s.startedAt;
|
setHandledResultId("scanner:apiLastHandledAt", s.startedAt);
|
||||||
const r = s.lastResult;
|
const r = s.lastResult;
|
||||||
const newCount = r.newFindings.reduce(
|
const newCount = r.newFindings.reduce(
|
||||||
(sum: number, f: { apis: unknown[] }) => sum + f.apis.length,
|
(sum: number, f: { apis: unknown[] }) => sum + f.apis.length,
|
||||||
@@ -456,7 +483,6 @@ export function ScannerPage() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const [fritzboxRunning, setFritzboxRunning] = useState(false);
|
const [fritzboxRunning, setFritzboxRunning] = useState(false);
|
||||||
const lastFritzboxHandledAt = useRef<string | null>(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let cancelled = false;
|
let cancelled = false;
|
||||||
@@ -469,16 +495,16 @@ export function ScannerPage() {
|
|||||||
|
|
||||||
setFritzboxRunning(s.running);
|
setFritzboxRunning(s.running);
|
||||||
|
|
||||||
if (!s.running && s.lastResult && s.startedAt !== lastFritzboxHandledAt.current) {
|
if (!s.running && s.lastResult && s.startedAt !== getHandledResultId("scanner:fritzboxLastHandledAt")) {
|
||||||
lastFritzboxHandledAt.current = s.startedAt;
|
setHandledResultId("scanner:fritzboxLastHandledAt", s.startedAt);
|
||||||
setFritzboxSummary({ found: s.lastResult.found, uniqueDevices: s.lastResult.uniqueDevices });
|
setFritzboxSummary({ found: s.lastResult.found, uniqueDevices: s.lastResult.uniqueDevices });
|
||||||
setFritzboxError(null);
|
setFritzboxError(null);
|
||||||
setStaleDevices(s.lastResult.staleDevices);
|
setStaleDevices(s.lastResult.staleDevices);
|
||||||
setDeviceChanges(s.lastResult.deviceChanges);
|
setDeviceChanges(s.lastResult.deviceChanges);
|
||||||
queryClient.invalidateQueries({ queryKey: ["devices"] });
|
queryClient.invalidateQueries({ queryKey: ["devices"] });
|
||||||
queryClient.invalidateQueries({ queryKey: ["logs"] });
|
queryClient.invalidateQueries({ queryKey: ["logs"] });
|
||||||
} else if (!s.running && s.lastError && s.startedAt !== lastFritzboxHandledAt.current) {
|
} else if (!s.running && s.lastError && s.startedAt !== getHandledResultId("scanner:fritzboxLastHandledAt")) {
|
||||||
lastFritzboxHandledAt.current = s.startedAt;
|
setHandledResultId("scanner:fritzboxLastHandledAt", s.startedAt);
|
||||||
setFritzboxError(s.lastError);
|
setFritzboxError(s.lastError);
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
@@ -512,7 +538,6 @@ export function ScannerPage() {
|
|||||||
// die Seite offen ist - egal ob DIESER Browser den Scan gestartet hat oder
|
// die Seite offen ist - egal ob DIESER Browser den Scan gestartet hat oder
|
||||||
// ein anderes Gerät: der Fortschritt/das letzte Ergebnis kommt direkt vom
|
// ein anderes Gerät: der Fortschritt/das letzte Ergebnis kommt direkt vom
|
||||||
// Backend, ist also für jeden sichtbar, der die Seite gerade offen hat.
|
// Backend, ist also für jeden sichtbar, der die Seite gerade offen hat.
|
||||||
const lastHandledResultAt = useRef<string | null>(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let cancelled = false;
|
let cancelled = false;
|
||||||
@@ -529,8 +554,8 @@ export function ScannerPage() {
|
|||||||
setBulkStatus(
|
setBulkStatus(
|
||||||
`Scanne ${status.progress.currentLabel ?? "…"} (${status.progress.current + 1} von ${status.progress.total})`
|
`Scanne ${status.progress.currentLabel ?? "…"} (${status.progress.current + 1} von ${status.progress.total})`
|
||||||
);
|
);
|
||||||
} else if (status.lastResult && status.startedAt !== lastHandledResultAt.current) {
|
} else if (status.lastResult && status.startedAt !== getHandledResultId("scanner:bulkLastHandledAt")) {
|
||||||
lastHandledResultAt.current = status.startedAt;
|
setHandledResultId("scanner:bulkLastHandledAt", status.startedAt);
|
||||||
const r = status.lastResult;
|
const r = status.lastResult;
|
||||||
const pending = r.nameChanges.length + r.staleServices.length;
|
const pending = r.nameChanges.length + r.staleServices.length;
|
||||||
setBulkStatus(
|
setBulkStatus(
|
||||||
|
|||||||
Reference in New Issue
Block a user