feature: Replace setTimeout with requestAnimationFrame for UI polling

Co-authored-by: jhbruhn <1036566+jhbruhn@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot] 2025-12-28 08:40:46 +00:00
parent 46553ea0e9
commit 641bc04766

View file

@ -42,7 +42,7 @@ interface MachineState {
isDeleting: boolean; isDeleting: boolean;
// Polling control // Polling control
pollIntervalId: NodeJS.Timeout | null; pollRafId: number | null;
serviceCountIntervalId: NodeJS.Timeout | null; serviceCountIntervalId: NodeJS.Timeout | null;
// Actions // Actions
@ -81,7 +81,7 @@ export const useMachineStore = create<MachineState>((set, get) => ({
isPairingError: false, isPairingError: false,
isCommunicating: false, isCommunicating: false,
isDeleting: false, isDeleting: false,
pollIntervalId: null, pollRafId: null,
serviceCountIntervalId: null, serviceCountIntervalId: null,
// Connect to machine // Connect to machine
@ -370,48 +370,57 @@ export const useMachineStore = create<MachineState>((set, get) => ({
return 2000; // Default for idle states return 2000; // Default for idle states
}; };
// Main polling function // Track last poll time for throttling
const poll = async () => { let lastPollTime = 0;
await refreshStatus();
// Refresh progress during sewing // Main polling function using requestAnimationFrame
if (get().machineStatus === MachineStatus.SEWING) { const poll = async (timestamp: number) => {
await refreshProgress(); // Check if enough time has passed since last poll
const interval = getPollInterval();
const elapsed = timestamp - lastPollTime;
if (elapsed >= interval) {
lastPollTime = timestamp;
await refreshStatus();
// Refresh progress during sewing
if (get().machineStatus === MachineStatus.SEWING) {
await refreshProgress();
}
// follows the apps logic:
// Check if we have a cached pattern and pattern info needs refreshing
const { useMachineCacheStore } = await import("./useMachineCacheStore");
if (
useMachineCacheStore.getState().resumeAvailable &&
get().patternInfo?.totalStitches == 0
) {
await refreshPatternInfo();
}
} }
// follows the apps logic: // Schedule next poll using requestAnimationFrame
// Check if we have a cached pattern and pattern info needs refreshing const pollRafId = requestAnimationFrame(poll);
const { useMachineCacheStore } = await import("./useMachineCacheStore"); set({ pollRafId });
if (
useMachineCacheStore.getState().resumeAvailable &&
get().patternInfo?.totalStitches == 0
) {
await refreshPatternInfo();
}
// Schedule next poll with updated interval
const newInterval = getPollInterval();
const pollIntervalId = setTimeout(poll, newInterval);
set({ pollIntervalId });
}; };
// Start polling // Start polling with requestAnimationFrame
const initialInterval = getPollInterval(); const pollRafId = requestAnimationFrame(poll);
const pollIntervalId = setTimeout(poll, initialInterval);
// Service count polling (every 10 seconds) // Service count polling (every 10 seconds)
const serviceCountIntervalId = setInterval(refreshServiceCount, 10000); const serviceCountIntervalId = setInterval(refreshServiceCount, 10000);
set({ pollIntervalId, serviceCountIntervalId }); set({ pollRafId, serviceCountIntervalId });
}, },
// Stop polling // Stop polling
_stopPolling: () => { _stopPolling: () => {
const { pollIntervalId, serviceCountIntervalId } = get(); const { pollRafId, serviceCountIntervalId } = get();
if (pollIntervalId) { if (pollRafId) {
clearTimeout(pollIntervalId); cancelAnimationFrame(pollRafId);
set({ pollIntervalId: null }); set({ pollRafId: null });
} }
if (serviceCountIntervalId) { if (serviceCountIntervalId) {