2021-09-13 13:14:26 +02:00
|
|
|
//
|
|
|
|
// AccountListViewModel.swift
|
|
|
|
// Mastodon
|
|
|
|
//
|
|
|
|
// Created by Cirno MainasuK on 2021-9-13.
|
|
|
|
//
|
|
|
|
|
|
|
|
import UIKit
|
|
|
|
import Combine
|
|
|
|
import CoreData
|
|
|
|
import CoreDataStack
|
2021-09-15 14:18:19 +02:00
|
|
|
import MastodonSDK
|
2021-09-14 12:21:15 +02:00
|
|
|
import MastodonMeta
|
2022-09-30 13:28:09 +02:00
|
|
|
import MastodonCore
|
|
|
|
import MastodonUI
|
2021-09-13 13:14:26 +02:00
|
|
|
|
2022-10-09 14:07:57 +02:00
|
|
|
final class AccountListViewModel: NSObject {
|
2021-09-13 13:14:26 +02:00
|
|
|
|
|
|
|
var disposeBag = Set<AnyCancellable>()
|
|
|
|
|
|
|
|
// input
|
|
|
|
let context: AppContext
|
2022-10-09 14:07:57 +02:00
|
|
|
let authContext: AuthContext
|
2021-09-13 13:14:26 +02:00
|
|
|
|
|
|
|
// output
|
2022-10-09 14:07:57 +02:00
|
|
|
@Published var items: [Item] = []
|
|
|
|
|
2021-09-16 06:23:47 +02:00
|
|
|
let dataSourceDidUpdate = PassthroughSubject<Void, Never>()
|
2021-09-13 13:14:26 +02:00
|
|
|
var diffableDataSource: UITableViewDiffableDataSource<Section, Item>!
|
|
|
|
|
2022-10-09 14:07:57 +02:00
|
|
|
init(context: AppContext, authContext: AuthContext) {
|
2021-09-13 13:14:26 +02:00
|
|
|
self.context = context
|
2022-10-09 14:07:57 +02:00
|
|
|
self.authContext = authContext
|
2023-05-25 16:26:17 +02:00
|
|
|
|
2022-10-09 14:07:57 +02:00
|
|
|
super.init()
|
|
|
|
// end init
|
2021-09-13 13:14:26 +02:00
|
|
|
|
2023-05-25 16:26:17 +02:00
|
|
|
AuthenticationServiceProvider.shared.$authentications
|
2021-09-13 13:14:26 +02:00
|
|
|
.receive(on: DispatchQueue.main)
|
|
|
|
.sink { [weak self] authentications in
|
|
|
|
guard let self = self else { return }
|
|
|
|
guard let diffableDataSource = self.diffableDataSource else { return }
|
|
|
|
|
|
|
|
var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
|
|
|
|
snapshot.appendSections([.main])
|
2022-10-09 14:07:57 +02:00
|
|
|
let authenticationItems: [Item] = authentications.map {
|
|
|
|
Item.authentication(record: $0)
|
|
|
|
}
|
|
|
|
snapshot.appendItems(authenticationItems, toSection: .main)
|
2021-09-14 12:21:15 +02:00
|
|
|
snapshot.appendItems([.addAccount], toSection: .main)
|
2021-09-13 13:14:26 +02:00
|
|
|
|
2021-09-16 06:23:47 +02:00
|
|
|
diffableDataSource.apply(snapshot) {
|
|
|
|
self.dataSourceDidUpdate.send()
|
|
|
|
}
|
2021-09-13 13:14:26 +02:00
|
|
|
}
|
|
|
|
.store(in: &disposeBag)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
extension AccountListViewModel {
|
|
|
|
enum Section: Hashable {
|
|
|
|
case main
|
|
|
|
}
|
|
|
|
|
|
|
|
enum Item: Hashable {
|
2023-05-25 16:26:17 +02:00
|
|
|
case authentication(record: MastodonAuthentication)
|
2021-09-14 12:21:15 +02:00
|
|
|
case addAccount
|
2021-09-13 13:14:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func setupDiffableDataSource(
|
|
|
|
tableView: UITableView,
|
|
|
|
managedObjectContext: NSManagedObjectContext
|
|
|
|
) {
|
|
|
|
diffableDataSource = UITableViewDiffableDataSource(tableView: tableView) { tableView, indexPath, item in
|
|
|
|
switch item {
|
2022-10-09 14:07:57 +02:00
|
|
|
case .authentication(let record):
|
2021-09-13 13:14:26 +02:00
|
|
|
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: AccountListTableViewCell.self), for: indexPath) as! AccountListTableViewCell
|
2023-06-02 11:12:30 +02:00
|
|
|
if let activeAuthentication = AuthenticationServiceProvider.shared.authenticationSortedByActivation().first
|
2022-10-09 14:07:57 +02:00
|
|
|
{
|
|
|
|
AccountListViewModel.configure(
|
2023-05-25 16:26:17 +02:00
|
|
|
in: managedObjectContext,
|
2022-10-09 14:07:57 +02:00
|
|
|
cell: cell,
|
2023-05-25 16:26:17 +02:00
|
|
|
authentication: record,
|
2022-10-09 14:07:57 +02:00
|
|
|
activeAuthentication: activeAuthentication
|
|
|
|
)
|
|
|
|
}
|
2021-09-14 12:21:15 +02:00
|
|
|
return cell
|
|
|
|
case .addAccount:
|
|
|
|
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: AddAccountTableViewCell.self), for: indexPath) as! AddAccountTableViewCell
|
2021-09-13 13:14:26 +02:00
|
|
|
return cell
|
|
|
|
}
|
|
|
|
}
|
2021-09-14 12:21:15 +02:00
|
|
|
|
|
|
|
var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
|
|
|
|
snapshot.appendSections([.main])
|
|
|
|
diffableDataSource?.apply(snapshot)
|
2021-09-13 13:14:26 +02:00
|
|
|
}
|
|
|
|
|
2021-09-14 12:21:15 +02:00
|
|
|
static func configure(
|
2023-05-25 16:26:17 +02:00
|
|
|
in context: NSManagedObjectContext,
|
2021-09-14 12:21:15 +02:00
|
|
|
cell: AccountListTableViewCell,
|
2021-09-16 10:30:21 +02:00
|
|
|
authentication: MastodonAuthentication,
|
2022-10-09 14:07:57 +02:00
|
|
|
activeAuthentication: MastodonAuthentication
|
2021-09-14 12:21:15 +02:00
|
|
|
) {
|
2024-01-05 12:56:08 +01:00
|
|
|
guard let account = authentication.account() else { return }
|
|
|
|
|
2021-09-14 12:21:15 +02:00
|
|
|
// avatar
|
2022-01-27 14:23:39 +01:00
|
|
|
cell.avatarButton.avatarImageView.configure(
|
2024-01-05 12:56:08 +01:00
|
|
|
configuration: .init(url: account.avatarImageURL())
|
2022-01-27 14:23:39 +01:00
|
|
|
)
|
2021-09-14 12:21:15 +02:00
|
|
|
|
|
|
|
// name
|
|
|
|
do {
|
2024-01-05 12:56:08 +01:00
|
|
|
let content = MastodonContent(content: account.displayNameWithFallback, emojis: account.emojis.asDictionary)
|
2021-09-14 12:21:15 +02:00
|
|
|
let metaContent = try MastodonMetaContent.convert(document: content)
|
|
|
|
cell.nameLabel.configure(content: metaContent)
|
|
|
|
} catch {
|
|
|
|
assertionFailure()
|
2024-01-05 12:56:08 +01:00
|
|
|
cell.nameLabel.configure(content: PlaintextMetaContent(string: account.displayNameWithFallback))
|
2021-09-14 12:21:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// username
|
2024-01-05 12:56:08 +01:00
|
|
|
let usernameMetaContent = PlaintextMetaContent(string: "@" + account.acctWithDomain)
|
2021-09-15 14:18:19 +02:00
|
|
|
cell.usernameLabel.configure(content: usernameMetaContent)
|
|
|
|
|
2021-09-16 10:30:21 +02:00
|
|
|
// badge
|
|
|
|
let accessToken = authentication.userAccessToken
|
|
|
|
let count = UserDefaults.shared.getNotificationCountWithAccessToken(accessToken: accessToken)
|
|
|
|
cell.badgeButton.setBadge(number: count)
|
|
|
|
|
2021-09-15 14:18:19 +02:00
|
|
|
// checkmark
|
2022-10-09 14:07:57 +02:00
|
|
|
let isActive = activeAuthentication.userID == authentication.userID
|
|
|
|
cell.tintColor = .label
|
|
|
|
cell.checkmarkImageView.isHidden = !isActive
|
|
|
|
if isActive {
|
|
|
|
cell.accessibilityTraits.insert(.selected)
|
|
|
|
} else {
|
|
|
|
cell.accessibilityTraits.remove(.selected)
|
|
|
|
}
|
2021-09-16 10:30:21 +02:00
|
|
|
|
|
|
|
cell.accessibilityLabel = [
|
|
|
|
cell.nameLabel.text,
|
|
|
|
cell.usernameLabel.text,
|
|
|
|
cell.badgeButton.accessibilityLabel
|
|
|
|
]
|
|
|
|
.compactMap { $0 }
|
2022-11-07 02:15:09 +01:00
|
|
|
.joined(separator: ", ")
|
2021-09-14 12:21:15 +02:00
|
|
|
}
|
|
|
|
}
|