158 lines
6.2 KiB
TypeScript
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,
|
|
};
|
|
}
|