feat: update list fetch trigger logic for UserTimeline scene

This commit is contained in:
CMK 2021-11-10 17:55:12 +08:00
parent dd118023b9
commit 832b146c82
5 changed files with 99 additions and 16 deletions

View File

@ -377,6 +377,7 @@
DB71FD5225F8CCAA00512AE1 /* APIService+Status.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB71FD5125F8CCAA00512AE1 /* APIService+Status.swift */; };
DB72601C25E36A2100235243 /* MastodonServerRulesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB72601B25E36A2100235243 /* MastodonServerRulesViewController.swift */; };
DB72602725E36A6F00235243 /* MastodonServerRulesViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB72602625E36A6F00235243 /* MastodonServerRulesViewModel.swift */; };
DB7274F4273BB9B200577D95 /* ListBatchFetchViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB7274F3273BB9B200577D95 /* ListBatchFetchViewModel.swift */; };
DB73B490261F030A002E9E9F /* SafariActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB73B48F261F030A002E9E9F /* SafariActivity.swift */; };
DB73BF3B2711885500781945 /* UserDefaults+Notification.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB73BF3A2711885500781945 /* UserDefaults+Notification.swift */; };
DB73BF4127118B6D00781945 /* Instance.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB73BF4027118B6D00781945 /* Instance.swift */; };
@ -1195,6 +1196,7 @@
DB71FD5125F8CCAA00512AE1 /* APIService+Status.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APIService+Status.swift"; sourceTree = "<group>"; };
DB72601B25E36A2100235243 /* MastodonServerRulesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonServerRulesViewController.swift; sourceTree = "<group>"; };
DB72602625E36A6F00235243 /* MastodonServerRulesViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonServerRulesViewModel.swift; sourceTree = "<group>"; };
DB7274F3273BB9B200577D95 /* ListBatchFetchViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListBatchFetchViewModel.swift; sourceTree = "<group>"; };
DB73B48F261F030A002E9E9F /* SafariActivity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SafariActivity.swift; sourceTree = "<group>"; };
DB73BF3A2711885500781945 /* UserDefaults+Notification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UserDefaults+Notification.swift"; sourceTree = "<group>"; };
DB73BF4027118B6D00781945 /* Instance.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Instance.swift; sourceTree = "<group>"; };
@ -2972,6 +2974,7 @@
DB9D6C2225E502C60051B173 /* MosaicImageViewModel.swift */,
2DA6055025F74407006356F9 /* AudioContainerViewModel.swift */,
5DF1054625F8870E00D6C0D4 /* VideoPlayerViewModel.swift */,
DB7274F3273BB9B200577D95 /* ListBatchFetchViewModel.swift */,
);
path = ViewModel;
sourceTree = "<group>";
@ -4233,6 +4236,7 @@
2D24E11D2626D8B100A59D4F /* NotificationStatusTableViewCell.swift in Sources */,
DB6C8C0F25F0A6AE00AAA452 /* Mastodon+Entity+Error.swift in Sources */,
DB1E346825F518E20079D7DF /* CategoryPickerSection.swift in Sources */,
DB7274F4273BB9B200577D95 /* ListBatchFetchViewModel.swift in Sources */,
2D61254D262547C200299647 /* APIService+Notification.swift in Sources */,
DB040ED126538E3D00BEE9D8 /* Trie.swift in Sources */,
DB73BF4B27140C0800781945 /* UITableViewDiffableDataSource.swift in Sources */,

View File

@ -7,12 +7,12 @@
<key>AppShared.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>42</integer>
<integer>36</integer>
</dict>
<key>CoreDataStack.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>43</integer>
<integer>38</integer>
</dict>
<key>Mastodon - ASDK.xcscheme_^#shared#^_</key>
<dict>
@ -102,7 +102,7 @@
<key>MastodonIntent.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>45</integer>
<integer>39</integer>
</dict>
<key>MastodonIntents.xcscheme_^#shared#^_</key>
<dict>
@ -122,7 +122,7 @@
<key>ShareActionExtension.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>44</integer>
<integer>37</integer>
</dict>
</dict>
<key>SuppressBuildableAutocreation</key>

View File

