pull/387/head
Niels Andriesse 5 years ago
parent 69c30fef70
commit 3f1358ac4d

@ -5,7 +5,7 @@ final class EditClosedGroupVC : BaseVC, UITableViewDataSource, UITableViewDelega
private let thread: TSGroupThread private let thread: TSGroupThread
private var name = "" private var name = ""
private var zombies: Set<String> = [] private var zombies: Set<String> = []
private var members: [String] = [] { didSet { handleMembersChanged() } } private var membersAndZombies: [String] = [] { didSet { handleMembersChanged() } }
private var isEditingGroupName = false { didSet { handleIsEditingGroupNameChanged() } } private var isEditingGroupName = false { didSet { handleIsEditingGroupNameChanged() } }
private var tableViewHeightConstraint: NSLayoutConstraint! private var tableViewHeightConstraint: NSLayoutConstraint!
@ -78,7 +78,7 @@ final class EditClosedGroupVC : BaseVC, UITableViewDataSource, UITableViewDelega
setUpViewHierarchy() setUpViewHierarchy()
// Always show zombies at the bottom // Always show zombies at the bottom
zombies = Storage.shared.getZombieMembers(for: groupPublicKey) zombies = Storage.shared.getZombieMembers(for: groupPublicKey)
members = GroupUtilities.getClosedGroupMembers(thread).sorted { getDisplayName(for: $0) < getDisplayName(for: $1) } membersAndZombies = GroupUtilities.getClosedGroupMembers(thread).sorted { getDisplayName(for: $0) < getDisplayName(for: $1) }
+ zombies.sorted { getDisplayName(for: $0) < getDisplayName(for: $1) } + zombies.sorted { getDisplayName(for: $0) < getDisplayName(for: $1) }
updateNavigationBarButtons() updateNavigationBarButtons()
name = thread.groupModel.groupName! name = thread.groupModel.groupName!
@ -107,7 +107,7 @@ final class EditClosedGroupVC : BaseVC, UITableViewDataSource, UITableViewDelega
membersLabel.font = .systemFont(ofSize: Values.mediumFontSize) membersLabel.font = .systemFont(ofSize: Values.mediumFontSize)
membersLabel.text = "Members" membersLabel.text = "Members"
// Add members button // Add members button
let hasContactsToAdd = !Set(ContactUtilities.getAllContacts()).subtracting(self.members).isEmpty let hasContactsToAdd = !Set(ContactUtilities.getAllContacts()).subtracting(self.membersAndZombies).isEmpty
if (!hasContactsToAdd) { if (!hasContactsToAdd) {
addMembersButton.isUserInteractionEnabled = false addMembersButton.isUserInteractionEnabled = false
let disabledColor = Colors.text.withAlphaComponent(Values.mediumOpacity) let disabledColor = Colors.text.withAlphaComponent(Values.mediumOpacity)
@ -147,29 +147,31 @@ final class EditClosedGroupVC : BaseVC, UITableViewDataSource, UITableViewDelega
// MARK: Table View Data Source / Delegate // MARK: Table View Data Source / Delegate
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return members.count return membersAndZombies.count
} }
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "UserCell") as! UserCell let cell = tableView.dequeueReusableCell(withIdentifier: "UserCell") as! UserCell
let publicKey = members[indexPath.row] let publicKey = membersAndZombies[indexPath.row]
cell.publicKey = publicKey cell.publicKey = publicKey
cell.isZombie = zombies.contains(publicKey) cell.isZombie = zombies.contains(publicKey)
cell.accessory = !canBeRemoved(publicKey) ? .lock : .none let userPublicKey = getUserHexEncodedPublicKey()
let isCurrentUserAdmin = thread.groupModel.groupAdminIds.contains(userPublicKey)
cell.accessory = !isCurrentUserAdmin ? .lock : .none
cell.update() cell.update()
return cell return cell
} }
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
let publicKey = members[indexPath.row] let userPublicKey = getUserHexEncodedPublicKey()
return canBeRemoved(publicKey) return thread.groupModel.groupAdminIds.contains(userPublicKey)
} }
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? { func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let publicKey = members[indexPath.row] let publicKey = membersAndZombies[indexPath.row]
let removeAction = UITableViewRowAction(style: .destructive, title: "Remove") { [weak self] _, _ in let removeAction = UITableViewRowAction(style: .destructive, title: "Remove") { [weak self] _, _ in
guard let self = self, let index = self.members.firstIndex(of: publicKey) else { return } guard let self = self, let index = self.membersAndZombies.firstIndex(of: publicKey) else { return }
self.members.remove(at: index) self.membersAndZombies.remove(at: index)
} }
removeAction.backgroundColor = Colors.destructive removeAction.backgroundColor = Colors.destructive
return [ removeAction ] return [ removeAction ]
@ -190,7 +192,7 @@ final class EditClosedGroupVC : BaseVC, UITableViewDataSource, UITableViewDelega
} }
private func handleMembersChanged() { private func handleMembersChanged() {
tableViewHeightConstraint.constant = CGFloat(members.count) * 67 tableViewHeightConstraint.constant = CGFloat(membersAndZombies.count) * 67
tableView.reloadData() tableView.reloadData()
} }
@ -239,15 +241,15 @@ final class EditClosedGroupVC : BaseVC, UITableViewDataSource, UITableViewDelega
@objc private func addMembers() { @objc private func addMembers() {
let title = "Add Members" let title = "Add Members"
let userSelectionVC = UserSelectionVC(with: title, excluding: Set(members)) { [weak self] selectedUsers in let userSelectionVC = UserSelectionVC(with: title, excluding: Set(membersAndZombies)) { [weak self] selectedUsers in
guard let self = self else { return } guard let self = self else { return }
var members = self.members var members = self.membersAndZombies
members.append(contentsOf: selectedUsers) members.append(contentsOf: selectedUsers)
func getDisplayName(for publicKey: String) -> String { func getDisplayName(for publicKey: String) -> String {
return Storage.shared.getContact(with: publicKey)?.displayName(for: .regular) ?? publicKey return Storage.shared.getContact(with: publicKey)?.displayName(for: .regular) ?? publicKey
} }
self.members = members.sorted { getDisplayName(for: $0) < getDisplayName(for: $1) } self.membersAndZombies = members.sorted { getDisplayName(for: $0) < getDisplayName(for: $1) }
let hasContactsToAdd = !Set(ContactUtilities.getAllContacts()).subtracting(self.members).isEmpty let hasContactsToAdd = !Set(ContactUtilities.getAllContacts()).subtracting(self.membersAndZombies).isEmpty
self.addMembersButton.isUserInteractionEnabled = hasContactsToAdd self.addMembersButton.isUserInteractionEnabled = hasContactsToAdd
let color = hasContactsToAdd ? Colors.accent : Colors.text.withAlphaComponent(Values.mediumOpacity) let color = hasContactsToAdd ? Colors.accent : Colors.text.withAlphaComponent(Values.mediumOpacity)
self.addMembersButton.layer.borderColor = color.cgColor self.addMembersButton.layer.borderColor = color.cgColor
@ -264,9 +266,11 @@ final class EditClosedGroupVC : BaseVC, UITableViewDataSource, UITableViewDelega
editVC.navigationController!.popViewController(animated: true) editVC.navigationController!.popViewController(animated: true)
} }
} }
let members = Set(self.members) let storage = SNMessagingKitConfiguration.shared.storage
let members = Set(self.membersAndZombies)
let name = self.name let name = self.name
guard members != Set(thread.groupModel.groupMemberIds) || name != thread.groupModel.groupName else { let zombies = storage.getZombieMembers(for: groupPublicKey)
guard members != Set(thread.groupModel.groupMemberIds + zombies) || name != thread.groupModel.groupName else {
return popToConversationVC(self) return popToConversationVC(self)
} }
if !members.contains(getUserHexEncodedPublicKey()) { if !members.contains(getUserHexEncodedPublicKey()) {
@ -305,10 +309,4 @@ final class EditClosedGroupVC : BaseVC, UITableViewDataSource, UITableViewDelega
alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .default, handler: nil)) alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .default, handler: nil))
presentAlert(alert) presentAlert(alert)
} }
private func canBeRemoved(_ publicKey: String) -> Bool {
let userPublicKey = getUserHexEncodedPublicKey()
let isCurrentUserAdmin = thread.groupModel.groupAdminIds.contains(userPublicKey)
return isCurrentUserAdmin || (publicKey == userPublicKey)
}
} }

@ -108,8 +108,9 @@ extension MessageSender {
let addedMembers = members.subtracting(group.groupMemberIds) let addedMembers = members.subtracting(group.groupMemberIds)
if !addedMembers.isEmpty { promises.append(addMembers(addedMembers, to: groupPublicKey, using: transaction)) } if !addedMembers.isEmpty { promises.append(addMembers(addedMembers, to: groupPublicKey, using: transaction)) }
// Remove members if needed // Remove members if needed
let removedMembers = Set(group.groupMemberIds).subtracting(members) let zombies = SNMessagingKitConfiguration.shared.storage.getZombieMembers(for: groupPublicKey)
if !removedMembers.isEmpty { promises.append(removeMembers(removedMembers, to: groupPublicKey, using: transaction)) } let removedMembers = Set(group.groupMemberIds + zombies).subtracting(members)
if !removedMembers.isEmpty{ promises.append(removeMembers(removedMembers, to: groupPublicKey, using: transaction)) }
// Return // Return
return when(fulfilled: promises).map2 { _ in } return when(fulfilled: promises).map2 { _ in }
} }
@ -198,11 +199,12 @@ extension MessageSender {
let userPublicKey = getUserHexEncodedPublicKey() let userPublicKey = getUserHexEncodedPublicKey()
let groupID = LKGroupUtilities.getEncodedClosedGroupIDAsData(groupPublicKey) let groupID = LKGroupUtilities.getEncodedClosedGroupIDAsData(groupPublicKey)
let threadID = TSGroupThread.threadId(fromGroupId: groupID) let threadID = TSGroupThread.threadId(fromGroupId: groupID)
let storage = SNMessagingKitConfiguration.shared.storage
guard let thread = TSGroupThread.fetch(uniqueId: threadID, transaction: transaction) else { guard let thread = TSGroupThread.fetch(uniqueId: threadID, transaction: transaction) else {
SNLog("Can't remove members from nonexistent closed group.") SNLog("Can't remove members from nonexistent closed group.")
return Promise(error: Error.noThread) return Promise(error: Error.noThread)
} }
guard !membersToRemove.isEmpty else { guard !membersToRemove.isEmpty || !storage.getZombieMembers(for: groupPublicKey).isEmpty else {
SNLog("Invalid closed group update.") SNLog("Invalid closed group update.")
return Promise(error: Error.invalidClosedGroupUpdate) return Promise(error: Error.invalidClosedGroupUpdate)
} }
@ -217,7 +219,6 @@ extension MessageSender {
} }
let members = Set(group.groupMemberIds).subtracting(membersToRemove) let members = Set(group.groupMemberIds).subtracting(membersToRemove)
// Update zombie list // Update zombie list
let storage = SNMessagingKitConfiguration.shared.storage
let zombies = storage.getZombieMembers(for: groupPublicKey).subtracting(membersToRemove) let zombies = storage.getZombieMembers(for: groupPublicKey).subtracting(membersToRemove)
storage.setZombieMembers(for: groupPublicKey, to: zombies, using: transaction) storage.setZombieMembers(for: groupPublicKey, to: zombies, using: transaction)
// Send the update to the group and generate + distribute a new encryption key pair // Send the update to the group and generate + distribute a new encryption key pair

Loading…
Cancel
Save