Implement basic closed group editing UI
This commit is contained in:
parent
8411cae22e
commit
5e79b4eeee
|
@ -568,6 +568,7 @@
|
||||||
BFF3FB9730634F37D25903F4 /* Pods_Signal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D17BB5C25D615AB49813100C /* Pods_Signal.framework */; };
|
BFF3FB9730634F37D25903F4 /* Pods_Signal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D17BB5C25D615AB49813100C /* Pods_Signal.framework */; };
|
||||||
C31A6C5A247F214E001123EF /* UIView+Glow.swift in Sources */ = {isa = PBXBuildFile; fileRef = C31A6C59247F214E001123EF /* UIView+Glow.swift */; };
|
C31A6C5A247F214E001123EF /* UIView+Glow.swift in Sources */ = {isa = PBXBuildFile; fileRef = C31A6C59247F214E001123EF /* UIView+Glow.swift */; };
|
||||||
C31A6C5C247F2CF3001123EF /* CGRect+Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = C31A6C5B247F2CF3001123EF /* CGRect+Utilities.swift */; };
|
C31A6C5C247F2CF3001123EF /* CGRect+Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = C31A6C5B247F2CF3001123EF /* CGRect+Utilities.swift */; };
|
||||||
|
C31D1DD325216101005D4DA8 /* UIView+Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = C31D1DD225216101005D4DA8 /* UIView+Utilities.swift */; };
|
||||||
C329FEEC24F7277900B1C64C /* LightModeSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = C329FEEB24F7277900B1C64C /* LightModeSheet.swift */; };
|
C329FEEC24F7277900B1C64C /* LightModeSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = C329FEEB24F7277900B1C64C /* LightModeSheet.swift */; };
|
||||||
C329FEEF24F7743F00B1C64C /* UIViewController+Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = C329FEED24F7742E00B1C64C /* UIViewController+Utilities.swift */; };
|
C329FEEF24F7743F00B1C64C /* UIViewController+Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = C329FEED24F7742E00B1C64C /* UIViewController+Utilities.swift */; };
|
||||||
C34C8F7423A7830B00D82669 /* SpaceMono-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = C34C8F7323A7830A00D82669 /* SpaceMono-Bold.ttf */; };
|
C34C8F7423A7830B00D82669 /* SpaceMono-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = C34C8F7323A7830A00D82669 /* SpaceMono-Bold.ttf */; };
|
||||||
|
@ -596,6 +597,7 @@
|
||||||
C3DAB3242480CB2B00725F25 /* SRCopyableLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3DAB3232480CB2A00725F25 /* SRCopyableLabel.swift */; };
|
C3DAB3242480CB2B00725F25 /* SRCopyableLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3DAB3232480CB2A00725F25 /* SRCopyableLabel.swift */; };
|
||||||
C3DFFAC623E96F0D0058DAF8 /* Sheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3DFFAC523E96F0D0058DAF8 /* Sheet.swift */; };
|
C3DFFAC623E96F0D0058DAF8 /* Sheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3DFFAC523E96F0D0058DAF8 /* Sheet.swift */; };
|
||||||
C3DFFAC823E970080058DAF8 /* OpenGroupSuggestionSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3DFFAC723E970080058DAF8 /* OpenGroupSuggestionSheet.swift */; };
|
C3DFFAC823E970080058DAF8 /* OpenGroupSuggestionSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3DFFAC723E970080058DAF8 /* OpenGroupSuggestionSheet.swift */; };
|
||||||
|
C3E5C2FA251DBABB0040DFFC /* EditClosedGroupVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3E5C2F9251DBABB0040DFFC /* EditClosedGroupVC.swift */; };
|
||||||
CC875800737563D6891B741D /* Pods_SignalTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 748A5CAEDD7C919FC64C6807 /* Pods_SignalTests.framework */; };
|
CC875800737563D6891B741D /* Pods_SignalTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 748A5CAEDD7C919FC64C6807 /* Pods_SignalTests.framework */; };
|
||||||
D202868116DBE0E7009068E9 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D2AEACDB16C426DA00C364C0 /* CFNetwork.framework */; };
|
D202868116DBE0E7009068E9 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D2AEACDB16C426DA00C364C0 /* CFNetwork.framework */; };
|
||||||
D202868216DBE0F4009068E9 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D2179CFD16BB0B480006F3AB /* SystemConfiguration.framework */; };
|
D202868216DBE0F4009068E9 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D2179CFD16BB0B480006F3AB /* SystemConfiguration.framework */; };
|
||||||
|
@ -1362,6 +1364,7 @@
|
||||||
B9EB5ABC1884C002007CBB57 /* MessageUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MessageUI.framework; path = System/Library/Frameworks/MessageUI.framework; sourceTree = SDKROOT; };
|
B9EB5ABC1884C002007CBB57 /* MessageUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MessageUI.framework; path = System/Library/Frameworks/MessageUI.framework; sourceTree = SDKROOT; };
|
||||||
C31A6C59247F214E001123EF /* UIView+Glow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Glow.swift"; sourceTree = "<group>"; };
|
C31A6C59247F214E001123EF /* UIView+Glow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Glow.swift"; sourceTree = "<group>"; };
|
||||||
C31A6C5B247F2CF3001123EF /* CGRect+Utilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CGRect+Utilities.swift"; sourceTree = "<group>"; };
|
C31A6C5B247F2CF3001123EF /* CGRect+Utilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CGRect+Utilities.swift"; sourceTree = "<group>"; };
|
||||||
|
C31D1DD225216101005D4DA8 /* UIView+Utilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Utilities.swift"; sourceTree = "<group>"; };
|
||||||
C329FEEB24F7277900B1C64C /* LightModeSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LightModeSheet.swift; sourceTree = "<group>"; };
|
C329FEEB24F7277900B1C64C /* LightModeSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LightModeSheet.swift; sourceTree = "<group>"; };
|
||||||
C329FEED24F7742E00B1C64C /* UIViewController+Utilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+Utilities.swift"; sourceTree = "<group>"; };
|
C329FEED24F7742E00B1C64C /* UIViewController+Utilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+Utilities.swift"; sourceTree = "<group>"; };
|
||||||
C34C8F7323A7830A00D82669 /* SpaceMono-Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "SpaceMono-Bold.ttf"; sourceTree = "<group>"; };
|
C34C8F7323A7830A00D82669 /* SpaceMono-Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "SpaceMono-Bold.ttf"; sourceTree = "<group>"; };
|
||||||
|
@ -1394,6 +1397,7 @@
|
||||||
C3DAB3232480CB2A00725F25 /* SRCopyableLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SRCopyableLabel.swift; sourceTree = "<group>"; };
|
C3DAB3232480CB2A00725F25 /* SRCopyableLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SRCopyableLabel.swift; sourceTree = "<group>"; };
|
||||||
C3DFFAC523E96F0D0058DAF8 /* Sheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Sheet.swift; sourceTree = "<group>"; };
|
C3DFFAC523E96F0D0058DAF8 /* Sheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Sheet.swift; sourceTree = "<group>"; };
|
||||||
C3DFFAC723E970080058DAF8 /* OpenGroupSuggestionSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenGroupSuggestionSheet.swift; sourceTree = "<group>"; };
|
C3DFFAC723E970080058DAF8 /* OpenGroupSuggestionSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenGroupSuggestionSheet.swift; sourceTree = "<group>"; };
|
||||||
|
C3E5C2F9251DBABB0040DFFC /* EditClosedGroupVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditClosedGroupVC.swift; sourceTree = "<group>"; };
|
||||||
D17BB5C25D615AB49813100C /* Pods_Signal.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Signal.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
D17BB5C25D615AB49813100C /* Pods_Signal.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Signal.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
D2179CFB16BB0B3A0006F3AB /* CoreTelephony.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreTelephony.framework; path = System/Library/Frameworks/CoreTelephony.framework; sourceTree = SDKROOT; };
|
D2179CFB16BB0B3A0006F3AB /* CoreTelephony.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreTelephony.framework; path = System/Library/Frameworks/CoreTelephony.framework; sourceTree = SDKROOT; };
|
||||||
D2179CFD16BB0B480006F3AB /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
|
D2179CFD16BB0B480006F3AB /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
|
||||||
|
@ -2654,6 +2658,7 @@
|
||||||
B8544E3023D16CA500299F14 /* DeviceUtilities.swift */,
|
B8544E3023D16CA500299F14 /* DeviceUtilities.swift */,
|
||||||
C329FEED24F7742E00B1C64C /* UIViewController+Utilities.swift */,
|
C329FEED24F7742E00B1C64C /* UIViewController+Utilities.swift */,
|
||||||
B885D5F52334A32100EE0D8E /* UIView+Constraints.swift */,
|
B885D5F52334A32100EE0D8E /* UIView+Constraints.swift */,
|
||||||
|
C31D1DD225216101005D4DA8 /* UIView+Utilities.swift */,
|
||||||
);
|
);
|
||||||
path = Utilities;
|
path = Utilities;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -2709,6 +2714,7 @@
|
||||||
B80C6B582384C4E700FDBC8B /* DeviceNameModal.swift */,
|
B80C6B582384C4E700FDBC8B /* DeviceNameModal.swift */,
|
||||||
B80C6B5A2384C7F900FDBC8B /* DeviceNameModalDelegate.swift */,
|
B80C6B5A2384C7F900FDBC8B /* DeviceNameModalDelegate.swift */,
|
||||||
B82B408D239DC00D00A248E7 /* DisplayNameVC.swift */,
|
B82B408D239DC00D00A248E7 /* DisplayNameVC.swift */,
|
||||||
|
C3E5C2F9251DBABB0040DFFC /* EditClosedGroupVC.swift */,
|
||||||
B88847BB23E10BC6009836D2 /* GroupMembersVC.swift */,
|
B88847BB23E10BC6009836D2 /* GroupMembersVC.swift */,
|
||||||
B8BB82A4238F627000BA5194 /* HomeVC.swift */,
|
B8BB82A4238F627000BA5194 /* HomeVC.swift */,
|
||||||
B8CCF63E23975CFB0091D419 /* JoinPublicChatVC.swift */,
|
B8CCF63E23975CFB0091D419 /* JoinPublicChatVC.swift */,
|
||||||
|
@ -3705,6 +3711,7 @@
|
||||||
4541B71D209D3B7A0008608F /* ContactShareViewModel.swift in Sources */,
|
4541B71D209D3B7A0008608F /* ContactShareViewModel.swift in Sources */,
|
||||||
4C618199219DF03A009BD6B5 /* OWSButton.swift in Sources */,
|
4C618199219DF03A009BD6B5 /* OWSButton.swift in Sources */,
|
||||||
34AC09F3211B39B100997B47 /* NewNonContactConversationViewController.m in Sources */,
|
34AC09F3211B39B100997B47 /* NewNonContactConversationViewController.m in Sources */,
|
||||||
|
C31D1DD325216101005D4DA8 /* UIView+Utilities.swift in Sources */,
|
||||||
4C3E245C21F29FCE000AE092 /* Toast.swift in Sources */,
|
4C3E245C21F29FCE000AE092 /* Toast.swift in Sources */,
|
||||||
34BBC84B220B2CB200857249 /* ImageEditorTextViewController.swift in Sources */,
|
34BBC84B220B2CB200857249 /* ImageEditorTextViewController.swift in Sources */,
|
||||||
34AC09FA211B39B100997B47 /* SharingThreadPickerViewController.m in Sources */,
|
34AC09FA211B39B100997B47 /* SharingThreadPickerViewController.m in Sources */,
|
||||||
|
@ -3770,6 +3777,7 @@
|
||||||
45C9DEB81DF4E35A0065CA84 /* WebRTCCallMessageHandler.swift in Sources */,
|
45C9DEB81DF4E35A0065CA84 /* WebRTCCallMessageHandler.swift in Sources */,
|
||||||
34D1F0501F7D45A60066283D /* GifPickerCell.swift in Sources */,
|
34D1F0501F7D45A60066283D /* GifPickerCell.swift in Sources */,
|
||||||
3496957421A301A100DCFE74 /* OWSBackupAPI.swift in Sources */,
|
3496957421A301A100DCFE74 /* OWSBackupAPI.swift in Sources */,
|
||||||
|
C3E5C2FA251DBABB0040DFFC /* EditClosedGroupVC.swift in Sources */,
|
||||||
34D99C931F2937CC00D284D6 /* OWSAnalytics.swift in Sources */,
|
34D99C931F2937CC00D284D6 /* OWSAnalytics.swift in Sources */,
|
||||||
B8783E9E23EB948D00404FB8 /* UILabel+Interaction.swift in Sources */,
|
B8783E9E23EB948D00404FB8 /* UILabel+Interaction.swift in Sources */,
|
||||||
B80C6B5B2384C7F900FDBC8B /* DeviceNameModalDelegate.swift in Sources */,
|
B80C6B5B2384C7F900FDBC8B /* DeviceNameModalDelegate.swift in Sources */,
|
||||||
|
|
|
@ -0,0 +1,272 @@
|
||||||
|
|
||||||
|
@objc(LKEditClosedGroupVC)
|
||||||
|
final class EditClosedGroupVC : BaseVC, UITableViewDataSource, UITableViewDelegate {
|
||||||
|
private let thread: TSGroupThread
|
||||||
|
private var isEditingGroupName = false { didSet { handleIsEditingGroupNameChanged() } }
|
||||||
|
|
||||||
|
private lazy var members: [String] = {
|
||||||
|
func getDisplayName(for hexEncodedPublicKey: String) -> String {
|
||||||
|
return UserDisplayNameUtilities.getPrivateChatDisplayName(for: hexEncodedPublicKey) ?? hexEncodedPublicKey
|
||||||
|
}
|
||||||
|
return GroupUtilities.getClosedGroupMembers(thread).sorted { getDisplayName(for: $0) < getDisplayName(for: $1) }
|
||||||
|
}()
|
||||||
|
|
||||||
|
// MARK: Components
|
||||||
|
private lazy var groupNameLabel: UILabel = {
|
||||||
|
let result = UILabel()
|
||||||
|
result.textColor = Colors.text
|
||||||
|
result.font = .boldSystemFont(ofSize: Values.veryLargeFontSize)
|
||||||
|
result.lineBreakMode = .byTruncatingTail
|
||||||
|
result.textAlignment = .center
|
||||||
|
return result
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var groupNameTextField: TextField = {
|
||||||
|
let result = TextField(placeholder: "Enter a group name", usesDefaultHeight: false)
|
||||||
|
result.textAlignment = .center
|
||||||
|
return result
|
||||||
|
}()
|
||||||
|
|
||||||
|
@objc private lazy var tableView: UITableView = {
|
||||||
|
let result = UITableView()
|
||||||
|
result.dataSource = self
|
||||||
|
result.delegate = self
|
||||||
|
result.register(Cell.self, forCellReuseIdentifier: "Cell")
|
||||||
|
result.separatorStyle = .none
|
||||||
|
result.backgroundColor = .clear
|
||||||
|
result.isScrollEnabled = false
|
||||||
|
return result
|
||||||
|
}()
|
||||||
|
|
||||||
|
// MARK: Lifecycle
|
||||||
|
@objc(initWithThreadID:)
|
||||||
|
init(with threadID: String) {
|
||||||
|
var thread: TSGroupThread!
|
||||||
|
Storage.read { transaction in
|
||||||
|
thread = TSGroupThread.fetch(uniqueId: threadID, transaction: transaction)!
|
||||||
|
}
|
||||||
|
self.thread = thread
|
||||||
|
super.init(nibName: nil, bundle: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder: NSCoder) {
|
||||||
|
preconditionFailure("Use init(with:) instead.")
|
||||||
|
}
|
||||||
|
|
||||||
|
override func viewDidLoad() {
|
||||||
|
super.viewDidLoad()
|
||||||
|
setUpGradientBackground()
|
||||||
|
setUpNavBarStyle()
|
||||||
|
setNavBarTitle("Edit Group")
|
||||||
|
let backButton = UIBarButtonItem(title: "Back", style: .plain, target: nil, action: nil)
|
||||||
|
backButton.tintColor = Colors.text
|
||||||
|
navigationItem.backBarButtonItem = backButton
|
||||||
|
setUpViewHierarchy()
|
||||||
|
updateNavigationBarButtons()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func setUpViewHierarchy() {
|
||||||
|
// Group name container
|
||||||
|
groupNameLabel.text = thread.groupModel.groupName
|
||||||
|
let groupNameContainer = UIView()
|
||||||
|
groupNameContainer.addSubview(groupNameLabel)
|
||||||
|
groupNameLabel.pin(to: groupNameContainer)
|
||||||
|
groupNameContainer.addSubview(groupNameTextField)
|
||||||
|
groupNameTextField.pin(to: groupNameContainer)
|
||||||
|
groupNameContainer.set(.height, to: 40)
|
||||||
|
groupNameTextField.alpha = 0
|
||||||
|
// Top container
|
||||||
|
let topContainer = UIView()
|
||||||
|
topContainer.addSubview(groupNameContainer)
|
||||||
|
groupNameContainer.center(in: topContainer)
|
||||||
|
topContainer.set(.height, to: 40)
|
||||||
|
let topContainerTapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(showEditGroupNameUI))
|
||||||
|
topContainer.addGestureRecognizer(topContainerTapGestureRecognizer)
|
||||||
|
// Members label
|
||||||
|
let membersLabel = UILabel()
|
||||||
|
membersLabel.textColor = Colors.text
|
||||||
|
membersLabel.font = .systemFont(ofSize: Values.mediumFontSize)
|
||||||
|
membersLabel.text = "Members"
|
||||||
|
// Add members button
|
||||||
|
let addMembersButton = Button(style: .prominentOutline, size: .large)
|
||||||
|
addMembersButton.setTitle("Add Members", for: UIControl.State.normal)
|
||||||
|
addMembersButton.addTarget(self, action: #selector(addMembers), for: UIControl.Event.touchUpInside)
|
||||||
|
addMembersButton.contentEdgeInsets = UIEdgeInsets(top: 0, leading: Values.mediumSpacing, bottom: 0, trailing: Values.mediumSpacing)
|
||||||
|
// Middle stack view
|
||||||
|
let middleStackView = UIStackView(arrangedSubviews: [ membersLabel, addMembersButton ])
|
||||||
|
middleStackView.axis = .horizontal
|
||||||
|
middleStackView.alignment = .center
|
||||||
|
middleStackView.layoutMargins = UIEdgeInsets(top: Values.smallSpacing, leading: Values.mediumSpacing, bottom: Values.smallSpacing, trailing: Values.mediumSpacing)
|
||||||
|
middleStackView.isLayoutMarginsRelativeArrangement = true
|
||||||
|
// Main stack view
|
||||||
|
let mainStackView = UIStackView(arrangedSubviews: [
|
||||||
|
UIView.vSpacer(Values.veryLargeSpacing),
|
||||||
|
topContainer,
|
||||||
|
UIView.vSpacer(Values.veryLargeSpacing),
|
||||||
|
UIView.separator(),
|
||||||
|
middleStackView,
|
||||||
|
UIView.separator(),
|
||||||
|
tableView
|
||||||
|
])
|
||||||
|
mainStackView.axis = .vertical
|
||||||
|
mainStackView.alignment = .fill
|
||||||
|
mainStackView.set(.width, to: UIScreen.main.bounds.width)
|
||||||
|
// Scroll view
|
||||||
|
let scrollView = UIScrollView()
|
||||||
|
scrollView.showsVerticalScrollIndicator = false
|
||||||
|
scrollView.addSubview(mainStackView)
|
||||||
|
mainStackView.pin(to: scrollView)
|
||||||
|
view.addSubview(scrollView)
|
||||||
|
scrollView.pin(to: view)
|
||||||
|
mainStackView.pin(.bottom, to: .bottom, of: view)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: Table View Data Source / Delegate
|
||||||
|
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||||
|
return members.count
|
||||||
|
}
|
||||||
|
|
||||||
|
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||||
|
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") as! Cell
|
||||||
|
let publicKey = members[indexPath.row]
|
||||||
|
cell.publicKey = publicKey
|
||||||
|
return cell
|
||||||
|
}
|
||||||
|
|
||||||
|
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
|
||||||
|
let publicKey = members[indexPath.row]
|
||||||
|
return publicKey != getUserHexEncodedPublicKey()
|
||||||
|
}
|
||||||
|
|
||||||
|
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
|
||||||
|
let removeAction = UITableViewRowAction(style: .destructive, title: "Remove") { [weak self] _, _ in
|
||||||
|
// TODO: Implement
|
||||||
|
}
|
||||||
|
removeAction.backgroundColor = Colors.destructive
|
||||||
|
return [ removeAction ]
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: Updating
|
||||||
|
private func updateNavigationBarButtons() {
|
||||||
|
if isEditingGroupName {
|
||||||
|
let cancelButton = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(handleCancelGroupNameEditingButtonTapped))
|
||||||
|
cancelButton.tintColor = Colors.text
|
||||||
|
navigationItem.leftBarButtonItem = cancelButton
|
||||||
|
} else {
|
||||||
|
navigationItem.leftBarButtonItem = nil
|
||||||
|
}
|
||||||
|
let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(handleSaveGroupNameButtonTapped))
|
||||||
|
doneButton.tintColor = Colors.text
|
||||||
|
navigationItem.rightBarButtonItem = doneButton
|
||||||
|
}
|
||||||
|
|
||||||
|
private func handleIsEditingGroupNameChanged() {
|
||||||
|
updateNavigationBarButtons()
|
||||||
|
UIView.animate(withDuration: 0.25) {
|
||||||
|
self.groupNameLabel.alpha = self.isEditingGroupName ? 0 : 1
|
||||||
|
self.groupNameTextField.alpha = self.isEditingGroupName ? 1 : 0
|
||||||
|
}
|
||||||
|
if isEditingGroupName {
|
||||||
|
groupNameTextField.becomeFirstResponder()
|
||||||
|
} else {
|
||||||
|
groupNameTextField.resignFirstResponder()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: Interaction
|
||||||
|
@objc private func showEditGroupNameUI() {
|
||||||
|
isEditingGroupName = true
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc private func handleCancelGroupNameEditingButtonTapped() {
|
||||||
|
isEditingGroupName = false
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc private func handleSaveGroupNameButtonTapped() {
|
||||||
|
isEditingGroupName = false
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc private func addMembers() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: - Cell
|
||||||
|
|
||||||
|
private extension EditClosedGroupVC {
|
||||||
|
|
||||||
|
final class Cell : UITableViewCell {
|
||||||
|
var publicKey = "" { didSet { update() } }
|
||||||
|
|
||||||
|
// MARK: Components
|
||||||
|
private lazy var profilePictureView = ProfilePictureView()
|
||||||
|
|
||||||
|
private lazy var displayNameLabel: UILabel = {
|
||||||
|
let result = UILabel()
|
||||||
|
result.textColor = Colors.text
|
||||||
|
result.font = .boldSystemFont(ofSize: Values.mediumFontSize)
|
||||||
|
result.lineBreakMode = .byTruncatingTail
|
||||||
|
return result
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var separator: UIView = {
|
||||||
|
let result = UIView()
|
||||||
|
result.backgroundColor = Colors.separator
|
||||||
|
result.set(.height, to: Values.separatorThickness)
|
||||||
|
return result
|
||||||
|
}()
|
||||||
|
|
||||||
|
// MARK: Initialization
|
||||||
|
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
||||||
|
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||||||
|
setUpViewHierarchy()
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder: NSCoder) {
|
||||||
|
super.init(coder: coder)
|
||||||
|
setUpViewHierarchy()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func setUpViewHierarchy() {
|
||||||
|
// Set the cell background color
|
||||||
|
backgroundColor = Colors.cellBackground
|
||||||
|
// Set up the highlight color
|
||||||
|
let selectedBackgroundView = UIView()
|
||||||
|
selectedBackgroundView.backgroundColor = .clear // Disabled for now
|
||||||
|
self.selectedBackgroundView = selectedBackgroundView
|
||||||
|
// Set up the profile picture image view
|
||||||
|
let profilePictureViewSize = Values.smallProfilePictureSize
|
||||||
|
profilePictureView.set(.width, to: profilePictureViewSize)
|
||||||
|
profilePictureView.set(.height, to: profilePictureViewSize)
|
||||||
|
profilePictureView.size = profilePictureViewSize
|
||||||
|
// Set up the main stack view
|
||||||
|
let stackView = UIStackView(arrangedSubviews: [ profilePictureView, displayNameLabel ])
|
||||||
|
stackView.axis = .horizontal
|
||||||
|
stackView.alignment = .center
|
||||||
|
stackView.spacing = Values.mediumSpacing
|
||||||
|
contentView.addSubview(stackView)
|
||||||
|
stackView.pin(.leading, to: .leading, of: contentView, withInset: Values.mediumSpacing)
|
||||||
|
stackView.pin(.top, to: .top, of: contentView, withInset: Values.mediumSpacing)
|
||||||
|
contentView.pin(.trailing, to: .trailing, of: stackView, withInset: Values.mediumSpacing)
|
||||||
|
contentView.pin(.bottom, to: .bottom, of: stackView, withInset: Values.mediumSpacing)
|
||||||
|
stackView.set(.width, to: UIScreen.main.bounds.width - 2 * Values.mediumSpacing)
|
||||||
|
// Set up the separator
|
||||||
|
contentView.addSubview(separator)
|
||||||
|
separator.pin(.leading, to: .leading, of: contentView)
|
||||||
|
contentView.pin(.trailing, to: .trailing, of: separator)
|
||||||
|
separator.pin(.bottom, to: .bottom, of: contentView)
|
||||||
|
separator.set(.width, to: UIScreen.main.bounds.width)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: Updating
|
||||||
|
private func update() {
|
||||||
|
profilePictureView.hexEncodedPublicKey = publicKey
|
||||||
|
profilePictureView.update()
|
||||||
|
displayNameLabel.text = UserDisplayNameUtilities.getPrivateChatDisplayName(for: publicKey) ?? publicKey
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -63,7 +63,7 @@ final class SeedModal : Modal {
|
||||||
let disclaimerLabel = UILabel()
|
let disclaimerLabel = UILabel()
|
||||||
disclaimerLabel.textColor = Colors.text.withAlphaComponent(Values.unimportantElementOpacity)
|
disclaimerLabel.textColor = Colors.text.withAlphaComponent(Values.unimportantElementOpacity)
|
||||||
disclaimerLabel.font = .systemFont(ofSize: 10)
|
disclaimerLabel.font = .systemFont(ofSize: 10)
|
||||||
disclaimerLabel.text = NSLocalizedString("modal_seed_disclaimer", comment: "")
|
disclaimerLabel.text = "It is not possible to use the same Session ID on multiple devices simultaneously"
|
||||||
disclaimerLabel.numberOfLines = 0
|
disclaimerLabel.numberOfLines = 0
|
||||||
disclaimerLabel.lineBreakMode = .byWordWrapping
|
disclaimerLabel.lineBreakMode = .byWordWrapping
|
||||||
disclaimerLabel.textAlignment = .center
|
disclaimerLabel.textAlignment = .center
|
||||||
|
|
|
@ -651,34 +651,37 @@ const CGFloat kIconViewLength = 24;
|
||||||
|
|
||||||
|
|
||||||
if (self.isGroupThread && self.isPrivateGroupChat) {
|
if (self.isGroupThread && self.isPrivateGroupChat) {
|
||||||
// [OWSTableItem
|
if (((TSGroupThread *)self.thread).usesSharedSenderKeys) {
|
||||||
|
[mainSection addItem:[OWSTableItem
|
||||||
|
itemWithCustomCellBlock:^{
|
||||||
|
UITableViewCell *cell =
|
||||||
|
[weakSelf disclosureCellWithName:NSLocalizedString(@"EDIT_GROUP_ACTION",
|
||||||
|
@"table cell label in conversation settings")
|
||||||
|
iconName:@"table_ic_group_edit"
|
||||||
|
accessibilityIdentifier:ACCESSIBILITY_IDENTIFIER_WITH_NAME(
|
||||||
|
OWSConversationSettingsViewController, @"edit_group")];
|
||||||
|
cell.userInteractionEnabled = !weakSelf.hasLeftGroup;
|
||||||
|
return cell;
|
||||||
|
}
|
||||||
|
actionBlock:^{
|
||||||
|
[weakSelf editGroup];
|
||||||
|
}]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
// [mainSection addItem:[OWSTableItem
|
||||||
// itemWithCustomCellBlock:^{
|
// itemWithCustomCellBlock:^{
|
||||||
// UITableViewCell *cell =
|
// UITableViewCell *cell =
|
||||||
// [weakSelf disclosureCellWithName:NSLocalizedString(@"EDIT_GROUP_ACTION",
|
// [weakSelf disclosureCellWithName:NSLocalizedString(@"LIST_GROUP_MEMBERS_ACTION",
|
||||||
// @"table cell label in conversation settings")
|
// @"table cell label in conversation settings")
|
||||||
// iconName:@"table_ic_group_edit"
|
// iconName:@"table_ic_group_members"
|
||||||
// accessibilityIdentifier:ACCESSIBILITY_IDENTIFIER_WITH_NAME(
|
// accessibilityIdentifier:ACCESSIBILITY_IDENTIFIER_WITH_NAME(
|
||||||
// OWSConversationSettingsViewController, @"edit_group")];
|
// OWSConversationSettingsViewController, @"group_members")];
|
||||||
// cell.userInteractionEnabled = !weakSelf.hasLeftGroup;
|
|
||||||
// return cell;
|
// return cell;
|
||||||
// }
|
// }
|
||||||
// actionBlock:^{
|
// actionBlock:^{
|
||||||
// [weakSelf showUpdateGroupView:UpdateGroupMode_Default];
|
// [weakSelf showGroupMembersView];
|
||||||
// }],
|
// }]
|
||||||
[mainSection addItem:[OWSTableItem
|
// ];
|
||||||
itemWithCustomCellBlock:^{
|
|
||||||
UITableViewCell *cell =
|
|
||||||
[weakSelf disclosureCellWithName:NSLocalizedString(@"LIST_GROUP_MEMBERS_ACTION",
|
|
||||||
@"table cell label in conversation settings")
|
|
||||||
iconName:@"table_ic_group_members"
|
|
||||||
accessibilityIdentifier:ACCESSIBILITY_IDENTIFIER_WITH_NAME(
|
|
||||||
OWSConversationSettingsViewController, @"group_members")];
|
|
||||||
return cell;
|
|
||||||
}
|
|
||||||
actionBlock:^{
|
|
||||||
[weakSelf showGroupMembersView];
|
|
||||||
}]
|
|
||||||
];
|
|
||||||
NSString *userPublicKey = OWSIdentityManager.sharedManager.identityKeyPair.hexEncodedPublicKey;
|
NSString *userPublicKey = OWSIdentityManager.sharedManager.identityKeyPair.hexEncodedPublicKey;
|
||||||
if ([((TSGroupThread *)self.thread).groupModel.groupMemberIds containsObject:userPublicKey]) {
|
if ([((TSGroupThread *)self.thread).groupModel.groupMemberIds containsObject:userPublicKey]) {
|
||||||
[mainSection addItem:[OWSTableItem
|
[mainSection addItem:[OWSTableItem
|
||||||
|
@ -1144,6 +1147,12 @@ const CGFloat kIconViewLength = 24;
|
||||||
[self presentContactViewController];
|
[self presentContactViewController];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)editGroup
|
||||||
|
{
|
||||||
|
LKEditClosedGroupVC *editClosedGroupVC = [[LKEditClosedGroupVC alloc] initWithThreadID:self.thread.uniqueId];
|
||||||
|
[self.navigationController pushViewController:editClosedGroupVC animated:YES];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)didTapLeaveGroup
|
- (void)didTapLeaveGroup
|
||||||
{
|
{
|
||||||
UIAlertController *alert =
|
UIAlertController *alert =
|
||||||
|
|
|
@ -2728,6 +2728,3 @@
|
||||||
"vc_contact_selection_contacts_title" = "Contacts";
|
"vc_contact_selection_contacts_title" = "Contacts";
|
||||||
"vc_contact_selection_closed_groups_title" = "Closed Groups";
|
"vc_contact_selection_closed_groups_title" = "Closed Groups";
|
||||||
"vc_contact_selection_open_groups_title" = "Open Groups";
|
"vc_contact_selection_open_groups_title" = "Open Groups";
|
||||||
|
|
||||||
// MARK: Next round of translation
|
|
||||||
"modal_seed_disclaimer" = "It is not possible to use the same Session ID on multiple devices simultaneously";
|
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
|
||||||
|
public extension UIView {
|
||||||
|
|
||||||
|
static func hSpacer(_ width: CGFloat) -> UIView {
|
||||||
|
let result = UIView()
|
||||||
|
result.set(.width, to: width)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
static func vSpacer(_ height: CGFloat) -> UIView {
|
||||||
|
let result = UIView()
|
||||||
|
result.set(.height, to: height)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
static func separator() -> UIView {
|
||||||
|
let result = UIView()
|
||||||
|
result.set(.height, to: Values.separatorThickness)
|
||||||
|
result.backgroundColor = Colors.separator
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue