// // 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() let fetchedResultsController: FollowedTagsFetchedResultController private weak var tableView: UITableView? var diffableDataSource: UITableViewDiffableDataSource? // input let context: AppContext let authContext: AuthContext // output let presentHashtagTimeline = PassthroughSubject() 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() 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) } }