mirror of
https://github.com/jhbruhn/respira.git
synced 2026-01-27 02:13:41 +00:00
Merge pull request #60 from jhbruhn/refactor/remove-cross-store-dependencies
Some checks are pending
Build, Test, and Lint / Build, Test, and Lint (push) Waiting to run
Draft Release / Draft Release (push) Waiting to run
Draft Release / Build Web App (push) Blocked by required conditions
Draft Release / Build Release - macos-latest (push) Blocked by required conditions
Draft Release / Build Release - ubuntu-latest (push) Blocked by required conditions
Draft Release / Build Release - windows-latest (push) Blocked by required conditions
Draft Release / Upload to GitHub Release (push) Blocked by required conditions
Some checks are pending
Build, Test, and Lint / Build, Test, and Lint (push) Waiting to run
Draft Release / Draft Release (push) Waiting to run
Draft Release / Build Web App (push) Blocked by required conditions
Draft Release / Build Release - macos-latest (push) Blocked by required conditions
Draft Release / Build Release - ubuntu-latest (push) Blocked by required conditions
Draft Release / Build Release - windows-latest (push) Blocked by required conditions
Draft Release / Upload to GitHub Release (push) Blocked by required conditions
refactor: Remove cross-store dependencies using Zustand event store
This commit is contained in:
commit
a173ee33a4
5 changed files with 103 additions and 11 deletions
52
src/stores/storeEvents.ts
Normal file
52
src/stores/storeEvents.ts
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/**
|
||||
* 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 the pattern deleted event.
|
||||
*
|
||||
* The subscription remains active until the returned unsubscribe function is called.
|
||||
* If the unsubscribe function is not called, the listener will persist for the
|
||||
* lifetime of the event store (typically the lifetime of the application).
|
||||
*
|
||||
* Call the returned unsubscribe function when the listener is no longer needed,
|
||||
* especially for short-lived components or non-module-level subscriptions.
|
||||
*
|
||||
* @param callback - Function to call when the event is emitted.
|
||||
* @returns Unsubscribe function that removes the listener when invoked.
|
||||
*/
|
||||
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 type { PesPatternData } from "../formats/import/pesImporter";
|
||||
import { uuidToString } from "../services/PatternCacheService";
|
||||
import { onPatternDeleted } from "./storeEvents";
|
||||
|
||||
/**
|
||||
* Machine Cache Store
|
||||
|
|
@ -192,3 +193,18 @@ export const useMachineCacheStore = create<MachineCacheState>((set, get) => ({
|
|||
});
|
||||
},
|
||||
}));
|
||||
|
||||
// Subscribe to pattern deleted event.
|
||||
// This subscription is intended to persist for the lifetime of the application,
|
||||
// so the unsubscribe function returned by `onPatternDeleted` is intentionally
|
||||
// not stored or called.
|
||||
onPatternDeleted(() => {
|
||||
try {
|
||||
useMachineCacheStore.getState().clearResumeState();
|
||||
} catch (error) {
|
||||
console.error(
|
||||
"[MachineCacheStore] Failed to clear resume state on pattern deleted event:",
|
||||
error,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import { SewingMachineError } from "../utils/errorCodeHelpers";
|
|||
import { uuidToString } from "../services/PatternCacheService";
|
||||
import { createStorageService } from "../platform";
|
||||
import type { IStorageService } from "../platform/interfaces/IStorageService";
|
||||
import { usePatternStore } from "./usePatternStore";
|
||||
import { useEventStore } from "./storeEvents";
|
||||
|
||||
interface MachineState {
|
||||
// Service instances
|
||||
|
|
@ -291,16 +291,8 @@ export const useMachineStore = create<MachineState>((set, get) => ({
|
|||
sewingProgress: null,
|
||||
});
|
||||
|
||||
// Clear uploaded pattern data in pattern store
|
||||
usePatternStore.getState().clearUploadedPattern();
|
||||
|
||||
// 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();
|
||||
// Emit pattern deleted event for other stores to react
|
||||
useEventStore.getState().emitPatternDeleted();
|
||||
|
||||
await refreshStatus();
|
||||
} catch (err) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { create } from "zustand";
|
||||
import type { PesPatternData } from "../formats/import/pesImporter";
|
||||
import { uuidToString } from "../services/PatternCacheService";
|
||||
import { onPatternDeleted } from "./storeEvents";
|
||||
|
||||
/**
|
||||
* Machine Upload Store
|
||||
|
|
@ -126,3 +127,18 @@ export const useMachineUploadStore = create<MachineUploadState>((set) => ({
|
|||
set({ uploadProgress: 0, isUploading: false });
|
||||
},
|
||||
}));
|
||||
|
||||
// Subscribe to pattern deleted event.
|
||||
// This subscription is intended to persist for the lifetime of the application,
|
||||
// so the unsubscribe function returned by `onPatternDeleted` is intentionally
|
||||
// not stored or called.
|
||||
onPatternDeleted(() => {
|
||||
try {
|
||||
useMachineUploadStore.getState().reset();
|
||||
} catch (error) {
|
||||
console.error(
|
||||
"[MachineUploadStore] Failed to reset on pattern deleted event:",
|
||||
error,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { create } from "zustand";
|
||||
import type { PesPatternData } from "../formats/import/pesImporter";
|
||||
import { onPatternDeleted } from "./storeEvents";
|
||||
|
||||
interface PatternState {
|
||||
// Original pattern (pre-upload)
|
||||
|
|
@ -121,3 +122,18 @@ export const useUploadedPatternOffset = () =>
|
|||
usePatternStore((state) => state.uploadedPatternOffset);
|
||||
export const usePatternRotation = () =>
|
||||
usePatternStore((state) => state.patternRotation);
|
||||
|
||||
// Subscribe to pattern deleted event.
|
||||
// This subscription is intended to persist for the lifetime of the application,
|
||||
// so the unsubscribe function returned by `onPatternDeleted` is intentionally
|
||||
// not stored or called.
|
||||
onPatternDeleted(() => {
|
||||
try {
|
||||
usePatternStore.getState().clearUploadedPattern();
|
||||
} catch (error) {
|
||||
console.error(
|
||||
"[PatternStore] Failed to clear uploaded pattern on pattern deleted event:",
|
||||
error,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue