feature/backend-rewrite #2
@@ -104,21 +104,43 @@ class CommentsViewModel: ObservableObject {
|
|||||||
func deleteComment(commentId: String, parentId: String? = nil) async {
|
func deleteComment(commentId: String, parentId: String? = nil) async {
|
||||||
guard !deletingIds.contains(commentId) else { return }
|
guard !deletingIds.contains(commentId) else { return }
|
||||||
deletingIds.insert(commentId)
|
deletingIds.insert(commentId)
|
||||||
defer { deletingIds.remove(commentId) }
|
|
||||||
|
// Optimistic removal — update the UI immediately before the network call
|
||||||
|
var removedComment: BookComment?
|
||||||
|
var removedAtIndex: Int?
|
||||||
|
if let parentId {
|
||||||
|
if let idx = comments.firstIndex(where: { $0.id == parentId }) {
|
||||||
|
var parent = comments[idx]
|
||||||
|
removedComment = parent.replies?.first(where: { $0.id == commentId })
|
||||||
|
removedAtIndex = idx
|
||||||
|
parent.replies = (parent.replies ?? []).filter { $0.id != commentId }
|
||||||
|
comments[idx] = parent
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
removedAtIndex = comments.firstIndex(where: { $0.id == commentId })
|
||||||
|
removedComment = removedAtIndex.map { comments[$0] }
|
||||||
|
comments.removeAll { $0.id == commentId }
|
||||||
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
try await APIClient.shared.deleteComment(commentId: commentId)
|
try await APIClient.shared.deleteComment(commentId: commentId)
|
||||||
if let parentId {
|
|
||||||
if let idx = comments.firstIndex(where: { $0.id == parentId }) {
|
|
||||||
var parent = comments[idx]
|
|
||||||
parent.replies = (parent.replies ?? []).filter { $0.id != commentId }
|
|
||||||
comments[idx] = parent
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
comments.removeAll { $0.id == commentId }
|
|
||||||
}
|
|
||||||
} catch {
|
} catch {
|
||||||
// Silently ignore — comment may have already been deleted
|
// Revert the optimistic removal on failure
|
||||||
|
if let removed = removedComment {
|
||||||
|
if let parentId, let idx = removedAtIndex {
|
||||||
|
var parent = comments[idx]
|
||||||
|
var replies = parent.replies ?? []
|
||||||
|
replies.append(removed)
|
||||||
|
replies.sort { $0.created < $1.created }
|
||||||
|
parent.replies = replies
|
||||||
|
comments[idx] = parent
|
||||||
|
} else if let idx = removedAtIndex {
|
||||||
|
comments.insert(removed, at: min(idx, comments.count))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deletingIds.remove(commentId)
|
||||||
}
|
}
|
||||||
|
|
||||||
func vote(commentId: String, vote: String, parentId: String? = nil) async {
|
func vote(commentId: String, vote: String, parentId: String? = nil) async {
|
||||||
|
|||||||
Reference in New Issue
Block a user