import { getAssistantBridge } from "../../services/assistantBridge"; import { type ArtifactRepositoryPort, type AutomationRepositoryPort, type CaptureRepositoryPort, type RendererRepositories, type RuntimeRepositoryPort, type ReviewSampleRepositoryPort, type LearningRepositoryPort, type SnapshotRepositoryPort, type OverlayRepositoryPort, type ScanExportPort, } from "./rendererBridgeRepositoryTypes"; import type { AppSnapshot } from "../../types/domain"; import type { ArtifactStoreLoadResult, ArtifactStoreSaveResult, LoadScannerLearningRulesResult, BooleanResult, CaptureSourceInfo, FocusGenshinResult, RuntimeInfo, SaveResultWithPath, ScrollResult, KeyPressResult, AutomationGuard, ClickResult, ReviewSampleListResult, SaveScannerLearningRulesResult, GoodImportFileResult, } from "../../types/global"; const EMPTY_SNAPSHOT: AppSnapshot | null = null; const EMPTY_CAPTURE_SOURCE_LIST: CaptureSourceInfo[] = []; const EMPTY_SAVE_RESULT: SaveResultWithPath = { ok: false, path: "" }; const EMPTY_RUNTIME_INFO: RuntimeInfo = { ok: false, isElevated: false, platform: "unknown", }; const EMPTY_ARTIFACT_STORE_LOAD_RESULT: ArtifactStoreLoadResult = { ok: false, artifacts: [], total: 0, path: "", }; const EMPTY_ARTIFACT_STORE_SAVE_RESULT: ArtifactStoreSaveResult = { ok: false, added: 0, updated: 0, total: 0, path: "", }; const EMPTY_REVIEW_SAMPLES_RESULT: ReviewSampleListResult = { ok: false, samples: [], total: 0, path: "", }; const EMPTY_SCANNER_LEARNING_RULES_RESULT: LoadScannerLearningRulesResult = { ok: false, path: "", rules: {}, }; const EMPTY_SCAN_STATUS_RESULT: SaveResultWithPath = { ok: false, path: "" }; const EMPTY_SAVE_RULES_RESULT: SaveScannerLearningRulesResult = { ok: false, path: "", rules: {}, total: 0, }; const EMPTY_GOOD_IMPORT_FILE_RESULT: GoodImportFileResult = { ok: false, canceled: false, path: "", error: "Electron bridge unavailable.", }; async function createBridgeSafeCall( callback: () => Promise | TResult | null | undefined, fallback: TResult, ): Promise { try { const result = await callback(); return result == null ? fallback : result; } catch { return fallback; } } function emptyAutomationGuard(): AutomationGuard { return { ok: false, escapePressed: false }; } function emptyFocusGenshinResult(): FocusGenshinResult { return { focused: false, alreadyForeground: false }; } function emptyClickResult(): ClickResult { return { ok: false, x: 0, y: 0, clicked: false, moved: false, focused: false, inputBlocked: false, }; } function emptyScrollResult(): ScrollResult { return { ok: false, notchesSent: 0, inputBlocked: false }; } function emptyKeyPressResult(key = ""): KeyPressResult { return { ok: false, key, inputBlocked: false, eventsSent: 0 }; } function emptyBooleanResult(): BooleanResult { return { ok: false }; } export function createRendererRepositories(): RendererRepositories | null { const bridge = getAssistantBridge(); if (!bridge) return null; const artifactRepo: ArtifactRepositoryPort = { loadAll: () => createBridgeSafeCall( () => bridge.loadArtifacts(), EMPTY_ARTIFACT_STORE_LOAD_RESULT, ), saveMany: (records) => createBridgeSafeCall( () => bridge.saveArtifacts(records), EMPTY_ARTIFACT_STORE_SAVE_RESULT, ), }; const captureRepo: CaptureRepositoryPort = { listSources: () => createBridgeSafeCall(() => bridge.listCaptureSources(), EMPTY_CAPTURE_SOURCE_LIST), captureSource: (sourceId, delayMs, focusGenshin, options) => bridge.captureSource(sourceId, delayMs, focusGenshin, options), }; const runtimeRepo: RuntimeRepositoryPort = { getRuntimeInfo: () => createBridgeSafeCall( () => bridge.getRuntimeInfo(), EMPTY_RUNTIME_INFO, ), }; const reviewSamplesRepo: ReviewSampleRepositoryPort = { loadSamples: (limit = 50) => createBridgeSafeCall( () => bridge.loadReviewSamples(limit), EMPTY_REVIEW_SAMPLES_RESULT, ), saveSample: (sample) => createBridgeSafeCall( () => bridge.saveReviewSample(sample), EMPTY_SCAN_STATUS_RESULT, ), }; const learningRepo: LearningRepositoryPort = { loadRules: () => createBridgeSafeCall( () => bridge.loadScannerLearningRules(), EMPTY_SCANNER_LEARNING_RULES_RESULT, ), saveRules: (rules) => createBridgeSafeCall( () => bridge.saveScannerLearningRules(rules), EMPTY_SAVE_RULES_RESULT, ), }; const snapshotRepo: SnapshotRepositoryPort = { load: () => createBridgeSafeCall(() => bridge.loadSnapshot(), EMPTY_SNAPSHOT), save: (snapshot) => createBridgeSafeCall(() => bridge.saveSnapshot(snapshot), EMPTY_SAVE_RESULT), runMockScan: () => createBridgeSafeCall(() => bridge.runMockScan(), EMPTY_SNAPSHOT), publishScannerStatus: (status) => createBridgeSafeCall(() => bridge.publishScannerStatus(status), EMPTY_SCAN_STATUS_RESULT), }; const automationRepo: AutomationRepositoryPort = { getAutomationGuard: () => createBridgeSafeCall( () => bridge.getAutomationGuard(), emptyAutomationGuard(), ), focusGenshinForScanStart: () => createBridgeSafeCall( () => typeof bridge.focusGenshinForScanStart === "function" ? bridge.focusGenshinForScanStart() : bridge.focusGenshin(), emptyFocusGenshinResult(), ), focusGenshin: () => createBridgeSafeCall( () => bridge.focusGenshin(), emptyFocusGenshinResult(), ), focusMainWindow: () => createBridgeSafeCall(() => bridge.focusMainWindow(), emptyBooleanResult()), clickScreen: (x, y) => createBridgeSafeCall(() => bridge.clickScreen(x, y), emptyClickResult()), scrollScreen: (notches, anchorX, anchorY) => createBridgeSafeCall(() => bridge.scrollScreen(notches, anchorX, anchorY), emptyScrollResult()), keyPress: (key) => createBridgeSafeCall(() => bridge.keyPress(key), emptyKeyPressResult(key)), onCommand: bridge.onScannerCommand, }; const overlayRepo: OverlayRepositoryPort = { show: () => createBridgeSafeCall(() => bridge.showOverlay(), emptyBooleanResult()), }; const exportRepo: ScanExportPort = { exportGood: (payload) => createBridgeSafeCall(() => bridge.exportGood(payload), EMPTY_SAVE_RESULT), importGoodFile: () => createBridgeSafeCall(() => bridge.importGoodFile(), EMPTY_GOOD_IMPORT_FILE_RESULT), }; return { artifacts: artifactRepo, capture: captureRepo, runtime: runtimeRepo, reviewSamples: reviewSamplesRepo, learning: learningRepo, snapshot: snapshotRepo, automation: automationRepo, overlay: overlayRepo, export: exportRepo, canExportGood: bridge.canExportGood, canShowOverlay: bridge.canShowOverlay, canAutoScan: bridge.canAutoScan, canReviewSamples: bridge.canReviewSamples, isAvailable: true, }; }