Skip to content

Commit

Permalink
Add scroll-to-top button to Reader streams (#23957)
Browse files Browse the repository at this point in the history
  • Loading branch information
kean authored Jan 7, 2025
2 parents f0e5730 + 2069c49 commit 46d183f
Show file tree
Hide file tree
Showing 9 changed files with 53 additions and 81 deletions.
2 changes: 2 additions & 0 deletions RELEASE-NOTES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
* [*] Show selected filter in the Discover navigation bar [#23956]
* [*] Enable fast deceleration for filters on the Discover tab [#23954]
* [*] Disable universal links support for QR code login. You can only scan the codes using the app now. [#23953]
* [*] Add scroll-to-top button to Reader streams [#23957]


25.6
-----
Expand Down
6 changes: 3 additions & 3 deletions WordPress/Classes/Utility/Analytics/WPAnalyticsEvent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import Foundation

case createSheetShown
case createSheetActionTapped
case createAnnouncementModalShown

// Media Editor
case mediaEditorShown
Expand Down Expand Up @@ -117,6 +116,7 @@ import Foundation
case readerCommentTextCopied
case readerPostContextMenuButtonTapped
case readerAddSiteToFavoritesTapped
case readerButtonScrollToTopTapped

// Stats - Empty Stats nudges
case statsPublicizeNudgeShown
Expand Down Expand Up @@ -625,8 +625,6 @@ import Foundation
return "create_sheet_shown"
case .createSheetActionTapped:
return "create_sheet_action_tapped"
case .createAnnouncementModalShown:
return "create_announcement_modal_shown"
// Media Editor
case .mediaEditorShown:
return "media_editor_shown"
Expand Down Expand Up @@ -819,6 +817,8 @@ import Foundation
return "reader_post_context_menu_button_tapped"
case .readerAddSiteToFavoritesTapped:
return "reader_add_site_to_favorites_tapped"
case .readerButtonScrollToTopTapped:
return "reader_button_scroll_to_top_tapped"

// Stats - Empty Stats nudges
case .statsPublicizeNudgeShown:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ private final class ReaderPostCellView: UIView {
avatarView.widthAnchor.constraint(equalToConstant: ReaderPostCell.avatarSize),
avatarView.heightAnchor.constraint(equalToConstant: ReaderPostCell.avatarSize),
avatarView.centerYAnchor.constraint(equalTo: timeLabel.centerYAnchor),
avatarView.trailingAnchor.constraint(equalTo: headerView.leadingAnchor, constant: -8),
avatarView.trailingAnchor.constraint(equalTo: headerView.leadingAnchor, constant: -9),

headerView.topAnchor.constraint(equalTo: topAnchor, constant: 6),
headerView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: insets.left),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import UIKit

class ReaderStreamBaseCell: UITableViewCell {
static let insets = UIEdgeInsets(top: 0, left: 44, bottom: 0, right: 16)
static let insets = UIEdgeInsets(top: 0, left: 46, bottom: 0, right: 16)

var isCompact: Bool = true {
didSet {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,16 @@ import AutomatticTracks
return refreshControl
}()

private lazy var buttonScrollToTop = ReaderButtonScrollToTop.make { [weak self] in
self?.tableView.scrollToTop(animated: true)
}

let titleView = ReaderNavigationCustomTitleView()

private let loadMoreThreashold = 5
private let refreshInterval = 300
private var cleanupAndRefreshAfterScrolling = false
private let recentlyBlockedSitePostObjectIDs = NSMutableArray()
private let heightForFooterView = CGFloat(44)
private let estimatedHeightsCache = NSCache<AnyObject, AnyObject>()
private var isFeed = false
private var syncIsFillingGap = false
Expand Down Expand Up @@ -303,6 +306,7 @@ import AutomatticTracks
setupTableView()
setupFooterView()
setupContentHandler()
setupButtonScrollToTop()

observeNetworkStatus()

Expand Down Expand Up @@ -493,9 +497,14 @@ import AutomatticTracks
content.initializeContent(tableView: tableView, delegate: self)
}

private func setupButtonScrollToTop() {
view.addSubview(buttonScrollToTop)
buttonScrollToTop.pinEdges([.leading, .bottom], to: view.safeAreaLayoutGuide, insets: isCompact ? UIEdgeInsets(horizontal: 8, vertical: 16) : UIEdgeInsets(.all, 20))
}

private func setupFooterView() {
var frame = footerView.frame
frame.size.height = heightForFooterView
frame.size.height = 44
footerView.frame = frame
tableView.tableFooterView = footerView
footerView.isHidden = true
Expand Down Expand Up @@ -1661,6 +1670,7 @@ extension ReaderStreamViewController: UITableViewDelegate, JPScrollViewDelegate
layoutEmptyStateView()
processJetpackBannerVisibility(scrollView)
titleView.updateAlpha(in: scrollView)
buttonScrollToTop.setButtonHidden(scrollView.contentOffset.y < view.bounds.height / 3, animated: true)
}
}

Expand Down
34 changes: 34 additions & 0 deletions WordPress/Classes/ViewRelated/Reader/ReaderButtonScrollToTop.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import UIKit

final class ReaderButtonScrollToTop: UIButton {
private var isButtonHidden = false

static func make(closure: @escaping () -> Void) -> ReaderButtonScrollToTop {
var configuration = UIButton.Configuration.bordered()
configuration.image = UIImage(systemName: "arrow.up")?
.withConfiguration(UIImage.SymbolConfiguration(pointSize: 12, weight: .regular))
configuration.cornerStyle = .capsule
configuration.baseBackgroundColor = .secondarySystemBackground
configuration.baseForegroundColor = .label
configuration.contentInsets = .init(top: 10, leading: 10, bottom: 10, trailing: 10)

return ReaderButtonScrollToTop(configuration: configuration, primaryAction: .init { _ in
closure()
WPAnalytics.track(.readerButtonScrollToTopTapped)
})
}

func setButtonHidden(_ isHidden: Bool, animated: Bool) {
guard isButtonHidden != isHidden else { return }
isButtonHidden = isHidden

UIView.animate(withDuration: animated ? 0.33 : 0.0) {
self.alpha = isHidden ? 0 : 1
self.isUserInteractionEnabled = !isHidden
}
}

override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
bounds.insetBy(dx: -8, dy: -10).contains(point)
}
}

This file was deleted.

This file was deleted.

Binary file not shown.

0 comments on commit 46d183f

Please sign in to comment.