mirror of
https://github.com/jhbruhn/respira.git
synced 2026-01-27 02:13:41 +00:00
fix: Resolve TypeScript import paths and type errors in hooks refactor
- Fix import paths in domain hooks (useErrorPopoverState, useMachinePolling) - Fix import path in platform hooks (useBluetoothDeviceListener) - Correct RefObject type signatures in useAutoScroll and useClickOutside - Add proper type parameters to hook usages in components - Fix useRef initialization in useMachinePolling - Add type guard for undefined in useErrorPopoverState All TypeScript build errors resolved. Build and tests passing. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
e1aadc9e1f
commit
0db0bcd40a
12 changed files with 49 additions and 71 deletions
|
|
@ -1,5 +1,5 @@
|
|||
import { useEffect, useState, useCallback } from "react";
|
||||
import type { BluetoothDevice } from "../types/electron";
|
||||
import { useState, useCallback, useEffect } from "react";
|
||||
import { useBluetoothDeviceListener } from "@/hooks";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
|
|
@ -11,42 +11,37 @@ import {
|
|||
import { Button } from "@/components/ui/button";
|
||||
|
||||
export function BluetoothDevicePicker() {
|
||||
const [devices, setDevices] = useState<BluetoothDevice[]>([]);
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [isScanning, setIsScanning] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
// Only set up listener in Electron
|
||||
if (window.electronAPI?.onBluetoothDeviceList) {
|
||||
window.electronAPI.onBluetoothDeviceList((deviceList) => {
|
||||
console.log("[BluetoothPicker] Received device list:", deviceList);
|
||||
setDevices(deviceList);
|
||||
// Open the picker when scan starts (even if empty at first)
|
||||
if (!isOpen) {
|
||||
setIsOpen(true);
|
||||
setIsScanning(true);
|
||||
}
|
||||
// Stop showing scanning state once we have devices
|
||||
if (deviceList.length > 0) {
|
||||
setIsScanning(false);
|
||||
}
|
||||
});
|
||||
// Use Bluetooth device listener hook
|
||||
const { devices, isScanning } = useBluetoothDeviceListener((deviceList) => {
|
||||
console.log("[BluetoothPicker] Received device list:", deviceList);
|
||||
// Open the picker when devices are received
|
||||
if (!isOpen && deviceList.length >= 0) {
|
||||
setIsOpen(true);
|
||||
}
|
||||
}, [isOpen]);
|
||||
});
|
||||
|
||||
// Close modal and reset when scan completes with no selection
|
||||
useEffect(() => {
|
||||
if (isOpen && !isScanning && devices.length === 0) {
|
||||
const timer = setTimeout(() => {
|
||||
setIsOpen(false);
|
||||
}, 2000);
|
||||
return () => clearTimeout(timer);
|
||||
}
|
||||
}, [isOpen, isScanning, devices]);
|
||||
|
||||
const handleSelectDevice = useCallback((deviceId: string) => {
|
||||
console.log("[BluetoothPicker] User selected device:", deviceId);
|
||||
window.electronAPI?.selectBluetoothDevice(deviceId);
|
||||
setIsOpen(false);
|
||||
setDevices([]);
|
||||
}, []);
|
||||
|
||||
const handleCancel = useCallback(() => {
|
||||
console.log("[BluetoothPicker] User cancelled device selection");
|
||||
window.electronAPI?.selectBluetoothDevice("");
|
||||
setIsOpen(false);
|
||||
setDevices([]);
|
||||
setIsScanning(false);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ export function ProgressMonitor() {
|
|||
}, [colorBlocks, currentStitch]);
|
||||
|
||||
// Auto-scroll to current block
|
||||
const currentBlockRef = useAutoScroll(currentBlockIndex);
|
||||
const currentBlockRef = useAutoScroll<HTMLDivElement>(currentBlockIndex);
|
||||
|
||||
return (
|
||||
<Card className="p-0 gap-0 lg:h-full border-l-4 border-accent-600 dark:border-accent-500 flex flex-col lg:overflow-hidden">
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { useState, useRef, useEffect } from "react";
|
||||
import { useState, useRef } from "react";
|
||||
import { useClickOutside } from "@/hooks";
|
||||
import { useShallow } from "zustand/react/shallow";
|
||||
import { useMachineStore, usePatternUploaded } from "../stores/useMachineStore";
|
||||
import { usePatternStore } from "../stores/usePatternStore";
|
||||
|
|
@ -269,29 +270,11 @@ export function WorkflowStepper() {
|
|||
const popoverRef = useRef<HTMLDivElement>(null);
|
||||
const stepRefs = useRef<{ [key: number]: HTMLDivElement | null }>({});
|
||||
|
||||
// Close popover when clicking outside
|
||||
useEffect(() => {
|
||||
const handleClickOutside = (event: MouseEvent) => {
|
||||
if (
|
||||
popoverRef.current &&
|
||||
!popoverRef.current.contains(event.target as Node)
|
||||
) {
|
||||
// Check if click was on a step circle
|
||||
const clickedStep = Object.values(stepRefs.current).find((ref) =>
|
||||
ref?.contains(event.target as Node),
|
||||
);
|
||||
if (!clickedStep) {
|
||||
setShowPopover(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (showPopover) {
|
||||
document.addEventListener("mousedown", handleClickOutside);
|
||||
return () =>
|
||||
document.removeEventListener("mousedown", handleClickOutside);
|
||||
}
|
||||
}, [showPopover]);
|
||||
// Close popover when clicking outside (exclude step circles)
|
||||
useClickOutside<HTMLDivElement>(popoverRef, () => setShowPopover(false), {
|
||||
enabled: showPopover,
|
||||
excludeRefs: [stepRefs],
|
||||
});
|
||||
|
||||
const handleStepClick = (stepId: number) => {
|
||||
// Only allow clicking on current step or earlier completed steps
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ export function useErrorPopoverState(
|
|||
) {
|
||||
setWasManuallyDismissed(true);
|
||||
// Also track the specific machine error code if present
|
||||
if (hasError(machineError)) {
|
||||
if (hasError(machineError) && machineError !== undefined) {
|
||||
setDismissedErrorCode(machineError);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ export function useMachinePolling(
|
|||
const [isPolling, setIsPolling] = useState(false);
|
||||
const pollTimeoutRef = useRef<NodeJS.Timeout | null>(null);
|
||||
const serviceCountIntervalRef = useRef<NodeJS.Timeout | null>(null);
|
||||
const pollFunctionRef = useRef<() => Promise<void>>();
|
||||
const pollFunctionRef = useRef<(() => Promise<void>) | undefined>(undefined);
|
||||
|
||||
// Function to determine polling interval based on machine status
|
||||
const getPollInterval = useCallback((status: MachineStatus) => {
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
import { useCallback } from "react";
|
||||
import type { PesPatternData } from "../formats/import/pesImporter";
|
||||
import { transformStitchesRotation } from "../utils/rotationUtils";
|
||||
import { encodeStitchesToPen } from "../formats/pen/encoder";
|
||||
import { decodePenData } from "../formats/pen/decoder";
|
||||
import type { PesPatternData } from "../../formats/import/pesImporter";
|
||||
import { transformStitchesRotation } from "../../utils/rotationUtils";
|
||||
import { encodeStitchesToPen } from "../../formats/pen/encoder";
|
||||
import { decodePenData } from "../../formats/pen/decoder";
|
||||
import {
|
||||
calculatePatternCenter,
|
||||
calculateBoundsFromDecodedStitches,
|
||||
} from "../components/PatternCanvas/patternCanvasHelpers";
|
||||
} from "../../components/PatternCanvas/patternCanvasHelpers";
|
||||
|
||||
export interface UsePatternRotationUploadParams {
|
||||
uploadPattern: (
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { useMemo } from "react";
|
||||
import type { PesPatternData } from "../formats/import/pesImporter";
|
||||
import type { MachineInfo } from "../types/machine";
|
||||
import { calculateRotatedBounds } from "../utils/rotationUtils";
|
||||
import { calculatePatternCenter } from "../components/PatternCanvas/patternCanvasHelpers";
|
||||
import type { PesPatternData } from "../../formats/import/pesImporter";
|
||||
import type { MachineInfo } from "../../types/machine";
|
||||
import { calculateRotatedBounds } from "../../utils/rotationUtils";
|
||||
import { calculatePatternCenter } from "../../components/PatternCanvas/patternCanvasHelpers";
|
||||
|
||||
export interface PatternBoundsCheckResult {
|
||||
fits: boolean;
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ import { useState, useCallback } from "react";
|
|||
import {
|
||||
convertPesToPen,
|
||||
type PesPatternData,
|
||||
} from "../formats/import/pesImporter";
|
||||
import type { IFileService } from "../platform/interfaces/IFileService";
|
||||
} from "../../formats/import/pesImporter";
|
||||
import type { IFileService } from "../../platform/interfaces/IFileService";
|
||||
|
||||
export interface UseFileUploadParams {
|
||||
fileService: IFileService;
|
||||
|
|
|
|||
|
|
@ -7,10 +7,10 @@
|
|||
|
||||
import { useState, useEffect, useCallback, type RefObject } from "react";
|
||||
import type Konva from "konva";
|
||||
import type { PesPatternData } from "../formats/import/pesImporter";
|
||||
import type { MachineInfo } from "../types/machine";
|
||||
import { calculateInitialScale } from "../utils/konvaRenderers";
|
||||
import { calculateZoomToPoint } from "../components/PatternCanvas/patternCanvasHelpers";
|
||||
import type { PesPatternData } from "../../formats/import/pesImporter";
|
||||
import type { MachineInfo } from "../../types/machine";
|
||||
import { calculateInitialScale } from "../../utils/konvaRenderers";
|
||||
import { calculateZoomToPoint } from "../../components/PatternCanvas/patternCanvasHelpers";
|
||||
|
||||
interface UseCanvasViewportOptions {
|
||||
containerRef: RefObject<HTMLDivElement | null>;
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
import { useState, useEffect, useCallback, useRef } from "react";
|
||||
import type Konva from "konva";
|
||||
import type { KonvaEventObject } from "konva/lib/Node";
|
||||
import type { PesPatternData } from "../formats/import/pesImporter";
|
||||
import type { PesPatternData } from "../../formats/import/pesImporter";
|
||||
|
||||
interface UsePatternTransformOptions {
|
||||
pesData: PesPatternData | null;
|
||||
|
|
|
|||
|
|
@ -31,10 +31,10 @@ export interface UseAutoScrollOptions {
|
|||
inline?: ScrollLogicalPosition;
|
||||
}
|
||||
|
||||
export function useAutoScroll<T extends HTMLElement>(
|
||||
export function useAutoScroll<T extends HTMLElement = HTMLElement>(
|
||||
dependency: unknown,
|
||||
options?: UseAutoScrollOptions,
|
||||
): RefObject<T> {
|
||||
): RefObject<T | null> {
|
||||
const ref = useRef<T>(null);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
|
|||
|
|
@ -43,8 +43,8 @@ export interface UseClickOutsideOptions {
|
|||
)[];
|
||||
}
|
||||
|
||||
export function useClickOutside<T extends HTMLElement>(
|
||||
ref: RefObject<T>,
|
||||
export function useClickOutside<T extends HTMLElement = HTMLElement>(
|
||||
ref: RefObject<T | null>,
|
||||
handler: (event: MouseEvent) => void,
|
||||
options?: UseClickOutsideOptions,
|
||||
): void {
|
||||
|
|
|
|||
Loading…
Reference in a new issue