Move mode picker below device status bar; fix invisible calendar lines; add CalDAV calendar support
Build and push server image / build-and-push (push) Successful in 50s
Build and push server image / build-and-push (push) Successful in 50s
Calendar rule/grid lines were light gray, which dithers away to near-invisible on the 6-color e-ink palette -- now black. CalDAV accounts (Nextcloud, Fastmail, iCloud, ...) can now be linked alongside the existing single ICS subscription, since one account can expose several calendars. A frame's Calendar tab now lists calendars per person rather than one opt-in per person: your own row shows every calendar you have available with a full add/remove toggle, while other linked users' rows show only calendars they've included, toggleable off (mute) but not on -- only a calendar's owner can add it to a shared frame. FrameCalendar replaces the old single-boolean UserFrame.calendar_included; existing opt-ins are migrated forward.
This commit is contained in:
@@ -18,7 +18,7 @@ from fastapi.templating import Jinja2Templates
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from .. import mail
|
||||
from .. import caldav_client, mail
|
||||
from ..auth import (
|
||||
SESSION_COOKIE,
|
||||
SESSION_LIFETIME_S,
|
||||
@@ -30,6 +30,7 @@ from ..auth import (
|
||||
destroy_session,
|
||||
get_server_settings,
|
||||
hash_password,
|
||||
require_user_api,
|
||||
users_exist,
|
||||
verify_password,
|
||||
)
|
||||
@@ -424,6 +425,9 @@ def settings_submit(
|
||||
immich_url: str = Form(""),
|
||||
immich_api_key: str = Form(""),
|
||||
calendar_ics_url: str = Form(""),
|
||||
calendar_caldav_url: str = Form(""),
|
||||
calendar_caldav_username: str = Form(""),
|
||||
calendar_caldav_password: str = Form(""),
|
||||
current_password: str = Form(""),
|
||||
new_password: str = Form(""),
|
||||
db: Session = Depends(get_db),
|
||||
@@ -452,6 +456,23 @@ def settings_submit(
|
||||
else:
|
||||
user.calendar_ics_url = stripped_ics
|
||||
|
||||
stripped_caldav_url = calendar_caldav_url.strip()
|
||||
if stripped_caldav_url and not valid_http_url(stripped_caldav_url):
|
||||
error = "CalDAV URL must be a plain http:// or https:// URL."
|
||||
else:
|
||||
if stripped_caldav_url != user.calendar_caldav_url:
|
||||
# Server (and likely account) changed -- last discovery no
|
||||
# longer describes what's actually there.
|
||||
user.calendar_caldav_calendars = None
|
||||
user.calendar_caldav_checked_at = 0.0
|
||||
user.calendar_caldav_url = stripped_caldav_url
|
||||
user.calendar_caldav_username = calendar_caldav_username.strip()
|
||||
# Blank password field = keep the existing one, same idiom as the
|
||||
# Immich API key -- a secret that round-trips through HTML is a
|
||||
# secret in every browser's autofill store.
|
||||
if calendar_caldav_password.strip():
|
||||
user.calendar_caldav_password = calendar_caldav_password.strip()
|
||||
|
||||
if new_password:
|
||||
if not user.password_hash or not verify_password(current_password, user.password_hash):
|
||||
error = "Current password is wrong -- password not changed."
|
||||
@@ -466,6 +487,28 @@ def settings_submit(
|
||||
)
|
||||
|
||||
|
||||
@router.post("/api/settings/caldav-discover")
|
||||
def api_caldav_discover(request: Request, db: Session = Depends(get_db)):
|
||||
"""Lists the calendars in the CalDAV account already saved on this
|
||||
user's Settings (not whatever's currently typed in the form but not
|
||||
yet saved -- same idiom as /api/frames/{id}/albums using the frame's
|
||||
already-saved Immich creds). Caches the result on the user row so
|
||||
every frame's Calendar tab can offer it without a live round-trip."""
|
||||
user = require_user_api(request, db)
|
||||
if not user.calendar_caldav_url or not user.calendar_caldav_username:
|
||||
raise HTTPException(400, "Save a CalDAV URL and username first")
|
||||
try:
|
||||
calendars = caldav_client.discover_calendars(
|
||||
user.calendar_caldav_url, user.calendar_caldav_username, user.calendar_caldav_password
|
||||
)
|
||||
except caldav_client.CalDavError as e:
|
||||
raise HTTPException(502, f"Could not discover calendars: {e}") from e
|
||||
user.calendar_caldav_calendars = calendars
|
||||
user.calendar_caldav_checked_at = time.time()
|
||||
db.commit()
|
||||
return calendars
|
||||
|
||||
|
||||
def _require_admin_page(request: Request, db: Session) -> User:
|
||||
user = current_user(request, db)
|
||||
if user is None or not user.is_admin:
|
||||
|
||||
Reference in New Issue
Block a user