Add photo frame idle mode and switch to Skylight-style theme
- After 5 min of no touch/motion, dashboard hides behind a fullscreen photo slideshow with centered time and date overlay - Photos loaded from PHOTOS_PATH env var (defaults to ~/Pictures/dashboard) via IPC + file:// URLs; traversal-guarded, recursive up to 2 levels - Motion or touch exits idle back to dashboard - Theme repainted warm cream / sage / stone ink with Nunito font and rounded cards; dark tokens kept so component classes still resolve - Adds PHOTO_FRAME.md with Samba cifs mount + systemd env instructions
This commit is contained in:
50
src/hooks/useIdle.ts
Normal file
50
src/hooks/useIdle.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useUIStore } from '@/stores/uiStore';
|
||||
|
||||
type ElectronAPILike = {
|
||||
motion?: { onDetected: (cb: () => void) => () => void };
|
||||
};
|
||||
|
||||
/**
|
||||
* Tracks touch/mouse/keyboard activity. After `timeoutMs` of no activity,
|
||||
* flips the UI into idle mode (photo frame). Any activity exits idle.
|
||||
* Motion detected by Electron's MotionDetector also cancels idle.
|
||||
*/
|
||||
export function useIdle(timeoutMs: number) {
|
||||
const isIdle = useUIStore((s) => s.isIdle);
|
||||
const setIdle = useUIStore((s) => s.setIdle);
|
||||
|
||||
useEffect(() => {
|
||||
if (timeoutMs <= 0) return;
|
||||
|
||||
let timer: ReturnType<typeof setTimeout> | null = null;
|
||||
|
||||
const reset = () => {
|
||||
if (timer) clearTimeout(timer);
|
||||
if (useUIStore.getState().isIdle) setIdle(false);
|
||||
timer = setTimeout(() => setIdle(true), timeoutMs);
|
||||
};
|
||||
|
||||
const events: Array<keyof DocumentEventMap> = [
|
||||
'touchstart',
|
||||
'mousedown',
|
||||
'mousemove',
|
||||
'keydown',
|
||||
'wheel',
|
||||
];
|
||||
for (const e of events) document.addEventListener(e, reset, { passive: true });
|
||||
|
||||
const api = (window as unknown as { electronAPI?: ElectronAPILike }).electronAPI;
|
||||
const unsubMotion = api?.motion?.onDetected?.(() => reset());
|
||||
|
||||
reset();
|
||||
|
||||
return () => {
|
||||
if (timer) clearTimeout(timer);
|
||||
for (const e of events) document.removeEventListener(e, reset);
|
||||
if (unsubMotion) unsubMotion();
|
||||
};
|
||||
}, [timeoutMs, setIdle]);
|
||||
|
||||
return isIdle;
|
||||
}
|
||||
Reference in New Issue
Block a user