mirror of https://github.com/oxen-io/session-ios
				
				
				
			
			You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			184 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			Swift
		
	
			
		
		
	
	
			184 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			Swift
		
	
| 
 | |
| final class MentionSelectionView : UIView, UITableViewDataSource, UITableViewDelegate {
 | |
|     var candidates: [Mention] = [] {
 | |
|         didSet {
 | |
|             tableView.isScrollEnabled = (candidates.count > 4)
 | |
|             tableView.reloadData()
 | |
|         }
 | |
|     }
 | |
|     var openGroupServer: String?
 | |
|     var openGroupChannel: UInt64?
 | |
|     var openGroupRoom: String?
 | |
|     weak var delegate: MentionSelectionViewDelegate?
 | |
| 
 | |
|     // MARK: Components
 | |
|     lazy var tableView: UITableView = { // TODO: Make this private
 | |
|         let result = UITableView()
 | |
|         result.dataSource = self
 | |
|         result.delegate = self
 | |
|         result.register(Cell.self, forCellReuseIdentifier: "Cell")
 | |
|         result.separatorStyle = .none
 | |
|         result.backgroundColor = .clear
 | |
|         result.showsVerticalScrollIndicator = false
 | |
|         return result
 | |
|     }()
 | |
| 
 | |
|     // MARK: Initialization
 | |
|     override init(frame: CGRect) {
 | |
|         super.init(frame: frame)
 | |
|         setUpViewHierarchy()
 | |
|     }
 | |
| 
 | |
|     required init?(coder: NSCoder) {
 | |
|         super.init(coder: coder)
 | |
|         setUpViewHierarchy()
 | |
|     }
 | |
| 
 | |
|     private func setUpViewHierarchy() {
 | |
|         // Table view
 | |
|         addSubview(tableView)
 | |
|         tableView.pin(to: self)
 | |
|         // Top separator
 | |
|         let topSeparator = UIView()
 | |
|         topSeparator.backgroundColor = Colors.separator
 | |
|         topSeparator.set(.height, to: Values.separatorThickness)
 | |
|         addSubview(topSeparator)
 | |
|         topSeparator.pin(.leading, to: .leading, of: self)
 | |
|         topSeparator.pin(.top, to: .top, of: self)
 | |
|         topSeparator.pin(.trailing, to: .trailing, of: self)
 | |
|         // Bottom separator
 | |
|         let bottomSeparator = UIView()
 | |
|         bottomSeparator.backgroundColor = Colors.separator
 | |
|         bottomSeparator.set(.height, to: Values.separatorThickness)
 | |
|         addSubview(bottomSeparator)
 | |
|         bottomSeparator.pin(.leading, to: .leading, of: self)
 | |
|         bottomSeparator.pin(.trailing, to: .trailing, of: self)
 | |
|         bottomSeparator.pin(.bottom, to: .bottom, of: self)
 | |
|     }
 | |
| 
 | |
|     // MARK: Data
 | |
|     func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
 | |
|         return candidates.count
 | |
|     }
 | |
| 
 | |
|     func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
 | |
|         let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") as! Cell
 | |
|         let mentionCandidate = candidates[indexPath.row]
 | |
|         cell.mentionCandidate = mentionCandidate
 | |
|         cell.openGroupServer = openGroupServer
 | |
|         cell.openGroupChannel = openGroupChannel
 | |
|         cell.openGroupRoom = openGroupRoom
 | |
|         cell.separator.isHidden = (indexPath.row == (candidates.count - 1))
 | |
|         return cell
 | |
|     }
 | |
| 
 | |
|     // MARK: Interaction
 | |
|     func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
 | |
|         let mentionCandidate = candidates[indexPath.row]
 | |
|         delegate?.handleMentionSelected(mentionCandidate, from: self)
 | |
|     }
 | |
| }
 | |
| 
 | |
| // MARK: - Cell
 | |
| 
 | |
| private extension MentionSelectionView {
 | |
| 
 | |
|     final class Cell : UITableViewCell {
 | |
|         var mentionCandidate = Mention(publicKey: "", displayName: "") { didSet { update() } }
 | |
|         var openGroupServer: String?
 | |
|         var openGroupChannel: UInt64?
 | |
|         var openGroupRoom: String?
 | |
| 
 | |
|         // MARK: Components
 | |
|         private lazy var profilePictureView = ProfilePictureView()
 | |
| 
 | |
|         private lazy var moderatorIconImageView = UIImageView(image: #imageLiteral(resourceName: "Crown"))
 | |
| 
 | |
|         private lazy var displayNameLabel: UILabel = {
 | |
|             let result = UILabel()
 | |
|             result.textColor = Colors.text
 | |
|             result.font = .systemFont(ofSize: Values.smallFontSize)
 | |
|             result.lineBreakMode = .byTruncatingTail
 | |
|             return result
 | |
|         }()
 | |
| 
 | |
|         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() {
 | |
|             // Cell background color
 | |
|             backgroundColor = .clear
 | |
|             // Highlight color
 | |
|             let selectedBackgroundView = UIView()
 | |
|             selectedBackgroundView.backgroundColor = .clear
 | |
|             self.selectedBackgroundView = selectedBackgroundView
 | |
|             // Profile picture image view
 | |
|             let profilePictureViewSize = Values.smallProfilePictureSize
 | |
|             profilePictureView.set(.width, to: profilePictureViewSize)
 | |
|             profilePictureView.set(.height, to: profilePictureViewSize)
 | |
|             profilePictureView.size = profilePictureViewSize
 | |
|             // Main stack view
 | |
|             let mainStackView = UIStackView(arrangedSubviews: [ profilePictureView, displayNameLabel ])
 | |
|             mainStackView.axis = .horizontal
 | |
|             mainStackView.alignment = .center
 | |
|             mainStackView.spacing = Values.mediumSpacing
 | |
|             mainStackView.set(.height, to: profilePictureViewSize)
 | |
|             contentView.addSubview(mainStackView)
 | |
|             mainStackView.pin(.leading, to: .leading, of: contentView, withInset: Values.mediumSpacing)
 | |
|             mainStackView.pin(.top, to: .top, of: contentView, withInset: Values.smallSpacing)
 | |
|             contentView.pin(.trailing, to: .trailing, of: mainStackView, withInset: Values.mediumSpacing)
 | |
|             contentView.pin(.bottom, to: .bottom, of: mainStackView, withInset: Values.smallSpacing)
 | |
|             mainStackView.set(.width, to: UIScreen.main.bounds.width - 2 * Values.mediumSpacing)
 | |
|             // Moderator icon image view
 | |
|             moderatorIconImageView.set(.width, to: 20)
 | |
|             moderatorIconImageView.set(.height, to: 20)
 | |
|             contentView.addSubview(moderatorIconImageView)
 | |
|             moderatorIconImageView.pin(.trailing, to: .trailing, of: profilePictureView, withInset: 1)
 | |
|             moderatorIconImageView.pin(.bottom, to: .bottom, of: profilePictureView, withInset: 4.5)
 | |
|             // Separator
 | |
|             addSubview(separator)
 | |
|             separator.pin(.leading, to: .leading, of: self)
 | |
|             separator.pin(.trailing, to: .trailing, of: self)
 | |
|             separator.pin(.bottom, to: .bottom, of: self)
 | |
|         }
 | |
| 
 | |
|         // MARK: Updating
 | |
|         private func update() {
 | |
|             displayNameLabel.text = mentionCandidate.displayName
 | |
|             profilePictureView.publicKey = mentionCandidate.publicKey
 | |
|             profilePictureView.update()
 | |
|             if let server = openGroupServer, let room = openGroupRoom {
 | |
|                 let isUserModerator = OpenGroupAPIV2.isUserModerator(mentionCandidate.publicKey, for: room, on: server)
 | |
|                 moderatorIconImageView.isHidden = !isUserModerator
 | |
|             } else if let server = openGroupServer, let channel = openGroupChannel {
 | |
|                 let isUserModerator = OpenGroupAPI.isUserModerator(mentionCandidate.publicKey, for: channel, on: server)
 | |
|                 moderatorIconImageView.isHidden = !isUserModerator
 | |
|             } else {
 | |
|                 moderatorIconImageView.isHidden = true
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| // MARK: - Delegate
 | |
| 
 | |
| protocol MentionSelectionViewDelegate : class {
 | |
| 
 | |
|     func handleMentionSelected(_ mention: Mention, from view: MentionSelectionView)
 | |
| }
 |