157 lines
4.7 KiB
Swift
157 lines
4.7 KiB
Swift
//
|
|
// Copyright 2019 Signal Messenger, LLC
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
//
|
|
|
|
import SignalServiceKit
|
|
public import SignalUI
|
|
|
|
// MARK: -
|
|
|
|
public struct EmojiItem {
|
|
// If a specific emoji is not specified, this item represents "all" emoji
|
|
let emoji: String?
|
|
let count: Int
|
|
|
|
let didSelect: () -> Void
|
|
}
|
|
|
|
public class EmojiCountsCollectionView: UICollectionView {
|
|
|
|
let itemHeight: CGFloat = 36
|
|
|
|
public var items = [EmojiItem]() {
|
|
didSet {
|
|
AssertIsOnMainThread()
|
|
reloadData()
|
|
}
|
|
}
|
|
|
|
public init() {
|
|
let layout = UICollectionViewFlowLayout()
|
|
layout.minimumInteritemSpacing = 0
|
|
layout.minimumLineSpacing = 0
|
|
layout.estimatedItemSize = CGSize(square: itemHeight)
|
|
layout.scrollDirection = .horizontal
|
|
super.init(frame: .zero, collectionViewLayout: layout)
|
|
|
|
delegate = self
|
|
dataSource = self
|
|
showsHorizontalScrollIndicator = false
|
|
backgroundColor = .clear
|
|
|
|
register(EmojiCountCell.self, forCellWithReuseIdentifier: EmojiCountCell.reuseIdentifier)
|
|
|
|
contentInset = UIEdgeInsets(top: 8, leading: 8, bottom: 8, trailing: 8)
|
|
autoSetDimension(.height, toSize: itemHeight + contentInset.top + contentInset.bottom)
|
|
}
|
|
|
|
func setSelectedIndex(_ index: Int) {
|
|
selectItem(at: IndexPath(item: index, section: 0), animated: true, scrollPosition: .centeredHorizontally)
|
|
}
|
|
|
|
required public init(coder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
}
|
|
|
|
// MARK: - UICollectionViewDelegateFlowLayout
|
|
|
|
extension EmojiCountsCollectionView: UICollectionViewDelegateFlowLayout {
|
|
public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
|
Logger.debug("")
|
|
|
|
guard let item = items[safe: indexPath.row] else {
|
|
owsFailDebug("Invalid index path: \(indexPath)")
|
|
return
|
|
}
|
|
|
|
item.didSelect()
|
|
}
|
|
}
|
|
|
|
// MARK: - UICollectionViewDataSource
|
|
|
|
extension EmojiCountsCollectionView: UICollectionViewDataSource {
|
|
|
|
public func numberOfSections(in collectionView: UICollectionView) -> Int {
|
|
return 1
|
|
}
|
|
|
|
public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection sectionIdx: Int) -> Int {
|
|
return items.count
|
|
}
|
|
|
|
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
|
|
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: EmojiCountCell.reuseIdentifier, for: indexPath)
|
|
|
|
guard let item = items[safe: indexPath.row] else {
|
|
owsFailDebug("Invalid index path: \(indexPath)")
|
|
return cell
|
|
}
|
|
|
|
guard let emojiCell = cell as? EmojiCountCell else {
|
|
owsFailDebug("unexpected cell type")
|
|
return cell
|
|
}
|
|
|
|
emojiCell.configure(with: item)
|
|
|
|
return emojiCell
|
|
}
|
|
}
|
|
|
|
class EmojiCountCell: UICollectionViewCell {
|
|
let emoji = UILabel()
|
|
let count = UILabel()
|
|
|
|
static let reuseIdentifier = "EmojiCountCell"
|
|
|
|
override init(frame: CGRect) {
|
|
super.init(frame: .zero)
|
|
|
|
let selectedBackground = UIView()
|
|
selectedBackground.backgroundColor = (Theme.isDarkThemeEnabled
|
|
? UIColor.ows_gray60
|
|
: UIColor.ows_gray05)
|
|
selectedBackgroundView = selectedBackground
|
|
|
|
let stackView = UIStackView(arrangedSubviews: [emoji, count])
|
|
stackView.isLayoutMarginsRelativeArrangement = true
|
|
stackView.layoutMargins = UIEdgeInsets(top: 8, leading: 8, bottom: 8, trailing: 8)
|
|
stackView.spacing = 4
|
|
contentView.addSubview(stackView)
|
|
stackView.autoPinEdgesToSuperviewEdges()
|
|
stackView.autoSetDimension(.height, toSize: 32)
|
|
|
|
emoji.font = .systemFont(ofSize: 22)
|
|
|
|
count.font = UIFont.dynamicTypeSubheadlineClamped.monospaced().semibold()
|
|
count.textColor = Theme.primaryTextColor
|
|
}
|
|
|
|
required init?(coder aDecoder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
func configure(with item: EmojiItem) {
|
|
emoji.text = item.emoji
|
|
emoji.isHidden = item.emoji == nil
|
|
|
|
if item.emoji != nil {
|
|
count.text = item.count.abbreviatedString
|
|
} else {
|
|
count.text = String(
|
|
format: OWSLocalizedString("REACTION_DETAIL_ALL_FORMAT",
|
|
comment: "The header used to indicate All reactions to a given message. Embeds {{number of reactions}}"),
|
|
item.count.abbreviatedString
|
|
)
|
|
}
|
|
}
|
|
|
|
override func layoutSubviews() {
|
|
super.layoutSubviews()
|
|
|
|
selectedBackgroundView?.layer.cornerRadius = height / 2
|
|
}
|
|
}
|