// // 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> = [] @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) } }