Skip to content

Commit 7880131

Browse files
committed
Improve stream headers
1 parent 84ea375 commit 7880131

10 files changed

+187
-90
lines changed
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import UIKit
2+
import WordPressUI
3+
4+
// A container view for stream headers.
5+
class ReaderBaseHeaderView: UIView {
6+
let contentView = UIView()
7+
8+
var isCompact: Bool = true {
9+
didSet {
10+
guard oldValue != isCompact else { return }
11+
setNeedsUpdateConstraints()
12+
}
13+
}
14+
15+
private var contentViewConstraints: [NSLayoutConstraint] = []
16+
17+
override init(frame: CGRect) {
18+
super.init(frame: frame)
19+
20+
addSubview(contentView)
21+
}
22+
23+
required init?(coder: NSCoder) {
24+
fatalError("init(coder:) has not been implemented")
25+
}
26+
27+
override func updateConstraints() {
28+
NSLayoutConstraint.deactivate(contentViewConstraints)
29+
contentViewConstraints = []
30+
31+
let insets = Self.makeInsets(isCompact: isCompact)
32+
contentViewConstraints += contentView.pinEdges(.horizontal, to: isCompact ? self : readableContentGuide, insets: insets)
33+
contentViewConstraints += contentView.pinEdges(.vertical, insets: insets)
34+
35+
super.updateConstraints()
36+
}
37+
38+
static func makeInsets(isCompact: Bool) -> UIEdgeInsets {
39+
UIEdgeInsets(
40+
top: 4, // To align with the large title on iPad
41+
left: isCompact ? 16 : ReaderStreamBaseCell.insets.left, // Align with the text in the feed
42+
bottom: 12, // Add spacing below
43+
right: 0
44+
)
45+
}
46+
}

WordPress/Classes/ViewRelated/Reader/ReaderDiscoverHeaderView.swift

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ protocol ReaderDiscoverHeaderViewDelegate: AnyObject {
44
func readerDiscoverHeaderView(_ view: ReaderDiscoverHeaderView, didChangeSelection selection: ReaderDiscoverChannel)
55
}
66

