chore: add publishing state in navigationBar
This commit is contained in:
parent
50a30cd18e
commit
b60fe36b25
|
@ -49,6 +49,7 @@
|
|||
2D42FF8F25C8228A004A627A /* UIButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D42FF8E25C8228A004A627A /* UIButton.swift */; };
|
||||
2D45E5BF25C9549700A6D639 /* PublicTimelineViewModel+State.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D45E5BE25C9549700A6D639 /* PublicTimelineViewModel+State.swift */; };
|
||||
2D46975E25C2A54100CF4AA9 /* NSLayoutConstraint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D46975D25C2A54100CF4AA9 /* NSLayoutConstraint.swift */; };
|
||||
2D571B2F26004EC000540450 /* NavigationBarProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D571B2E26004EC000540450 /* NavigationBarProgressView.swift */; };
|
||||
2D59819B25E4A581000FB903 /* MastodonConfirmEmailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D59819A25E4A581000FB903 /* MastodonConfirmEmailViewController.swift */; };
|
||||
2D5981A125E4A593000FB903 /* MastodonConfirmEmailViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D5981A025E4A593000FB903 /* MastodonConfirmEmailViewModel.swift */; };
|
||||
2D5981BA25E4D7F8000FB903 /* ThirdPartyMailer in Frameworks */ = {isa = PBXBuildFile; productRef = 2D5981B925E4D7F8000FB903 /* ThirdPartyMailer */; };
|
||||
|
@ -300,6 +301,7 @@
|
|||
2D42FF8E25C8228A004A627A /* UIButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIButton.swift; sourceTree = "<group>"; };
|
||||
2D45E5BE25C9549700A6D639 /* PublicTimelineViewModel+State.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "PublicTimelineViewModel+State.swift"; sourceTree = "<group>"; };
|
||||
2D46975D25C2A54100CF4AA9 /* NSLayoutConstraint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSLayoutConstraint.swift; sourceTree = "<group>"; };
|
||||
2D571B2E26004EC000540450 /* NavigationBarProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationBarProgressView.swift; sourceTree = "<group>"; };
|
||||
2D59819A25E4A581000FB903 /* MastodonConfirmEmailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonConfirmEmailViewController.swift; sourceTree = "<group>"; };
|
||||
2D5981A025E4A593000FB903 /* MastodonConfirmEmailViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonConfirmEmailViewModel.swift; sourceTree = "<group>"; };
|
||||
2D5A3D0225CF8742002347D6 /* ControlContainableScrollViews.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ControlContainableScrollViews.swift; sourceTree = "<group>"; };
|
||||
|
@ -593,6 +595,7 @@
|
|||
children = (
|
||||
2D152A8B25C295CC009AA50C /* StatusView.swift */,
|
||||
2D694A7325F9EB4E0038ADDC /* ContentWarningOverlayView.swift */,
|
||||
2D571B2E26004EC000540450 /* NavigationBarProgressView.swift */,
|
||||
);
|
||||
path = Content;
|
||||
sourceTree = "<group>";
|
||||
|
@ -1605,6 +1608,7 @@
|
|||
2D5A3D3825CF8D9F002347D6 /* ScrollViewContainer.swift in Sources */,
|
||||
DB1E347825F519300079D7DF /* PickServerItem.swift in Sources */,
|
||||
DB1FD45A25F27898004CFCFC /* CategoryPickerItem.swift in Sources */,
|
||||
2D571B2F26004EC000540450 /* NavigationBarProgressView.swift in Sources */,
|
||||
0FAA101225E105390017CCDE /* PrimaryActionButton.swift in Sources */,
|
||||
DB8AF53025C13561002E6C99 /* AppContext.swift in Sources */,
|
||||
DB92CF7225E7BB98002C1017 /* PollOptionTableViewCell.swift in Sources */,
|
||||
|
|
|
@ -9,20 +9,25 @@ import Combine
|
|||
import Foundation
|
||||
import UIKit
|
||||
|
||||
|
||||
final class HomeTimelineNavigationBarState {
|
||||
static let errorCountMax: Int = 3
|
||||
var disposeBag = Set<AnyCancellable>()
|
||||
var errorCountDownDispose: AnyCancellable?
|
||||
var timerDispose: AnyCancellable?
|
||||
var networkErrorCountSubject = PassthroughSubject<Bool, Never>()
|
||||
|
||||
var titleViewBeforePublishing: UIView? // used for restore titleView after published
|
||||
|
||||
var newTopContent = CurrentValueSubject<Bool, Never>(false)
|
||||
var newBottomContent = CurrentValueSubject<Bool, Never>(false)
|
||||
var hasContentBeforeFetching: Bool = true
|
||||
|
||||
weak var viewController: HomeTimelineViewController?
|
||||
|
||||
let timestampUpdatePublisher = Timer.publish(every: NavigationBarProgressView.progressAnimationDuration, on: .main, in: .common)
|
||||
.autoconnect()
|
||||
.share()
|
||||
.eraseToAnyPublisher()
|
||||
|
||||
init() {
|
||||
reCountdown()
|
||||
subscribeNewContent()
|
||||
|
@ -40,15 +45,42 @@ extension HomeTimelineNavigationBarState {
|
|||
}
|
||||
|
||||
func showPublishingNewPostInNavigationBar() {
|
||||
titleViewBeforePublishing = viewController?.navigationItem.titleView
|
||||
let progressView = HomeTimelineNavigationBarView.progressView
|
||||
if let navigationBar = viewController?.navigationBar(), progressView.superview == nil {
|
||||
navigationBar.addSubview(progressView)
|
||||
NSLayoutConstraint.activate([
|
||||
progressView.bottomAnchor.constraint(equalTo: navigationBar.bottomAnchor),
|
||||
progressView.leadingAnchor.constraint(equalTo: navigationBar.leadingAnchor),
|
||||
progressView.trailingAnchor.constraint(equalTo: navigationBar.trailingAnchor),
|
||||
progressView.heightAnchor.constraint(equalToConstant: 3)
|
||||
])
|
||||
}
|
||||
progressView.layoutIfNeeded()
|
||||
progressView.progress = 0
|
||||
viewController?.navigationItem.titleView = HomeTimelineNavigationBarView.publishingLabel
|
||||
|
||||
var times: Int = 0
|
||||
timerDispose = timestampUpdatePublisher
|
||||
.map { _ in
|
||||
times += 1
|
||||
return Double(times)
|
||||
}
|
||||
.scan(0) { value,count in
|
||||
value + 1 / pow(Double(2), count)
|
||||
}
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink { value in
|
||||
print(value)
|
||||
progressView.progress = CGFloat(value)
|
||||
}
|
||||
}
|
||||
|
||||
func showPublishedInNavigationBar() {
|
||||
timerDispose = nil
|
||||
HomeTimelineNavigationBarView.progressView.removeFromSuperview()
|
||||
viewController?.navigationItem.titleView = HomeTimelineNavigationBarView.publishedView
|
||||
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 3) {
|
||||
if let titleView = self.titleViewBeforePublishing, let navigationItem = self.viewController?.navigationItem {
|
||||
navigationItem.titleView = titleView
|
||||
}
|
||||
self.showMastodonLogoInNavigationBar()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,7 +92,10 @@ extension HomeTimelineNavigationBarState {
|
|||
extension HomeTimelineNavigationBarState {
|
||||
func handleScrollViewDidScroll(_ scrollView: UIScrollView) {
|
||||
let contentOffsetY = scrollView.contentOffset.y
|
||||
print(contentOffsetY)
|
||||
let isShowingNewPostsNew = viewController?.navigationItem.titleView === HomeTimelineNavigationBarView.newPostsView
|
||||
if !isShowingNewPostsNew {
|
||||
return
|
||||
}
|
||||
let isTop = contentOffsetY < -scrollView.contentInset.top
|
||||
if isTop {
|
||||
newTopContent.value = false
|
||||
|
@ -138,6 +173,7 @@ extension HomeTimelineNavigationBarState {
|
|||
networkErrorCountSubject.send(false)
|
||||
case .finished:
|
||||
reCountdown()
|
||||
showPublishingNewPostInNavigationBar()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,19 @@ final class HomeTimelineNavigationBarView {
|
|||
return view
|
||||
}()
|
||||
|
||||
static var progressView: NavigationBarProgressView = {
|
||||
let view = NavigationBarProgressView()
|
||||
return view
|
||||
}()
|
||||
|
||||
static var publishingLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.translatesAutoresizingMaskIntoConstraints = false
|
||||
label.textColor = .black
|
||||
label.font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 17, weight: .semibold))
|
||||
label.text = L10n.Scene.HomeTimeline.NavigationBarState.publishing
|
||||
return label
|
||||
}()
|
||||
|
||||
static func addLabelToView(label: UILabel,view:UIView) {
|
||||
view.addSubview(label)
|
||||
|
|
|
@ -58,6 +58,7 @@ extension HomeTimelineViewModel.LoadOldestState {
|
|||
.delay(for: .seconds(1), scheduler: DispatchQueue.main)
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink { completion in
|
||||
viewModel.homeTimelineNavigationBarState.receiveCompletion(completion: completion)
|
||||
switch completion {
|
||||
case .failure(let error):
|
||||
os_log("%{public}s[%{public}ld], %{public}s: fetch toots failed. %s", ((#file as NSString).lastPathComponent), #line, #function, error.localizedDescription)
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
//
|
||||
// NavigationBarProgressView.swift
|
||||
// Mastodon
|
||||
//
|
||||
// Created by sxiaojian on 2021/3/16.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class NavigationBarProgressView: UIView {
|
||||
|
||||
static let progressAnimationDuration: TimeInterval = 0.3
|
||||
|
||||
let sliderView: UIView = {
|
||||
let view = UIView()
|
||||
view.backgroundColor = Asset.Colors.buttonDefault.color
|
||||
view.translatesAutoresizingMaskIntoConstraints = false
|
||||
return view
|
||||
}()
|
||||
|
||||
var sliderTrailingAnchor: NSLayoutConstraint!
|
||||
|
||||
var progress: CGFloat = 0 {
|
||||
willSet(value) {
|
||||
sliderTrailingAnchor.constant = (1 - progress) * bounds.width
|
||||
UIView.animate(withDuration: NavigationBarProgressView.progressAnimationDuration) {
|
||||
self.setNeedsLayout()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
_init()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
super.init(coder: coder)
|
||||
_init()
|
||||
}
|
||||
}
|
||||
|
||||
extension NavigationBarProgressView {
|
||||
func _init() {
|
||||
self.translatesAutoresizingMaskIntoConstraints = false
|
||||
self.backgroundColor = .clear
|
||||
addSubview(sliderView)
|
||||
sliderTrailingAnchor = trailingAnchor.constraint(equalTo: sliderView.trailingAnchor)
|
||||
NSLayoutConstraint.activate([
|
||||
sliderView.topAnchor.constraint(equalTo: topAnchor),
|
||||
sliderView.leadingAnchor.constraint(equalTo: leadingAnchor),
|
||||
sliderView.bottomAnchor.constraint(equalTo: bottomAnchor),
|
||||
sliderTrailingAnchor
|
||||
])
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue