feat: safe HTML descriptions, custom reminder picker, synced default event duration

- Render event descriptions as sanitized HTML (links/line breaks) instead of
  raw escaped text; no script execution
- Reminder picker: presets + custom number+unit (minutes/hours/days/weeks)
- Grey out + hint the reminder editor when a calendar's notifications are off
  (reminders are kept, just not fired)
- New synced setting default_event_duration_minutes (default 60) for new events

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-06-15 10:00:52 +02:00
parent e6bc7eab9d
commit c515e9d7e1
8 changed files with 218 additions and 16 deletions

View File

@@ -210,6 +210,13 @@ def _migrate():
logging.info("Migration: added reminders_enabled to %s", tbl)
except Exception:
pass
# Synced default duration (minutes) for newly created events.
try:
conn.execute(text("ALTER TABLE user_settings ADD COLUMN default_event_duration_minutes INTEGER DEFAULT 60"))
conn.commit()
logging.info("Migration: added default_event_duration_minutes to user_settings")
except Exception:
pass
_migrate()

View File

@@ -106,6 +106,8 @@ class UserSettings(Base):
# Default reminder in minutes-before-start applied to all events client-side
# (0 = at start time). NULL = no default reminder.
default_reminder_minutes = Column(Integer, nullable=True)
# Default duration (in minutes) applied to a newly created event's end time.
default_event_duration_minutes = Column(Integer, default=60)
user = relationship("User", back_populates="settings")

View File

@@ -30,6 +30,7 @@ class SettingsUpdate(BaseModel):
private_event_visibility: Optional[str] = None
group_visible_calendar_id: Optional[int] = None
default_reminder_minutes: Optional[int] = None # null = off
default_event_duration_minutes: Optional[int] = None
def _settings_dict(s: models.UserSettings) -> dict:
@@ -52,6 +53,7 @@ def _settings_dict(s: models.UserSettings) -> dict:
"private_event_visibility": s.private_event_visibility or "busy",
"group_visible_calendar_id": s.group_visible_calendar_id,
"default_reminder_minutes": s.default_reminder_minutes,
"default_event_duration_minutes": s.default_event_duration_minutes or 60,
}