From 2e86449c41dd40d67c6b86ca72d48a190ed4525f Mon Sep 17 00:00:00 2001 From: sunxiaojian Date: Wed, 14 Apr 2021 20:02:41 +0800 Subject: [PATCH] fix: bottom loader display aways --- .../Section/NotificationSection.swift | 8 +------- .../NotificationViewController.swift | 13 +++++++++++++ ...otificationViewModel+LoadOldestState.swift | 19 ++++++++++++++++--- .../NotificationViewModel+diffable.swift | 5 ++++- .../Notification/NotificationViewModel.swift | 1 + .../NotificationStatusTableViewCell.swift | 7 +++++++ 6 files changed, 42 insertions(+), 11 deletions(-) diff --git a/Mastodon/Diffiable/Section/NotificationSection.swift b/Mastodon/Diffiable/Section/NotificationSection.swift index 01273e9f..9fbad362 100644 --- a/Mastodon/Diffiable/Section/NotificationSection.swift +++ b/Mastodon/Diffiable/Section/NotificationSection.swift @@ -147,13 +147,7 @@ extension NotificationSection { requestUserID: String, statusItemAttribute: Item.StatusAttribute ) { - // disable interaction - cell.statusView.isUserInteractionEnabled = false - // remove item don't display - cell.statusView.actionToolbarContainer.removeFromSuperview() - cell.statusView.avatarView.removeFromSuperview() - - + // setup attribute statusItemAttribute.setupForStatus(status: status) diff --git a/Mastodon/Scene/Notification/NotificationViewController.swift b/Mastodon/Scene/Notification/NotificationViewController.swift index d5eb149a..a1921558 100644 --- a/Mastodon/Scene/Notification/NotificationViewController.swift +++ b/Mastodon/Scene/Notification/NotificationViewController.swift @@ -156,6 +156,19 @@ extension NotificationViewController: UITableViewDelegate { break } } + + func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { + guard let diffableDataSource = viewModel.diffableDataSource else { return } + guard let item = diffableDataSource.itemIdentifier(for: indexPath) else { return } + switch item { + case .bottomLoader: + if !tableView.isDragging && !tableView.isDecelerating { + viewModel.loadoldestStateMachine.enter(NotificationViewModel.LoadOldestState.Loading.self) + } + default: + break + } + } } diff --git a/Mastodon/Scene/Notification/NotificationViewModel+LoadOldestState.swift b/Mastodon/Scene/Notification/NotificationViewModel+LoadOldestState.swift index 13c82093..bf049eac 100644 --- a/Mastodon/Scene/Notification/NotificationViewModel+LoadOldestState.swift +++ b/Mastodon/Scene/Notification/NotificationViewModel+LoadOldestState.swift @@ -9,6 +9,7 @@ import os.log import Foundation import GameplayKit import MastodonSDK +import CoreDataStack extension NotificationViewModel { class LoadOldestState: GKState { @@ -42,13 +43,24 @@ extension NotificationViewModel.LoadOldestState { override func didEnter(from previousState: GKState?) { super.didEnter(from: previousState) guard let viewModel = viewModel, let stateMachine = stateMachine else { return } - guard let activeMastodonAuthenticationBox = viewModel.context.authenticationService.activeMastodonAuthenticationBox.value else { + guard let activeMastodonAuthenticationBox = viewModel.activeMastodonAuthenticationBox.value else { assertionFailure() stateMachine.enter(Fail.self) return } - - guard let last = viewModel.fetchedResultsController.fetchedObjects?.last else { + let notifications: [MastodonNotification]? = { + let request = MastodonNotification.sortedFetchRequest + request.predicate = MastodonNotification.predicate(domain: activeMastodonAuthenticationBox.domain) + request.returnsObjectsAsFaults = false + do { + return try self.viewModel?.context.managedObjectContext.fetch(request) + } catch { + assertionFailure(error.localizedDescription) + return nil + } + }() + + guard let last = notifications?.last else { stateMachine.enter(Idle.self) return } @@ -78,6 +90,7 @@ extension NotificationViewModel.LoadOldestState { } receiveValue: { [weak viewModel] response in guard let viewModel = viewModel else { return } if viewModel.selectedIndex.value == 1 { + viewModel.noMoreNotification.value = response.value.isEmpty let list = response.value.filter { $0.type == Mastodon.Entity.Notification.NotificationType.mention } if list.isEmpty { stateMachine.enter(NoMore.self) diff --git a/Mastodon/Scene/Notification/NotificationViewModel+diffable.swift b/Mastodon/Scene/Notification/NotificationViewModel+diffable.swift index 2d68586d..a4c86521 100644 --- a/Mastodon/Scene/Notification/NotificationViewModel+diffable.swift +++ b/Mastodon/Scene/Notification/NotificationViewModel+diffable.swift @@ -72,7 +72,7 @@ extension NotificationViewModel: NSFetchedResultsControllerDelegate { var newSnapshot = NSDiffableDataSourceSnapshot() newSnapshot.appendSections([.main]) newSnapshot.appendItems(notifications.map({NotificationItem.notification(objectID: $0.objectID)}), toSection: .main) - if !notifications.isEmpty { + if !notifications.isEmpty && self.noMoreNotification.value == false { newSnapshot.appendItems([.bottomLoader], toSection: .main) } @@ -112,6 +112,9 @@ extension NotificationViewModel: NSFetchedResultsControllerDelegate { guard sourceIndexPath.row < oldSnapshot.itemIdentifiers(inSection: .main).count else { return nil } + if oldSnapshot.itemIdentifiers.elementsEqual(newSnapshot.itemIdentifiers) { + return nil + } let timelineItem = oldSnapshot.itemIdentifiers(inSection: .main)[sourceIndexPath.row] guard let itemIndex = newSnapshot.itemIdentifiers(inSection: .main).firstIndex(of: timelineItem) else { return nil } let targetIndexPath = IndexPath(row: itemIndex, section: 0) diff --git a/Mastodon/Scene/Notification/NotificationViewModel.swift b/Mastodon/Scene/Notification/NotificationViewModel.swift index 26d21e79..85806acf 100644 --- a/Mastodon/Scene/Notification/NotificationViewModel.swift +++ b/Mastodon/Scene/Notification/NotificationViewModel.swift @@ -24,6 +24,7 @@ final class NotificationViewModel: NSObject { let viewDidLoad = PassthroughSubject() let selectedIndex = CurrentValueSubject(0) + let noMoreNotification = CurrentValueSubject(false) let activeMastodonAuthenticationBox: CurrentValueSubject let fetchedResultsController: NSFetchedResultsController! diff --git a/Mastodon/Scene/Notification/TableViewCell/NotificationStatusTableViewCell.swift b/Mastodon/Scene/Notification/TableViewCell/NotificationStatusTableViewCell.swift index 37b74599..6bdf0fd1 100644 --- a/Mastodon/Scene/Notification/TableViewCell/NotificationStatusTableViewCell.swift +++ b/Mastodon/Scene/Notification/TableViewCell/NotificationStatusTableViewCell.swift @@ -79,6 +79,7 @@ final class NotificationStatusTableViewCell: UITableViewCell { statusView.pollTableView.dataSource = nil statusView.playerContainerView.reset() statusView.playerContainerView.isHidden = true + disposeBag.removeAll() } @@ -133,6 +134,12 @@ extension NotificationStatusTableViewCell { } func addStatusAndContainer() { + statusView.isUserInteractionEnabled = false + // remove item don't display + statusView.actionToolbarContainer.removeFromSuperview() + statusView.avatarView.removeFromSuperview() + statusView.usernameLabel.removeFromSuperview() + contentView.addSubview(statusContainer) statusContainer.pin(top: 40, left: 63, bottom: 14, right: 14)