session-ios/Session/Conversations/Input View/MentionSelectionView.swift
Morgan Pretty eeccfb47d5 Fixed all of the build errors from merge, migrated Call logic, started idBlinding migration and bug fixes
Fixed some broken file paths
Fixed a couple of bugs with closed groups
Fixed a few migration issues
Fixed a bug with the ProfilePictureView in open groups (was including the open parenthesis in the initials)
Migrated the Id Blinding changes to work with GRDB
Migrated the call logic to work with GRDB
Updated the code to work the with hard fork changes
2022-06-09 18:37:44 +10:00

214 lines
7.6 KiB
Swift

// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import UIKit
import SessionUIKit
import SessionUtilitiesKit
import SignalUtilitiesKit
final class MentionSelectionView: UIView, UITableViewDataSource, UITableViewDelegate {
var candidates: [ConversationViewModel.MentionInfo] = [] {
didSet {
tableView.isScrollEnabled = (candidates.count > 4)
tableView.reloadData()
}
}
weak var delegate: MentionSelectionViewDelegate?
var contentOffset: CGPoint {
get { tableView.contentOffset }
set { tableView.contentOffset = newValue }
}
// MARK: - Components
private lazy var tableView: UITableView = {
let result: UITableView = UITableView()
result.dataSource = self
result.delegate = self
result.separatorStyle = .none
result.backgroundColor = .clear
result.showsVerticalScrollIndicator = false
result.register(view: Cell.self)
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 = 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 = 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: Cell = tableView.dequeue(type: Cell.self, for: indexPath)
cell.update(
with: candidates[indexPath.row].profile,
threadVariant: candidates[indexPath.row].threadVariant,
isUserModeratorOrAdmin: OpenGroupManager.isUserModeratorOrAdmin(
candidates[indexPath.row].profile.id,
for: candidates[indexPath.row].openGroupRoomToken,
on: candidates[indexPath.row].openGroupServer
),
isLast: (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 {
// MARK: - UI
private lazy var profilePictureView: ProfilePictureView = ProfilePictureView()
private lazy var moderatorIconImageView: UIImageView = UIImageView(image: #imageLiteral(resourceName: "Crown"))
private lazy var displayNameLabel: UILabel = {
let result: UILabel = UILabel()
result.textColor = Colors.text
result.font = .systemFont(ofSize: Values.smallFontSize)
result.lineBreakMode = .byTruncatingTail
return result
}()
lazy var separator: UIView = {
let result: UIView = 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
fileprivate func update(
with profile: Profile,
threadVariant: SessionThread.Variant,
isUserModeratorOrAdmin: Bool,
isLast: Bool
) {
displayNameLabel.text = profile.displayName(for: threadVariant)
profilePictureView.update(
publicKey: profile.id,
profile: profile,
threadVariant: threadVariant
)
moderatorIconImageView.isHidden = !isUserModeratorOrAdmin
separator.isHidden = isLast
}
}
}
// MARK: - Delegate
protocol MentionSelectionViewDelegate: AnyObject {
func handleMentionSelected(_ mention: ConversationViewModel.MentionInfo, from view: MentionSelectionView)
}