summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Cleberg <[email protected]>2026-04-12 11:49:45 -0500
committerChristian Cleberg <[email protected]>2026-04-12 11:49:45 -0500
commit9e48e4681487b1c69577c0e9e5f83d8d8225e494 (patch)
tree825ce946dac13ad24a123b647722a6cab6c51599
parentc0744a35891f89e50ab407a0b8557ce9d5c5e6cc (diff)
downloadhutch-9e48e4681487b1c69577c0e9e5f83d8d8225e494.tar.gz
hutch-9e48e4681487b1c69577c0e9e5f83d8d8225e494.tar.bz2
hutch-9e48e4681487b1c69577c0e9e5f83d8d8225e494.zip
feat: add prioritization of polling hutch-stats for logged in user
-rw-r--r--Hutch.xcodeproj/project.pbxproj12
-rw-r--r--Hutch/Networking/HutchStatsService.swift19
-rw-r--r--Hutch/Views/Lookup/UserProfileView.swift5
-rw-r--r--Hutch/Views/More/ProfileView.swift5
-rw-r--r--HutchTests/ContributionCalendarTests.swift24
5 files changed, 52 insertions, 13 deletions
diff --git a/Hutch.xcodeproj/project.pbxproj b/Hutch.xcodeproj/project.pbxproj
index 1fe01ce..7e0ee15 100644
--- a/Hutch.xcodeproj/project.pbxproj
+++ b/Hutch.xcodeproj/project.pbxproj
@@ -532,7 +532,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
- MARKETING_VERSION = 2.15.1;
+ MARKETING_VERSION = 2.15.2;
PRODUCT_BUNDLE_IDENTIFIER = net.cleberg.Hutch;
PRODUCT_NAME = "$(TARGET_NAME)";
STRING_CATALOG_GENERATE_SYMBOLS = YES;
@@ -569,7 +569,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
- MARKETING_VERSION = 2.15.1;
+ MARKETING_VERSION = 2.15.2;
PRODUCT_BUNDLE_IDENTIFIER = net.cleberg.Hutch;
PRODUCT_NAME = "$(TARGET_NAME)";
STRING_CATALOG_GENERATE_SYMBOLS = YES;
@@ -632,7 +632,7 @@
APPLICATION_EXTENSION_API_ONLY = YES;
CODE_SIGN_ENTITLEMENTS = HutchWidgetExtension/HutchWidgetExtension.entitlements;
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 33;
+ CURRENT_PROJECT_VERSION = 34;
DEVELOPMENT_TEAM = ZCNAX3VL9D;
GENERATE_INFOPLIST_FILE = NO;
INFOPLIST_FILE = HutchWidgetExtension/Info.plist;
@@ -642,7 +642,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
- MARKETING_VERSION = 2.15.1;
+ MARKETING_VERSION = 2.15.2;
PRODUCT_BUNDLE_IDENTIFIER = net.cleberg.Hutch.HutchWidgetExtension;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
@@ -661,7 +661,7 @@
APPLICATION_EXTENSION_API_ONLY = YES;
CODE_SIGN_ENTITLEMENTS = HutchWidgetExtension/HutchWidgetExtension.entitlements;
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 33;
+ CURRENT_PROJECT_VERSION = 34;
DEVELOPMENT_TEAM = ZCNAX3VL9D;
GENERATE_INFOPLIST_FILE = NO;
INFOPLIST_FILE = HutchWidgetExtension/Info.plist;
@@ -671,7 +671,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
- MARKETING_VERSION = 2.15.1;
+ MARKETING_VERSION = 2.15.2;
PRODUCT_BUNDLE_IDENTIFIER = net.cleberg.Hutch.HutchWidgetExtension;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
diff --git a/Hutch/Networking/HutchStatsService.swift b/Hutch/Networking/HutchStatsService.swift
index 69a2a20..52d86b9 100644
--- a/Hutch/Networking/HutchStatsService.swift
+++ b/Hutch/Networking/HutchStatsService.swift
@@ -9,20 +9,23 @@ struct HutchStatsService: ContributionCalendarServing {
private let session: URLSession
private let decoder: JSONDecoder
private let baseURL: URL
+ private let currentActor: String?
init(
session: URLSession = .shared,
- configuration: AppConfiguration
+ configuration: AppConfiguration,
+ currentActor: String? = nil
) {
self.session = session
self.baseURL = configuration.hutchStatsBaseURL
self.decoder = JSONDecoder()
+ self.currentActor = currentActor
}
func fetchContributionCalendar(actor: String, endingOn endDate: Date) async throws -> ContributionCalendarResponse {
return try await fetch(
path: "api/contributions/\(actor)",
- queryItems: trailingYearQueryItems(endingOn: endDate),
+ queryItems: contributionQueryItems(actor: actor, endingOn: endDate),
responseType: ContributionCalendarResponse.self
)
}
@@ -30,7 +33,7 @@ struct HutchStatsService: ContributionCalendarServing {
func fetchContributionStats(actor: String, endingOn endDate: Date) async throws -> ContributionStatsResponse {
return try await fetch(
path: "api/contributions/\(actor)/stats",
- queryItems: trailingYearQueryItems(endingOn: endDate),
+ queryItems: contributionQueryItems(actor: actor, endingOn: endDate),
responseType: ContributionStatsResponse.self
)
}
@@ -86,15 +89,21 @@ struct HutchStatsService: ContributionCalendarServing {
return normalizedStartDate...normalizedEndDate
}
- private func trailingYearQueryItems(endingOn endDate: Date) -> [URLQueryItem] {
+ func contributionQueryItems(actor: String, endingOn endDate: Date) -> [URLQueryItem] {
let range = trailingRange(endingOn: endDate)
let start = Self.rangeFormatter.string(from: range.lowerBound)
let end = Self.rangeFormatter.string(from: range.upperBound)
- return [
+ var queryItems = [
URLQueryItem(name: "from", value: start),
URLQueryItem(name: "to", value: end)
]
+
+ if actor == currentActor {
+ queryItems.append(URLQueryItem(name: "prioritize", value: "self"))
+ }
+
+ return queryItems
}
private static let rangeFormatter: DateFormatter = {
diff --git a/Hutch/Views/Lookup/UserProfileView.swift b/Hutch/Views/Lookup/UserProfileView.swift
index bc04b08..b467c63 100644
--- a/Hutch/Views/Lookup/UserProfileView.swift
+++ b/Hutch/Views/Lookup/UserProfileView.swift
@@ -175,7 +175,10 @@ struct UserProfileView: View {
ownerUsername: owner,
actor: actor,
client: appState.client,
- statsService: HutchStatsService(configuration: appState.configuration)
+ statsService: HutchStatsService(
+ configuration: appState.configuration,
+ currentActor: appState.currentUser?.canonicalName
+ )
)
profileViewModel = newViewModel
vm = newViewModel
diff --git a/Hutch/Views/More/ProfileView.swift b/Hutch/Views/More/ProfileView.swift
index a7172e4..53c5ce3 100644
--- a/Hutch/Views/More/ProfileView.swift
+++ b/Hutch/Views/More/ProfileView.swift
@@ -46,7 +46,10 @@ struct ProfileView: View {
ownerUsername: owner,
actor: actor,
client: appState.client,
- statsService: HutchStatsService(configuration: appState.configuration)
+ statsService: HutchStatsService(
+ configuration: appState.configuration,
+ currentActor: appState.currentUser?.canonicalName
+ )
)
contributionViewModel = newViewModel
vm = newViewModel
diff --git a/HutchTests/ContributionCalendarTests.swift b/HutchTests/ContributionCalendarTests.swift
index 4ce2f1f..9e76e42 100644
--- a/HutchTests/ContributionCalendarTests.swift
+++ b/HutchTests/ContributionCalendarTests.swift
@@ -94,6 +94,30 @@ struct ContributionCalendarTests {
}
@Test
+ func selfContributionRequestsIncludeExplicitPrioritySignal() {
+ let service = HutchStatsService(
+ configuration: AppConfiguration(),
+ currentActor: "~alice"
+ )
+ let endDate = ContributionDateParser.parse("2026-04-11")!
+ let queryItems = service.contributionQueryItems(actor: "~alice", endingOn: endDate)
+
+ #expect(queryItems.contains(URLQueryItem(name: "prioritize", value: "self")))
+ }
+
+ @Test
+ func otherContributionRequestsDoNotIncludePrioritySignal() {
+ let service = HutchStatsService(
+ configuration: AppConfiguration(),
+ currentActor: "~alice"
+ )
+ let endDate = ContributionDateParser.parse("2026-04-11")!
+ let queryItems = service.contributionQueryItems(actor: "~bob", endingOn: endDate)
+
+ #expect(queryItems.contains(URLQueryItem(name: "prioritize", value: "self")) == false)
+ }
+
+ @Test
func contributionIntensityBucketsMatchProductRules() {
#expect(ContributionIntensity(count: 0) == .empty)
#expect(ContributionIntensity(count: 1) == .level1)