7-
final class ReaderDiscoverHeaderView: UIView, UITextViewDelegate {
8-
private let titleView = ReaderStreamTitleView(insets: nil)
7+
final class ReaderDiscoverHeaderView: ReaderBaseHeaderView, UITextViewDelegate {
8+
private let titleView = ReaderTitleView()
99
private let channelsStackView = UIStackView(spacing: 8, [])
1010
private var channelViews: [ReaderDiscoverChannelView] = []
1111

@@ -22,10 +22,11 @@ final class ReaderDiscoverHeaderView: UIView, UITextViewDelegate {
2222
scrollView.clipsToBounds = false
2323
channelsStackView.pinEdges()
2424
scrollView.heightAnchor.constraint(equalTo: channelsStackView.heightAnchor).isActive = true
25+
scrollView.contentInset = UIEdgeInsets(.leading, -10) // Align the "channels"
2526

2627
let stackView = UIStackView(axis: .vertical, spacing: 8, [titleView, scrollView])
27-
addSubview(stackView)
28-
stackView.pinEdges(insets: ReaderStreamTitleView.preferredInsets)
28+
contentView.addSubview(stackView)
29+
stackView.pinEdges()
2930

3031
titleView.titleLabel.text = SharedStrings.Reader.discover
3132
titleView.detailsTextView.attributedText = {
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import UIKit
2+
import WordPressUI
3+
4+
final class ReaderHeaderView: ReaderBaseHeaderView {
5+
let titleView = ReaderTitleView()
6+
7+
override init(frame: CGRect) {
8+
super.init(frame: frame)
9+
10+
contentView.addSubview(titleView)
11+
titleView.pinEdges()
12+
}
13+
14+
required init?(coder: NSCoder) {
15+
fatalError("init(coder:) has not been implemented")
16+
}
17+
}
18+
19+
extension ReaderHeaderView {
20+
static func makeForFollowing() -> ReaderHeaderView {
21+
let view = ReaderHeaderView()
22+
view.titleView.titleLabel.text = SharedStrings.Reader.recent
23+
view.titleView.detailsTextView.text = Strings.followingDetails
24+
return view
25+
}
26+
}
27+
28+
private enum Strings {
29+
static let followingDetails = NSLocalizedString("reader.following.header.details", value: "Stay current with the blogs you've subscribed to.", comment: "Screen header details")
30+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import UIKit
2+
import WordPressUI
3+
4+
/// A custom replacement for a navigation bar title view.
5+
final class ReaderNavigationCustomTitleView: UIView {
6+
let textLabel = UILabel()
7+
8+
override init(frame: CGRect) {
9+
super.init(frame: frame)
10+
11+
textLabel.font = WPStyleGuide.navigationBarStandardFont
12+
textLabel.alpha = 0
13+
14+
// The label has to be a subview of the title view because
15+
// navigation bar doesn't seem to allow you to change the alpha
16+
// of `navigationItem.titleView` itself.
17+
addSubview(textLabel)
18+
textLabel.pinEdges()
19+
}
20+
21+
required init?(coder: NSCoder) {
22+
fatalError("init(coder:) has not been implemented")
23+
}
24+
25+
func updateAlpha(in scrollView: UIScrollView) {
26+
let offsetY = scrollView.contentOffset.y
27+
if offsetY < 16 {
28+
textLabel.alpha = 0
29+
} else {
30+
let alpha = (offsetY - 16) / 24
31+
textLabel.alpha = max(0, min(1, alpha))
32+
}
33+
}
34+
}

WordPress/Classes/ViewRelated/Reader/ReaderPostCell.swift

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,7 @@ final class ReaderPostCell: ReaderStreamBaseCell {
5151

5252
override func updateConstraints() {
5353
NSLayoutConstraint.deactivate(contentViewConstraints)
54-
contentViewConstraints = [
55-
view.leadingAnchor.constraint(equalTo: isCompact ? contentView.leadingAnchor : contentView.readableContentGuide.leadingAnchor),
56-
view.trailingAnchor.constraint(equalTo: isCompact ? contentView.trailingAnchor : contentView.readableContentGuide.trailingAnchor)
57-
]
58-
NSLayoutConstraint.activate(contentViewConstraints)
59-
54+
contentViewConstraints = view.pinEdges(.horizontal, to: isCompact ? contentView : contentView.readableContentGuide)
6055
super.updateConstraints()
6156
}
6257
}

WordPress/Classes/ViewRelated/Reader/ReaderStreamTitleView.swift

Lines changed: 0 additions & 70 deletions
This file was deleted.

WordPress/Classes/ViewRelated/Reader/ReaderStreamViewController+Helper.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ extension ReaderStreamViewController {
1212

1313
func headerForStream(_ topic: ReaderAbstractTopic?, isLoggedIn: Bool, container: UITableViewController) -> UIView? {
1414
if let topic, ReaderHelpers.topicIsFollowing(topic) {
15-
return ReaderStreamTitleView.makeForFollowing()
15+
return ReaderHeaderView.makeForFollowing()
1616
}
1717
if let topic,
1818
let header = headerForStream(topic) {

WordPress/Classes/ViewRelated/Reader/ReaderStreamViewController.swift

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,13 @@ import AutomatticTracks
198198

199199
var isEmbeddedInDiscover = false
200200

201+
private var isCompact = true {
202+
didSet {
203+
guard oldValue != isCompact else { return }
204+
didChangeIsCompact(isCompact)
205+
}
206+
}
207+
201208
// MARK: - Init
202209

203210
/// Convenience method for instantiating an instance of ReaderStreamViewController
@@ -275,6 +282,8 @@ import AutomatticTracks
275282
override func viewDidLoad() {
276283
super.viewDidLoad()
277284

285+
isCompact = traitCollection.horizontalSizeClass == .compact
286+
278287
// Setup Site Blocking Controller
279288
self.siteBlockingController.delegate = self
280289

@@ -353,6 +362,17 @@ import AutomatticTracks
353362
}
354363
}
355364

365+
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
366+
super.traitCollectionDidChange(previousTraitCollection)
367+
368+
isCompact = traitCollection.horizontalSizeClass == .compact
369+
}
370+
371+
private func didChangeIsCompact(_ isCompact: Bool) {
372+
(tableView.tableHeaderView as? ReaderBaseHeaderView)?.isCompact = isCompact
373+
tableView.reloadData()
374+
}
375+
356376
// MARK: - Topic acquisition
357377

358378
/// Fetches a site topic for the value of the `siteID` property.
@@ -471,6 +491,7 @@ import AutomatticTracks
471491
headerView.isHidden = tableHeaderView.isHidden
472492
}
473493

494+
(headerView as? ReaderBaseHeaderView)?.isCompact = isCompact
474495
tableView.tableHeaderView = headerView
475496
streamHeader = headerView as? ReaderStreamHeader
476497

@@ -1398,8 +1419,6 @@ extension ReaderStreamViewController: WPTableViewHandlerDelegate {
13981419
return cell
13991420
}
14001421

1401-
let isCompact = traitCollection.horizontalSizeClass == .compact
1402-
14031422
if post.isCross() {
14041423
let cell = tableConfiguration.crossPostCell(tableView)
14051424
cell.isCompact = isCompact
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import UIKit
2+
import WordPressUI
3+
4+
/// A Reader stream header with a large title and a description.
5+
final class ReaderTitleView: UIView {
6+
let titleLabel = UILabel()
7+
let detailsTextView = UITextView.makeLabel()
8+
9+
init() {
10+
super.init(frame: .zero)
11+
12+
titleLabel.font = UIFont.preferredFont(forTextStyle: .largeTitle).withWeight(.bold)
13+
detailsTextView.font = UIFont.preferredFont(forTextStyle: .subheadline)
14+
detailsTextView.textColor = .secondaryLabel
15+
16+
let stackView = UIStackView(axis: .vertical, alignment: .leading, [titleLabel, detailsTextView])
17+
addSubview(stackView)
18+
stackView.pinEdges()
19+
}
20+
21+
required init?(coder: NSCoder) {
22+
fatalError("init(coder:) has not been implemented")
23+
}
24+
}

0 commit comments

Comments
 (0)