another.im-ios/Monal/Classes/CreateGroupMenu.swift
2024-11-18 15:53:52 +01:00

142 lines
7.3 KiB
Swift

//
// AddContactMenu.swift
// Monal
//
// Created by Jan on 27.10.22.
// Copyright © 2022 monal-im.org. All rights reserved.
//
import OrderedCollections
struct CreateGroupMenu: View {
private var appDelegate: MonalAppDelegate
private var delegate: SheetDismisserProtocol
@State private var enabledAccounts: [xmpp]
@State private var selectedAccount: xmpp?
@State private var groupName: String = ""
@State private var showAlert = false
// note: dismissLabel is not accessed but defined at the .alert() section
@State private var alertPrompt = AlertPrompt(dismissLabel: Text("Close"))
@State private var selectedContacts: OrderedSet<ObservableKVOWrapper<MLContact>> = []
@State private var isEditingGroupName = false
@StateObject private var overlay = LoadingOverlayState()
init(delegate: SheetDismisserProtocol) {
self.appDelegate = UIApplication.shared.delegate as! MonalAppDelegate
self.delegate = delegate
let enabledAccounts = MLXMPPManager.sharedInstance().connectedXMPP as! [xmpp]
self.enabledAccounts = enabledAccounts
_selectedAccount = State(wrappedValue: enabledAccounts.first)
}
private func errorAlert(title: Text, message: Text = Text("")) {
alertPrompt.title = title
alertPrompt.message = message
showAlert = true
}
// When a Form is placed inside a Popover, and the horizontal size class is regular, the spacing chosen by SwiftUI is incorrect.
// In particular, the spacing between the top of the first element and the navigation bar is too small, meaning the two overlap.
// This only happens when the view is inside a popover, and the horizontal size class is regular.
// Therefore, it is inconvenient to apply some manual spacing, as this we would have to work out in which situations it should be applied.
// Placing a Text view inside the header causes SwiftUI to add consistent spacing in all situations.
var popoverFormSpacingWorkaround: some View {
Text("")
}
var body: some View {
Form {
if enabledAccounts.isEmpty {
Text("Please make sure at least one account has connected before trying to create new group.")
.foregroundColor(.secondary)
}
else
{
Section(header: popoverFormSpacingWorkaround) {
if enabledAccounts.count > 1 {
Picker(selection: $selectedAccount, label: Text("Use account")) {
ForEach(Array(self.enabledAccounts.enumerated()), id: \.element) { idx, account in
Text(account.connectionProperties.identity.jid).tag(account as xmpp?)
}
}
.pickerStyle(.menu)
}
TextField(NSLocalizedString("Group Name (optional)", comment: "placeholder when creating new group"), text: $groupName, onEditingChanged: { isEditingGroupName = $0 })
.autocorrectionDisabled()
.autocapitalization(.none)
.addClearButton(isEditing: isEditingGroupName, text:$groupName)
Button(action: {
guard let generatedJid = self.selectedAccount!.mucProcessor.generateMucJid() else {
errorAlert(title: Text("Error creating group!"), message: Text("Your server does not provide a MUC component."))
return
}
showLoadingOverlay(overlay, headline: NSLocalizedString("Creating Group", comment: ""))
guard let roomJid = self.selectedAccount!.mucProcessor.createGroup(generatedJid) else {
//room already existing in our local bookmarks --> just open it
//this should never happen since we randomly generated a jid above
hideLoadingOverlay(overlay)
let groupContact = MLContact.createContact(fromJid: generatedJid, andAccountID: self.selectedAccount!.accountID)
self.delegate.dismissWithoutAnimation()
if let activeChats = self.appDelegate.activeChats {
activeChats.presentChat(with:groupContact)
}
return
}
self.selectedAccount!.mucProcessor.addUIHandler({_data in let data = _data as! NSDictionary
let success : Bool = data["success"] as! Bool;
if success {
DataLayer.sharedInstance().setFullName(self.groupName, forContact:roomJid, andAccount:self.selectedAccount!.accountID)
self.selectedAccount!.mucProcessor.changeName(ofMuc: roomJid, to: self.groupName)
for user in self.selectedContacts {
self.selectedAccount!.mucProcessor.setAffiliation(kMucAffiliationMember, ofUser: user.contactJid, inMuc: roomJid)
self.selectedAccount!.mucProcessor.inviteUser(user.contactJid, inMuc: roomJid)
}
let groupContact = MLContact.createContact(fromJid: roomJid, andAccountID: self.selectedAccount!.accountID)
hideLoadingOverlay(overlay)
self.delegate.dismissWithoutAnimation()
if let activeChats = self.appDelegate.activeChats {
activeChats.presentChat(with:groupContact)
}
} else {
hideLoadingOverlay(overlay)
errorAlert(title: Text("Error creating group!"), message: Text(data["errorMessage"] as! String))
}
}, forMuc: roomJid)
}, label: {
Text("Create new group")
})
}
Section(header: Text("Selected Group Members")) {
NavigationLink(destination: LazyClosureView(ContactPicker(self.selectedAccount!, binding: $selectedContacts))) {
Text("Change Group Members")
}
ForEach(self.selectedContacts, id: \.obj.contactJid) { contact in
ContactEntry(contact: contact)
}
.onDelete(perform: { indexSet in
self.selectedContacts.remove(at: indexSet.first!)
})
}
}
}
.alert(isPresented: $showAlert) {
Alert(title: alertPrompt.title, message: alertPrompt.message, dismissButton:.default(Text("Close"), action: {
showAlert = false
}))
}
.addLoadingOverlay(overlay)
.navigationBarTitle(Text("Create new group"), displayMode: .inline)
}
}
struct CreateGroupMenu_Previews: PreviewProvider {
static var delegate = SheetDismisserProtocol()
static var previews: some View {
CreateGroupMenu(delegate: delegate)
}
}