Add unfollow hashtag action to Explore screen

Closes #417
This commit is contained in:
Shadowfacts 2023-07-04 09:56:35 -07:00
parent 54034ff727
commit 8f8e2a2aea
2 changed files with 39 additions and 26 deletions

View File

@ -22,7 +22,9 @@ class ToggleFollowHashtagService {
self.presenter = presenter self.presenter = presenter
} }
func toggleFollow() async { @discardableResult
func toggleFollow() async -> Bool {
let success: Bool
let context = mastodonController.persistentContainer.viewContext let context = mastodonController.persistentContainer.viewContext
var config: ToastConfiguration var config: ToastConfiguration
if let existing = mastodonController.followedHashtags.first(where: { $0.name == hashtagName }) { if let existing = mastodonController.followedHashtags.first(where: { $0.name == hashtagName }) {
@ -36,11 +38,14 @@ class ToggleFollowHashtagService {
config = ToastConfiguration(title: "Unfollowed Hashtag") config = ToastConfiguration(title: "Unfollowed Hashtag")
config.systemImageName = "checkmark" config.systemImageName = "checkmark"
config.dismissAutomaticallyAfter = 2 config.dismissAutomaticallyAfter = 2
success = true
} catch { } catch {
config = ToastConfiguration(from: error, with: "Error Unfollowing Hashtag", in: presenter) { toast in config = ToastConfiguration(from: error, with: "Error Unfollowing Hashtag", in: presenter) { toast in
toast.dismissToast(animated: true) toast.dismissToast(animated: true)
await self.toggleFollow() await self.toggleFollow()
} }
success = false
} }
} else { } else {
do { do {
@ -53,15 +58,19 @@ class ToggleFollowHashtagService {
config = ToastConfiguration(title: "Followed Hashtag") config = ToastConfiguration(title: "Followed Hashtag")
config.systemImageName = "checkmark" config.systemImageName = "checkmark"
config.dismissAutomaticallyAfter = 2 config.dismissAutomaticallyAfter = 2
success = true
} catch { } catch {
config = ToastConfiguration(from: error, with: "Error Following Hashtag", in: presenter) { toast in config = ToastConfiguration(from: error, with: "Error Following Hashtag", in: presenter) { toast in
toast.dismissToast(animated: true) toast.dismissToast(animated: true)
await self.toggleFollow() await self.toggleFollow()
} }
success = false
} }
} }
presenter.showToast(configuration: config, animated: true) presenter.showToast(configuration: config, animated: true)
mastodonController.persistentContainer.save(context: context) mastodonController.persistentContainer.save(context: context)
return success
} }
} }

View File

@ -288,15 +288,6 @@ class ExploreViewController: UIViewController, UICollectionViewDelegate, Collect
} }
} }
func removeSavedHashtag(_ hashtag: Hashtag) {
let context = mastodonController.persistentContainer.viewContext
let req = SavedHashtag.fetchRequest(name: hashtag.name, account: mastodonController.accountInfo!)
if let hashtag = try? context.fetch(req).first {
context.delete(hashtag)
try! context.save()
}
}
func removeSavedInstance(_ instanceURL: URL) { func removeSavedInstance(_ instanceURL: URL) {
let context = mastodonController.persistentContainer.viewContext let context = mastodonController.persistentContainer.viewContext
let req = SavedInstance.fetchRequest(url: instanceURL, account: mastodonController.accountInfo!) let req = SavedInstance.fetchRequest(url: instanceURL, account: mastodonController.accountInfo!)
@ -307,36 +298,45 @@ class ExploreViewController: UIViewController, UICollectionViewDelegate, Collect
} }
private func trailingSwipeActionsForCell(at indexPath: IndexPath) -> UISwipeActionsConfiguration? { private func trailingSwipeActionsForCell(at indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let title: String var actions = [UIContextualAction]()
let handler: UIContextualAction.Handler
switch dataSource.itemIdentifier(for: indexPath) { switch dataSource.itemIdentifier(for: indexPath) {
case let .list(list): case let .list(list):
title = NSLocalizedString("Delete", comment: "delete swipe action title") actions.append(UIContextualAction(style: .destructive, title: "Delete", handler: { _, _, completion in
handler = { (_, _, completion) in
self.deleteList(list, completion: completion) self.deleteList(list, completion: completion)
} }))
case let .savedHashtag(hashtag): case let .savedHashtag(hashtag):
title = NSLocalizedString("Unsave", comment: "unsave swipe action title") let name = hashtag.name.lowercased()
handler = { (_, _, completion) in let context = mastodonController.persistentContainer.viewContext
self.removeSavedHashtag(hashtag) let existing = try? context.fetch(SavedHashtag.fetchRequest(name: name, account: mastodonController.accountInfo!)).first
completion(true) if let existing {
actions.append(UIContextualAction(style: .destructive, title: "Unsave", handler: { _, _, completion in
context.delete(existing)
try! context.save()
}))
}
if mastodonController.instanceFeatures.canFollowHashtags,
mastodonController.followedHashtags.contains(where: { $0.name.lowercased() == name }) {
actions.append(UIContextualAction(style: .destructive, title: "Unfollow", handler: { _, _, completion in
Task {
let success =
await ToggleFollowHashtagService(hashtagName: hashtag.name, presenter: self)
.toggleFollow()
completion(success)
}
}))
} }
case let .savedInstance(url): case let .savedInstance(url):
title = NSLocalizedString("Unsave", comment: "unsave swipe action title") actions.append(UIContextualAction(style: .destructive, title: "Unsave", handler: { _, _, completion in
handler = { (_, _, completion) in
self.removeSavedInstance(url) self.removeSavedInstance(url)
completion(true) completion(true)
} }))
default: default:
return nil return nil
} }
return UISwipeActionsConfiguration(actions: actions)
return UISwipeActionsConfiguration(actions: [
UIContextualAction(style: .destructive, title: title, handler: handler)
])
} }
// MARK: - Collection View Delegate // MARK: - Collection View Delegate
@ -581,3 +581,7 @@ extension ExploreViewController: UICollectionViewDragDelegate {
return [UIDragItem(itemProvider: provider)] return [UIDragItem(itemProvider: provider)]
} }
} }
extension ExploreViewController: TuskerNavigationDelegate {
var apiController: MastodonController! { mastodonController }
}