Skip to content

feat: added support for ICS calendars - #3637

Draft
agokule wants to merge 3 commits into
noctalia-dev:mainfrom
agokule:feat/ics-calendar-support
Draft

feat: added support for ICS calendars#3637
agokule wants to merge 3 commits into
noctalia-dev:mainfrom
agokule:feat/ics-calendar-support

Conversation

@agokule

@agokule agokule commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Summary

I added a new type of calendar (ICS) to the settings page which can take a URL to an *.ics file, and use that for the calendar.

In terms of code changes, it's mostly the same stuff that was in #2928 before it got closed. However it does fix the 2 main pain points that were mentioned because it turns out that the parseICalEvents function was edited to support both of those pain points, so there weren't a lot of changes needed to make it work.

Motivation

Many apps expose their calendars in this format, so it is important to support it.

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Refactoring
  • Build / packaging

Related Issue

This closes #3294
Also this goes hand in hand with PR #3636, we coincidentally happened to be working on this at the same time!

Testing

Ran just test, all tests passed.

I put this content in a file testing.ics:

BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Sample Event//EN
CALSCALE:GREGORIAN
METHOD:PUBLISH
BEGIN:VEVENT
SUMMARY:Sample Team Meeting (ICS)
DTSTART:20260725T150000Z
DTEND:20260725T160000Z
LOCATION:Online Room A
DESCRIPTION:Review daily goals and projects.
STATUS:CONFIRMED
END:VEVENT
END:VCALENDAR

And then ran python -m http.server in that directory, this creates a static http server at port 8000 to that directory. Then I added http://localhost:8000/testing.ics using the Noctalia settings UI as an ICS calendar, and the event "Sample Team Meeting (ICS)" showed up as happening today (see screenshot below)

Manual Coverage

  • Tested on Niri
  • Tested on Hyprland
  • Tested on Sway
  • Tested on another compositor:
  • Tested with different bar positions and density settings
  • Tested at different interface scaling values
  • Tested with multiple monitors

Screenshots / Videos

image

Checklist

  • This PR is ready for review, or it is marked as Draft.
  • I read and followed the relevant guidance in CONTRIBUTING.md.
  • I ran just format with clang-format v22+ installed, or this PR has no code changes.
  • I ran the relevant build or test commands, or explained why they were not run.
  • I self-reviewed the changes.
  • I checked for new warnings or errors.
  • I will update end-user documentation after merge, or this PR does not change user-facing configuration or behavior.
  • I added or updated assets/translations/en.json, or this PR adds no new user-facing strings.
  • I did not edit non-English translation files unless this PR is explicitly for translation tooling, an import/export sync, or a maintainer-requested locale change.
  • I used the existing canonical names for config keys, IPC names, paths, and identifiers.

Additional Notes

N/A

@ItsLemmy

Copy link
Copy Markdown
Collaborator

[P1] Normalize webcal:// URLs before passing them to libcurl

fetchIcs() forwards the configured URL unchanged /src/calendar/calendar_service.cpp#L543-L558.
The related issue explicitly requires webcal:// support, but the HTTP client passes the value directly to CURLOPT_URL; libcurl does not support a webcal protocol.

Result: common calendar subscription links fail with CURLE_UNSUPPORTED_PROTOCOL, so a core requested input cannot load.

Normalize webcal://… to https://… before constructing the request. Alternatively, reject it in settings with an actionable error, but that would not satisfy issue #3294.

[P2] Reject successful HTTP responses that are not valid calendars

After any HTTP 200, fetchIcs() treats the parser output as authoritative /src/calendar/calendar_service.cpp#L560-L577. parseICalEvents() does not validate the VCALENDAR envelope; HTML login pages, expired-share pages, proxy errors, and malformed ICS therefore parse as an empty event list. accountDone(..., true, {}) then replaces previously cached events and persists the empty result.

Validate that the response is an actual calendar before calling accountDone(..., true, ...). Invalid content should use the failure path so stale events remain available. A structured parser result distinguishing “valid empty calendar” from “invalid input” would be safest.

@ItsLemmy
ItsLemmy marked this pull request as draft July 30, 2026 13:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] Support subscribing to public/read-only ICS (webcal) URLs as a calendar provider

2 participants