+ {empty ? (
+
+
{timeStr}
+
{dateStr}
+
+ No photos found{emptyDir ? ` in ${emptyDir}` : ''}.
+
+
Touch anywhere to exit
+
+ ) : (
+ <>
+ {prevSrc && (
+

+ )}
+ {currentSrc && (
+

+ )}
+ {/* Gradient + centered clock/date overlay (Skylight style) */}
+
+
+
+
{timeStr}
+
{dateStr}
+
+
+
+ >
+ )}
+
+ );
+}
diff --git a/src/components/photoframe/index.ts b/src/components/photoframe/index.ts
new file mode 100644
index 0000000..b77409b
--- /dev/null
+++ b/src/components/photoframe/index.ts
@@ -0,0 +1 @@
+export { PhotoFrame } from './PhotoFrame';
diff --git a/src/config/environment.ts b/src/config/environment.ts
index ebc12e6..bdc559d 100644
--- a/src/config/environment.ts
+++ b/src/config/environment.ts
@@ -20,6 +20,10 @@ export const env = {
// Screen management
screenIdleTimeout: parseInt(import.meta.env.VITE_SCREEN_IDLE_TIMEOUT || '300000', 10),
+ // Photo frame idle timeout (ms) - 5 minutes default
+ photoFrameIdleTimeout: parseInt(import.meta.env.VITE_PHOTO_FRAME_IDLE_TIMEOUT || '300000', 10),
+ photoFrameInterval: parseInt(import.meta.env.VITE_PHOTO_FRAME_INTERVAL || '15000', 10),
+
// Presence detection
presenceEnabled: import.meta.env.VITE_PRESENCE_DETECTION_ENABLED === 'true',
presenceConfidenceThreshold: parseFloat(import.meta.env.VITE_PRESENCE_CONFIDENCE_THRESHOLD || '0.6'),
diff --git a/src/hooks/useIdle.ts b/src/hooks/useIdle.ts
new file mode 100644
index 0000000..ec57d12
--- /dev/null
+++ b/src/hooks/useIdle.ts
@@ -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