Requiring both ends to sit exactly on midnight was too strict. A holiday stored
as the 16th at 00:00 through the 21st at 01:00 slipped through and rendered as
a one-hour slot. Starting on a day boundary and running into a later day is
enough to call it all-day.
The agenda row now names the weekday on both sides when an event crosses a day.
Showing only "00:00 – 01:00" for something that runs from Wednesday to Monday
is true and useless.
The timezone handling above this is deliberately untouched: timed events show
the right time, so the UTC assumption for timestamps without an offset is not
what produced the odd hour.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The target template left AppIcon.appiconset with an entry carrying no filename
— an empty slot. watchOS refuses to install an app without a valid icon, which
is why the Watch app's Install button kept coming back after ten seconds with
no error anywhere. Reuses the iOS 1024 icon, which is already alpha-free.
Both watch targets also called themselves "CalendarrWatch", which is what would
have appeared under the icon and in the complication gallery.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The watch receives the phone's payload over WatchConnectivity and writes it
into its own App Group container through the same SnapshotStore, so there is
one wire format and one reader. The agenda, the detail screen and the filter
all read that; the complications read what the app last wrote, since an
extension cannot run a WCSession of its own.
Complication timelines land on event boundaries rather than a schedule, so the
next appointment flips in the exact minute it changes without spending refresh
budget.
CalendarrWatchShared holds what both watch targets need, attached to each the
way Shared/ is attached to the app and the widgets.
recommendations() is implemented because watchOS requires it — iOS has a
default, the watch does not, since the complication gallery has to be
populated. Found by building, not by reading.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The companion dropdown in Xcode's target template came up empty, which left
both bundle identifiers starting with a bare dot and
WKCompanionAppBundleIdentifier as an empty string. Both are set explicitly
here, along with the App Group entitlements and watchOS 26 as the floor.
The iOS app had no Embed Watch Content phase, so the watch app would have built
and never shipped. Added, with the matching target dependency: the product now
lands at Calendarr iOS.app/Watch/CalendarrWatch.app with the complications
inside it.
Folders follow what they contain: CalendarrWatch is the app,
CalendarrWatchComplications the extension. Xcode had them the other way round.
Package.resolved is now tracked. It pins AppAuth, whose version drift is what
produced the two compile errors fixed in 75a6a5b.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>