Answer "signed out" vs "never ran" in one read; make SnapshotTheme constructible

Signing out deletes the cached events — keeping them would leak the previous
user's calendar to anything reading the container — so an absent cache alone
cannot distinguish "signed out" from "Calendarr has never run on this machine".
Those need different messages, so read() now falls back to the session record
and reports .loggedOut when one exists and says so. Every consumer would
otherwise have to reimplement that two-step, and any that forgot would tell a
signed-out user to go install an app they already have.

SnapshotTheme only had the compiler's internal memberwise initializer, so no
consumer outside the package could actually build one.
This commit is contained in:
Scarriffle
2026-08-10 17:41:32 +02:00
parent ab2328969e
commit d5a9dad769
2 changed files with 17 additions and 1 deletions
@@ -79,6 +79,12 @@ public struct SnapshotTheme: Sendable, Hashable {
public let line: String
public let primary: String
public let accent: String
public init(today: String, text: String, background: String,
line: String, primary: String, accent: String) {
self.today = today; self.text = text; self.background = background
self.line = line; self.primary = primary; self.accent = accent
}
}
// MARK: - Snapshot
@@ -59,7 +59,17 @@ public struct SnapshotStore: Sendable {
}
let url = container.appendingPathComponent(Self.cacheFilename)
guard FileManager.default.fileExists(atPath: url.path) else { return .neverWritten }
guard FileManager.default.fileExists(atPath: url.path) else {
// No cache. Signing out deletes the events — keeping them would leak
// the previous user's calendar — so the session file is what tells
// "signed out" apart from "never ran here". Answering that in one
// call keeps every consumer from reimplementing the distinction.
if let session = SharedSessionStore(appGroupID: appGroupID).read(),
!session.isLoggedIn {
return .loggedOut(writtenAt: session.writtenAt)
}
return .neverWritten
}
let data: Data
do { data = try Data(contentsOf: url) }