11import AutomatticTracks
22import UIKit
3- import Gridicons
43import WordPressShared
54import WordPressUI
65
7- class PostCompactCell : UITableViewCell {
8- @IBOutlet weak var titleLabel : UILabel !
9- @IBOutlet weak var timestampLabel : UILabel !
10- @IBOutlet weak var badgesLabel : UILabel !
11- @IBOutlet weak var menuButton : UIButton !
12- @IBOutlet weak var featuredImageView : CachedAnimatedImageView !
13- @IBOutlet weak var headerStackView : UIStackView !
14- @IBOutlet weak var innerView : UIView !
15- @IBOutlet weak var contentStackView : UIStackView !
16- @IBOutlet weak var ghostView : UIView !
17- @IBOutlet weak var separator : UIView !
18-
19- @IBOutlet weak var trailingContentConstraint : NSLayoutConstraint !
20-
21- private var iPadReadableLeadingAnchor : NSLayoutConstraint ?
22- private var iPadReadableTrailingAnchor : NSLayoutConstraint ?
23-
24- lazy var imageLoader : ImageLoader = {
25- return ImageLoader ( imageView: featuredImageView, gifStrategy: . mediumGIFs)
26- } ( )
6+ final class PostCompactCell : UITableViewCell , Reusable {
7+ private let titleLabel = UILabel ( )
8+ private let detailsLabel = UILabel ( )
9+ private let featuredImageView = AsyncImageView ( )
2710
2811 private var post : Post ? {
2912 didSet {
30- guard let post, post != oldValue else {
31- return
32- }
33-
13+ guard let post, post != oldValue else { return }
3414 viewModel = PostCardStatusViewModel ( post: post)
3515 }
3616 }
3717
3818 private var viewModel : PostCardStatusViewModel ?
3919
40- func configure ( with post : Post ) {
41- self . post = post
20+ override init ( style : UITableViewCell . CellStyle , reuseIdentifier : String ? ) {
21+ super . init ( style : style , reuseIdentifier : reuseIdentifier )
4222
43- resetGhostStyles ( )
44- configureTitle ( )
45- configureDate ( )
46- configureStatus ( )
47- configureFeaturedImage ( )
48- configureMenuInteraction ( )
23+ setupStyles ( )
24+ setupLayout ( )
4925 }
5026
51- @ IBAction func more ( _ sender : Any ) {
52- // Do nothing. The compact cell is only shown in the dashboard, where the more button is hidden.
27+ required init ? ( coder : NSCoder ) {
28+ fatalError ( " init(coder:) has not been implemented " )
5329 }
5430
55- override func awakeFromNib( ) {
56- super. awakeFromNib ( )
57- applyStyles ( )
58- setupReadableGuideForiPad ( )
59- setupSeparator ( )
60- setupAccessibility ( )
61- }
31+ func configure( with post: Post ) {
32+ self . post = post
6233
63- private func resetGhostStyles ( ) {
64- toggleGhost ( visible : false )
65- menuButton . layer . opacity = Constants . opacity
34+ titleLabel . text = post . titleForDisplay ( )
35+ detailsLabel . text = post . contentPreviewForDisplay ( )
36+ configureFeaturedImage ( )
6637 }
6738
68- private func applyStyles ( ) {
39+ private func setupStyles ( ) {
6940 WPStyleGuide . configureTableViewCell ( self )
7041 WPStyleGuide . applyPostCardStyle ( self )
71- WPStyleGuide . configureLabel ( timestampLabel, textStyle: . subheadline)
72- WPStyleGuide . configureLabel ( badgesLabel, textStyle: . subheadline)
7342
74- titleLabel. font = AppStyleGuide . prominentFont ( textStyle : . headline, weight : . bold )
43+ titleLabel. font = . preferredFont ( forTextStyle : . headline)
7544 titleLabel. adjustsFontForContentSizeCategory = true
76-
7745 titleLabel. textColor = . label
78- timestampLabel. textColor = . secondaryLabel
79- menuButton. tintColor = . secondaryLabel
46+ titleLabel. numberOfLines = 1
8047
81- menuButton. setImage ( . gridicon( . ellipsis) , for: . normal)
48+ detailsLabel. font = . preferredFont( forTextStyle: . subheadline)
49+ detailsLabel. textColor = . secondaryLabel
50+ detailsLabel. numberOfLines = 1
8251
8352 featuredImageView. layer. cornerRadius = Constants . imageRadius
53+ featuredImageView. layer. masksToBounds = true
8454
85- innerView. backgroundColor = . secondarySystemGroupedBackground
86- backgroundColor = . secondarySystemGroupedBackground
87- contentView. backgroundColor = . secondarySystemGroupedBackground
88- }
89-
90- private func setupSeparator( ) {
91- WPStyleGuide . applyBorderStyle ( separator)
55+ contentView. backgroundColor = . systemBackground
9256 }
9357
94- private func setupReadableGuideForiPad( ) {
95- guard WPDeviceIdentification . isiPad ( ) else { return }
96-
97- iPadReadableLeadingAnchor = innerView. leadingAnchor. constraint ( equalTo: readableContentGuide. leadingAnchor)
98- iPadReadableTrailingAnchor = innerView. trailingAnchor. constraint ( equalTo: readableContentGuide. trailingAnchor)
58+ private func setupLayout( ) {
59+ let stackView = UIStackView ( alignment: . top, spacing: 8 , [
60+ UIStackView ( axis: . vertical, alignment: . leading, spacing: 2 , [
61+ titleLabel, detailsLabel
62+ ] ) ,
63+ featuredImageView
64+ ] )
65+ contentView. addSubview ( stackView)
66+ stackView. pinEdges ( insets: UIEdgeInsets ( horizontal: 16 , vertical: 8 ) )
9967
100- iPadReadableLeadingAnchor? . isActive = true
101- iPadReadableTrailingAnchor? . isActive = true
68+ NSLayoutConstraint . activate ( [
69+ featuredImageView. widthAnchor. constraint ( equalToConstant: Constants . imageSize. width) ,
70+ featuredImageView. heightAnchor. constraint ( equalToConstant: Constants . imageSize. height) ,
71+ ] )
10272 }
10373
10474 private func configureFeaturedImage( ) {
75+ featuredImageView. prepareForReuse ( )
76+
10577 if let post, let url = post. featuredImageURL {
10678 featuredImageView. isHidden = false
10779
@@ -110,108 +82,15 @@ class PostCompactCell: UITableViewCell {
11082 WordPressAppDelegate . crashLogging? . logError ( error)
11183 } )
11284
113- imageLoader. loadImage ( with: url, from: host, preferredSize: CGSize ( width: featuredImageView. frame. width, height: featuredImageView. frame. height) )
85+ let targetSize = Constants . imageSize. scaled ( by: traitCollection. displayScale)
86+ featuredImageView. setImage ( with: url, host: host, size: targetSize)
11487 } else {
11588 featuredImageView. isHidden = true
11689 }
11790 }
11891
119- private func configureTitle( ) {
120- titleLabel. text = post? . titleForDisplay ( )
121- }
122-
123- private func configureDate( ) {
124- guard let post else {
125- return
126- }
127-
128- timestampLabel. text = post. latest ( ) . dateStringForDisplay ( )
129- timestampLabel. isHidden = false
130- }
131-
132- private func configureExcerpt( ) {
133- guard let post else {
134- return
135- }
136-
137- timestampLabel. text = post. contentPreviewForDisplay ( )
138- timestampLabel. isHidden = false
139- }
140-
141- private func configureStatus( ) {
142- guard let viewModel else {
143- return
144- }
145- badgesLabel. textColor = viewModel. statusColor
146- badgesLabel. text = viewModel. statusAndBadges ( separatedBy: Constants . separator)
147- if badgesLabel. text? . isEmpty ?? true {
148- badgesLabel. isHidden = true
149- } else {
150- badgesLabel. isHidden = false
151- }
152- }
153-
154- private func configureMenuInteraction( ) {
155- menuButton. isEnabled = true
156- menuButton. alpha = 1.0
157- }
158-
159- private func setupAccessibility( ) {
160- menuButton. accessibilityLabel =
161- NSLocalizedString ( " More " , comment: " Accessibility label for the More button in Post List (compact view). " )
162- }
163-
16492 private enum Constants {
165- static let separator = " · "
166- static let imageRadius : CGFloat = 2
167- static let opacity : Float = 1
168- static let margin : CGFloat = 16
169- }
170- }
171-
172- extension PostCompactCell : GhostableView {
173- func ghostAnimationWillStart( ) {
174- toggleGhost ( visible: true )
175- menuButton. layer. opacity = GhostConstants . opacity
176- }
177-
178- private func toggleGhost( visible: Bool ) {
179- isUserInteractionEnabled = !visible
180- menuButton. isGhostableDisabled = true
181- separator. isGhostableDisabled = true
182- ghostView. isHidden = !visible
183- ghostView. backgroundColor = . secondarySystemGroupedBackground
184- contentStackView. isHidden = visible
185- }
186-
187- private enum GhostConstants {
188- static let opacity : Float = 0.5
189- }
190- }
191-
192- extension PostCompactCell : NibReusable { }
193-
194- // MARK: - For display on the Posts Card (Dashboard)
195-
196- extension PostCompactCell {
197- /// Configure the cell to be displayed in the Posts Card
198- /// No "more" button and show a description, instead of a date
199- func configureForDashboard( with post: Post ) {
200- configure ( with: post)
201- separator. isHidden = true
202- menuButton. isHidden = true
203- trailingContentConstraint. constant = Constants . margin
204- headerStackView. spacing = Constants . margin
205-
206- disableiPadReadableMargin ( )
207-
208- if !post. isScheduled ( ) {
209- configureExcerpt ( )
210- }
211- }
212-
213- func disableiPadReadableMargin( ) {
214- iPadReadableLeadingAnchor? . isActive = false
215- iPadReadableTrailingAnchor? . isActive = false
93+ static let imageRadius : CGFloat = 4
94+ static let imageSize = CGSize ( width: 40 , height: 40 )
21695 }
21796}
0 commit comments