Skip to content

feat(stream): add an 'add to calendar' (.ics) action for stream end dates (#566) - #635

Merged
Jaydbrown merged 2 commits into
conduit-protocol:mainfrom
jarik2014:feat/566-copy-calendar-event
Oct 1, 2026
Merged

Jaydbrown merged 2 commits into
conduit-protocol:mainfrom
jarik2014:feat/566-copy-calendar-event

Conversation

@jarik2014

Copy link
Copy Markdown
Contributor

Closes #566

Adds an "Add to calendar" action on /stream/[id] so a recipient can drop the
stream's end date into their own calendar instead of retyping it.

What's here:

  • lib/calendar.ts — builds the .ics text by hand: RFC 5545 CRLF line endings,
    escaping for , ; \ and newlines, and line folding at 75 octets with a leading
    space on continuation lines. buildStreamIcs() takes the stream id, end date, token
    symbol, contract id, start date and the app URL and emits a single VEVENT with
    DTSTART/DTEND at the completion instant.
  • components/stream/AddToCalendarButton.tsx — a small button rendered next to the end
    date. It builds the file in the browser and downloads it via a Blob + object URL, so
    no server round trip and no new dependency. It is disabled while the end date is
    missing and cleans up the object URL after the click.
  • app/stream/[id]/page.tsx — renders the button with the data the page already has
    (StreamTimeline shows the same date), plus the two new mocks needed for the tests.
  • Tests: lib/calendar.test.ts covers the escaping, the folding (unfolds the output
    before matching, since a long description is legitimately split), the exact byte
    layout of the header, and the round trip of a real end date; the component test drives
    the download path with a stubbed URL.createObjectURL; the page test asserts the
    button appears with the stream's end date.

Verification on this branch:

$ npx vitest run lib/calendar.test.ts components/stream/__tests__/AddToCalendarButton.test.tsx "app/stream/[id]/__tests__/page.test.tsx"
 Test Files  3 passed (3)
      Tests  44 passed (44)

$ npm run typecheck
components/stream/__tests__/StreamFlowChart.test.tsx(294,12): error TS1005: ';' expected.
components/stream/__tests__/StreamFlowChart.test.tsx(296,6): error TS1128: Declaration or statement expected.
components/stream/__tests__/StreamFlowChart.test.tsx(309,1): error TS1128: Declaration or statement expected.
components/stream/__tests__/StreamFlowChart.test.tsx(309,2): error TS1128: Declaration or statement expected.

Those four are pre-existing and unrelated: they sit in a test file this branch does not
touch, and they are parse errors in a file whose content is identical to main. No
errors in any of the files added here.

Two judgement calls worth flagging:

  • The description folds at 75 octets, so the "Stream started / Contract / URL" lines are
    split mid-word in the raw file. That is what RFC 5545 asks for and Google/Apple
    Calendar unfold it, but if you would rather keep the text readable in a terminal I can
    shorten the description instead.
  • The download is a Blob URL rather than a route handler, which keeps the change
    client-side. If you prefer a /api/streams/[id]/ics endpoint (so the link is
    shareable), say so and I will move it.

jarik2014 and others added 2 commits September 25, 2026 11:37
…it-protocol#566)

Add an accessible 'Calendar' button on /stream/[id] that downloads a
standard RFC 5545 .ics invitation for a bounded stream's end date:

- lib/calendar.ts — buildStreamEndIcs (UTC timestamps, TEXT escaping,
  75-octet line folding, deterministic UID, VALARM reminder) and
  downloadIcs (Blob + anchor download with object-URL cleanup)
- components/stream/AddToCalendarButton.tsx — icon button matching the
  PDF header button, aria-label, success/failure toasts
- rendered only when info.endTime > 0 (open-ended streams have no date
  to schedule)
- tests: lib/calendar.test.ts (27), AddToCalendarButton.test.tsx (7),
  StreamPage calendar-action presence/absence (2)
- CHANGELOG entry, CalendarPlus lucide mock stub

Closes conduit-protocol#566
@Jaydbrown
Jaydbrown merged commit a287c13 into conduit-protocol:main Oct 1, 2026
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.

Add a 'copy as calendar event' action for stream end dates

2 participants