Download apps/dashboard/src/store/timer.ts from AUXteam/Midday: direct link, hf CLI and curl.
- Browser
- Download file 3.4 kB
-
https://huggingface.co/spaces/AUXteam/Midday/resolve/main/apps/dashboard/src/store/timer.ts
- Command line
-
hf download hf://spaces/AUXteam/Midday/apps/dashboard/src/store/timer.ts
-
curl -L -o timer.ts https://huggingface.co/spaces/AUXteam/Midday/resolve/main/apps/dashboard/src/store/timer.ts
3.4 kB
| import { create } from "zustand"; | |
| interface TimerState { | |
| // Timer state | |
| isRunning: boolean; | |
| elapsedTime: number; | |
| projectName: string | null; | |
| projectId: string | null; | |
| // Internal state | |
| _intervalId: NodeJS.Timeout | null; | |
| _originalTitle: string | null; | |
| // Actions | |
| setTimerStatus: (status: { | |
| isRunning: boolean; | |
| elapsedTime: number; | |
| projectName: string | null; | |
| projectId: string | null; | |
| }) => void; | |
| tick: () => void; | |
| startInterval: () => void; | |
| stopInterval: () => void; | |
| reset: () => void; | |
| } | |
| // Format time as HH:MM:SS for document title | |
| const formatTime = (seconds: number): string => { | |
| const h = Math.floor(seconds / 3600); | |
| const m = Math.floor((seconds % 3600) / 60); | |
| const s = seconds % 60; | |
| return `${String(h).padStart(2, "0")}:${String(m).padStart(2, "0")}:${String(s).padStart(2, "0")}`; | |
| }; | |
| // Update document title (called from single interval only) | |
| const updateTitle = (elapsedTime: number, projectName: string | null) => { | |
| if (typeof window === "undefined") return; | |
| if (projectName) { | |
| document.title = `${formatTime(elapsedTime)} • ${projectName} | Midday`; | |
| } | |
| }; | |
| // Restore original title | |
| const restoreTitle = (originalTitle: string | null) => { | |
| if (typeof window === "undefined") return; | |
| if (originalTitle) { | |
| document.title = originalTitle; | |
| } | |
| }; | |
| export const useTimerStore = create<TimerState>()((set, get) => ({ | |
| // Initial state | |
| isRunning: false, | |
| elapsedTime: 0, | |
| projectName: null, | |
| projectId: null, | |
| _intervalId: null, | |
| _originalTitle: null, | |
| setTimerStatus: (status) => { | |
| const { isRunning: wasRunning } = get(); | |
| const { isRunning, elapsedTime, projectName, projectId } = status; | |
| set({ isRunning, elapsedTime, projectName, projectId }); | |
| // Handle interval start/stop based on running state change | |
| if (isRunning && !wasRunning) { | |
| get().startInterval(); | |
| } else if (!isRunning && wasRunning) { | |
| get().stopInterval(); | |
| } | |
| // Update title immediately when status changes | |
| if (isRunning && projectName) { | |
| updateTitle(elapsedTime, projectName); | |
| } | |
| }, | |
| tick: () => { | |
| const { isRunning, elapsedTime, projectName } = get(); | |
| if (!isRunning) return; | |
| const newElapsedTime = elapsedTime + 1; | |
| set({ elapsedTime: newElapsedTime }); | |
| // Update document title (single update per second) | |
| updateTitle(newElapsedTime, projectName); | |
| }, | |
| startInterval: () => { | |
| const { _intervalId } = get(); | |
| // Don't start if already running | |
| if (_intervalId) return; | |
| // Store original title | |
| if (typeof window !== "undefined") { | |
| set({ _originalTitle: document.title }); | |
| } | |
| // Start the single interval | |
| const intervalId = setInterval(() => { | |
| get().tick(); | |
| }, 1000); | |
| set({ _intervalId: intervalId }); | |
| }, | |
| stopInterval: () => { | |
| const { _intervalId, _originalTitle } = get(); | |
| if (_intervalId) { | |
| clearInterval(_intervalId); | |
| set({ _intervalId: null }); | |
| } | |
| // Restore original title | |
| restoreTitle(_originalTitle); | |
| }, | |
| reset: () => { | |
| const { _intervalId, _originalTitle } = get(); | |
| if (_intervalId) { | |
| clearInterval(_intervalId); | |
| } | |
| restoreTitle(_originalTitle); | |
| set({ | |
| isRunning: false, | |
| elapsedTime: 0, | |
| projectName: null, | |
| projectId: null, | |
| _intervalId: null, | |
| _originalTitle: null, | |
| }); | |
| }, | |
| })); | |