fix: "dismiss" not available on notifactions in "All Instance" view

This commit is contained in:
Stefan Hausotte 2026-04-14 18:46:34 +02:00
parent 666b8e57c3
commit d879440577
2 changed files with 88 additions and 0 deletions

View file

@ -56,6 +56,24 @@ struct MergedNotificationsOverviewView: View {
Section {
ForEach(pagination.items) { tagged in
notificationRow(tagged)
.swipeActions(edge: .leading) {
if tagged.item.unread {
Button {
Task { await markAsRead(tagged) }
} label: {
Label("Mark Read", systemImage: "envelope.open")
}
.tint(.blue)
}
}
.swipeActions(edge: .trailing, allowsFullSwipe: true) {
Button {
Task { await dismissNotification(tagged) }
} label: {
Label("Dismiss", systemImage: "xmark")
}
.tint(.gray)
}
}
if pagination.hasMore {
@ -166,6 +184,48 @@ struct MergedNotificationsOverviewView: View {
return TaggedItem.mergeAndDeduplicate(batches: batches, sources: sources)
.sorted { $0.item.updatedAt > $1.item.updatedAt }
}
private func markAsRead(_ tagged: TaggedItem<NotificationThread>) async {
await setNotificationRead(tagged)
}
private func dismissNotification(_ tagged: TaggedItem<NotificationThread>) async {
await setNotificationRead(tagged)
}
private func setNotificationRead(_ tagged: TaggedItem<NotificationThread>) async {
guard let client = tagged.authService.client else { return }
let service = NotificationService(client: client)
let notification = tagged.item
do {
try await service.markAsRead(id: notification.id)
withAnimation {
if statusFilter == "unread" {
pagination.items.removeAll { $0.id == tagged.id }
} else if let index = pagination.items.firstIndex(where: { $0.id == tagged.id }) {
let updated = NotificationThread(
id: notification.id,
unread: false,
pinned: notification.pinned,
updatedAt: notification.updatedAt,
url: notification.url,
subject: notification.subject,
repository: notification.repository,
)
pagination.items[index] = TaggedItem(
item: updated,
sourceKey: tagged.sourceKey,
instanceName: tagged.instanceName,
authService: tagged.authService,
)
}
}
NotificationCenter.default.post(name: .notificationsDidChange, object: nil)
} catch {
pagination.errorMessage = error.localizedDescription
pagination.showError = true
}
}
}
private struct MergedNotificationRow: View {

View file

@ -124,6 +124,34 @@ final class MergedInstanceUITests: ForgejoUITestBase {
XCTAssertTrue(instanceList.waitForExistence(timeout: 10), "Should return to instance list after disconnect")
}
@MainActor
func testMergedNotificationSwipeDismiss() throws {
try setupTwoInstances()
enterMergedMode()
app.tabBars.buttons["Notifications"].tap()
let notificationsList = app.collectionViews.firstMatch
XCTAssertTrue(notificationsList.waitForExistence(timeout: 10))
let firstCell = notificationsList.cells.firstMatch
XCTAssertTrue(firstCell.waitForExistence(timeout: 10), "Should have at least one notification")
// Swipe right to mark as read
firstCell.swipeRight()
let markReadButton = app.buttons["Mark Read"]
XCTAssertTrue(markReadButton.waitForExistence(timeout: 3), "Mark Read swipe action should appear")
markReadButton.tap()
// Swipe left to dismiss
let nextCell = notificationsList.cells.firstMatch
XCTAssertTrue(nextCell.waitForExistence(timeout: 5), "Should have another notification to dismiss")
nextCell.swipeLeft()
let dismissButton = app.buttons["Dismiss"]
XCTAssertTrue(dismissButton.waitForExistence(timeout: 3), "Dismiss swipe action should appear")
dismissButton.tap()
}
// MARK: - Server URL Helpers
private func resolveSecondServerURL() -> String? {