Skip to content

feat: vacation mode #121

Description

@jherforth

Vacation Mode — Implementation Plan

Date: 2026-07-06
Status: Planning


Overview

Add a vacation mode that mutes chore due-time sounds/chimes and replaces the standard screensaver with a fun DVD-style bouncing vacation image. Stored in localStorage (like screensaver settings), with UI in the AdminPanel Interface tab.


Phase 1: Storage & State Foundation

Step 1. Add vacation mode defaults and normalizer to client/src/utils/interfaceSettings.js

  • New key: VACATION_MODE_STORAGE_KEY = 'vacationModeSettings'
  • New defaults: DEFAULT_VACATION_MODE_SETTINGS = { enabled: false, startDate: '', endDate: '', muteSounds: true }
  • Export normalizeVacationModeSettings() and readLocalVacationModeSettings() (follow the exact pattern of readLocalScreensaverSettings)

Step 2. Wire vacation mode state into client/src/app.jsx

  • Import readLocalVacationModeSettings and add const [vacationMode, setVacationMode] = useState(readLocalVacationModeSettings)
  • Add useEffect listener for storage event (like how screensaver settings re-read on storage event at line 461)

Step 3. Mute chore sounds when vacation mode is active — modify app.jsx lines 864–874

  • The useChoreSoundScheduler({ enabled: ... }) call already gates on widgetSettings.chores.enabled && choreSoundGlobalEnabled && choreSoundDeviceEnabled
  • Add && !(vacationMode.enabled && vacationMode.muteSounds) to the enabled expression

Phase 2: AdminPanel UI

Step 4. Add vacation mode section to the Interface tab in client/src/components/AdminPanel.jsx

  • Place it between the Screensaver section and the Daylight Auto Dark Mode section (after the Screensaver Save button + Divider, around line 2506)
  • Section heading with an icon (BeachAccess or FlightTakeoff), info Alert, enabled Switch, muteSounds Switch, Save button
  • Mirror the existing Screensaver section pattern exactly

Step 5. Add saveVacationModeSettings function (mirrors saveScreensaverSettings at line 994)

  • Normalize, write to localStorage, fire storage event

Phase 3: Emoji Jump Out Vacation Screensaver

Step 6. Create client/src/components/VacationScreensaver.jsx

  • Props: onExit — same pattern as ScreenSaver.jsx
  • Emoji pops up from behind the bar/tray/dock in random directions with falling physics out of view at random interval: requestAnimationFrame loop, x,y + dx,dy, random initial velocity upwards + pick random direct to send the emojis + falling physics
  • 8 vacation emoji rendered at fontSize: '4rem': 🏖️ ⛱️ ✈️ ⛷️ 🚗 🎒 ⛺ 🚐
  • Exit on click/touch/Escape, wake lock, zIndex 9999

Step 7. Override screensaver in app.jsx (line 1030)

  • When vacationMode.enabled, render <VacationScreensaver> instead of <ScreenSaver>
  • Lazy-load + idle-warm like ScreenSaver

Phase 4: Visual Vacation Indicator

Step 8. Add a persistent badge in app.jsx when vacation mode is active

  • Top-right corner, subtle, icon + "Vacation Mode" text (like demo mode banner at line 880)

Phase 5: Chore Widget Visual Cues (Optional)

Step 9. Show muted-bell icon near chores with due times when vacation mode is active. Deferrable.


Relevant Files

File Change
client/src/utils/interfaceSettings.js Add vacation mode defaults, normalizer, reader
client/src/app.jsx Add vacationMode state, mute gate, screensaver override, visual indicator
client/src/components/AdminPanel.jsx Add vacation mode UI section + save handler
client/src/components/VacationScreensaver.jsx New — emoji jumping vacation screensaver

Verification

  1. Enable vacation mode → save → verify chore sounds stop
  2. Wait for screensaver timeout → verify vacation screensaver appears (not tabs/photos)
  3. Verify emoji popups: emojis jump out from behind the bottom bar
  4. Verify exit: click/touch/Escape exits vacation screensaver
  5. Verify vacation mode badge visible on main screen
  6. Disable vacation mode → verify normal screensaver and sounds resume
  7. Verify persistence across page refresh

Decisions

  • Storage: localStorage (matches screensaver pattern). Server-sync deferred.
  • Date range: Simple toggle for MVP. Date range pickers in v2.
  • Images: Emoji-based — no external assets, lightweight.
  • Mute scope: Chore due-time sounds only via useChoreSoundScheduler gate.

Other Aspects Worth Considering

  1. Calendar Widget — Could suppress calendar reminders during vacation.
  2. Device-Scoped Vacation — localStorage is per-browser. Server-side sync could enable all-device vacation mode later.
  3. Auto-Expiry — If date range is implemented, auto-disable after end date passes.

Open Questions

  1. Date range vs. simple toggle — Recommend simple on/off toggle for MVP.
  2. Device-scoped vs. global — Per-browser (localStorage) or all devices via server sync?
  3. Image assets — Emoji acceptable, or prefer custom SVG/PNG illustrations?

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

Status
Needs groomed

Relationships

None yet

Development

No branches or pull requests

Issue actions