Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions src/accessiclock/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,18 @@ def _load_config(self) -> None:
self.chime_half_hour = self.config.get("chime_half_hour", False)
self.chime_quarter_hour = self.config.get("chime_quarter_hour", False)

# Restore quiet hours
if self.config.get("quiet_hours_enabled", False) and self.clock_service:
from datetime import time as dt_time
try:
sh, sm = map(int, self.config["quiet_start"].split(":"))
eh, em = map(int, self.config["quiet_end"].split(":"))
self.clock_service.set_quiet_hours(dt_time(sh, sm), dt_time(eh, em))
except (KeyError, ValueError) as e:
logger.warning(f"Failed to restore quiet hours: {e}")
elif self.clock_service:
self.clock_service.quiet_hours_enabled = False

logger.info(f"Configuration loaded from {config_file}")
except Exception as e:
logger.warning(f"Failed to load config: {e}")
Expand All @@ -165,13 +177,24 @@ def save_config(self) -> None:
"""Save configuration to file."""
import json

quiet_config = {}
if self.clock_service and self.clock_service.quiet_hours_enabled:
quiet_config = {
"quiet_hours_enabled": True,
"quiet_start": self.clock_service.quiet_start.strftime("%H:%M"),
"quiet_end": self.clock_service.quiet_end.strftime("%H:%M"),
}
else:
quiet_config = {"quiet_hours_enabled": False}

self.config.update(
{
"volume": self.current_volume,
"clock": self.selected_clock,
"chime_hourly": self.chime_hourly,
"chime_half_hour": self.chime_half_hour,
"chime_quarter_hour": self.chime_quarter_hour,
**quiet_config,
}
)

Expand Down
23 changes: 23 additions & 0 deletions src/accessiclock/services/clock_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,29 @@ def _is_quiet_time(self, current_time: time) -> bool:
# Quiet hours within same day
return self.quiet_start <= current_time < self.quiet_end

@property
def quiet_hours_enabled(self) -> bool:
"""Return whether quiet hours are currently enabled."""
return self.quiet_start is not None and self.quiet_end is not None

@quiet_hours_enabled.setter
def quiet_hours_enabled(self, value: bool) -> None:
"""Enable or disable quiet hours. Disabling clears start/end times."""
if not value:
self.quiet_start = None
self.quiet_end = None

def set_quiet_hours(self, start: time, end: time) -> None:
"""
Set quiet hours range.

Args:
start: Start time for quiet hours.
end: End time for quiet hours.
"""
self.quiet_start = start
self.quiet_end = end

def reset_chime_tracking(self) -> None:
"""Reset the chime tracking (e.g., after settings change)."""
self._last_chime_minute = None
26 changes: 26 additions & 0 deletions tests/test_clock_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,3 +255,29 @@ def test_overnight_quiet_hours_boundaries(self):
assert service.should_chime_now(time(23, 0, 0)) is None
# Exactly at end - outside quiet hours
assert service.should_chime_now(time(7, 0, 0)) == "hour"

def test_set_quiet_hours_method(self):
"""set_quiet_hours should configure start and end times."""
from accessiclock.services.clock_service import ClockService

service = ClockService()
service.set_quiet_hours(time(22, 0), time(6, 0))

assert service.quiet_start == time(22, 0)
assert service.quiet_end == time(6, 0)
assert service.quiet_hours_enabled is True

def test_quiet_hours_enabled_property(self):
"""quiet_hours_enabled should reflect whether quiet hours are set."""
from accessiclock.services.clock_service import ClockService

service = ClockService()
assert service.quiet_hours_enabled is False

service.set_quiet_hours(time(22, 0), time(6, 0))
assert service.quiet_hours_enabled is True

service.quiet_hours_enabled = False
assert service.quiet_hours_enabled is False
assert service.quiet_start is None
assert service.quiet_end is None