mirror of https://github.com/oxen-io/session-ios
wip: emoji reacts message cell ui
parent
a20afe1c97
commit
692df74af6
@ -0,0 +1,46 @@
|
|||||||
|
|
||||||
|
final class ReactionContainerView : UIView {
|
||||||
|
private lazy var containerView: UIStackView = {
|
||||||
|
let result = UIStackView()
|
||||||
|
result.axis = .vertical
|
||||||
|
result.spacing = Values.smallSpacing
|
||||||
|
return result
|
||||||
|
}()
|
||||||
|
|
||||||
|
private var showingAllReactions = false
|
||||||
|
|
||||||
|
// MARK: Lifecycle
|
||||||
|
init() {
|
||||||
|
super.init(frame: CGRect.zero)
|
||||||
|
setUpViewHierarchy()
|
||||||
|
}
|
||||||
|
|
||||||
|
override init(frame: CGRect) {
|
||||||
|
preconditionFailure("Use init(viewItem:textColor:) instead.")
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder: NSCoder) {
|
||||||
|
preconditionFailure("Use init(viewItem:textColor:) instead.")
|
||||||
|
}
|
||||||
|
|
||||||
|
private func setUpViewHierarchy() {
|
||||||
|
addSubview(containerView)
|
||||||
|
containerView.pin(to: self)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func update(_ reactions: [(String, Int)]) {
|
||||||
|
for subview in containerView.arrangedSubviews {
|
||||||
|
containerView.removeArrangedSubview(subview)
|
||||||
|
}
|
||||||
|
let stackView = UIStackView()
|
||||||
|
stackView.axis = .horizontal
|
||||||
|
stackView.spacing = Values.smallSpacing
|
||||||
|
for reaction in reactions {
|
||||||
|
let reactionView = ReactionView(emoji: reaction.0, number: reaction.1)
|
||||||
|
stackView.addArrangedSubview(reactionView)
|
||||||
|
}
|
||||||
|
containerView.addArrangedSubview(stackView)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,49 @@
|
|||||||
|
import UIKit
|
||||||
|
|
||||||
|
final class ReactionView : UIView {
|
||||||
|
private let emoji: String
|
||||||
|
private let number: Int
|
||||||
|
|
||||||
|
// MARK: Settings
|
||||||
|
private static let height: CGFloat = 22
|
||||||
|
|
||||||
|
// MARK: Lifecycle
|
||||||
|
init(emoji: String, number: Int) {
|
||||||
|
self.emoji = emoji
|
||||||
|
self.number = number
|
||||||
|
super.init(frame: CGRect.zero)
|
||||||
|
setUpViewHierarchy()
|
||||||
|
}
|
||||||
|
|
||||||
|
override init(frame: CGRect) {
|
||||||
|
preconditionFailure("Use init(viewItem:textColor:) instead.")
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder: NSCoder) {
|
||||||
|
preconditionFailure("Use init(viewItem:textColor:) instead.")
|
||||||
|
}
|
||||||
|
|
||||||
|
private func setUpViewHierarchy() {
|
||||||
|
let emojiLabel = UILabel()
|
||||||
|
emojiLabel.text = emoji
|
||||||
|
emojiLabel.font = .systemFont(ofSize: Values.verySmallFontSize)
|
||||||
|
|
||||||
|
let numberLabel = UILabel()
|
||||||
|
numberLabel.text = self.number < 1000 ? "\(number)" : String(format: "%.2f", Float(number) / 1000) + "k"
|
||||||
|
numberLabel.font = .systemFont(ofSize: Values.verySmallFontSize)
|
||||||
|
numberLabel.textColor = Colors.text
|
||||||
|
|
||||||
|
let stackView = UIStackView(arrangedSubviews: [ emojiLabel, numberLabel ])
|
||||||
|
stackView.axis = .horizontal
|
||||||
|
stackView.spacing = Values.verySmallSpacing
|
||||||
|
stackView.alignment = .center
|
||||||
|
stackView.layoutMargins = UIEdgeInsets(top: 0, left: Values.smallSpacing, bottom: 0, right: Values.smallSpacing)
|
||||||
|
stackView.isLayoutMarginsRelativeArrangement = true
|
||||||
|
addSubview(stackView)
|
||||||
|
stackView.pin(to: self)
|
||||||
|
|
||||||
|
set(.height, to: ReactionView.height)
|
||||||
|
backgroundColor = Colors.receivedMessageBackground
|
||||||
|
layer.cornerRadius = ReactionView.height / 2
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
|
||||||
|
extension ReactMessage {
|
||||||
|
|
||||||
|
/// To be used for outgoing messages only.
|
||||||
|
public static func from(_ reaction: VisibleMessage.Reaction?) -> ReactMessage? {
|
||||||
|
guard let reaction = reaction else { return nil }
|
||||||
|
return ReactMessage(
|
||||||
|
timestamp: reaction.timestamp!,
|
||||||
|
authorId: reaction.publicKey!,
|
||||||
|
emoji: reaction.emoji)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension VisibleMessage.Reaction {
|
||||||
|
|
||||||
|
public static func from(_ reaction: ReactMessage?) -> VisibleMessage.Reaction? {
|
||||||
|
guard let reaction = reaction else { return nil }
|
||||||
|
let result = VisibleMessage.Reaction()
|
||||||
|
result.timestamp = reaction.timestamp
|
||||||
|
result.publicKey = reaction.authorId
|
||||||
|
result.emoji = reaction.emoji
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
|
||||||
|
@objc(SNReactMessage)
|
||||||
|
public final class ReactMessage : MTLModel {
|
||||||
|
|
||||||
|
public var timestamp: UInt64?
|
||||||
|
public var authorId: String?
|
||||||
|
|
||||||
|
@objc
|
||||||
|
public var emoji: String?
|
||||||
|
|
||||||
|
@objc
|
||||||
|
public var sender: String?
|
||||||
|
|
||||||
|
@objc
|
||||||
|
public var messageId: String?
|
||||||
|
|
||||||
|
@objc
|
||||||
|
public init(timestamp: UInt64, authorId: String, emoji: String?) {
|
||||||
|
self.timestamp = timestamp
|
||||||
|
self.authorId = authorId
|
||||||
|
self.emoji = emoji
|
||||||
|
super.init()
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc
|
||||||
|
public override init() {
|
||||||
|
super.init()
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc
|
||||||
|
public required init!(coder: NSCoder) {
|
||||||
|
super.init(coder: coder)
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc
|
||||||
|
public required init(dictionary dictionaryValue: [String: Any]!) throws {
|
||||||
|
try super.init(dictionary: dictionaryValue)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue