forked from shadowfacts/Tusker
176 lines
6.7 KiB
Swift
176 lines
6.7 KiB
Swift
//
|
|
// StatusSwipeAction.swift
|
|
// Tusker
|
|
//
|
|
// Created by Shadowfacts on 11/26/22.
|
|
// Copyright © 2022 Shadowfacts. All rights reserved.
|
|
//
|
|
|
|
import UIKit
|
|
import Pachyderm
|
|
|
|
enum StatusSwipeAction: String, Codable, Hashable, CaseIterable {
|
|
case reply
|
|
case favorite
|
|
case reblog
|
|
case share
|
|
case bookmark
|
|
case openInSafari
|
|
|
|
var displayName: String {
|
|
switch self {
|
|
case .reply:
|
|
return "Reply"
|
|
case .favorite:
|
|
return "Favorite"
|
|
case .reblog:
|
|
return "Reblog"
|
|
case .share:
|
|
return "Share"
|
|
case .bookmark:
|
|
return "Bookmark"
|
|
case .openInSafari:
|
|
return "Open in Safari"
|
|
}
|
|
}
|
|
|
|
var systemImageName: String {
|
|
switch self {
|
|
case .reply:
|
|
return "arrowshape.turn.up.left.fill"
|
|
case .favorite:
|
|
return "star.fill"
|
|
case .reblog:
|
|
return "repeat"
|
|
case .share:
|
|
return "square.and.arrow.up"
|
|
case .bookmark:
|
|
return "bookmark.fill"
|
|
case .openInSafari:
|
|
return "safari"
|
|
}
|
|
}
|
|
|
|
func createAction(status: StatusMO, container: StatusSwipeActionContainer) -> UIContextualAction? {
|
|
switch self {
|
|
case .reply:
|
|
return createReplyAction(status: status, container: container)
|
|
case .favorite:
|
|
return createFavoriteAction(status: status, container: container)
|
|
case .reblog:
|
|
return createReblogAction(status: status, container: container)
|
|
case .share:
|
|
return createShareAction(status: status, container: container)
|
|
case .bookmark:
|
|
return createBookmarkAction(status: status, container: container)
|
|
case .openInSafari:
|
|
return createOpenInSafariAction(status: status, container: container)
|
|
}
|
|
}
|
|
}
|
|
|
|
protocol StatusSwipeActionContainer: UIView {
|
|
var mastodonController: MastodonController! { get }
|
|
var navigationDelegate: any TuskerNavigationDelegate { get }
|
|
var toastableViewController: ToastableViewController? { get }
|
|
|
|
var canReblog: Bool { get }
|
|
|
|
// necessary b/c the reblog-handling logic only exists in the cells
|
|
func performReplyAction()
|
|
}
|
|
|
|
private func createReplyAction(status: StatusMO, container: StatusSwipeActionContainer) -> UIContextualAction? {
|
|
guard container.mastodonController.loggedIn else {
|
|
return nil
|
|
}
|
|
let action = UIContextualAction(style: .normal, title: "Reply") { [unowned container] _, _, completion in
|
|
container.performReplyAction()
|
|
completion(true)
|
|
}
|
|
action.image = UIImage(systemName: "arrowshape.turn.up.left.fill")
|
|
action.backgroundColor = container.tintColor
|
|
return action
|
|
}
|
|
|
|
private func createFavoriteAction(status: StatusMO, container: StatusSwipeActionContainer) -> UIContextualAction? {
|
|
guard container.mastodonController.loggedIn else {
|
|
return nil
|
|
}
|
|
let title = status.favourited ? "Unfavorite" : "Favorite"
|
|
let action = UIContextualAction(style: .normal, title: title) { [unowned container] _, _, completion in
|
|
completion(true)
|
|
Task { @MainActor in
|
|
await FavoriteService(status: status, mastodonController: container.mastodonController, presenter: container.navigationDelegate).toggleFavorite()
|
|
}
|
|
}
|
|
action.image = UIImage(systemName: "star.fill")
|
|
action.backgroundColor = status.favourited ? UIColor(displayP3Red: 235/255, green: 77/255, blue: 62/255, alpha: 1) : UIColor(displayP3Red: 1, green: 204/255, blue: 0, alpha: 1)
|
|
return action
|
|
}
|
|
|
|
private func createReblogAction(status: StatusMO, container: StatusSwipeActionContainer) -> UIContextualAction? {
|
|
guard container.mastodonController.loggedIn,
|
|
container.canReblog else {
|
|
return nil
|
|
}
|
|
let title = status.reblogged ? "Unreblog" : "Reblog"
|
|
let action = UIContextualAction(style: .normal, title: title) { [unowned container] _, _, completion in
|
|
completion(true)
|
|
Task { @MainActor in
|
|
await ReblogService(status: status, mastodonController: container.mastodonController, presenter: container.navigationDelegate).toggleReblog()
|
|
}
|
|
}
|
|
action.image = UIImage(systemName: "repeat")
|
|
action.backgroundColor = status.reblogged ? UIColor(displayP3Red: 235/255, green: 77/255, blue: 62/255, alpha: 1) : container.tintColor
|
|
return action
|
|
}
|
|
|
|
private func createShareAction(status: StatusMO, container: StatusSwipeActionContainer) -> UIContextualAction {
|
|
let action = UIContextualAction(style: .normal, title: "Share") { [unowned container] _, _, completion in
|
|
container.navigationDelegate.showMoreOptions(forStatus: status.id, source: .view(container))
|
|
completion(true)
|
|
}
|
|
// bold to more closesly match other action symbols
|
|
let config = UIImage.SymbolConfiguration(weight: .bold)
|
|
action.image = UIImage(systemName: "square.and.arrow.up")!.applyingSymbolConfiguration(config)!
|
|
action.backgroundColor = .lightGray
|
|
return action
|
|
}
|
|
|
|
private func createBookmarkAction(status: StatusMO, container: StatusSwipeActionContainer) -> UIContextualAction? {
|
|
guard container.mastodonController.loggedIn else {
|
|
return nil
|
|
}
|
|
let bookmarked = status.bookmarked ?? false
|
|
let title = bookmarked ? "Unbookmark" : "Bookmark"
|
|
let action = UIContextualAction(style: .normal, title: title) { [unowned container] _, _, completion in
|
|
completion(true)
|
|
Task { @MainActor in
|
|
let request = (bookmarked ? Status.unbookmark : Status.bookmark)(status.id)
|
|
do {
|
|
let (status, _) = try await container.mastodonController.run(request)
|
|
container.mastodonController.persistentContainer.addOrUpdate(status: status)
|
|
} catch {
|
|
if let toastable = container.toastableViewController {
|
|
let config = ToastConfiguration(from: error, with: "Error \(bookmarked ? "Unb" : "B")ookmarking", in: toastable, retryAction: nil)
|
|
toastable.showToast(configuration: config, animated: true)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
action.image = UIImage(systemName: "bookmark.fill")
|
|
action.backgroundColor = .systemRed
|
|
return action
|
|
}
|
|
|
|
private func createOpenInSafariAction(status: StatusMO, container: StatusSwipeActionContainer) -> UIContextualAction {
|
|
let action = UIContextualAction(style: .normal, title: "Open in Safari") { [unowned container] _, _, completion in
|
|
container.navigationDelegate.selected(url: status.url!, allowUniversalLinks: false)
|
|
completion(true)
|
|
}
|
|
action.image = UIImage(systemName: "safari")
|
|
action.backgroundColor = container.tintColor
|
|
return action
|
|
}
|