fix(scan): repair pre-existing tsc errors so the build is green

The scan feature had 16 tsc errors from refactor drift; npm run build failed.

- modals/hooks/* are five levels deep but imported ../../../../lib (four);
  corrected to ../../../../../lib.
- useScanDiagnosticsModalModel / useScanReviewQueueModalModel picked
  saveReviewSample / canSaveReviewSample / loadReviewQueue from the modal Props,
  but the components wire those through from controller.*; source them from the
  controller type instead (fixes the downstream unknown-type errors).
- useScanResultCardModel let its field-row tuple array widen to
  (string | ParsedField)[][]; annotate it Array<[string, ParsedField]> like the
  sibling hook.
- ScanTopControlsModel was missing autoScanRunning (destructured by the
  component); add it. useScanTopControlsModel does not use refreshCaptureSources,
  so its input is Omit<...,"refreshCaptureSources">.

tsc, vite build, and the electron build all pass; 74 tests green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
AzuTear
2026-07-05 21:25:34 +02:00
parent b7dbc618b3
commit 92345ef51a
6 changed files with 27 additions and 18 deletions
@@ -60,11 +60,7 @@ export function useScanResultCardModel({
parsed, parsed,
}: Pick<ArtifactResultCardProps, "parsed">): ScanResultCardModel { }: Pick<ArtifactResultCardProps, "parsed">): ScanResultCardModel {
const substats = parsed.substats; const substats = parsed.substats;
const rows: Array<[string, ParsedField]> = [
return {
levelField: getLevelField(parsed),
quality: resolveQuality(parsed.confidence),
fieldRows: [
["Name", parsed.fields.name], ["Name", parsed.fields.name],
["Slot", parsed.fields.slot], ["Slot", parsed.fields.slot],
["Level", getLevelField(parsed)], ["Level", getLevelField(parsed)],
@@ -72,7 +68,12 @@ export function useScanResultCardModel({
["Set", parsed.fields.setName], ["Set", parsed.fields.setName],
["Equipped", parsed.fields.equipped], ["Equipped", parsed.fields.equipped],
["Substats", parsed.fields.substats], ["Substats", parsed.fields.substats],
].map(([label, field]) => ({ ];
return {
levelField: getLevelField(parsed),
quality: resolveQuality(parsed.confidence),
fieldRows: rows.map(([label, field]) => ({
label, label,
field, field,
confidenceClassName: resolveFieldConfidenceClass(field), confidenceClassName: resolveFieldConfidenceClass(field),
@@ -8,6 +8,7 @@ export interface ScanTopControlsModel {
canStartAutoScan: boolean; canStartAutoScan: boolean;
canStartManualScan: boolean; canStartManualScan: boolean;
canCaptureSingle: boolean; canCaptureSingle: boolean;
autoScanRunning: boolean;
handleSourceChange: (event: ChangeEvent<HTMLSelectElement>) => void; handleSourceChange: (event: ChangeEvent<HTMLSelectElement>) => void;
selectGenshinSource: () => void; selectGenshinSource: () => void;
openSettings: () => void; openSettings: () => void;
@@ -41,7 +42,7 @@ export function useScanTopControlsModel({
bridgeReady, bridgeReady,
isScanning, isScanning,
controller, controller,
}: ScanTopControlsSectionProps): ScanTopControlsModel { }: Omit<ScanTopControlsSectionProps, "refreshCaptureSources">): ScanTopControlsModel {
const { const {
setSettingsOpen, setSettingsOpen,
setDiagnosticsOpen, setDiagnosticsOpen,
@@ -116,6 +117,7 @@ export function useScanTopControlsModel({
canStartAutoScan: hasSourceSelected && !isScanning && !autoScanRunning && canAutoScan && !requiresAdminForAutoScan, canStartAutoScan: hasSourceSelected && !isScanning && !autoScanRunning && canAutoScan && !requiresAdminForAutoScan,
canStartManualScan: hasSourceSelected && !isScanning && !autoScanRunning && canCaptureSource, canStartManualScan: hasSourceSelected && !isScanning && !autoScanRunning && canCaptureSource,
canCaptureSingle: hasSourceSelected && !isScanning && !autoScanRunning && canCaptureSource, canCaptureSingle: hasSourceSelected && !isScanning && !autoScanRunning && canCaptureSource,
autoScanRunning,
handleSourceChange, handleSourceChange,
selectGenshinSource, selectGenshinSource,
openSettings, openSettings,
@@ -1,6 +1,6 @@
import { useCallback, type MouseEvent } from "react"; import { useCallback, type MouseEvent } from "react";
import type { ScanDetailsModalProps } from "../types"; import type { ScanDetailsModalProps } from "../types";
import type { ParsedArtifactCandidate } from "../../../../lib/artifactOcrParser"; import type { ParsedArtifactCandidate } from "../../../../../lib/artifactOcrParser";
export interface ScanDetailsModalModel { export interface ScanDetailsModalModel {
closeDetails: () => void; closeDetails: () => void;
@@ -1,5 +1,5 @@
import { detailFingerprint } from "../../../../lib/autoScanLoop"; import { detailFingerprint } from "../../../../../lib/autoScanLoop";
import { sourceVersion } from "../../../../lib/genshinData"; import { sourceVersion } from "../../../../../lib/genshinData";
import { useCallback, useMemo, type MouseEvent } from "react"; import { useCallback, useMemo, type MouseEvent } from "react";
import type { ScanDiagnosticsModalProps } from "../types"; import type { ScanDiagnosticsModalProps } from "../types";
@@ -39,16 +39,20 @@ export interface ScanDiagnosticsModalModel {
canSaveReviewSample: boolean; canSaveReviewSample: boolean;
} }
type ScanDiagnosticsController = ScanDiagnosticsModalProps["controller"];
interface UseScanDiagnosticsModalModelInput extends Pick< interface UseScanDiagnosticsModalModelInput extends Pick<
ScanDiagnosticsModalProps, ScanDiagnosticsModalProps,
| "setDetailsOpen" | "setDetailsOpen"
| "setDiagnosticsOpen" | "setDiagnosticsOpen"
| "saveReviewSample"
| "canSaveReviewSample"
| "latestCapture" | "latestCapture"
| "controller" | "controller"
> { > {
captureStatus: string; captureStatus: string;
// saveReviewSample / canSaveReviewSample live on the controller, not the modal
// props; the component wires them through from controller.* .
saveReviewSample: ScanDiagnosticsController["saveReviewSample"];
canSaveReviewSample: ScanDiagnosticsController["canSaveReviewSample"];
} }
export function useScanDiagnosticsModalModel({ export function useScanDiagnosticsModalModel({
@@ -1,5 +1,5 @@
import { useCallback, useMemo, type MouseEvent } from "react"; import { useCallback, useMemo, type MouseEvent } from "react";
import type { ReviewSampleAnalysis } from "../../../../lib/reviewSampleAnalysis"; import type { ReviewSampleAnalysis } from "../../../../../lib/reviewSampleAnalysis";
import type { ScanReviewQueueModalProps } from "../types"; import type { ScanReviewQueueModalProps } from "../types";
export interface ScanReviewQueueRow { export interface ScanReviewQueueRow {
@@ -18,8 +18,10 @@ export interface ScanReviewQueueModalModel {
interface UseScanReviewQueueModalModelInput extends Pick< interface UseScanReviewQueueModalModelInput extends Pick<
ScanReviewQueueModalProps, ScanReviewQueueModalProps,
"setReviewQueueOpen" | "loadReviewQueue" "setReviewQueueOpen"
> { > {
// loadReviewQueue is wired through from controller.* by the component.
loadReviewQueue: ScanReviewQueueModalProps["controller"]["loadReviewQueue"];
reviewAnalysis: ReviewSampleAnalysis; reviewAnalysis: ReviewSampleAnalysis;
reviewSampleTotal: number; reviewSampleTotal: number;
} }
@@ -1,6 +1,6 @@
import { useCallback, type ChangeEvent, type MouseEvent } from "react"; import { useCallback, type ChangeEvent, type MouseEvent } from "react";
import type { CaptureResult, RuntimeInfo } from "../../../../../types/global"; import type { CaptureResult, RuntimeInfo } from "../../../../../types/global";
import { clampScanLimit, clampSkipRows } from "../../../../lib/scannerSession"; import { clampScanLimit, clampSkipRows } from "../../../../../lib/scannerSession";
export interface ScanSettingsModalModel { export interface ScanSettingsModalModel {
closeSettings: () => void; closeSettings: () => void;