mastodon-ios/Mastodon/Scene/Profile/FollowedTags/FollowedTagsViewModel.swift

108 lines
3.4 KiB
Swift

//
// FollowedTagsViewModel.swift
// Mastodon
//
// Created by Marcus Kida on 23.11.22.
//
import os
import UIKit
import Combine
import CoreData
import CoreDataStack
import MastodonSDK
import MastodonCore
final class FollowedTagsViewModel: NSObject {
var disposeBag = Set<AnyCancellable>()
let fetchedResultsController: FollowedTagsFetchedResultController
private weak var tableView: UITableView?
var diffableDataSource: UITableViewDiffableDataSource<Section, Item>?
// input
let context: AppContext
let authContext: AuthContext
// output
let presentHashtagTimeline = PassthroughSubject<HashtagTimelineViewModel, Never>()
init(context: AppContext, authContext: AuthContext) {
self.context = context
self.authContext = authContext
self.fetchedResultsController = FollowedTagsFetchedResultController(
managedObjectContext: context.managedObjectContext,
domain: authContext.mastodonAuthenticationBox.domain,
user: authContext.mastodonAuthenticationBox.authenticationRecord.object(in: context.managedObjectContext)!.user
)
super.init()
self.fetchedResultsController
.$records
.receive(on: DispatchQueue.main)
.sink { [weak self] records in
guard let self = self else { return }
var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
snapshot.appendSections([.main])
snapshot.appendItems(records.map {.hashtag($0) })
self.diffableDataSource?.apply(snapshot, animatingDifferences: true)
}
.store(in: &disposeBag)
}
}
extension FollowedTagsViewModel {
func setupTableView(_ tableView: UITableView) {
self.tableView = tableView
setupDiffableDataSource(tableView: tableView)
tableView.delegate = self
fetchFollowedTags()
}
func fetchFollowedTags() {
Task { @MainActor in
try await context.apiService.getFollowedTags(
domain: authContext.mastodonAuthenticationBox.domain,
query: Mastodon.API.Account.FollowedTagsQuery(limit: nil),
authenticationBox: authContext.mastodonAuthenticationBox
)
}
}
func followOrUnfollow(_ tag: Tag) {
Task { @MainActor in
switch tag.following {
case true:
_ = try? await context.apiService.unfollowTag(
for: tag.name,
authenticationBox: authContext.mastodonAuthenticationBox
)
case false:
_ = try? await context.apiService.followTag(
for: tag.name,
authenticationBox: authContext.mastodonAuthenticationBox
)
}
fetchFollowedTags()
}
}
}
extension FollowedTagsViewModel: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
let object = fetchedResultsController.records[indexPath.row]
let hashtagTimelineViewModel = HashtagTimelineViewModel(
context: self.context,
authContext: self.authContext,
hashtag: object.name
)
presentHashtagTimeline.send(hashtagTimelineViewModel)
}
}