diff options
Diffstat (limited to 'Hutch')
| -rw-r--r-- | Hutch/Views/Home/HomeView.swift | 2 | ||||
| -rw-r--r-- | Hutch/Views/Home/HomeViewModel.swift | 61 | ||||
| -rw-r--r-- | Hutch/Views/Work/WorkView.swift | 2 |
3 files changed, 35 insertions, 30 deletions
diff --git a/Hutch/Views/Home/HomeView.swift b/Hutch/Views/Home/HomeView.swift index 409d095..3e95f0b 100644 --- a/Hutch/Views/Home/HomeView.swift +++ b/Hutch/Views/Home/HomeView.swift @@ -74,7 +74,7 @@ struct HomeView: View { .listStyle(.insetGrouped) .listSectionSpacing(.compact) .refreshable { - await viewModel.loadDashboard() + await viewModel.loadDashboard(forceRefresh: true) } .connectivityOverlay(hasContent: hasHomeContent(viewModel)) { await viewModel.loadDashboard() diff --git a/Hutch/Views/Home/HomeViewModel.swift b/Hutch/Views/Home/HomeViewModel.swift index 4436f0c..98dd968 100644 --- a/Hutch/Views/Home/HomeViewModel.swift +++ b/Hutch/Views/Home/HomeViewModel.swift @@ -343,7 +343,12 @@ final class HomeViewModel { self.accountID = accountID } - func loadDashboard() async { + /// Loads the dashboard. + /// + /// `forceRefresh` bypasses the cache. Without it, a pull to refresh returns + /// whatever is already cached and only schedules a background fetch, so new + /// mail cannot show up on the first pull. + func loadDashboard(forceRefresh: Bool = false) async { isLoadingProjects = true isLoadingAssignedTickets = true isLoadingRecentBuilds = true @@ -354,11 +359,11 @@ final class HomeViewModel { isShowingStaleSystemStatus = false systemStatusErrorMessage = nil - async let projectsTask = loadProjects() - async let jobsTask = loadRecentJobs() - async let assignedTicketsTask = loadAssignedTickets() - async let inboxUnreadTask = loadInboxUnreadSnapshot() - async let systemStatusTask = loadSystemStatusSnapshot() + async let projectsTask = loadProjects(forceRefresh: forceRefresh) + async let jobsTask = loadRecentJobs(forceRefresh: forceRefresh) + async let assignedTicketsTask = loadAssignedTickets(forceRefresh: forceRefresh) + async let inboxUnreadTask = loadInboxUnreadSnapshot(forceRefresh: forceRefresh) + async let systemStatusTask = loadSystemStatusSnapshot(forceRefresh: forceRefresh) let projectsResult = await projectsTask switch projectsResult { @@ -676,7 +681,7 @@ final class HomeViewModel { persistNeedsAttentionSnapshot() } - private func loadProjects() async -> Result<[Project], Error> { + private func loadProjects(forceRefresh: Bool) async -> Result<[Project], Error> { do { return .success(try await projectService.fetchProjects()) } catch { @@ -684,7 +689,7 @@ final class HomeViewModel { } } - private func loadRecentJobs() async -> Result<[HomeJobPayload], Error> { + private func loadRecentJobs(forceRefresh: Bool) async -> Result<[HomeJobPayload], Error> { do { let cached = try await client.executeCached( service: .builds, @@ -693,7 +698,7 @@ final class HomeViewModel { cacheKey: APICacheKeys.homeJobs(actor: currentUser.canonicalName), resourceType: .buildList, ttl: APICacheTTLs.homeDashboard, - policy: .cacheFirstThenRefresh + policy: forceRefresh ? .refreshIgnoringCache : .cacheFirstThenRefresh ) return .success(cached.value.jobs.results) } catch { @@ -701,15 +706,15 @@ final class HomeViewModel { } } - private func loadInboxUnreadSnapshot() async -> HomeInboxUnreadSnapshot? { + private func loadInboxUnreadSnapshot(forceRefresh: Bool) async -> HomeInboxUnreadSnapshot? { do { - return try await fetchUnreadInboxSnapshot() + return try await fetchUnreadInboxSnapshot(forceRefresh: forceRefresh) } catch { return nil } } - private func loadSystemStatusSnapshot() async -> Result<CachedSystemStatusValue<SystemStatusSnapshot>, Error> { + private func loadSystemStatusSnapshot(forceRefresh: Bool) async -> Result<CachedSystemStatusValue<SystemStatusSnapshot>, Error> { do { return .success(try await systemStatusRepository.snapshotResult()) } catch { @@ -717,8 +722,8 @@ final class HomeViewModel { } } - private func fetchUnreadInboxSnapshot() async throws -> HomeInboxUnreadSnapshot { - let mailingLists = try await fetchInboxMailingLists() + private func fetchUnreadInboxSnapshot(forceRefresh: Bool) async throws -> HomeInboxUnreadSnapshot { + let mailingLists = try await fetchInboxMailingLists(forceRefresh: forceRefresh) guard !mailingLists.isEmpty else { return HomeInboxUnreadSnapshot(unreadCount: 0, threads: []) } var startIndex = mailingLists.startIndex @@ -737,7 +742,7 @@ final class HomeViewModel { for mailingList in batch { group.addTask { do { - return .success(try await self.fetchUnreadThreadSnapshot(for: mailingList)) + return .success(try await self.fetchUnreadThreadSnapshot(for: mailingList, forceRefresh: forceRefresh)) } catch { return .failure(error) } @@ -776,7 +781,7 @@ final class HomeViewModel { ) } - private func fetchInboxMailingLists() async throws -> [InboxMailingListReference] { + private func fetchInboxMailingLists(forceRefresh: Bool) async throws -> [InboxMailingListReference] { var subscriptions: [HomeInboxSubscription] = [] var cursor: String? @@ -794,7 +799,7 @@ final class HomeViewModel { cacheKey: APICacheKeys.inboxSubscriptions(cursor: cursor), resourceType: .ticketList, ttl: APICacheTTLs.inboxSummary, - policy: .cacheFirstThenRefresh + policy: forceRefresh ? .refreshIgnoringCache : .cacheFirstThenRefresh ) let response = cached.value @@ -809,7 +814,7 @@ final class HomeViewModel { return subscriptions.compactMap(\.list).filter { seen.insert($0.rid).inserted } } - private func fetchUnreadThreadSnapshot(for mailingList: InboxMailingListReference) async throws -> HomeInboxUnreadSnapshot { + private func fetchUnreadThreadSnapshot(for mailingList: InboxMailingListReference, forceRefresh: Bool) async throws -> HomeInboxUnreadSnapshot { var unreadCount = 0 var cursor: String? var unreadThreads: [InboxThreadSummary] = [] @@ -828,7 +833,7 @@ final class HomeViewModel { cacheKey: APICacheKeys.inboxThreads(listRid: mailingList.rid, cursor: cursor), resourceType: .ticketList, ttl: APICacheTTLs.inboxSummary, - policy: .cacheFirstThenRefresh + policy: forceRefresh ? .refreshIgnoringCache : .cacheFirstThenRefresh ) let response = cached.value @@ -871,10 +876,10 @@ final class HomeViewModel { ) } - private func loadAssignedTickets() async -> Result<[HomeAssignedTicket], Error> { + private func loadAssignedTickets(forceRefresh: Bool) async -> Result<[HomeAssignedTicket], Error> { do { - let trackers = try await fetchAllTrackers() - let tickets = try await fetchAssignedTickets(for: trackers) + let trackers = try await fetchAllTrackers(forceRefresh: forceRefresh) + let tickets = try await fetchAssignedTickets(for: trackers, forceRefresh: forceRefresh) .sorted(by: Self.sortAssignedTicketsForTriage) return .success(tickets) } catch { @@ -882,7 +887,7 @@ final class HomeViewModel { } } - private func fetchAllTrackers() async throws -> [TrackerSummary] { + private func fetchAllTrackers(forceRefresh: Bool) async throws -> [TrackerSummary] { var allTrackers: [TrackerSummary] = [] var cursor: String? @@ -900,7 +905,7 @@ final class HomeViewModel { cacheKey: APICacheKeys.trackers(cursor: cursor), resourceType: .ticketList, ttl: APICacheTTLs.ticketList, - policy: .cacheFirstThenRefresh + policy: forceRefresh ? .refreshIgnoringCache : .cacheFirstThenRefresh ) let response = cached.value @@ -914,7 +919,7 @@ final class HomeViewModel { return allTrackers } - private func fetchAssignedTickets(for trackers: [TrackerSummary]) async throws -> [HomeAssignedTicket] { + private func fetchAssignedTickets(for trackers: [TrackerSummary], forceRefresh: Bool) async throws -> [HomeAssignedTicket] { guard !trackers.isEmpty else { return [] } var assignedTickets: [HomeAssignedTicket] = [] @@ -927,7 +932,7 @@ final class HomeViewModel { let batchTickets = try await withThrowingTaskGroup(of: [HomeAssignedTicket].self) { group in for tracker in batch { group.addTask { - try await self.fetchAssignedTickets(for: tracker) + try await self.fetchAssignedTickets(for: tracker, forceRefresh: forceRefresh) } } @@ -945,7 +950,7 @@ final class HomeViewModel { return assignedTickets } - private func fetchAssignedTickets(for tracker: TrackerSummary) async throws -> [HomeAssignedTicket] { + private func fetchAssignedTickets(for tracker: TrackerSummary, forceRefresh: Bool) async throws -> [HomeAssignedTicket] { let cached = try await client.executeCached( service: .todo, query: Self.trackerTicketsQuery, @@ -964,7 +969,7 @@ final class HomeViewModel { ), resourceType: .ticketList, ttl: APICacheTTLs.ticketList, - policy: .cacheFirstThenRefresh + policy: forceRefresh ? .refreshIgnoringCache : .cacheFirstThenRefresh ) let response = cached.value diff --git a/Hutch/Views/Work/WorkView.swift b/Hutch/Views/Work/WorkView.swift index 6ba1d0c..23acdfb 100644 --- a/Hutch/Views/Work/WorkView.swift +++ b/Hutch/Views/Work/WorkView.swift @@ -72,7 +72,7 @@ struct WorkView: View { .themedList() .listStyle(.insetGrouped) .refreshable { - await viewModel.loadDashboard() + await viewModel.loadDashboard(forceRefresh: true) } .connectivityOverlay(hasContent: hasWorkContent(viewModel)) { await viewModel.loadDashboard() |
