mirror of
https://github.com/jhbruhn/respira.git
synced 2026-01-27 02:13:41 +00:00
refactor: Remove cross-store dependencies using Zustand event store
Replace direct store imports and calls with a Zustand-based event system for decoupled cross-store communication. Changes: - Created storeEvents.ts using Zustand for event management - Removed direct usePatternStore import from useMachineStore - Removed dynamic imports for useMachineUploadStore and useMachineCacheStore - Added event subscriptions in usePatternStore, useMachineUploadStore, and useMachineCacheStore - useMachineStore now emits patternDeleted event instead of calling other stores directly Benefits: - Stores can be tested in isolation - No tight coupling between stores - Clear, explicit event-driven data flow - Uses Zustand's built-in subscription system - Easier to refactor stores independently Fixes #37 🤖 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
e49a63a4b1
commit
20e9fa13e7
5 changed files with 65 additions and 11 deletions
44
src/stores/storeEvents.ts
Normal file
44
src/stores/storeEvents.ts
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
/**
|
||||||
|
* Store Events
|
||||||
|
*
|
||||||
|
* Zustand-based event store for cross-store communication without tight coupling.
|
||||||
|
* Uses Zustand's built-in subscription system to emit and react to events.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { create } from "zustand";
|
||||||
|
|
||||||
|
interface EventState {
|
||||||
|
// Event counters - incrementing these triggers subscriptions
|
||||||
|
patternDeletedCount: number;
|
||||||
|
|
||||||
|
// Actions to emit events
|
||||||
|
emitPatternDeleted: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event store using Zustand for cross-store communication.
|
||||||
|
* Stores can emit events by calling actions, and subscribe to events using Zustand's subscribe.
|
||||||
|
*/
|
||||||
|
export const useEventStore = create<EventState>((set) => ({
|
||||||
|
patternDeletedCount: 0,
|
||||||
|
|
||||||
|
emitPatternDeleted: () => {
|
||||||
|
set((state) => ({ patternDeletedCount: state.patternDeletedCount + 1 }));
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subscribe to pattern deleted event
|
||||||
|
* @param callback - Function to call when event is emitted
|
||||||
|
* @returns Unsubscribe function
|
||||||
|
*/
|
||||||
|
export const onPatternDeleted = (callback: () => void): (() => void) => {
|
||||||
|
let prevCount = useEventStore.getState().patternDeletedCount;
|
||||||
|
|
||||||
|
return useEventStore.subscribe((state) => {
|
||||||
|
if (state.patternDeletedCount !== prevCount) {
|
||||||
|
prevCount = state.patternDeletedCount;
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { create } from "zustand";
|
import { create } from "zustand";
|
||||||
import type { PesPatternData } from "../formats/import/pesImporter";
|
import type { PesPatternData } from "../formats/import/pesImporter";
|
||||||
import { uuidToString } from "../services/PatternCacheService";
|
import { uuidToString } from "../services/PatternCacheService";
|
||||||
|
import { onPatternDeleted } from "./storeEvents";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Machine Cache Store
|
* Machine Cache Store
|
||||||
|
|
@ -192,3 +193,8 @@ export const useMachineCacheStore = create<MachineCacheState>((set, get) => ({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
// Subscribe to pattern deleted event
|
||||||
|
onPatternDeleted(() => {
|
||||||
|
useMachineCacheStore.getState().clearResumeState();
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ import { SewingMachineError } from "../utils/errorCodeHelpers";
|
||||||
import { uuidToString } from "../services/PatternCacheService";
|
import { uuidToString } from "../services/PatternCacheService";
|
||||||
import { createStorageService } from "../platform";
|
import { createStorageService } from "../platform";
|
||||||
import type { IStorageService } from "../platform/interfaces/IStorageService";
|
import type { IStorageService } from "../platform/interfaces/IStorageService";
|
||||||
import { usePatternStore } from "./usePatternStore";
|
import { useEventStore } from "./storeEvents";
|
||||||
|
|
||||||
interface MachineState {
|
interface MachineState {
|
||||||
// Service instances
|
// Service instances
|
||||||
|
|
@ -291,16 +291,8 @@ export const useMachineStore = create<MachineState>((set, get) => ({
|
||||||
sewingProgress: null,
|
sewingProgress: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Clear uploaded pattern data in pattern store
|
// Emit pattern deleted event for other stores to react
|
||||||
usePatternStore.getState().clearUploadedPattern();
|
useEventStore.getState().emitPatternDeleted();
|
||||||
|
|
||||||
// Clear upload state in upload store
|
|
||||||
const { useMachineUploadStore } = await import("./useMachineUploadStore");
|
|
||||||
useMachineUploadStore.getState().reset();
|
|
||||||
|
|
||||||
// Clear resume state in cache store
|
|
||||||
const { useMachineCacheStore } = await import("./useMachineCacheStore");
|
|
||||||
useMachineCacheStore.getState().clearResumeState();
|
|
||||||
|
|
||||||
await refreshStatus();
|
await refreshStatus();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { create } from "zustand";
|
import { create } from "zustand";
|
||||||
import type { PesPatternData } from "../formats/import/pesImporter";
|
import type { PesPatternData } from "../formats/import/pesImporter";
|
||||||
import { uuidToString } from "../services/PatternCacheService";
|
import { uuidToString } from "../services/PatternCacheService";
|
||||||
|
import { onPatternDeleted } from "./storeEvents";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Machine Upload Store
|
* Machine Upload Store
|
||||||
|
|
@ -126,3 +127,8 @@ export const useMachineUploadStore = create<MachineUploadState>((set) => ({
|
||||||
set({ uploadProgress: 0, isUploading: false });
|
set({ uploadProgress: 0, isUploading: false });
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
// Subscribe to pattern deleted event
|
||||||
|
onPatternDeleted(() => {
|
||||||
|
useMachineUploadStore.getState().reset();
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { create } from "zustand";
|
import { create } from "zustand";
|
||||||
import type { PesPatternData } from "../formats/import/pesImporter";
|
import type { PesPatternData } from "../formats/import/pesImporter";
|
||||||
|
import { onPatternDeleted } from "./storeEvents";
|
||||||
|
|
||||||
interface PatternState {
|
interface PatternState {
|
||||||
// Original pattern (pre-upload)
|
// Original pattern (pre-upload)
|
||||||
|
|
@ -121,3 +122,8 @@ export const useUploadedPatternOffset = () =>
|
||||||
usePatternStore((state) => state.uploadedPatternOffset);
|
usePatternStore((state) => state.uploadedPatternOffset);
|
||||||
export const usePatternRotation = () =>
|
export const usePatternRotation = () =>
|
||||||
usePatternStore((state) => state.patternRotation);
|
usePatternStore((state) => state.patternRotation);
|
||||||
|
|
||||||
|
// Subscribe to pattern deleted event
|
||||||
|
onPatternDeleted(() => {
|
||||||
|
usePatternStore.getState().clearUploadedPattern();
|
||||||
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue