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.
//
import Foundation
import CoreData
import Foundation
enum NotificationItem {
case notification(objectID: NSManagedObjectID)
case bottomLoader
@ -20,7 +19,7 @@ extension NotificationItem: Equatable {
switch (lhs, rhs) {
case (.bottomLoader, .bottomLoader):
return true
case (.notification(let idLeft),.notification(let idRight)):
case (.notification(let idLeft), .notification(let idRight)):
return idLeft == idRight
default:
return false

View File

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

View File

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

View File

@ -5,16 +5,15 @@
// Created by sxiaojian on 2021/4/12.
//
import UIKit
import Combine
import OSLog
import CoreData
import CoreDataStack
import MastodonSDK
import GameplayKit
import MastodonSDK
import OSLog
import UIKit
final class NotificationViewController: UIViewController, NeedsDependency {
weak var context: AppContext! { 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)
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
return control
}()
@ -41,11 +40,9 @@ final class NotificationViewController: UIViewController, NeedsDependency {
}()
let refreshControl = UIRefreshControl()
}
extension NotificationViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = Asset.Colors.Background.pure.color
@ -80,7 +77,6 @@ extension NotificationViewController {
}
}
.store(in: &disposeBag)
}
override func viewWillAppear(_ animated: Bool) {
@ -110,12 +106,11 @@ extension NotificationViewController {
self.tableView.reloadData()
}
}
}
extension NotificationViewController {
@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 {
return
}
@ -136,8 +131,8 @@ extension NotificationViewController {
}
// MARK: - UITableViewDelegate
extension NotificationViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
guard let diffableDataSource = viewModel.diffableDataSource else { return }
guard let item = diffableDataSource.itemIdentifier(for: indexPath) else { return }
@ -145,9 +140,9 @@ extension NotificationViewController: UITableViewDelegate {
case .notification(let objectID):
let notification = context.managedObjectContext.object(with: objectID) as! MastodonNotification
if notification.status != nil {
// TODO goto status detail vc
// TODO: goto status detail vc
} else {
let viewModel = ProfileViewModel(context: self.context, optionalMastodonUser: notification.account)
let viewModel = ProfileViewModel(context: context, optionalMastodonUser: notification.account)
DispatchQueue.main.async {
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 }
switch item {
case .bottomLoader:
if !tableView.isDragging && !tableView.isDecelerating {
if !tableView.isDragging, !tableView.isDecelerating {
viewModel.loadoldestStateMachine.enter(NotificationViewModel.LoadOldestState.Loading.self)
}
default:
break
}
}
}
// MARK: - ContentOffsetAdjustableTimelineViewControllerDelegate
extension NotificationViewController: ContentOffsetAdjustableTimelineViewControllerDelegate {
func navigationBar() -> UINavigationBar? {
return navigationController?.navigationBar
navigationController?.navigationBar
}
}
extension NotificationViewController: NotificationTableViewCellDelegate {
func userAvatarDidPressed(notification: MastodonNotification) {
let viewModel = ProfileViewModel(context: self.context, optionalMastodonUser: notification.account)
let viewModel = ProfileViewModel(context: context, optionalMastodonUser: notification.account)
DispatchQueue.main.async {
self.coordinator.present(scene: .profile(viewModel: viewModel), from: self, transition: .show)
}
@ -190,11 +185,10 @@ extension NotificationViewController: NotificationTableViewCellDelegate {
func parent() -> UIViewController {
self
}
}
// MARK: - UIScrollViewDelegate
extension NotificationViewController {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
handleScrollViewDidScroll(scrollView)
@ -204,6 +198,6 @@ extension NotificationViewController {
extension NotificationViewController: LoadMoreConfigurableTableViewContainer {
typealias BottomLoaderTableViewCell = CommonBottomLoader
typealias LoadingState = NotificationViewModel.LoadOldestState.Loading
var loadMoreConfigurableTableView: UITableView { return tableView }
var loadMoreConfigurableStateMachine: GKStateMachine { return viewModel.loadoldestStateMachine }
var loadMoreConfigurableTableView: UITableView { tableView }
var loadMoreConfigurableStateMachine: GKStateMachine { viewModel.loadoldestStateMachine }
}

View File

@ -5,13 +5,13 @@
// Created by sxiaojian on 2021/4/13.
//
import os.log
import func QuartzCore.CACurrentMediaTime
import Foundation
import CoreData
import CoreDataStack
import Foundation
import GameplayKit
import MastodonSDK
import os.log
import func QuartzCore.CACurrentMediaTime
extension NotificationViewModel {
class LoadLatestState: GKState {
@ -22,7 +22,7 @@ extension NotificationViewModel {
}
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)
}
}
@ -31,13 +31,13 @@ extension NotificationViewModel {
extension NotificationViewModel.LoadLatestState {
class Initial: NotificationViewModel.LoadLatestState {
override func isValidNextState(_ stateClass: AnyClass) -> Bool {
return stateClass == Loading.self
stateClass == Loading.self
}
}
class Loading: NotificationViewModel.LoadLatestState {
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?) {
@ -63,7 +63,7 @@ extension NotificationViewModel.LoadLatestState {
switch completion {
case .failure(let error):
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:
// handle isFetchingLatestTimeline in fetch controller delegate
break
@ -76,21 +76,18 @@ extension NotificationViewModel.LoadLatestState {
}
}
.store(in: &viewModel.disposeBag)
}
}
class Fail: NotificationViewModel.LoadLatestState {
override func isValidNextState(_ stateClass: AnyClass) -> Bool {
return stateClass == Loading.self || stateClass == Idle.self
stateClass == Loading.self || stateClass == Idle.self
}
}
class Idle: NotificationViewModel.LoadLatestState {
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.
//
import os.log
import CoreDataStack
import Foundation
import GameplayKit
import MastodonSDK
import CoreDataStack
import os.log
extension NotificationViewModel {
class LoadOldestState: GKState {
@ -20,7 +20,7 @@ extension NotificationViewModel {
}
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)
}
}
@ -37,7 +37,7 @@ extension NotificationViewModel.LoadOldestState {
class Loading: NotificationViewModel.LoadOldestState {
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?) {
@ -80,7 +80,7 @@ extension NotificationViewModel.LoadOldestState {
.sink { completion in
switch completion {
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:
// handle isFetchingLatestTimeline in fetch controller delegate
break
@ -111,20 +111,20 @@ extension NotificationViewModel.LoadOldestState {
class Fail: NotificationViewModel.LoadOldestState {
override func isValidNextState(_ stateClass: AnyClass) -> Bool {
return stateClass == Loading.self || stateClass == Idle.self
stateClass == Loading.self || stateClass == Idle.self
}
}
class Idle: NotificationViewModel.LoadOldestState {
override func isValidNextState(_ stateClass: AnyClass) -> Bool {
return stateClass == Loading.self
stateClass == Loading.self
}
}
class NoMore: NotificationViewModel.LoadOldestState {
override func isValidNextState(_ stateClass: AnyClass) -> Bool {
// reset state if needs
return stateClass == Idle.self
stateClass == Idle.self
}
override func didEnter(from previousState: GKState?) {

View File

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

View File

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

View File

@ -12,7 +12,7 @@ import UIKit
final class NotificationStatusTableViewCell: UITableViewCell {
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 pollCountdownSubscription: AnyCancellable?
var delegate: NotificationTableViewCellDelegate?

View File

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

View File

@ -5,10 +5,10 @@
// Created by sxiaojian on 2021/4/13.
//
import Foundation
import Combine
import CoreData
import CoreDataStack
import Foundation
import MastodonSDK
import OSLog
@ -16,8 +16,8 @@ extension APIService {
func allNotifications(
domain: String,
query: Mastodon.API.Notifications.Query,
mastodonAuthenticationBox: AuthenticationService.MastodonAuthenticationBox
) -> AnyPublisher<Mastodon.Response.Content<[Mastodon.Entity.Notification]>, Error> {
mastodonAuthenticationBox: AuthenticationService.MastodonAuthenticationBox) -> AnyPublisher<Mastodon.Response.Content<[Mastodon.Entity.Notification]>, Error>
{
let authorization = mastodonAuthenticationBox.userAuthorization
return Mastodon.API.Notifications.getNotifications(
session: session,
@ -28,10 +28,10 @@ extension APIService {
let log = OSLog.api
return self.backgroundManagedObjectContext.performChanges {
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?
if let statusEntity = notification.status {
let (statusInCoreData,_,_) = APIService.CoreData.createOrMergeStatus(
let (statusInCoreData, _, _) = APIService.CoreData.createOrMergeStatus(
into: self.backgroundManagedObjectContext,
for: nil,
domain: domain,
@ -45,7 +45,6 @@ extension APIService {
// 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))
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)