forked from shadowfacts/Tusker
Extract favoriting/reblogging to separate services
Allows displaying error popups and retrying
This commit is contained in:
parent
46db70d58b
commit
133921848d
|
@ -38,12 +38,14 @@
|
|||
D61A45EA28DF51EE002BE511 /* TimelineLikeCollectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D61A45E928DF51EE002BE511 /* TimelineLikeCollectionViewController.swift */; };
|
||||
D61ABEF628EE74D400B29151 /* StatusCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D61ABEF528EE74D400B29151 /* StatusCollectionViewCell.swift */; };
|
||||
D61ABEFC28F105DE00B29151 /* Pachyderm in Frameworks */ = {isa = PBXBuildFile; productRef = D61ABEFB28F105DE00B29151 /* Pachyderm */; };
|
||||
D61ABEFE28F1C92600B29151 /* FavoriteService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D61ABEFD28F1C92600B29151 /* FavoriteService.swift */; };
|
||||
D61AC1D5232E9FA600C54D2D /* InstanceSelectorTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D61AC1D4232E9FA600C54D2D /* InstanceSelectorTableViewController.swift */; };
|
||||
D61AC1D8232EA42D00C54D2D /* InstanceTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D61AC1D6232EA42D00C54D2D /* InstanceTableViewCell.swift */; };
|
||||
D61AC1D9232EA42D00C54D2D /* InstanceTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = D61AC1D7232EA42D00C54D2D /* InstanceTableViewCell.xib */; };
|
||||
D620483423D3801D008A63EF /* LinkTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D620483323D3801D008A63EF /* LinkTextView.swift */; };
|
||||
D620483623D38075008A63EF /* ContentTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D620483523D38075008A63EF /* ContentTextView.swift */; };
|
||||
D620483823D38190008A63EF /* StatusContentTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D620483723D38190008A63EF /* StatusContentTextView.swift */; };
|
||||
D621733328F1D5ED004C7DB1 /* ReblogService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D621733228F1D5ED004C7DB1 /* ReblogService.swift */; };
|
||||
D622757424EDF1CD00B82A16 /* ComposeAttachmentsList.swift in Sources */ = {isa = PBXBuildFile; fileRef = D622757324EDF1CD00B82A16 /* ComposeAttachmentsList.swift */; };
|
||||
D622757824EE133700B82A16 /* ComposeAssetPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = D622757724EE133700B82A16 /* ComposeAssetPicker.swift */; };
|
||||
D622757A24EE21D900B82A16 /* ComposeAttachmentRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = D622757924EE21D900B82A16 /* ComposeAttachmentRow.swift */; };
|
||||
|
@ -388,12 +390,14 @@
|
|||
D61A45E728DF477D002BE511 /* LoadingCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingCollectionViewCell.swift; sourceTree = "<group>"; };
|
||||
D61A45E928DF51EE002BE511 /* TimelineLikeCollectionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineLikeCollectionViewController.swift; sourceTree = "<group>"; };
|
||||
D61ABEF528EE74D400B29151 /* StatusCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusCollectionViewCell.swift; sourceTree = "<group>"; };
|
||||
D61ABEFD28F1C92600B29151 /* FavoriteService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FavoriteService.swift; sourceTree = "<group>"; };
|
||||
D61AC1D4232E9FA600C54D2D /* InstanceSelectorTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstanceSelectorTableViewController.swift; sourceTree = "<group>"; };
|
||||
D61AC1D6232EA42D00C54D2D /* InstanceTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstanceTableViewCell.swift; sourceTree = "<group>"; };
|
||||
D61AC1D7232EA42D00C54D2D /* InstanceTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = InstanceTableViewCell.xib; sourceTree = "<group>"; };
|
||||
D620483323D3801D008A63EF /* LinkTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkTextView.swift; sourceTree = "<group>"; };
|
||||
D620483523D38075008A63EF /* ContentTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentTextView.swift; sourceTree = "<group>"; };
|
||||
D620483723D38190008A63EF /* StatusContentTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusContentTextView.swift; sourceTree = "<group>"; };
|
||||
D621733228F1D5ED004C7DB1 /* ReblogService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReblogService.swift; sourceTree = "<group>"; };
|
||||
D622757324EDF1CD00B82A16 /* ComposeAttachmentsList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeAttachmentsList.swift; sourceTree = "<group>"; };
|
||||
D622757724EE133700B82A16 /* ComposeAssetPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeAssetPicker.swift; sourceTree = "<group>"; };
|
||||
D622757924EE21D900B82A16 /* ComposeAttachmentRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeAttachmentRow.swift; sourceTree = "<group>"; };
|
||||
|
@ -1475,6 +1479,8 @@
|
|||
D62E9988279DB2D100C26176 /* InstanceFeatures.swift */,
|
||||
D6F953EF21251A2900CF0F2B /* MastodonController.swift */,
|
||||
D6E9CDA7281A427800BBC98E /* PostService.swift */,
|
||||
D61ABEFD28F1C92600B29151 /* FavoriteService.swift */,
|
||||
D621733228F1D5ED004C7DB1 /* ReblogService.swift */,
|
||||
);
|
||||
path = API;
|
||||
sourceTree = "<group>";
|
||||
|
@ -1896,6 +1902,7 @@
|
|||
D681E4D3246E2AFF0053414F /* MuteConversationActivity.swift in Sources */,
|
||||
D6969EA0240C8384002843CE /* EmojiLabel.swift in Sources */,
|
||||
D64BC18623C1253A000D0238 /* AssetPreviewViewController.swift in Sources */,
|
||||
D61ABEFE28F1C92600B29151 /* FavoriteService.swift in Sources */,
|
||||
D663626221360B1900C9CBA2 /* Preferences.swift in Sources */,
|
||||
D626493823C0FD0000612E6E /* AllPhotosTableViewCell.swift in Sources */,
|
||||
D627943B23A55BA600D38C68 /* NavigableTableViewCell.swift in Sources */,
|
||||
|
@ -1947,6 +1954,7 @@
|
|||
D646C95A213B5D0500269FB5 /* LargeImageInteractionController.swift in Sources */,
|
||||
D6A3BC7C232195C600FD64D5 /* ActionNotificationGroupTableViewCell.swift in Sources */,
|
||||
D693A72825CF282E003A14E2 /* TrendingHashtagsViewController.swift in Sources */,
|
||||
D621733328F1D5ED004C7DB1 /* ReblogService.swift in Sources */,
|
||||
D62275A824F1CA2800B82A16 /* ComposeReplyContentView.swift in Sources */,
|
||||
D677284824ECBCB100C732D3 /* ComposeView.swift in Sources */,
|
||||
D68232F72464F4FD00325FB8 /* ComposeDrawingViewController.swift in Sources */,
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
//
|
||||
// FavoriteService.swift
|
||||
// Tusker
|
||||
//
|
||||
// Created by Shadowfacts on 10/8/22.
|
||||
// Copyright © 2022 Shadowfacts. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import Pachyderm
|
||||
|
||||
@MainActor
|
||||
class FavoriteService {
|
||||
|
||||
private let mastodonController: MastodonController
|
||||
private let presenter: any TuskerNavigationDelegate
|
||||
private let status: StatusMO
|
||||
|
||||
var hapticFeedback = true
|
||||
|
||||
init(status: StatusMO, mastodonController: MastodonController, presenter: any TuskerNavigationDelegate) {
|
||||
self.status = status
|
||||
self.mastodonController = mastodonController
|
||||
self.presenter = presenter
|
||||
}
|
||||
|
||||
func toggleFavorite() async {
|
||||
let oldValue = status.favourited
|
||||
status.favourited.toggle()
|
||||
mastodonController.persistentContainer.statusSubject.send(status.id)
|
||||
|
||||
if hapticFeedback {
|
||||
UIImpactFeedbackGenerator(style: .light).impactOccurred()
|
||||
}
|
||||
|
||||
let request = (status.favourited ? Status.favourite : Status.unfavourite)(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 Unfavoriting" : "Error Favoriting"
|
||||
let config = ToastConfiguration(from: error, with: title, in: presenter) { toast in
|
||||
// deliberately retain a strong reference to self
|
||||
toast.dismissToast(animated: true)
|
||||
await self.toggleFavorite()
|
||||
}
|
||||
presenter.showToast(configuration: config, animated: true)
|
||||
|
||||
if hapticFeedback {
|
||||
UINotificationFeedbackGenerator().notificationOccurred(.error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
//
|
||||
// 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 visibility: Status.Visibility? = nil
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
private func presentConfirmationAlert() {
|
||||
let image: UIImage?
|
||||
let reblogVisibilityActions: [CustomAlertController.MenuAction]?
|
||||
if mastodonController.instanceFeatures.reblogVisibility {
|
||||
image = UIImage(systemName: Status.Visibility.public.unfilledImageName)
|
||||
reblogVisibilityActions = [Status.Visibility.unlisted, .private].map { visibility in
|
||||
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()
|
||||
}
|
||||
}
|
||||
}
|
||||
} 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()
|
||||
}
|
||||
})
|
||||
])
|
||||
if let reblogVisibilityActions {
|
||||
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() async {
|
||||
let oldValue = status.reblogged
|
||||
status.reblogged.toggle()
|
||||
mastodonController.persistentContainer.statusSubject.send(status.id)
|
||||
|
||||
if hapticFeedback {
|
||||
UIImpactFeedbackGenerator(style: .light).impactOccurred()
|
||||
}
|
||||
|
||||
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 Unfavoriting" : "Error Favoriting"
|
||||
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 hapticFeedback {
|
||||
UINotificationFeedbackGenerator().notificationOccurred(.error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -10,7 +10,7 @@ import UIKit
|
|||
import SafariServices
|
||||
import Pachyderm
|
||||
|
||||
protocol TuskerNavigationDelegate: UIViewController {
|
||||
protocol TuskerNavigationDelegate: UIViewController, ToastableViewController {
|
||||
var apiController: MastodonController { get }
|
||||
|
||||
func conversation(mainStatusID: String, state: StatusState) -> ConversationTableViewController
|
||||
|
|
|
@ -384,93 +384,16 @@ class BaseStatusTableViewCell: UITableViewCell {
|
|||
@IBAction func favoritePressed() {
|
||||
guard let status = mastodonController.persistentContainer.status(for: statusID) else { fatalError("Missing cached status \(statusID!)") }
|
||||
|
||||
let oldValue = favorited
|
||||
favorited = !favorited
|
||||
|
||||
let realStatus = status.reblog ?? status
|
||||
let request = (favorited ? Status.favourite : Status.unfavourite)(realStatus.id)
|
||||
mastodonController.run(request) { response in
|
||||
DispatchQueue.main.async {
|
||||
if case let .success(newStatus, _) = response {
|
||||
self.favorited = newStatus.favourited ?? false
|
||||
self.mastodonController.persistentContainer.addOrUpdate(status: newStatus)
|
||||
UIImpactFeedbackGenerator(style: .light).impactOccurred()
|
||||
} else {
|
||||
self.favorited = oldValue
|
||||
print("Couldn't favorite status \(realStatus.id)")
|
||||
// todo: display error message
|
||||
UINotificationFeedbackGenerator().notificationOccurred(.error)
|
||||
return
|
||||
}
|
||||
}
|
||||
Task {
|
||||
await FavoriteService(status: status, mastodonController: mastodonController, presenter: delegate!).toggleFavorite()
|
||||
}
|
||||
}
|
||||
|
||||
@IBAction func reblogPressed() {
|
||||
guard let status = mastodonController.persistentContainer.status(for: statusID) else { fatalError("Missing cached status \(statusID!)") }
|
||||
|
||||
// if we are about to reblog and the user has confirmation enabled
|
||||
if !reblogged,
|
||||
Preferences.shared.confirmBeforeReblog {
|
||||
let image: UIImage?
|
||||
let reblogVisibilityActions: [CustomAlertController.MenuAction]?
|
||||
if mastodonController.instanceFeatures.reblogVisibility {
|
||||
image = UIImage(systemName: Status.Visibility.public.unfilledImageName)
|
||||
reblogVisibilityActions = [Status.Visibility.unlisted, .private].map { visibility in
|
||||
CustomAlertController.MenuAction(title: "Reblog as \(visibility.displayName)", subtitle: visibility.subtitle, image: UIImage(systemName: visibility.unfilledImageName)) { [unowned self] in
|
||||
self.toggleReblogInternal(visibility: visibility)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
image = nil
|
||||
reblogVisibilityActions = nil
|
||||
}
|
||||
|
||||
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: { [unowned self] in
|
||||
self.toggleReblogInternal(visibility: nil)
|
||||
}),
|
||||
])
|
||||
if let reblogVisibilityActions {
|
||||
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)
|
||||
delegate?.present(alert, animated: true)
|
||||
} else {
|
||||
toggleReblogInternal(visibility: nil)
|
||||
}
|
||||
}
|
||||
|
||||
private func toggleReblogInternal(visibility: Status.Visibility?) {
|
||||
guard let status = mastodonController.persistentContainer.status(for: statusID) else { fatalError("Missing cached status \(statusID!)") }
|
||||
|
||||
let oldValue = reblogged
|
||||
reblogged = !reblogged
|
||||
|
||||
let realStatus = status.reblog ?? status
|
||||
let request: Request<Status>
|
||||
if reblogged {
|
||||
request = Status.reblog(realStatus.id, visibility: visibility)
|
||||
} else {
|
||||
request = Status.unreblog(realStatus.id)
|
||||
}
|
||||
mastodonController.run(request) { response in
|
||||
DispatchQueue.main.async {
|
||||
if case let .success(newStatus, _) = response {
|
||||
self.reblogged = newStatus.reblogged ?? false
|
||||
self.mastodonController.persistentContainer.addOrUpdate(status: newStatus)
|
||||
UIImpactFeedbackGenerator(style: .light).impactOccurred()
|
||||
} else {
|
||||
self.reblogged = oldValue
|
||||
print("Couldn't reblog status \(realStatus.id)")
|
||||
// todo: display error message
|
||||
UINotificationFeedbackGenerator().notificationOccurred(.error)
|
||||
}
|
||||
}
|
||||
Task {
|
||||
await ReblogService(status: status, mastodonController: mastodonController, presenter: delegate!).toggleReblog()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -75,6 +75,8 @@ extension StatusCollectionViewCell {
|
|||
}
|
||||
|
||||
func doUpdateUI(status: StatusMO) {
|
||||
precondition(delegate != nil, "StatusCollectionViewCell must have delegate")
|
||||
|
||||
statusID = status.id
|
||||
accountID = status.account.id
|
||||
|
||||
|
@ -186,23 +188,8 @@ extension StatusCollectionViewCell {
|
|||
guard let status = mastodonController.persistentContainer.status(for: statusID) else {
|
||||
fatalError()
|
||||
}
|
||||
let oldValue = status.favourited
|
||||
status.favourited.toggle()
|
||||
// update ui before network request to make things appear speedy
|
||||
updateStatusState(status: status)
|
||||
|
||||
let request = (status.favourited ? Status.favourite : Status.unfavourite)(statusID)
|
||||
Task {
|
||||
do {
|
||||
let (newStatus, _) = try await mastodonController.run(request)
|
||||
mastodonController.persistentContainer.addOrUpdate(status: newStatus)
|
||||
// TODO: should this before the network request
|
||||
UIImpactFeedbackGenerator(style: .light).impactOccurred()
|
||||
} catch {
|
||||
status.favourited = oldValue
|
||||
// TODO: display error message
|
||||
UINotificationFeedbackGenerator().notificationOccurred(.error)
|
||||
}
|
||||
await FavoriteService(status: status, mastodonController: mastodonController, presenter: delegate!).toggleFavorite()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -210,64 +197,8 @@ extension StatusCollectionViewCell {
|
|||
guard let status = mastodonController.persistentContainer.status(for: statusID) else {
|
||||
fatalError()
|
||||
}
|
||||
|
||||
if !status.reblogged,
|
||||
Preferences.shared.confirmBeforeReblog {
|
||||
let image: UIImage?
|
||||
let reblogVisibilityActions: [CustomAlertController.MenuAction]?
|
||||
if mastodonController.instanceFeatures.reblogVisibility {
|
||||
image = UIImage(systemName: Status.Visibility.public.unfilledImageName)
|
||||
reblogVisibilityActions = [Status.Visibility.unlisted, .private].map { visibility in
|
||||
CustomAlertController.MenuAction(title: "Reblog as \(visibility.displayName)", subtitle: visibility.subtitle, image: UIImage(systemName: visibility.unfilledImageName)) { [unowned self] in
|
||||
self.doReblog(status: status, 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: { [unowned self] in
|
||||
self.doReblog(status: status, visibility: nil)
|
||||
})
|
||||
])
|
||||
if let reblogVisibilityActions {
|
||||
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)
|
||||
delegate?.present(alert, animated: true)
|
||||
} else {
|
||||
doReblog(status: status, visibility: nil)
|
||||
}
|
||||
}
|
||||
|
||||
private func doReblog(status: StatusMO, visibility: Status.Visibility?) {
|
||||
let oldValue = status.reblogged
|
||||
status.reblogged.toggle()
|
||||
updateStatusState(status: status)
|
||||
|
||||
let request: Request<Status>
|
||||
if status.reblogged {
|
||||
request = Status.reblog(statusID, visibility: visibility)
|
||||
} else {
|
||||
request = Status.unreblog(statusID)
|
||||
}
|
||||
Task {
|
||||
do {
|
||||
let (newStatus, _) = try await mastodonController.run(request)
|
||||
mastodonController.persistentContainer.addOrUpdate(status: newStatus)
|
||||
// TODO: should this before the network request
|
||||
UIImpactFeedbackGenerator(style: .light).impactOccurred()
|
||||
} catch {
|
||||
status.reblogged = oldValue
|
||||
// TODO: display error message
|
||||
UINotificationFeedbackGenerator().notificationOccurred(.error)
|
||||
}
|
||||
await ReblogService(status: status, mastodonController: mastodonController, presenter: delegate!).toggleReblog()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue