From fe1ccc69661603d419a642a450e4ac9e1258adb0 Mon Sep 17 00:00:00 2001 From: Christian Cleberg Date: Mon, 13 Apr 2026 19:44:44 -0500 Subject: fix: centralize URLs, tighten models, and polish SwiftUI bindings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add shared HutchDeepLinkURL constants for app, widgets, and tests. - Bump marketing version to 3.1.2 and build to 70 (app + widget extension). - Point Hutch stats default base URL at HutchStatsAPI; add SRHTWebURL status incident feed and reuse it from SystemStatusService. - Group Project into Metadata and Resources; split ContributionStatsResponse into StatsWindow and StatsTotals with updated decoding and tests. - Replace @Bindable usage with explicit Bindings in Profile, Projects list, and repository ACL flows; simplify Home pinned-item helper; add no-op bodies on cancel alert buttons where the compiler requires a statement. - Move repository row build-status indicator next to the relative-updated caption and reserve a fixed 8×8 slot so the row does not jump when status loads. - Use NSString.lastPathComponent for build artifact filenames; collapse duplicate ACL error branches; minor HutchStats HTTP and XMLParserDelegate cleanups. - Point widgets at HutchDeepLinkURL helpers; align tests with the new response and URL types. --- HutchTests/ContributionCalendarTests.swift | 108 +++++++++++++++++------------ 1 file changed, 62 insertions(+), 46 deletions(-) (limited to 'HutchTests/ContributionCalendarTests.swift') diff --git a/HutchTests/ContributionCalendarTests.swift b/HutchTests/ContributionCalendarTests.swift index 9e76e42..0328ad5 100644 --- a/HutchTests/ContributionCalendarTests.swift +++ b/HutchTests/ContributionCalendarTests.swift @@ -259,12 +259,12 @@ private final class MockContributionCalendarService: ContributionCalendarServing self.statsResponses = statsResponses } - func fetchContributionCalendar(actor: String, endingOn endDate: Date) async throws -> ContributionCalendarResponse { + func fetchContributionCalendar(actor _: String, endingOn _: Date) async throws -> ContributionCalendarResponse { fetchCalendarCallCount += 1 return calendarResponses[min(fetchCalendarCallCount - 1, calendarResponses.count - 1)] } - func fetchContributionStats(actor: String, endingOn endDate: Date) async throws -> ContributionStatsResponse { + func fetchContributionStats(actor _: String, endingOn _: Date) async throws -> ContributionStatsResponse { fetchStatsCallCount += 1 return statsResponses[min(fetchStatsCallCount - 1, statsResponses.count - 1)] } @@ -348,65 +348,81 @@ private extension ContributionCalendarResponse { private extension ContributionStatsResponse { static func empty(actor: String, year: Int) -> Self { ContributionStatsResponse( - actor: actor, - from: ContributionDateParser.parse("\(year)-01-01")!, - to: ContributionDateParser.parse("\(year)-01-07")!, - isIndexed: true, - lastPolledAt: ContributionDateParser.parseTimestamp("\(year)-01-07T12:00:00Z"), - indexingState: .indexed, - totalEvents: 0, - totalScore: 0, - activeDays: 0, - longestStreak: 0, - currentStreak: 0 + window: .init( + actor: actor, + from: ContributionDateParser.parse("\(year)-01-01")!, + to: ContributionDateParser.parse("\(year)-01-07")!, + isIndexed: true, + lastPolledAt: ContributionDateParser.parseTimestamp("\(year)-01-07T12:00:00Z"), + indexingState: .indexed + ), + totals: .init( + totalEvents: 0, + totalScore: 0, + activeDays: 0, + longestStreak: 0, + currentStreak: 0 + ) ) } static func active(actor: String, year: Int, totalEvents: Int, activeDays: Int, longestStreak: Int) -> Self { ContributionStatsResponse( - actor: actor, - from: ContributionDateParser.parse("\(year)-01-01")!, - to: ContributionDateParser.parse("\(year)-01-07")!, - isIndexed: true, - lastPolledAt: ContributionDateParser.parseTimestamp("\(year)-01-07T12:00:00Z"), - indexingState: .indexed, - totalEvents: totalEvents, - totalScore: Double(totalEvents), - activeDays: activeDays, - longestStreak: longestStreak, - currentStreak: 0 + window: .init( + actor: actor, + from: ContributionDateParser.parse("\(year)-01-01")!, + to: ContributionDateParser.parse("\(year)-01-07")!, + isIndexed: true, + lastPolledAt: ContributionDateParser.parseTimestamp("\(year)-01-07T12:00:00Z"), + indexingState: .indexed + ), + totals: .init( + totalEvents: totalEvents, + totalScore: Double(totalEvents), + activeDays: activeDays, + longestStreak: longestStreak, + currentStreak: 0 + ) ) } static func pending(actor: String, year: Int) -> Self { ContributionStatsResponse( - actor: actor, - from: ContributionDateParser.parse("\(year)-01-01")!, - to: ContributionDateParser.parse("\(year)-01-07")!, - isIndexed: false, - lastPolledAt: nil, - indexingState: .pending, - totalEvents: 0, - totalScore: 0, - activeDays: 0, - longestStreak: 0, - currentStreak: 0 + window: .init( + actor: actor, + from: ContributionDateParser.parse("\(year)-01-01")!, + to: ContributionDateParser.parse("\(year)-01-07")!, + isIndexed: false, + lastPolledAt: nil, + indexingState: .pending + ), + totals: .init( + totalEvents: 0, + totalScore: 0, + activeDays: 0, + longestStreak: 0, + currentStreak: 0 + ) ) } static func error(actor: String, year: Int) -> Self { ContributionStatsResponse( - actor: actor, - from: ContributionDateParser.parse("\(year)-01-01")!, - to: ContributionDateParser.parse("\(year)-01-07")!, - isIndexed: false, - lastPolledAt: nil, - indexingState: .error, - totalEvents: 0, - totalScore: 0, - activeDays: 0, - longestStreak: 0, - currentStreak: 0 + window: .init( + actor: actor, + from: ContributionDateParser.parse("\(year)-01-01")!, + to: ContributionDateParser.parse("\(year)-01-07")!, + isIndexed: false, + lastPolledAt: nil, + indexingState: .error + ), + totals: .init( + totalEvents: 0, + totalScore: 0, + activeDays: 0, + longestStreak: 0, + currentStreak: 0 + ) ) } } -- cgit v1.2.3