From 77cd5b5e56ec054b451a6165162fef655873a5d6 Mon Sep 17 00:00:00 2001 From: Christian Cleberg Date: Thu, 16 Jul 2026 00:42:38 -0500 Subject: fix: push mailing lists locally, fix upload menu, drop the events feed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Opening a mailing list from More → Projects still blanked. The cause was not in handleTabNavigation: the row called openMailingList and then dismiss(), so a path rebuild and a pop of this very view raced each other. Projects already lives in the More tab, so there is nothing to navigate to — push MailingListDetailView directly, which also lands back on the project rather than on Mailing Lists. Sources and trackers keep routing, because they really do land in other tabs. The upload controls did nothing. Two .confirmationDialog modifiers on one view leave one silently dead, and this view already had one for delete, so the tag picker never presented. It is a Menu now, which also puts the tags one tap away instead of two. The ticket activity feed is removed. todo.sr.ht's root events resolver joins event.participant_id, which references participant(id), against participant.user_id — different id spaces — so it returns an empty list for every user. The rows exist; that join cannot find them. Ticket.events is unaffected because it filters on ticket_id, which is why ticket timelines work. No client can fix this, and a screen that is permanently empty while blaming the token's scopes is worse than no screen. Recorded in SCOPE.md with the query. --- Hutch/Views/Activity/ActivityView.swift | 96 --------------------------------- 1 file changed, 96 deletions(-) delete mode 100644 Hutch/Views/Activity/ActivityView.swift (limited to 'Hutch/Views/Activity/ActivityView.swift') diff --git a/Hutch/Views/Activity/ActivityView.swift b/Hutch/Views/Activity/ActivityView.swift deleted file mode 100644 index 6379d45..0000000 --- a/Hutch/Views/Activity/ActivityView.swift +++ /dev/null @@ -1,96 +0,0 @@ -import SwiftUI - -struct ActivityView: View { - @Environment(AppState.self) private var appState - @State private var viewModel: ActivityViewModel? - - var body: some View { - Group { - if let viewModel { - content(viewModel) - } else { - SRHTLoadingStateView(message: "Loading Activity…") - } - } - .navigationTitle("Activity") - .navigationBarTitleDisplayMode(.inline) - .task { - let model = viewModel ?? ActivityViewModel(client: appState.client) - viewModel = model - await model.loadIfNeeded() - } - } - - @ViewBuilder - private func content(_ viewModel: ActivityViewModel) -> some View { - List { - ForEach(viewModel.events) { event in - NavigationLink { - TicketDetailView( - ownerUsername: event.ownerUsername, - trackerName: event.trackerName, - trackerId: event.trackerID, - trackerRid: event.trackerRID, - ticketId: event.ticketID - ) - } label: { - ActivityRow(event: event) - } - .themedRow() - } - - if viewModel.hasMore { - HStack { - Spacer() - ProgressView() - Spacer() - } - .themedRow() - .task { await viewModel.loadMore() } - } - } - .themedList() - .listStyle(.plain) - .refreshable { await viewModel.load() } - .overlay { - if viewModel.isLoading, viewModel.events.isEmpty { - SRHTLoadingStateView(message: "Loading Activity…") - } else if let error = viewModel.error, viewModel.events.isEmpty { - SRHTErrorStateView( - title: "Couldn't Load Activity", - message: error, - retryAction: { await viewModel.load() } - ) - } else if viewModel.events.isEmpty { - ContentUnavailableView( - "No Activity", - systemImage: "bell", - description: Text("Ticket activity you are subscribed to or involved in appears here.") - ) - } - } - } -} - -private struct ActivityRow: View { - let event: ActivityEvent - - var body: some View { - VStack(alignment: .leading, spacing: 4) { - Text(event.ticketSubject) - .font(.subheadline.weight(.medium)) - .lineLimit(2) - - Text("\(event.summary) • \(event.created.relativeDescription)") - .font(.caption) - .foregroundStyle(.secondary) - - Text("\(event.trackerOwner.canonicalName)/\(event.trackerName) #\(event.ticketID)") - .font(.caption2) - .foregroundStyle(.tertiary) - } - .padding(.vertical, 2) - .accessibilityElement(children: .combine) - .accessibilityLabel("\(event.ticketSubject), \(event.summary), \(event.created.relativeDescription)") - } -} -- cgit v1.2.3