forked from shadowfacts/Tusker
118 lines
4.4 KiB
Swift
118 lines
4.4 KiB
Swift
//
|
|
// ReblogService.swift
|
|
// Tusker
|
|
//
|
|
// Created by Shadowfacts on 10/8/22.
|
|
// Copyright © 2022 Shadowfacts. All rights reserved.
|
|
//
|
|
|
|
import UIKit
|
|
import Pachyderm
|
|
|
|
@MainActor
|
|
class ReblogService {
|
|
|
|
private let mastodonController: MastodonController
|
|
private let presenter: any TuskerNavigationDelegate
|
|
private let status: StatusMO
|
|
|
|
var hapticFeedback = true
|
|
var requireConfirmation = Preferences.shared.confirmBeforeReblog
|
|
|
|
init(status: StatusMO, mastodonController: MastodonController, presenter: any TuskerNavigationDelegate) {
|
|
self.status = status
|
|
self.mastodonController = mastodonController
|
|
self.presenter = presenter
|
|
}
|
|
|
|
func toggleReblog() async {
|
|
if !status.reblogged,
|
|
requireConfirmation {
|
|
presentConfirmationAlert()
|
|
} else {
|
|
await doToggleReblog(visibility: nil)
|
|
}
|
|
}
|
|
|
|
private func presentConfirmationAlert() {
|
|
let image: UIImage?
|
|
let reblogVisibilityActions: [CustomAlertController.MenuAction]
|
|
let maximumVisibility = status.visibility
|
|
if mastodonController.instanceFeatures.reblogVisibility {
|
|
image = UIImage(systemName: maximumVisibility.unfilledImageName)
|
|
reblogVisibilityActions = [Visibility.unlisted, .private].compactMap { visibility in
|
|
guard visibility < maximumVisibility else {
|
|
return nil
|
|
}
|
|
return CustomAlertController.MenuAction(title: "Reblog as \(visibility.displayName)", subtitle: visibility.subtitle, image: UIImage(systemName: visibility.unfilledImageName)) {
|
|
// deliberately retain a strong reference to self
|
|
Task {
|
|
await self.doToggleReblog(visibility: visibility)
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
image = nil
|
|
reblogVisibilityActions = []
|
|
}
|
|
|
|
let preview = ConfirmReblogStatusPreviewView(status: status)
|
|
var config = CustomAlertController.Configuration(title: "Are you sure you want to reblog this post?", content: preview, actions: [
|
|
CustomAlertController.Action(title: "Cancel", style: .cancel, handler: nil),
|
|
CustomAlertController.Action(title: "Reblog", image: image, style: .default, handler: {
|
|
// deliberately retain a strong reference to self
|
|
Task {
|
|
await self.doToggleReblog(visibility: nil)
|
|
}
|
|
})
|
|
])
|
|
if !reblogVisibilityActions.isEmpty {
|
|
var menuAction = CustomAlertController.Action(title: nil, image: UIImage(systemName: "chevron.down"), style: .menu(reblogVisibilityActions), handler: nil)
|
|
menuAction.isSecondaryMenu = true
|
|
config.actions.append(menuAction)
|
|
}
|
|
let alert = CustomAlertController(config: config)
|
|
presenter.present(alert, animated: true)
|
|
}
|
|
|
|
private func doToggleReblog(visibility: Visibility?) async {
|
|
let oldValue = status.reblogged
|
|
status.reblogged.toggle()
|
|
mastodonController.persistentContainer.statusSubject.send(status.id)
|
|
|
|
#if !os(visionOS)
|
|
if hapticFeedback {
|
|
UIImpactFeedbackGenerator(style: .light).impactOccurred()
|
|
}
|
|
#endif
|
|
|
|
let request: Request<Status>
|
|
if status.reblogged {
|
|
request = Status.reblog(status.id, visibility: visibility)
|
|
} else {
|
|
request = Status.unreblog(status.id)
|
|
}
|
|
do {
|
|
let (newStatus, _) = try await mastodonController.run(request)
|
|
mastodonController.persistentContainer.addOrUpdate(status: newStatus)
|
|
} catch {
|
|
status.favourited = oldValue
|
|
mastodonController.persistentContainer.statusSubject.send(status.id)
|
|
|
|
let title = oldValue ? "Error Unreblogging" : "Error Reblogging"
|
|
let config = ToastConfiguration(from: error, with: title, in: presenter) { toast in
|
|
toast.dismissToast(animated: true)
|
|
await self.toggleReblog()
|
|
}
|
|
presenter.showToast(configuration: config, animated: true)
|
|
|
|
#if !os(visionOS)
|
|
if hapticFeedback {
|
|
UINotificationFeedbackGenerator().notificationOccurred(.error)
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
}
|