diff options
Diffstat (limited to 'Hutch/Views')
| -rw-r--r-- | Hutch/Views/Home/HomeView.swift | 28 | ||||
| -rw-r--r-- | Hutch/Views/Inbox/InboxView.swift | 36 | ||||
| -rw-r--r-- | Hutch/Views/Inbox/InboxViewModel.swift | 16 |
3 files changed, 60 insertions, 20 deletions
diff --git a/Hutch/Views/Home/HomeView.swift b/Hutch/Views/Home/HomeView.swift index d3d370a..35e8f7c 100644 --- a/Hutch/Views/Home/HomeView.swift +++ b/Hutch/Views/Home/HomeView.swift @@ -26,11 +26,18 @@ struct HomeView: View { } } .task { - if viewModel == nil, let currentUser = appState.currentUser { - let vm = HomeViewModel(currentUser: currentUser, client: appState.client) - viewModel = vm - await vm.loadDashboard() + guard let currentUser = appState.currentUser else { return } + + let vm: HomeViewModel + if let viewModel { + vm = viewModel + } else { + let newViewModel = HomeViewModel(currentUser: currentUser, client: appState.client) + viewModel = newViewModel + vm = newViewModel } + + await vm.loadDashboard() } } @@ -214,17 +221,8 @@ private struct HomeInboxToolbarIcon: View { let hasUnreadThreads: Bool var body: some View { - ZStack(alignment: .topTrailing) { - Image(systemName: hasUnreadThreads ? "tray.fill" : "tray") - - if hasUnreadThreads { - Circle() - .fill(.blue) - .frame(width: 9, height: 9) - .offset(x: 4, y: -2) - } - } - .accessibilityLabel(hasUnreadThreads ? "Inbox, unread messages" : "Inbox") + Image(systemName: hasUnreadThreads ? "tray.fill" : "tray") + .accessibilityLabel(hasUnreadThreads ? "Inbox, unread messages" : "Inbox") } } diff --git a/Hutch/Views/Inbox/InboxView.swift b/Hutch/Views/Inbox/InboxView.swift index 5724964..6ca66ac 100644 --- a/Hutch/Views/Inbox/InboxView.swift +++ b/Hutch/Views/Inbox/InboxView.swift @@ -2,6 +2,7 @@ import SwiftUI struct InboxView: View { @Environment(AppState.self) private var appState + @Environment(\.scenePhase) private var scenePhase @State private var viewModel: InboxViewModel? @State private var selectedThreadID: InboxThreadSummary.ID? @State private var selectedThreadSnapshot: InboxThreadSummary? @@ -17,10 +18,21 @@ struct InboxView: View { } .navigationTitle("Inbox") .task { - if viewModel == nil { - let vm = InboxViewModel(client: appState.client) - viewModel = vm - await vm.loadThreads() + let vm: InboxViewModel + if let viewModel { + vm = viewModel + } else { + let newViewModel = InboxViewModel(client: appState.client) + viewModel = newViewModel + vm = newViewModel + } + + await vm.loadThreads() + } + .onChange(of: scenePhase) { _, newPhase in + guard newPhase == .active, let viewModel, !isShowingThreadDetail else { return } + Task { + await viewModel.loadThreads() } } } @@ -51,6 +63,20 @@ struct InboxView: View { prompt: "Search inbox" ) .listStyle(.plain) + .toolbar { + ToolbarItem(placement: .topBarTrailing) { + if viewModel.hasUnreadThreads { + Button("Mark All Read") { + withAnimation(.easeInOut(duration: 0.2)) { + viewModel.markAllThreadsRead() + } + Task { + await viewModel.loadThreads() + } + } + } + } + } .overlay { if viewModel.isLoading, viewModel.threads.isEmpty { SRHTLoadingStateView(message: "Loading inbox…") @@ -66,7 +92,7 @@ struct InboxView: View { ContentUnavailableView( "Inbox Zero", systemImage: "tray", - description: Text("Unread threads will appear here.") + description: Text("You're up to date.") ) } } diff --git a/Hutch/Views/Inbox/InboxViewModel.swift b/Hutch/Views/Inbox/InboxViewModel.swift index 1d4cfd3..edb7593 100644 --- a/Hutch/Views/Inbox/InboxViewModel.swift +++ b/Hutch/Views/Inbox/InboxViewModel.swift @@ -150,6 +150,18 @@ final class InboxViewModel { NeedsAttentionSnapshotStore.adjustUnreadInboxThreads(by: -1) } + func markAllThreadsRead() { + guard !threads.isEmpty else { return } + + let viewedAt = Date() + for thread in threads where thread.isUnread { + InboxReadStateStore.markViewed(max(viewedAt, thread.lastActivityAt), for: thread.id) + } + + threads.removeAll { $0.isUnread } + NeedsAttentionSnapshotStore.update(unreadInboxThreads: threads.count) + } + func markThreadUnread(_ thread: InboxThreadSummary) { InboxReadStateStore.markUnread(for: thread.id) updateThread(thread, isUnread: true) @@ -178,6 +190,10 @@ final class InboxViewModel { } } + var hasUnreadThreads: Bool { + threads.contains(where: \.isUnread) + } + private func fetchSubscriptions() async throws -> [InboxActivitySubscription] { var subscriptions: [InboxActivitySubscription] = [] var cursor: String? |
