Files
simplex-chat/apps/ios/Shared/Views/Chat/ComposeMessage/ContextMemberContactActionsView.swift
spaced4ndy 1fb8e63680 ui: add swipe/menu actions to member contact requests (#6138)
* ios: add swipe actions to member contact requests

* kotlin

* padding
2025-08-01 16:08:54 +01:00

111 lines
3.7 KiB
Swift

//
// ContextMemberContactActionsView.swift
// SimpleX (iOS)
//
// Created by spaced4ndy on 31.07.2025.
// Copyright © 2025 SimpleX Chat. All rights reserved.
//
import SwiftUI
import SimpleXChat
struct ContextMemberContactActionsView: View {
@EnvironmentObject var theme: AppTheme
var contact: Contact
var groupDirectInv: GroupDirectInvitation
@UserDefault(DEFAULT_TOOLBAR_MATERIAL) private var toolbarMaterial = ToolbarMaterial.defaultMaterial
@State private var inProgress = false
@State private var progressByTimeout = false
var body: some View {
VStack {
if groupDirectInv.memberRemoved {
Label("Member is deleted - can't accept request", systemImage: "info.circle")
.foregroundColor(theme.colors.secondary)
.font(.subheadline)
.padding(.horizontal)
.frame(maxWidth: .infinity, minHeight: 60)
} else {
HStack(spacing: 0) {
Button(role: .destructive, action: { showRejectMemberContactRequestAlert(contact) }) {
Label("Reject", systemImage: "multiply")
}
.frame(maxWidth: .infinity, minHeight: 60)
Button {
acceptMemberContactRequest(contact, inProgress: $inProgress)
} label: {
Label("Accept", systemImage: "checkmark")
}
.frame(maxWidth: .infinity, minHeight: 60)
}
}
}
.disabled(inProgress || groupDirectInv.memberRemoved)
.frame(maxWidth: .infinity)
.background(ToolbarMaterial.material(toolbarMaterial))
.opacity(progressByTimeout ? 0.4 : 1)
.overlay {
if progressByTimeout {
ProgressView()
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
.onChange(of: inProgress) { inPrgrs in
if inPrgrs {
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
progressByTimeout = inProgress
}
} else {
progressByTimeout = false
}
}
}
}
func showRejectMemberContactRequestAlert(_ contact: Contact) {
showAlert(
NSLocalizedString("Reject contact request", comment: "alert title"),
message: NSLocalizedString("The sender will NOT be notified", comment: "alert message"),
actions: {[
UIAlertAction(title: NSLocalizedString("Reject", comment: "alert action"), style: .destructive) { _ in
deleteContact(contact)
},
cancelAlertAction
]}
)
}
private func deleteContact(_ contact: Contact) {
Task {
do {
_ = try await apiDeleteContact(id: contact.contactId, chatDeleteMode: .full(notify: false))
await MainActor.run {
ChatModel.shared.removeChat(contact.id)
ChatModel.shared.chatId = nil
}
} catch let error {
logger.error("apiDeleteContact: \(responseError(error))")
await MainActor.run {
showAlert(
NSLocalizedString("Error deleting chat!", comment: "alert title"),
message: responseError(error)
)
}
}
}
}
func acceptMemberContactRequest(_ contact: Contact, inProgress: Binding<Bool>? = nil) {
Task {
await acceptMemberContact(contactId: contact.contactId, inProgress: inProgress)
}
}
#Preview {
ContextMemberContactActionsView(
contact: Contact.sampleData,
groupDirectInv: GroupDirectInvitation.sampleData
)
}