Add a new loading-state for timeline-switches (IOS-235)
Gosh, this took longer than expected. It didn't work for quite some time but the trick is to check for the states in several places, like in HomeTimelineViewModel+Diffable or when the timeline reached the end. Those triggered a reload and we don't want that in case the state is `contextSwitch`.
This commit is contained in:
parent
86ab9101a3
commit
1583ce0d9a
|
@ -12,7 +12,7 @@ extension HomeTimelineViewController: DataSourceProvider {
|
|||
func item(from source: DataSourceItem.Source) async -> DataSourceItem? {
|
||||
var _indexPath = source.indexPath
|
||||
if _indexPath == nil, let cell = source.tableViewCell {
|
||||
_indexPath = await self.indexPath(for: cell)
|
||||
_indexPath = self.indexPath(for: cell)
|
||||
}
|
||||
guard let indexPath = _indexPath else { return nil }
|
||||
|
||||
|
@ -37,8 +37,7 @@ extension HomeTimelineViewController: DataSourceProvider {
|
|||
viewModel?.dataController.update(status: status, intent: intent)
|
||||
}
|
||||
|
||||
@MainActor
|
||||
private func indexPath(for cell: UITableViewCell) async -> IndexPath? {
|
||||
private func indexPath(for cell: UITableViewCell) -> IndexPath? {
|
||||
return tableView.indexPath(for: cell)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -109,7 +109,7 @@ final class HomeTimelineViewController: UIViewController, NeedsDependency, Media
|
|||
viewModel.timelineContext = .following
|
||||
viewModel.dataController.records = []
|
||||
|
||||
viewModel.loadLatestStateMachine.enter(HomeTimelineViewModel.LoadLatestState.LoadingManually.self)
|
||||
viewModel.loadLatestStateMachine.enter(HomeTimelineViewModel.LoadLatestState.ContextSwitch.self)
|
||||
timelineSelectorButton.setAttributedTitle(
|
||||
.init(string: "Following", attributes: [
|
||||
.font: UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 20, weight: .semibold))
|
||||
|
@ -124,9 +124,7 @@ final class HomeTimelineViewController: UIViewController, NeedsDependency, Media
|
|||
guard let self, let viewModel = self.viewModel else { return }
|
||||
|
||||
viewModel.timelineContext = .localCommunity
|
||||
viewModel.dataController.records = []
|
||||
|
||||
viewModel.loadLatestStateMachine.enter(HomeTimelineViewModel.LoadLatestState.LoadingManually.self)
|
||||
viewModel.loadLatestStateMachine.enter(HomeTimelineViewModel.LoadLatestState.ContextSwitch.self)
|
||||
timelineSelectorButton.setAttributedTitle(
|
||||
.init(string: "Local", attributes: [
|
||||
.font: UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 20, weight: .semibold))
|
||||
|
@ -591,8 +589,12 @@ extension HomeTimelineViewController: UITableViewDelegate, AutoGenerateTableView
|
|||
// sourcery:end
|
||||
|
||||
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
|
||||
guard let viewModel,
|
||||
let currentState = viewModel.loadLatestStateMachine.currentState as? HomeTimelineViewModel.LoadLatestState,
|
||||
(currentState.self is HomeTimelineViewModel.LoadLatestState.ContextSwitch) == false else { return }
|
||||
|
||||
if indexPath.row == tableView.numberOfRows(inSection: indexPath.section) - 1 {
|
||||
viewModel?.timelineDidReachEnd()
|
||||
viewModel.timelineDidReachEnd()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,6 +40,9 @@ extension HomeTimelineViewModel {
|
|||
guard let self = self else { return }
|
||||
guard let diffableDataSource = self.diffableDataSource else { return }
|
||||
|
||||
guard let currentState = loadLatestStateMachine.currentState as? HomeTimelineViewModel.LoadLatestState,
|
||||
(currentState.self is HomeTimelineViewModel.LoadLatestState.ContextSwitch) == false else { return }
|
||||
|
||||
Task { @MainActor in
|
||||
let oldSnapshot = diffableDataSource.snapshot()
|
||||
var newSnapshot: NSDiffableDataSourceSnapshot<StatusSection, StatusItem> = {
|
||||
|
|
|
@ -70,7 +70,33 @@ extension HomeTimelineViewModel.LoadLatestState {
|
|||
|
||||
class Idle: HomeTimelineViewModel.LoadLatestState {
|
||||
override func isValidNextState(_ stateClass: AnyClass) -> Bool {
|
||||
return stateClass == Loading.self || stateClass == LoadingManually.self
|
||||
return stateClass == Loading.self || stateClass == LoadingManually.self || stateClass == ContextSwitch.self
|
||||
}
|
||||
}
|
||||
|
||||
class ContextSwitch: HomeTimelineViewModel.LoadLatestState {
|
||||
override func isValidNextState(_ stateClass: AnyClass) -> Bool {
|
||||
return stateClass == Loading.self || stateClass == LoadingManually.self || stateClass == ContextSwitch.self
|
||||
}
|
||||
|
||||
override func didEnter(from previousState: GKState?) {
|
||||
guard let viewModel else { return }
|
||||
guard let diffableDataSource = viewModel.diffableDataSource else {
|
||||
assertionFailure()
|
||||
return
|
||||
}
|
||||
|
||||
OperationQueue.main.addOperation {
|
||||
viewModel.dataController.records = []
|
||||
var snapshot = NSDiffableDataSourceSnapshot<StatusSection, StatusItem>()
|
||||
snapshot.appendSections([.main])
|
||||
snapshot.appendItems([.topLoader], toSection: .main)
|
||||
diffableDataSource.apply(snapshot) { [weak self] in
|
||||
guard let self else { return }
|
||||
|
||||
self.stateMachine?.enter(Loading.self)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -78,7 +104,7 @@ extension HomeTimelineViewModel.LoadLatestState {
|
|||
super.didEnter(from: previousState)
|
||||
|
||||
guard let viewModel else { return }
|
||||
|
||||
|
||||
let latestFeedRecords = viewModel.dataController.records.prefix(APIService.onceRequestStatusMaxCount)
|
||||
|
||||
Task {
|
||||
|
|
|
@ -55,6 +55,7 @@ final class HomeTimelineViewModel: NSObject {
|
|||
LoadLatestState.LoadingManually(viewModel: self),
|
||||
LoadLatestState.Fail(viewModel: self),
|
||||
LoadLatestState.Idle(viewModel: self),
|
||||
LoadLatestState.ContextSwitch(viewModel: self),
|
||||
])
|
||||
stateMachine.enter(LoadLatestState.Initial.self)
|
||||
return stateMachine
|
||||
|
|
Loading…
Reference in New Issue