2025-02-06 23:04:50 +02:00
|
|
|
import curses
|
2025-02-09 19:17:31 +02:00
|
|
|
from datetime import datetime, date, timedelta
|
2025-02-06 23:04:50 +02:00
|
|
|
|
|
|
|
class InputHandling:
|
|
|
|
|
|
|
|
def _handle_active_alarms_input(self, key):
|
|
|
|
"""Handle input for active alarms view"""
|
|
|
|
if not self.active_alarms:
|
|
|
|
# No active alarms, return to clock view
|
|
|
|
self.current_view = 'CLOCK'
|
|
|
|
return
|
|
|
|
|
|
|
|
# Get the first (or only) active alarm
|
|
|
|
alarm_id = list(self.active_alarms.keys())[0]
|
|
|
|
|
|
|
|
if key == ord('s'): # Snooze
|
|
|
|
# Send snooze command to control queue
|
|
|
|
self.control_queue.put({
|
|
|
|
'type': 'snooze',
|
|
|
|
'alarm_id': alarm_id
|
|
|
|
})
|
|
|
|
# Remove from active alarms
|
|
|
|
del self.active_alarms[alarm_id]
|
|
|
|
|
|
|
|
# Optional: show a snooze confirmation
|
|
|
|
self._show_error("Alarm Snoozed")
|
|
|
|
|
|
|
|
elif key == ord('d'): # Dismiss
|
|
|
|
# Send dismiss command to control queue
|
|
|
|
self.control_queue.put({
|
|
|
|
'type': 'dismiss',
|
|
|
|
'alarm_id': alarm_id
|
|
|
|
})
|
|
|
|
# Remove from active alarms
|
|
|
|
del self.active_alarms[alarm_id]
|
|
|
|
|
|
|
|
# Return to clock view
|
|
|
|
self.current_view = 'CLOCK'
|
|
|
|
|
|
|
|
def _handle_clock_input(self, key):
|
|
|
|
"""Handle input on the clock view"""
|
|
|
|
if key == ord('a'):
|
|
|
|
self.current_view = 'ADD_ALARM'
|
|
|
|
elif key == ord('s'):
|
|
|
|
self.current_view = 'LIST_ALARMS'
|
|
|
|
self.alarm_list = self.storage.get_saved_alerts()
|
|
|
|
|
|
|
|
def _handle_add_alarm_input(self, key):
|
|
|
|
"""Handle input for alarm creation"""
|
2025-02-09 19:17:31 +02:00
|
|
|
if not hasattr(self, 'alarm_draft'):
|
|
|
|
self.alarm_draft = {
|
|
|
|
'hour': datetime.now().hour,
|
|
|
|
'minute': datetime.now().minute,
|
|
|
|
'name': 'New Alarm',
|
|
|
|
'enabled': True,
|
|
|
|
'date': None,
|
|
|
|
'weekdays': [],
|
|
|
|
'current_weekday': 0, # Add this to track currently selected weekday
|
|
|
|
'editing_name': False,
|
|
|
|
'temp_name': ''
|
|
|
|
}
|
|
|
|
|
2025-02-06 23:04:50 +02:00
|
|
|
alarm = self.alarm_draft
|
|
|
|
|
|
|
|
# Escape key handling
|
|
|
|
if key == 27: # ESC
|
|
|
|
if alarm['editing_name']:
|
|
|
|
# Cancel name editing
|
|
|
|
alarm['name'] = alarm['temp_name']
|
|
|
|
alarm['editing_name'] = False
|
|
|
|
else:
|
|
|
|
# Return to clock view
|
|
|
|
self.current_view = 'CLOCK'
|
|
|
|
return
|
|
|
|
|
|
|
|
# Enter key handling
|
|
|
|
if key == 10: # ENTER
|
|
|
|
if alarm['editing_name']:
|
|
|
|
# Finish name editing
|
|
|
|
alarm['editing_name'] = False
|
|
|
|
self.selected_item = 0
|
|
|
|
else:
|
|
|
|
# Save alarm
|
|
|
|
try:
|
|
|
|
alarm_data = {
|
|
|
|
"name": alarm['name'],
|
|
|
|
"time": f"{alarm['hour']:02d}:{alarm['minute']:02d}:00",
|
|
|
|
"enabled": alarm['enabled'],
|
|
|
|
"repeat_rule": {
|
|
|
|
"type": "weekly" if alarm['weekdays'] else "once",
|
|
|
|
"days_of_week": [self.weekday_names[day].lower() for day in alarm['weekdays']],
|
|
|
|
"at": alarm['date'].strftime("%Y-%m-%d") if alarm['date'] and not alarm['weekdays'] else None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
self.storage.save_new_alert(alarm_data)
|
|
|
|
self.current_view = 'CLOCK'
|
|
|
|
except Exception as e:
|
|
|
|
self._show_error(str(e))
|
|
|
|
return
|
|
|
|
|
2025-02-09 19:17:31 +02:00
|
|
|
# Move selection using Left (h) and Right (l)
|
|
|
|
if not alarm['editing_name']:
|
|
|
|
if key in [ord('h'), curses.KEY_LEFT]:
|
|
|
|
self.selected_item = (self.selected_item - 1) % 6
|
|
|
|
elif key in [ord('l'), curses.KEY_RIGHT]:
|
|
|
|
self.selected_item = (self.selected_item + 1) % 6
|
2025-02-06 23:04:50 +02:00
|
|
|
|
2025-02-09 19:17:31 +02:00
|
|
|
# Handle numeric values (Hour, Minute, Date)
|
|
|
|
if key in [ord('k'), curses.KEY_UP, ord('j'), curses.KEY_DOWN]:
|
|
|
|
is_up = key in [ord('k'), curses.KEY_UP]
|
|
|
|
delta = 1 if is_up else -1
|
|
|
|
|
|
|
|
if self.selected_item == 0: # Hour
|
|
|
|
alarm['hour'] = (alarm['hour'] + delta) % 24
|
|
|
|
elif self.selected_item == 1: # Minute
|
|
|
|
alarm['minute'] = (alarm['minute'] + delta) % 60
|
|
|
|
elif self.selected_item == 2: # Date
|
|
|
|
if not alarm['date']:
|
2025-02-06 23:04:50 +02:00
|
|
|
alarm['date'] = datetime.now().date()
|
|
|
|
else:
|
|
|
|
try:
|
2025-02-09 19:17:31 +02:00
|
|
|
if not hasattr(self, 'date_edit_pos'):
|
|
|
|
self.date_edit_pos = 2 # Default to editing the day
|
2025-02-06 23:04:50 +02:00
|
|
|
current_date = alarm['date']
|
|
|
|
if self.date_edit_pos == 0: # Year
|
|
|
|
alarm['date'] = current_date.replace(year=max(current_date.year + delta, datetime.now().year))
|
|
|
|
elif self.date_edit_pos == 1: # Month
|
|
|
|
new_month = max(1, min(12, current_date.month + delta))
|
|
|
|
max_day = (datetime(current_date.year, new_month, 1) + timedelta(days=31)).replace(day=1) - timedelta(days=1)
|
|
|
|
alarm['date'] = current_date.replace(month=new_month, day=min(current_date.day, max_day.day))
|
|
|
|
elif self.date_edit_pos == 2: # Day
|
|
|
|
max_day = (datetime(current_date.year, current_date.month, 1) + timedelta(days=31)).replace(day=1) - timedelta(days=1)
|
|
|
|
alarm['date'] = current_date.replace(day=max(1, min(max_day.day, current_date.day + delta)))
|
|
|
|
except ValueError as e:
|
|
|
|
self._show_error(str(e))
|
|
|
|
|
2025-02-09 19:17:31 +02:00
|
|
|
# Weekday Selection
|
|
|
|
elif self.selected_item == 3: # When weekdays are selected
|
2025-02-06 23:04:50 +02:00
|
|
|
if key in [ord('h'), curses.KEY_LEFT]:
|
2025-02-09 19:17:31 +02:00
|
|
|
# Move selection left
|
|
|
|
alarm['current_weekday'] = (alarm['current_weekday'] - 1) % 7
|
2025-02-06 23:04:50 +02:00
|
|
|
elif key in [ord('l'), curses.KEY_RIGHT]:
|
2025-02-09 19:17:31 +02:00
|
|
|
# Move selection right
|
|
|
|
alarm['current_weekday'] = (alarm['current_weekday'] + 1) % 7
|
|
|
|
elif key == 32: # SPACE to toggle selection
|
|
|
|
current_day = alarm['current_weekday']
|
2025-02-06 23:04:50 +02:00
|
|
|
if current_day in alarm['weekdays']:
|
|
|
|
alarm['weekdays'].remove(current_day)
|
|
|
|
else:
|
|
|
|
alarm['weekdays'].append(current_day)
|
|
|
|
alarm['weekdays'].sort()
|
|
|
|
|
|
|
|
# Clear date if weekdays are selected
|
|
|
|
if alarm['weekdays']:
|
|
|
|
alarm['date'] = None
|
|
|
|
|
2025-02-09 19:17:31 +02:00
|
|
|
# Name Editing
|
|
|
|
elif self.selected_item == 4:
|
|
|
|
if key == 32: # SPACE to start editing
|
|
|
|
if not alarm['editing_name']:
|
|
|
|
alarm['editing_name'] = True
|
|
|
|
alarm['temp_name'] = alarm['name']
|
|
|
|
alarm['name'] = ''
|
|
|
|
elif alarm['editing_name']:
|
|
|
|
if key == curses.KEY_BACKSPACE or key == 127:
|
|
|
|
alarm['name'] = alarm['name'][:-1]
|
|
|
|
elif 32 <= key <= 126: # Printable ASCII
|
|
|
|
alarm['name'] += chr(key)
|
|
|
|
|
|
|
|
# Enabled/Disabled Toggle
|
|
|
|
elif self.selected_item == 5 and key == 32:
|
|
|
|
alarm['enabled'] = not alarm['enabled']
|
2025-02-06 23:04:50 +02:00
|
|
|
|
|
|
|
def _handle_list_alarms_input(self, key):
|
|
|
|
"""Handle input for alarm list view"""
|
|
|
|
total_items = len(self.alarm_list) + 1 # +1 for "Add new alarm" option
|
|
|
|
|
|
|
|
if key == 27: # ESC
|
|
|
|
self.current_view = 'CLOCK'
|
|
|
|
elif key in [ord('j'), curses.KEY_DOWN]:
|
|
|
|
self.selected_item = (self.selected_item + 1) % total_items
|
|
|
|
elif key in [ord('k'), curses.KEY_UP]:
|
|
|
|
self.selected_item = (self.selected_item - 1) % total_items
|
|
|
|
elif key == ord('d'):
|
|
|
|
# Only delete if a real alarm is selected (not the "Add new" option)
|
|
|
|
if self.selected_item < len(self.alarm_list) and self.alarm_list:
|
|
|
|
try:
|
|
|
|
alarm_to_delete = self.alarm_list[self.selected_item]
|
|
|
|
self.storage.remove_saved_alert(alarm_to_delete['id'])
|
|
|
|
self.alarm_list = self.storage.get_saved_alerts()
|
|
|
|
# Adjust selected item if needed
|
|
|
|
if self.selected_item >= len(self.alarm_list):
|
|
|
|
self.selected_item = len(self.alarm_list)
|
|
|
|
except Exception as e:
|
|
|
|
self._show_error(f"Failed to delete alarm: {e}")
|
|
|
|
elif key in [ord('a'), 10]: # 'a' or Enter
|
|
|
|
if self.selected_item == len(self.alarm_list):
|
|
|
|
# "Add new alarm" option selected
|
|
|
|
self.current_view = 'ADD_ALARM'
|
|
|
|
else:
|
|
|
|
# TODO: Implement alarm editing
|
|
|
|
self._show_error("Alarm editing not implemented yet")
|