@ -72,6 +72,16 @@ extension UserTimelineViewController {
statusTableViewCellDelegate: self
)
// setup batch fetch
viewModel.listBatchFetchViewModel.setup(scrollView: tableView)
viewModel.listBatchFetchViewModel.shouldFetch
.receive(on: DispatchQueue.main)
.sink { [weak self] _ in
guard let self = self else { return }
self.viewModel.stateMachine.enter(UserTimelineViewModel.State.Loading.self)
}
.store(in: &disposeBag)
// trigger user timeline loading
Publishers.CombineLatest(
viewModel.domain.removeDuplicates().eraseToAnyPublisher(),
@ -104,11 +114,11 @@ extension UserTimelineViewController {
extension UserTimelineViewController: StatusTableViewControllerAspect { }
// MARK: - UIScrollViewDelegate
extension UserTimelineViewController {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
aspectScrollViewDidScroll(scrollView)
}
}
//extension UserTimelineViewController {
// func scrollViewDidScroll(_ scrollView: UIScrollView) {
// aspectScrollViewDidScroll(scrollView)
// }
//}
// MARK: - TableViewCellHeightCacheableContainer
extension UserTimelineViewController: TableViewCellHeightCacheableContainer {
@ -186,13 +196,13 @@ extension UserTimelineViewController: ScrollViewContainer {
}
// MARK: - LoadMoreConfigurableTableViewContainer
extension UserTimelineViewController: LoadMoreConfigurableTableViewContainer {
typealias BottomLoaderTableViewCell = TimelineBottomLoaderTableViewCell
typealias LoadingState = UserTimelineViewModel.State.Loading
var loadMoreConfigurableTableView: UITableView { return tableView }
var loadMoreConfigurableStateMachine: GKStateMachine { return viewModel.stateMachine }
}
//extension UserTimelineViewController: LoadMoreConfigurableTableViewContainer {
// typealias BottomLoaderTableViewCell = TimelineBottomLoaderTableViewCell
// typealias LoadingState = UserTimelineViewModel.State.Loading
//
// var loadMoreConfigurableTableView: UITable``````View { return tableView }
// var loadMoreConfigurableStateMachine: GKStateMachine { return viewModel.stateMachine }
//}
extension UserTimelineViewController {
override var keyCommands: [UIKeyCommand]? {

View File

@ -23,6 +23,7 @@ final class UserTimelineViewModel {
let userID: CurrentValueSubject<String?, Never>
let queryFilter: CurrentValueSubject<QueryFilter, Never>
let statusFetchedResultsController: StatusFetchedResultsController
let listBatchFetchViewModel = ListBatchFetchViewModel()
var cellFrameCache = NSCache<NSNumber, NSValue>()
let isBlocking = CurrentValueSubject<Bool, Never>(false)

View File

@ -0,0 +1,68 @@
//
// ListBatchFetchViewModel.swift
// Mastodon
//
// Created by Cirno MainasuK on 2021-11-10.
//
import UIKit
import Combine
// ref: Texture.ASBatchFetchingDelegate
final class ListBatchFetchViewModel {
var disposeBag = Set<AnyCancellable>()
// timer running on `common` mode
let timerPublisher = Timer.publish(every: 1.0, on: .main, in: .common)
.autoconnect()
.share()
.eraseToAnyPublisher()
// input
private(set) weak var scrollView: UIScrollView?
let hasMore = CurrentValueSubject<Bool, Never>(true)
// output
let shouldFetch = PassthroughSubject<Void, Never>()
init() {
Publishers.CombineLatest(
hasMore,
timerPublisher
)
.sink { [weak self] hasMore, _ in
guard let self = self else { return }
guard hasMore else { return }
guard let scrollView = self.scrollView else { return }
// skip trigger if user interacting
if scrollView.isDragging || scrollView.isTracking { return }
// send fetch request
if scrollView.contentSize.height < scrollView.frame.height {
self.shouldFetch.send()
} else {
let frame = scrollView.frame
let contentOffset = scrollView.contentOffset
let contentSize = scrollView.contentSize
let visibleBottomY = contentOffset.y + frame.height
let offset = 2 * frame.height
let fetchThrottleOffsetY = contentSize.height - offset
if visibleBottomY > fetchThrottleOffsetY {
self.shouldFetch.send()
}
}
}
.store(in: &disposeBag)
}
}
extension ListBatchFetchViewModel {
func setup(scrollView: UIScrollView) {
self.scrollView = scrollView
}
}