Files
genshin-assistant/src/features/scan/components/hooks/useScanTopControlsModel.ts
T
2026-07-07 22:02:24 +02:00

158 lines
6.2 KiB
TypeScript

import { useCallback, useMemo } from "react";
import type { ChangeEvent } from "react";
import type { ScanTopControlsSectionProps } from "../types";
export interface ScanTopControlsModel {
shouldShowGenshinSourceButton: boolean;
bridgeDisabled: boolean;
canStartAutoScan: boolean;
canStartManualScan: boolean;
canCaptureSingle: boolean;
autoScanRunning: boolean;
handleSourceChange: (event: ChangeEvent<HTMLSelectElement>) => void;
selectGenshinSource: () => void;
openSettings: () => void;
openDiagnostics: () => void;
captureSingleArtifact: () => void;
stopScan: () => void;
runGuidedAutoScan: () => void;
runAutoReviewScan: () => void;
bridgeStatusText: string;
bridgePillClass: string;
runtimeStatusText: string;
runtimePillClass: string;
playerStatusText: string;
autoScanButtonTitle: string;
autoScanButtonLabel: string;
manualScanButtonTitle: string;
captureSingleButtonTitle: string;
refreshCaptureSourcesTitle: string;
diagnosticsButtonTitle: string;
scanSetupButtonTitle: string;
showPlayerProgress: boolean;
progressWidth: number;
progressStats: Array<{ label: string; value: number | string; extraClass?: string }>;
}
export function useScanTopControlsModel({
captureSources,
selectedSourceId,
setSelectedSourceId,
captureSelectedSource,
bridgeReady,
isScanning,
controller,
}: Omit<ScanTopControlsSectionProps, "refreshCaptureSources">): ScanTopControlsModel {
const {
setSettingsOpen,
setDiagnosticsOpen,
requestScanStop,
runGuidedAutoScan,
runAutoReviewScan,
autoScanRunning,
canCaptureSource,
canAutoScan,
hasSourceSelected,
requiresAdminForAutoScan,
reviewStatus,
runtimeInfo,
autoScanStats,
storedTotal,
scanProgressPercent,
genshinSource,
} = controller;
const handleSourceChange = useCallback(
(event: ChangeEvent<HTMLSelectElement>) => setSelectedSourceId(event.target.value),
[setSelectedSourceId],
);
const selectGenshinSource = useCallback(() => {
if (genshinSource) {
setSelectedSourceId(genshinSource.id);
}
}, [genshinSource, setSelectedSourceId]);
const openSettings = useCallback(() => setSettingsOpen(true), [setSettingsOpen]);
const openDiagnostics = useCallback(() => setDiagnosticsOpen(true), [setDiagnosticsOpen]);
const captureSingleArtifact = useCallback(() => captureSelectedSource(0, true), [captureSelectedSource]);
const stopScan = useCallback(() => requestScanStop("Stop-Button gedrueckt."), [requestScanStop]);
const startGuidedAutoScan = useCallback(() => {
void runGuidedAutoScan();
}, [runGuidedAutoScan]);
const bridgeStatusText = bridgeReady ? "Bridge verbunden" : "Bridge fehlt";
const bridgePillClass = bridgeReady ? "elevated" : "standard";
const runtimeStatusText = runtimeInfo?.isElevated ? "Admin bereit" : "Standard";
const runtimePillClass = runtimeInfo?.isElevated ? "elevated" : "standard";
const playerStatusText = reviewStatus
|| (runtimeInfo?.isElevated
? "App laeuft als Administrator. Auto-Scan prueft den Screen ohne OCR und startet erst, wenn eine Artifact-Detailkarte offen ist."
: "App laeuft im Standard-Modus - Auto-Scan braucht Administrator-Rechte. Bitte die App schliessen und als Administrator neu starten.");
const autoScanButtonTitle = requiresAdminForAutoScan
? "App laeuft nicht als Administrator. Bitte die App als Administrator neu starten."
: "Prueft zuerst ohne OCR den Screen, oeffnet bei Bedarf per Inventory-Kamera-Sequenz das Artifact-Inventar und scannt erst mit sichtbarer Detailkarte.";
const autoScanButtonLabel = autoScanRunning ? "Scan laeuft..." : "Auto-Scan starten";
const manualScanButtonTitle = "Du klickst die Artifacts in Genshin selbst an; die App liest nur mit. Kein Auto-Klick, kein Scrollen.";
const captureSingleButtonTitle = "Liest das gerade in Genshin geoeffnete Artifact einmalig.";
const refreshCaptureSourcesTitle = "Fenster- und Bildschirmquellen neu suchen";
const diagnosticsButtonTitle = bridgeReady
? "Scanner Diagnose oeffnen: Rechte, Grid-Erkennung und Logs."
: "Scanner Diagnose ist nur in der Electron-App vollstaendig nutzbar.";
const scanSetupButtonTitle = bridgeReady
? "Scan-Ziel, Skip-Zeilen und Operator-Optionen anpassen."
: "Scan-Setup ist nur in der Electron-App vollstaendig nutzbar.";
const showPlayerProgress = autoScanRunning || autoScanStats.clicked > 0 || autoScanStats.parsed > 0;
const progressStats = useMemo(
() => [
{ label: "Klicks", value: autoScanStats.clicked },
{ label: "Positionen", value: autoScanStats.attempted },
{ label: "Verifiziert", value: autoScanStats.verified },
{ label: "ms/Artifact", value: autoScanStats.averageMsPerParsed || "-" },
{ label: "Gespeichert", value: autoScanStats.stored },
{ label: "Review", value: autoScanStats.review },
{ label: "Sammlung", value: storedTotal ?? "-", extraClass: "collection" },
],
[
autoScanStats.clicked,
autoScanStats.attempted,
autoScanStats.verified,
autoScanStats.averageMsPerParsed,
autoScanStats.stored,
autoScanStats.review,
storedTotal,
],
);
return {
shouldShowGenshinSourceButton: Boolean(genshinSource && selectedSourceId !== genshinSource.id),
bridgeDisabled: !bridgeReady || captureSources.length === 0,
canStartAutoScan: hasSourceSelected && !isScanning && !autoScanRunning && canAutoScan && !requiresAdminForAutoScan,
canStartManualScan: hasSourceSelected && !isScanning && !autoScanRunning && canCaptureSource,
canCaptureSingle: hasSourceSelected && !isScanning && !autoScanRunning && canCaptureSource,
autoScanRunning,
handleSourceChange,
selectGenshinSource,
openSettings,
openDiagnostics,
captureSingleArtifact,
stopScan,
runGuidedAutoScan: startGuidedAutoScan,
runAutoReviewScan,
bridgeStatusText,
bridgePillClass,
runtimeStatusText,
runtimePillClass,
playerStatusText,
autoScanButtonTitle,
autoScanButtonLabel,
manualScanButtonTitle,
captureSingleButtonTitle,
refreshCaptureSourcesTitle,
diagnosticsButtonTitle,
scanSetupButtonTitle,
showPlayerProgress,
progressWidth: scanProgressPercent,
progressStats,
};
}