1
1
import InlineKit
2
2
import UIKit
3
+
3
4
class MessageReactionView : UIView {
4
5
// MARK: - Properties
5
-
6
+
6
7
private let emoji : String
7
8
private let count : Int
8
- private let isSelected : Bool
9
+ private let byCurrentUser : Bool
9
10
private let outgoing : Bool
10
-
11
+
11
12
var onTap : ( ( String ) -> Void ) ?
12
-
13
+
13
14
// MARK: - UI Components
14
-
15
+
15
16
private lazy var containerView : UIView = {
16
17
let view = UIView ( )
17
- view. layer. cornerRadius = 12
18
+ UIView . performWithoutAnimation {
19
+ view. layer. cornerRadius = 14
20
+ }
18
21
view. translatesAutoresizingMaskIntoConstraints = false
19
22
return view
20
23
} ( )
21
-
24
+
22
25
private lazy var stackView : UIStackView = {
23
26
let stack = UIStackView ( )
24
27
stack. axis = . horizontal
@@ -27,89 +30,109 @@ class MessageReactionView: UIView {
27
30
stack. translatesAutoresizingMaskIntoConstraints = false
28
31
return stack
29
32
} ( )
30
-
33
+
31
34
private lazy var emojiLabel : UILabel = {
32
35
let label = UILabel ( )
33
- label. font = UIFont . systemFont ( ofSize: 16 )
36
+ label. font = UIFont . systemFont ( ofSize: 17 )
34
37
label. text = emoji
35
38
return label
36
39
} ( )
37
-
40
+
38
41
private lazy var countLabel : UILabel = {
39
42
let label = UILabel ( )
40
43
label. font = UIFont . systemFont ( ofSize: 12 , weight: . medium)
41
44
label. text = " \( count) "
42
45
return label
43
46
} ( )
44
-
47
+
45
48
// MARK: - Initialization
46
-
47
- init ( emoji: String , count: Int , isSelected : Bool , outgoing: Bool ) {
49
+
50
+ init ( emoji: String , count: Int , byCurrentUser : Bool , outgoing: Bool ) {
48
51
self . emoji = emoji
49
52
self . count = count
50
- self . isSelected = isSelected
53
+ self . byCurrentUser = byCurrentUser
51
54
self . outgoing = outgoing
52
-
55
+
53
56
super. init ( frame: . zero)
54
57
setupView ( )
55
58
}
56
-
59
+
57
60
@available ( * , unavailable)
58
61
required init ? ( coder: NSCoder ) {
59
62
fatalError ( " init(coder:) has not been implemented " )
60
63
}
61
-
64
+
62
65
// MARK: - Setup
63
-
66
+
64
67
private func setupView( ) {
65
68
// Configure container appearance
66
- containerView. backgroundColor = isSelected ?
67
- ( outgoing ? UIColor . white . withAlphaComponent ( 0.3 ) : ColorManager . shared . selectedColor . withAlphaComponent ( 0.3 ) ) :
68
- ( outgoing ? UIColor . white . withAlphaComponent ( 0.15 ) : UIColor . systemGray6 )
69
-
69
+ containerView. backgroundColor = byCurrentUser ?
70
+ ( outgoing ? UIColor . reactionBackgroundOutgoingSelf : UIColor . reactionBackgroundIncomingSelf ) :
71
+ ( outgoing ? UIColor . reactionBackgroundOutgoing : UIColor . reactionBackgroundIncoming )
72
+
70
73
// Configure text colors
71
- countLabel. textColor = outgoing ? . white. withAlphaComponent ( 0.9 ) : . darkGray
72
-
74
+ countLabel. textColor = outgoing ? . white : . label
75
+
73
76
// Add subviews
74
77
addSubview ( containerView)
75
78
containerView. addSubview ( stackView)
76
-
79
+
77
80
stackView. addArrangedSubview ( emojiLabel)
78
81
stackView. addArrangedSubview ( countLabel)
79
-
82
+
80
83
// Setup constraints
81
84
NSLayoutConstraint . activate ( [
82
85
containerView. topAnchor. constraint ( equalTo: topAnchor) ,
83
86
containerView. leadingAnchor. constraint ( equalTo: leadingAnchor) ,
84
87
containerView. trailingAnchor. constraint ( equalTo: trailingAnchor) ,
85
88
containerView. bottomAnchor. constraint ( equalTo: bottomAnchor) ,
86
-
89
+
87
90
stackView. topAnchor. constraint ( equalTo: containerView. topAnchor, constant: 4 ) ,
88
- stackView. leadingAnchor. constraint ( equalTo: containerView. leadingAnchor, constant: 8 ) ,
89
- stackView. trailingAnchor. constraint ( equalTo: containerView. trailingAnchor, constant: - 8 ) ,
90
- stackView. bottomAnchor. constraint ( equalTo: containerView. bottomAnchor, constant: - 4 )
91
+ stackView. leadingAnchor. constraint ( equalTo: containerView. leadingAnchor, constant: 6 ) ,
92
+ stackView. trailingAnchor. constraint ( equalTo: containerView. trailingAnchor, constant: - 6 ) ,
93
+ stackView. bottomAnchor. constraint ( equalTo: containerView. bottomAnchor, constant: - 4 ) ,
91
94
] )
92
-
95
+
93
96
// Add tap gesture
94
97
let tapGesture = UITapGestureRecognizer ( target: self , action: #selector( handleTap) )
95
98
containerView. addGestureRecognizer ( tapGesture)
96
99
containerView. isUserInteractionEnabled = true
97
100
}
98
-
101
+
99
102
// MARK: - Actions
100
-
103
+
101
104
@objc private func handleTap( ) {
102
105
onTap ? ( emoji)
103
106
}
104
-
107
+
105
108
// MARK: - Layout
106
-
109
+
107
110
override var intrinsicContentSize : CGSize {
108
111
let stackSize = stackView. systemLayoutSizeFitting ( UIView . layoutFittingCompressedSize)
109
- return CGSize ( width: stackSize. width + 16 , height: stackSize. height + 8 )
112
+ return CGSize ( width: stackSize. width + 5 , height: stackSize. height + 8 )
110
113
}
111
-
114
+
112
115
override func sizeThatFits( _ size: CGSize ) -> CGSize {
113
- return intrinsicContentSize
116
+ intrinsicContentSize
117
+ }
118
+ }
119
+
120
+ extension UIColor {
121
+ /// Background color for reactions on outgoing messages by others
122
+ static let reactionBackgroundOutgoing = UIColor ( . white) . withAlphaComponent ( 0.3 )
123
+
124
+ /// Background color for reactions on outgoing messages by the current user
125
+ static let reactionBackgroundOutgoingSelf = UIColor ( . white) . withAlphaComponent ( 0.4 )
126
+
127
+ /// Background color for reactions on incoming messages by the current user
128
+ static let reactionBackgroundIncomingSelf = UIColor { traitCollection in
129
+ traitCollection. userInterfaceStyle == . dark ?
130
+ UIColor ( hex: " #4F4E52 " ) ! : UIColor ( hex: " #DCDCDC " ) !
131
+ }
132
+
133
+ /// Background color for reactions on incoming messages by others
134
+ static let reactionBackgroundIncoming = UIColor { traitCollection in
135
+ traitCollection. userInterfaceStyle == . dark ?
136
+ UIColor ( hex: " #414044 " ) ! : UIColor ( hex: " #EBEBEB " ) !
114
137
}
115
138
}
0 commit comments