chore: format file

This commit is contained in:
sunxiaojian 2021-04-15 10:16:30 +08:00
parent 2e86449c41
commit 80d76acc27
11 changed files with 66 additions and 87 deletions

View File

@ -5,11 +5,10 @@
// Created by sxiaojian on 2021/4/13. // Created by sxiaojian on 2021/4/13.
// //
import Foundation
import CoreData import CoreData
import Foundation
enum NotificationItem { enum NotificationItem {
case notification(objectID: NSManagedObjectID) case notification(objectID: NSManagedObjectID)
case bottomLoader case bottomLoader
@ -20,7 +19,7 @@ extension NotificationItem: Equatable {
switch (lhs, rhs) { switch (lhs, rhs) {
case (.bottomLoader, .bottomLoader): case (.bottomLoader, .bottomLoader):
return true return true
case (.notification(let idLeft),.notification(let idRight)): case (.notification(let idLeft), .notification(let idRight)):
return idLeft == idRight return idLeft == idRight
default: default:
return false return false

View File

@ -5,12 +5,12 @@
// Created by sxiaojian on 2021/4/13. // Created by sxiaojian on 2021/4/13.
// //
import Combine
import CoreData import CoreData
import CoreDataStack import CoreDataStack
import Foundation import Foundation
import MastodonSDK import MastodonSDK
import UIKit import UIKit
import Combine
enum NotificationSection: Equatable, Hashable { enum NotificationSection: Equatable, Hashable {
case main case main
@ -25,8 +25,8 @@ extension NotificationSection {
dependency: NeedsDependency, dependency: NeedsDependency,
requestUserID: String requestUserID: String
) -> UITableViewDiffableDataSource<NotificationSection, NotificationItem> { ) -> UITableViewDiffableDataSource<NotificationSection, NotificationItem> {
return UITableViewDiffableDataSource(tableView: tableView) { UITableViewDiffableDataSource(tableView: tableView) {
[weak delegate,weak dependency] [weak delegate, weak dependency]
(tableView, indexPath, notificationItem) -> UITableViewCell? in (tableView, indexPath, notificationItem) -> UITableViewCell? in
guard let dependency = dependency else { return nil } guard let dependency = dependency else { return nil }
switch notificationItem { switch notificationItem {
@ -136,7 +136,6 @@ extension NotificationSection {
} }
} }
extension NotificationSection { extension NotificationSection {
static func configure( static func configure(
cell: NotificationStatusTableViewCell, cell: NotificationStatusTableViewCell,
@ -147,7 +146,6 @@ extension NotificationSection {
requestUserID: String, requestUserID: String,
statusItemAttribute: Item.StatusAttribute statusItemAttribute: Item.StatusAttribute
) { ) {
// setup attribute // setup attribute
statusItemAttribute.setupForStatus(status: status) statusItemAttribute.setupForStatus(status: status)
@ -176,7 +174,6 @@ extension NotificationSection {
cell.statusView.avatarStackedContainerButton.isHidden = true cell.statusView.avatarStackedContainerButton.isHidden = true
cell.statusView.configure(with: AvatarConfigurableViewConfiguration(avatarImageURL: status.author.avatarImageURL())) cell.statusView.configure(with: AvatarConfigurableViewConfiguration(avatarImageURL: status.author.avatarImageURL()))
// set text // set text
cell.statusView.activeTextLabel.configure(content: (status.reblog ?? status).content) cell.statusView.activeTextLabel.configure(content: (status.reblog ?? status).content)
@ -338,7 +335,6 @@ extension NotificationSection {
cell.statusView.dateLabel.text = createdAt.shortTimeAgoSinceNow cell.statusView.dateLabel.text = createdAt.shortTimeAgoSinceNow
} }
.store(in: &cell.disposeBag) .store(in: &cell.disposeBag)
} }
static func configureHeader( static func configureHeader(
@ -366,7 +362,6 @@ extension NotificationSection {
} }
} }
static func configurePoll( static func configurePoll(
cell: NotificationStatusTableViewCell, cell: NotificationStatusTableViewCell,
poll: Poll?, poll: Poll?,
@ -486,7 +481,7 @@ extension NotificationSection {
} }
} }
extension NotificationSection { extension NotificationSection {
private static func formattedNumberTitleForActionButton(_ number: Int?) -> String { private static func formattedNumberTitleForActionButton(_ number: Int?) -> String {
guard let number = number, number > 0 else { return "" } guard let number = number, number > 0 else { return "" }
return String(number) return String(number)

View File

@ -87,7 +87,7 @@ class GestureSubscription<S: Subscriber>: Subscription where S.Input == GestureT
extension UIView { extension UIView {
func gesture(_ gestureType: GestureType = .tap()) -> GesturePublisher { func gesture(_ gestureType: GestureType = .tap()) -> GesturePublisher {
self.isUserInteractionEnabled = true isUserInteractionEnabled = true
return GesturePublisher(view: self, gestureType: gestureType) return GesturePublisher(view: self, gestureType: gestureType)
} }
} }

View File

@ -5,16 +5,15 @@
// Created by sxiaojian on 2021/4/12. // Created by sxiaojian on 2021/4/12.
// //
import UIKit
import Combine import Combine
import OSLog
import CoreData import CoreData
import CoreDataStack import CoreDataStack
import MastodonSDK
import GameplayKit import GameplayKit
import MastodonSDK
import OSLog
import UIKit
final class NotificationViewController: UIViewController, NeedsDependency { final class NotificationViewController: UIViewController, NeedsDependency {
weak var context: AppContext! { willSet { precondition(!isViewLoaded) } } weak var context: AppContext! { willSet { precondition(!isViewLoaded) } }
weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } } weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } }
@ -22,7 +21,7 @@ final class NotificationViewController: UIViewController, NeedsDependency {
private(set) lazy var viewModel = NotificationViewModel(context: context) private(set) lazy var viewModel = NotificationViewModel(context: context)
let segmentControl: UISegmentedControl = { let segmentControl: UISegmentedControl = {
let control = UISegmentedControl(items: [L10n.Scene.Notification.Title.everything,L10n.Scene.Notification.Title.mentions]) let control = UISegmentedControl(items: [L10n.Scene.Notification.Title.everything, L10n.Scene.Notification.Title.mentions])
control.selectedSegmentIndex = 0 control.selectedSegmentIndex = 0
return control return control
}() }()
@ -41,11 +40,9 @@ final class NotificationViewController: UIViewController, NeedsDependency {
}() }()
let refreshControl = UIRefreshControl() let refreshControl = UIRefreshControl()
} }
extension NotificationViewController { extension NotificationViewController {
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
view.backgroundColor = Asset.Colors.Background.pure.color view.backgroundColor = Asset.Colors.Background.pure.color
@ -80,7 +77,6 @@ extension NotificationViewController {
} }
} }
.store(in: &disposeBag) .store(in: &disposeBag)
} }
override func viewWillAppear(_ animated: Bool) { override func viewWillAppear(_ animated: Bool) {
@ -110,12 +106,11 @@ extension NotificationViewController {
self.tableView.reloadData() self.tableView.reloadData()
} }
} }
} }
extension NotificationViewController { extension NotificationViewController {
@objc private func segmentedControlValueChanged(_ sender: UISegmentedControl) { @objc private func segmentedControlValueChanged(_ sender: UISegmentedControl) {
os_log("%{public}s[%{public}ld], %{public}s: select at index: %ld", ((#file as NSString).lastPathComponent), #line, #function, sender.selectedSegmentIndex) os_log("%{public}s[%{public}ld], %{public}s: select at index: %ld", (#file as NSString).lastPathComponent, #line, #function, sender.selectedSegmentIndex)
guard let domain = viewModel.activeMastodonAuthenticationBox.value?.domain else { guard let domain = viewModel.activeMastodonAuthenticationBox.value?.domain else {
return return
} }
@ -136,8 +131,8 @@ extension NotificationViewController {
} }
// MARK: - UITableViewDelegate // MARK: - UITableViewDelegate
extension NotificationViewController: UITableViewDelegate { extension NotificationViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
guard let diffableDataSource = viewModel.diffableDataSource else { return } guard let diffableDataSource = viewModel.diffableDataSource else { return }
guard let item = diffableDataSource.itemIdentifier(for: indexPath) else { return } guard let item = diffableDataSource.itemIdentifier(for: indexPath) else { return }
@ -145,9 +140,9 @@ extension NotificationViewController: UITableViewDelegate {
case .notification(let objectID): case .notification(let objectID):
let notification = context.managedObjectContext.object(with: objectID) as! MastodonNotification let notification = context.managedObjectContext.object(with: objectID) as! MastodonNotification
if notification.status != nil { if notification.status != nil {
// TODO goto status detail vc // TODO: goto status detail vc
} else { } else {
let viewModel = ProfileViewModel(context: self.context, optionalMastodonUser: notification.account) let viewModel = ProfileViewModel(context: context, optionalMastodonUser: notification.account)
DispatchQueue.main.async { DispatchQueue.main.async {
self.coordinator.present(scene: .profile(viewModel: viewModel), from: self, transition: .show) self.coordinator.present(scene: .profile(viewModel: viewModel), from: self, transition: .show)
} }
@ -162,26 +157,26 @@ extension NotificationViewController: UITableViewDelegate {
guard let item = diffableDataSource.itemIdentifier(for: indexPath) else { return } guard let item = diffableDataSource.itemIdentifier(for: indexPath) else { return }
switch item { switch item {
case .bottomLoader: case .bottomLoader:
if !tableView.isDragging && !tableView.isDecelerating { if !tableView.isDragging, !tableView.isDecelerating {
viewModel.loadoldestStateMachine.enter(NotificationViewModel.LoadOldestState.Loading.self) viewModel.loadoldestStateMachine.enter(NotificationViewModel.LoadOldestState.Loading.self)
} }
default: default:
break break
} }
} }
} }
// MARK: - ContentOffsetAdjustableTimelineViewControllerDelegate // MARK: - ContentOffsetAdjustableTimelineViewControllerDelegate
extension NotificationViewController: ContentOffsetAdjustableTimelineViewControllerDelegate { extension NotificationViewController: ContentOffsetAdjustableTimelineViewControllerDelegate {
func navigationBar() -> UINavigationBar? { func navigationBar() -> UINavigationBar? {
return navigationController?.navigationBar navigationController?.navigationBar
} }
} }
extension NotificationViewController: NotificationTableViewCellDelegate { extension NotificationViewController: NotificationTableViewCellDelegate {
func userAvatarDidPressed(notification: MastodonNotification) { func userAvatarDidPressed(notification: MastodonNotification) {
let viewModel = ProfileViewModel(context: self.context, optionalMastodonUser: notification.account) let viewModel = ProfileViewModel(context: context, optionalMastodonUser: notification.account)
DispatchQueue.main.async { DispatchQueue.main.async {
self.coordinator.present(scene: .profile(viewModel: viewModel), from: self, transition: .show) self.coordinator.present(scene: .profile(viewModel: viewModel), from: self, transition: .show)
} }
@ -190,11 +185,10 @@ extension NotificationViewController: NotificationTableViewCellDelegate {
func parent() -> UIViewController { func parent() -> UIViewController {
self self
} }
} }
// MARK: - UIScrollViewDelegate // MARK: - UIScrollViewDelegate
extension NotificationViewController { extension NotificationViewController {
func scrollViewDidScroll(_ scrollView: UIScrollView) { func scrollViewDidScroll(_ scrollView: UIScrollView) {
handleScrollViewDidScroll(scrollView) handleScrollViewDidScroll(scrollView)
@ -204,6 +198,6 @@ extension NotificationViewController {
extension NotificationViewController: LoadMoreConfigurableTableViewContainer { extension NotificationViewController: LoadMoreConfigurableTableViewContainer {
typealias BottomLoaderTableViewCell = CommonBottomLoader typealias BottomLoaderTableViewCell = CommonBottomLoader
typealias LoadingState = NotificationViewModel.LoadOldestState.Loading typealias LoadingState = NotificationViewModel.LoadOldestState.Loading
var loadMoreConfigurableTableView: UITableView { return tableView } var loadMoreConfigurableTableView: UITableView { tableView }
var loadMoreConfigurableStateMachine: GKStateMachine { return viewModel.loadoldestStateMachine } var loadMoreConfigurableStateMachine: GKStateMachine { viewModel.loadoldestStateMachine }
} }

View File

@ -5,13 +5,13 @@
// Created by sxiaojian on 2021/4/13. // Created by sxiaojian on 2021/4/13.
// //
import os.log
import func QuartzCore.CACurrentMediaTime
import Foundation
import CoreData import CoreData
import CoreDataStack import CoreDataStack
import Foundation
import GameplayKit import GameplayKit
import MastodonSDK import MastodonSDK
import os.log
import func QuartzCore.CACurrentMediaTime
extension NotificationViewModel { extension NotificationViewModel {
class LoadLatestState: GKState { class LoadLatestState: GKState {
@ -22,7 +22,7 @@ extension NotificationViewModel {
} }
override func didEnter(from previousState: GKState?) { override func didEnter(from previousState: GKState?) {
os_log("%{public}s[%{public}ld], %{public}s: enter %s, previous: %s", ((#file as NSString).lastPathComponent), #line, #function, self.debugDescription, previousState.debugDescription) os_log("%{public}s[%{public}ld], %{public}s: enter %s, previous: %s", (#file as NSString).lastPathComponent, #line, #function, debugDescription, previousState.debugDescription)
viewModel?.loadLatestStateMachinePublisher.send(self) viewModel?.loadLatestStateMachinePublisher.send(self)
} }
} }
@ -31,13 +31,13 @@ extension NotificationViewModel {
extension NotificationViewModel.LoadLatestState { extension NotificationViewModel.LoadLatestState {
class Initial: NotificationViewModel.LoadLatestState { class Initial: NotificationViewModel.LoadLatestState {
override func isValidNextState(_ stateClass: AnyClass) -> Bool { override func isValidNextState(_ stateClass: AnyClass) -> Bool {
return stateClass == Loading.self stateClass == Loading.self
} }
} }
class Loading: NotificationViewModel.LoadLatestState { class Loading: NotificationViewModel.LoadLatestState {
override func isValidNextState(_ stateClass: AnyClass) -> Bool { override func isValidNextState(_ stateClass: AnyClass) -> Bool {
return stateClass == Fail.self || stateClass == Idle.self stateClass == Fail.self || stateClass == Idle.self
} }
override func didEnter(from previousState: GKState?) { override func didEnter(from previousState: GKState?) {
@ -63,7 +63,7 @@ extension NotificationViewModel.LoadLatestState {
switch completion { switch completion {
case .failure(let error): case .failure(let error):
viewModel.isFetchingLatestNotification.value = false viewModel.isFetchingLatestNotification.value = false
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: fetch notification failed. %s", ((#file as NSString).lastPathComponent), #line, #function, error.localizedDescription) os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: fetch notification failed. %s", (#file as NSString).lastPathComponent, #line, #function, error.localizedDescription)
case .finished: case .finished:
// handle isFetchingLatestTimeline in fetch controller delegate // handle isFetchingLatestTimeline in fetch controller delegate
break break
@ -76,21 +76,18 @@ extension NotificationViewModel.LoadLatestState {
} }
} }
.store(in: &viewModel.disposeBag) .store(in: &viewModel.disposeBag)
} }
} }
class Fail: NotificationViewModel.LoadLatestState { class Fail: NotificationViewModel.LoadLatestState {
override func isValidNextState(_ stateClass: AnyClass) -> Bool { override func isValidNextState(_ stateClass: AnyClass) -> Bool {
return stateClass == Loading.self || stateClass == Idle.self stateClass == Loading.self || stateClass == Idle.self
} }
} }
class Idle: NotificationViewModel.LoadLatestState { class Idle: NotificationViewModel.LoadLatestState {
override func isValidNextState(_ stateClass: AnyClass) -> Bool { override func isValidNextState(_ stateClass: AnyClass) -> Bool {
return stateClass == Loading.self stateClass == Loading.self
} }
} }
} }

View File

@ -5,11 +5,11 @@
// Created by sxiaojian on 2021/4/14. // Created by sxiaojian on 2021/4/14.
// //
import os.log import CoreDataStack
import Foundation import Foundation
import GameplayKit import GameplayKit
import MastodonSDK import MastodonSDK
import CoreDataStack import os.log
extension NotificationViewModel { extension NotificationViewModel {
class LoadOldestState: GKState { class LoadOldestState: GKState {
@ -20,7 +20,7 @@ extension NotificationViewModel {
} }
override func didEnter(from previousState: GKState?) { override func didEnter(from previousState: GKState?) {
os_log("%{public}s[%{public}ld], %{public}s: enter %s, previous: %s", ((#file as NSString).lastPathComponent), #line, #function, self.debugDescription, previousState.debugDescription) os_log("%{public}s[%{public}ld], %{public}s: enter %s, previous: %s", (#file as NSString).lastPathComponent, #line, #function, debugDescription, previousState.debugDescription)
viewModel?.loadOldestStateMachinePublisher.send(self) viewModel?.loadOldestStateMachinePublisher.send(self)
} }
} }
@ -37,7 +37,7 @@ extension NotificationViewModel.LoadOldestState {
class Loading: NotificationViewModel.LoadOldestState { class Loading: NotificationViewModel.LoadOldestState {
override func isValidNextState(_ stateClass: AnyClass) -> Bool { override func isValidNextState(_ stateClass: AnyClass) -> Bool {
return stateClass == Fail.self || stateClass == Idle.self || stateClass == NoMore.self stateClass == Fail.self || stateClass == Idle.self || stateClass == NoMore.self
} }
override func didEnter(from previousState: GKState?) { override func didEnter(from previousState: GKState?) {
@ -80,7 +80,7 @@ extension NotificationViewModel.LoadOldestState {
.sink { completion in .sink { completion in
switch completion { switch completion {
case .failure(let error): case .failure(let error):
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: fetch notification failed. %s", ((#file as NSString).lastPathComponent), #line, #function, error.localizedDescription) os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: fetch notification failed. %s", (#file as NSString).lastPathComponent, #line, #function, error.localizedDescription)
case .finished: case .finished:
// handle isFetchingLatestTimeline in fetch controller delegate // handle isFetchingLatestTimeline in fetch controller delegate
break break
@ -111,20 +111,20 @@ extension NotificationViewModel.LoadOldestState {
class Fail: NotificationViewModel.LoadOldestState { class Fail: NotificationViewModel.LoadOldestState {
override func isValidNextState(_ stateClass: AnyClass) -> Bool { override func isValidNextState(_ stateClass: AnyClass) -> Bool {
return stateClass == Loading.self || stateClass == Idle.self stateClass == Loading.self || stateClass == Idle.self
} }
} }
class Idle: NotificationViewModel.LoadOldestState { class Idle: NotificationViewModel.LoadOldestState {
override func isValidNextState(_ stateClass: AnyClass) -> Bool { override func isValidNextState(_ stateClass: AnyClass) -> Bool {
return stateClass == Loading.self stateClass == Loading.self
} }
} }
class NoMore: NotificationViewModel.LoadOldestState { class NoMore: NotificationViewModel.LoadOldestState {
override func isValidNextState(_ stateClass: AnyClass) -> Bool { override func isValidNextState(_ stateClass: AnyClass) -> Bool {
// reset state if needs // reset state if needs
return stateClass == Idle.self stateClass == Idle.self
} }
override func didEnter(from previousState: GKState?) { override func didEnter(from previousState: GKState?) {

View File

@ -5,13 +5,12 @@
// Created by sxiaojian on 2021/4/13. // Created by sxiaojian on 2021/4/13.
// //
import os.log
import UIKit
import CoreData import CoreData
import CoreDataStack import CoreDataStack
import os.log
import UIKit
extension NotificationViewModel { extension NotificationViewModel {
func setupDiffableDataSource( func setupDiffableDataSource(
for tableView: UITableView, for tableView: UITableView,
delegate: NotificationTableViewCellDelegate, delegate: NotificationTableViewCellDelegate,
@ -33,19 +32,18 @@ extension NotificationViewModel {
requestUserID: userid requestUserID: userid
) )
} }
} }
extension NotificationViewModel: NSFetchedResultsControllerDelegate { extension NotificationViewModel: NSFetchedResultsControllerDelegate {
func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) { func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
os_log("%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function) os_log("%{public}s[%{public}ld], %{public}s", (#file as NSString).lastPathComponent, #line, #function)
} }
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChangeContentWith snapshot: NSDiffableDataSourceSnapshotReference) { func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChangeContentWith snapshot: NSDiffableDataSourceSnapshotReference) {
os_log("%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function) os_log("%{public}s[%{public}ld], %{public}s", (#file as NSString).lastPathComponent, #line, #function)
guard let tableView = self.tableView else { return } guard let tableView = self.tableView else { return }
guard let navigationBar = self.contentOffsetAdjustableTimelineViewControllerDelegate?.navigationBar() else { return } guard let navigationBar = contentOffsetAdjustableTimelineViewControllerDelegate?.navigationBar() else { return }
guard let diffableDataSource = self.diffableDataSource else { return } guard let diffableDataSource = self.diffableDataSource else { return }
let oldSnapshot = diffableDataSource.snapshot() let oldSnapshot = diffableDataSource.snapshot()
@ -56,7 +54,6 @@ extension NotificationViewModel: NSFetchedResultsControllerDelegate {
managedObjectContext.parent = parentManagedObjectContext managedObjectContext.parent = parentManagedObjectContext
managedObjectContext.perform { managedObjectContext.perform {
let notifications: [MastodonNotification] = { let notifications: [MastodonNotification] = {
let request = MastodonNotification.sortedFetchRequest let request = MastodonNotification.sortedFetchRequest
request.returnsObjectsAsFaults = false request.returnsObjectsAsFaults = false
@ -71,8 +68,8 @@ extension NotificationViewModel: NSFetchedResultsControllerDelegate {
var newSnapshot = NSDiffableDataSourceSnapshot<NotificationSection, NotificationItem>() var newSnapshot = NSDiffableDataSourceSnapshot<NotificationSection, NotificationItem>()
newSnapshot.appendSections([.main]) newSnapshot.appendSections([.main])
newSnapshot.appendItems(notifications.map({NotificationItem.notification(objectID: $0.objectID)}), toSection: .main) newSnapshot.appendItems(notifications.map { NotificationItem.notification(objectID: $0.objectID) }, toSection: .main)
if !notifications.isEmpty && self.noMoreNotification.value == false { if !notifications.isEmpty, self.noMoreNotification.value == false {
newSnapshot.appendItems([.bottomLoader], toSection: .main) newSnapshot.appendItems([.bottomLoader], toSection: .main)
} }

View File

@ -5,16 +5,15 @@
// Created by sxiaojian on 2021/4/12. // Created by sxiaojian on 2021/4/12.
// //
import Foundation
import Combine import Combine
import UIKit
import CoreData import CoreData
import CoreDataStack import CoreDataStack
import Foundation
import GameplayKit import GameplayKit
import MastodonSDK import MastodonSDK
import UIKit
final class NotificationViewModel: NSObject { final class NotificationViewModel: NSObject {
var disposeBag = Set<AnyCancellable>() var disposeBag = Set<AnyCancellable>()
// input // input
@ -23,8 +22,8 @@ final class NotificationViewModel: NSObject {
weak var contentOffsetAdjustableTimelineViewControllerDelegate: ContentOffsetAdjustableTimelineViewControllerDelegate? weak var contentOffsetAdjustableTimelineViewControllerDelegate: ContentOffsetAdjustableTimelineViewControllerDelegate?
let viewDidLoad = PassthroughSubject<Void, Never>() let viewDidLoad = PassthroughSubject<Void, Never>()
let selectedIndex = CurrentValueSubject<Int,Never>(0) let selectedIndex = CurrentValueSubject<Int, Never>(0)
let noMoreNotification = CurrentValueSubject<Bool,Never>(false) let noMoreNotification = CurrentValueSubject<Bool, Never>(false)
let activeMastodonAuthenticationBox: CurrentValueSubject<AuthenticationService.MastodonAuthenticationBox?, Never> let activeMastodonAuthenticationBox: CurrentValueSubject<AuthenticationService.MastodonAuthenticationBox?, Never>
let fetchedResultsController: NSFetchedResultsController<MastodonNotification>! let fetchedResultsController: NSFetchedResultsController<MastodonNotification>!
@ -33,7 +32,7 @@ final class NotificationViewModel: NSObject {
let isFetchingLatestNotification = CurrentValueSubject<Bool, Never>(false) let isFetchingLatestNotification = CurrentValueSubject<Bool, Never>(false)
//output // output
var diffableDataSource: UITableViewDiffableDataSource<NotificationSection, NotificationItem>! var diffableDataSource: UITableViewDiffableDataSource<NotificationSection, NotificationItem>!
// top loader // top loader
private(set) lazy var loadLatestStateMachine: GKStateMachine = { private(set) lazy var loadLatestStateMachine: GKStateMachine = {
@ -63,6 +62,7 @@ final class NotificationViewModel: NSObject {
stateMachine.enter(LoadOldestState.Initial.self) stateMachine.enter(LoadOldestState.Initial.self)
return stateMachine return stateMachine
}() }()
lazy var loadOldestStateMachinePublisher = CurrentValueSubject<LoadOldestState?, Never>(nil) lazy var loadOldestStateMachinePublisher = CurrentValueSubject<LoadOldestState?, Never>(nil)
init(context: AppContext) { init(context: AppContext) {
@ -71,7 +71,7 @@ final class NotificationViewModel: NSObject {
self.fetchedResultsController = { self.fetchedResultsController = {
let fetchRequest = MastodonNotification.sortedFetchRequest let fetchRequest = MastodonNotification.sortedFetchRequest
fetchRequest.returnsObjectsAsFaults = false fetchRequest.returnsObjectsAsFaults = false
fetchRequest.relationshipKeyPathsForPrefetching = [#keyPath(MastodonNotification.status),#keyPath(MastodonNotification.account)] fetchRequest.relationshipKeyPathsForPrefetching = [#keyPath(MastodonNotification.status), #keyPath(MastodonNotification.account)]
let controller = NSFetchedResultsController( let controller = NSFetchedResultsController(
fetchRequest: fetchRequest, fetchRequest: fetchRequest,
managedObjectContext: context.managedObjectContext, managedObjectContext: context.managedObjectContext,
@ -83,7 +83,7 @@ final class NotificationViewModel: NSObject {
}() }()
super.init() super.init()
self.fetchedResultsController.delegate = self fetchedResultsController.delegate = self
context.authenticationService.activeMastodonAuthenticationBox context.authenticationService.activeMastodonAuthenticationBox
.sink(receiveValue: { [weak self] box in .sink(receiveValue: { [weak self] box in
guard let self = self else { return } guard let self = self else { return }
@ -95,7 +95,7 @@ final class NotificationViewModel: NSObject {
.store(in: &disposeBag) .store(in: &disposeBag)
notificationPredicate notificationPredicate
.compactMap{ $0 } .compactMap { $0 }
.sink { [weak self] predicate in .sink { [weak self] predicate in
guard let self = self else { return } guard let self = self else { return }
self.fetchedResultsController.fetchRequest.predicate = predicate self.fetchedResultsController.fetchRequest.predicate = predicate
@ -112,12 +112,11 @@ final class NotificationViewModel: NSObject {
} }
.store(in: &disposeBag) .store(in: &disposeBag)
self.viewDidLoad viewDidLoad
.sink { [weak self] in .sink { [weak self] in
guard let domain = self?.activeMastodonAuthenticationBox.value?.domain else { return } guard let domain = self?.activeMastodonAuthenticationBox.value?.domain else { return }
self?.notificationPredicate.value = MastodonNotification.predicate(domain: domain) self?.notificationPredicate.value = MastodonNotification.predicate(domain: domain)
} }
.store(in: &disposeBag) .store(in: &disposeBag)
} }

View File

@ -12,7 +12,7 @@ import UIKit
final class NotificationStatusTableViewCell: UITableViewCell { final class NotificationStatusTableViewCell: UITableViewCell {
static let actionImageBorderWidth: CGFloat = 2 static let actionImageBorderWidth: CGFloat = 2
static let statusPadding: UIEdgeInsets = UIEdgeInsets(top: 50, left: 73, bottom: 24, right: 24) static let statusPadding = UIEdgeInsets(top: 50, left: 73, bottom: 24, right: 24)
var disposeBag = Set<AnyCancellable>() var disposeBag = Set<AnyCancellable>()
var pollCountdownSubscription: AnyCancellable? var pollCountdownSubscription: AnyCancellable?
var delegate: NotificationTableViewCellDelegate? var delegate: NotificationTableViewCellDelegate?

View File

@ -6,16 +6,16 @@
// //
import Combine import Combine
import CoreDataStack
import Foundation import Foundation
import UIKit import UIKit
import CoreDataStack
protocol NotificationTableViewCellDelegate: class { protocol NotificationTableViewCellDelegate: AnyObject {
var context: AppContext! { get } var context: AppContext! { get }
func parent() -> UIViewController func parent() -> UIViewController
func userAvatarDidPressed(notification:MastodonNotification) func userAvatarDidPressed(notification: MastodonNotification)
} }
final class NotificationTableViewCell: UITableViewCell { final class NotificationTableViewCell: UITableViewCell {
@ -113,7 +113,6 @@ extension NotificationTableViewCell {
]) ])
} }
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection) super.traitCollectionDidChange(previousTraitCollection)
actionImageBackground.layer.borderColor = Asset.Colors.Background.pure.color.cgColor actionImageBackground.layer.borderColor = Asset.Colors.Background.pure.color.cgColor

View File

@ -5,10 +5,10 @@
// Created by sxiaojian on 2021/4/13. // Created by sxiaojian on 2021/4/13.
// //
import Foundation
import Combine import Combine
import CoreData import CoreData
import CoreDataStack import CoreDataStack
import Foundation
import MastodonSDK import MastodonSDK
import OSLog import OSLog
@ -16,8 +16,8 @@ extension APIService {
func allNotifications( func allNotifications(
domain: String, domain: String,
query: Mastodon.API.Notifications.Query, query: Mastodon.API.Notifications.Query,
mastodonAuthenticationBox: AuthenticationService.MastodonAuthenticationBox mastodonAuthenticationBox: AuthenticationService.MastodonAuthenticationBox) -> AnyPublisher<Mastodon.Response.Content<[Mastodon.Entity.Notification]>, Error>
) -> AnyPublisher<Mastodon.Response.Content<[Mastodon.Entity.Notification]>, Error> { {
let authorization = mastodonAuthenticationBox.userAuthorization let authorization = mastodonAuthenticationBox.userAuthorization
return Mastodon.API.Notifications.getNotifications( return Mastodon.API.Notifications.getNotifications(
session: session, session: session,
@ -28,10 +28,10 @@ extension APIService {
let log = OSLog.api let log = OSLog.api
return self.backgroundManagedObjectContext.performChanges { return self.backgroundManagedObjectContext.performChanges {
response.value.forEach { notification in response.value.forEach { notification in
let (mastodonUser,_) = APIService.CoreData.createOrMergeMastodonUser(into: self.backgroundManagedObjectContext, for: nil, in: domain, entity: notification.account, userCache: nil, networkDate: Date(), log: log) let (mastodonUser, _) = APIService.CoreData.createOrMergeMastodonUser(into: self.backgroundManagedObjectContext, for: nil, in: domain, entity: notification.account, userCache: nil, networkDate: Date(), log: log)
var status: Status? var status: Status?
if let statusEntity = notification.status { if let statusEntity = notification.status {
let (statusInCoreData,_,_) = APIService.CoreData.createOrMergeStatus( let (statusInCoreData, _, _) = APIService.CoreData.createOrMergeStatus(
into: self.backgroundManagedObjectContext, into: self.backgroundManagedObjectContext,
for: nil, for: nil,
domain: domain, domain: domain,
@ -45,7 +45,6 @@ extension APIService {
// use constrain to avoid repeated save // use constrain to avoid repeated save
let notification = MastodonNotification.insert(into: self.backgroundManagedObjectContext, domain: domain, property: MastodonNotification.Property(id: notification.id, type: notification.type.rawValue, account: mastodonUser, status: status, createdAt: notification.createdAt)) let notification = MastodonNotification.insert(into: self.backgroundManagedObjectContext, domain: domain, property: MastodonNotification.Property(id: notification.id, type: notification.type.rawValue, account: mastodonUser, status: status, createdAt: notification.createdAt))
os_log(.info, log: log, "%{public}s[%{public}ld], %{public}s: fetch mastodon user [%s](%s)", (#file as NSString).lastPathComponent, #line, #function, notification.type, notification.account.username) os_log(.info, log: log, "%{public}s[%{public}ld], %{public}s: fetch mastodon user [%s](%s)", (#file as NSString).lastPathComponent, #line, #function, notification.type, notification.account.username)
} }
} }
.setFailureType(to: Error.self) .setFailureType(to: Error.self)