2022-10-08 16:15:12 +00:00
//
// R e b l o g S e r v i c e . s w i f t
// T u s k e r
//
// C r e a t e d b y S h a d o w f a c t s o n 1 0 / 8 / 2 2 .
// C o p y r i g h t © 2 0 2 2 S h a d o w f a c t s . A l l r i g h t s r e s e r v e d .
//
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 {
2023-06-27 04:41:43 +00:00
await doToggleReblog ( visibility : nil )
2022-10-08 16:15:12 +00:00
}
}
private func presentConfirmationAlert ( ) {
let image : UIImage ?
2023-06-27 04:40:43 +00:00
let reblogVisibilityActions : [ CustomAlertController . MenuAction ]
let maximumVisibility = status . visibility
2022-10-08 16:15:12 +00:00
if mastodonController . instanceFeatures . reblogVisibility {
2023-06-27 04:40:43 +00:00
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 ) ) {
2022-10-08 16:15:12 +00:00
// d e l i b e r a t e l y r e t a i n a s t r o n g r e f e r e n c e t o s e l f
Task {
2023-06-27 04:41:43 +00:00
await self . doToggleReblog ( visibility : visibility )
2022-10-08 16:15:12 +00:00
}
}
}
} else {
image = nil
2023-06-27 04:40:43 +00:00
reblogVisibilityActions = [ ]
2022-10-08 16:15:12 +00:00
}
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 : {
// d e l i b e r a t e l y r e t a i n a s t r o n g r e f e r e n c e t o s e l f
Task {
2023-06-27 04:41:43 +00:00
await self . doToggleReblog ( visibility : nil )
2022-10-08 16:15:12 +00:00
}
} )
] )
2023-06-27 04:40:43 +00:00
if ! reblogVisibilityActions . isEmpty {
2022-10-08 16:15:12 +00:00
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 )
}
2023-06-27 04:41:43 +00:00
private func doToggleReblog ( visibility : Visibility ? ) async {
2022-10-08 16:15:12 +00:00
let oldValue = status . reblogged
status . reblogged . toggle ( )
mastodonController . persistentContainer . statusSubject . send ( status . id )
2023-10-20 02:50:20 +00:00
#if ! os ( visionOS )
2022-10-08 16:15:12 +00:00
if hapticFeedback {
UIImpactFeedbackGenerator ( style : . light ) . impactOccurred ( )
}
2023-10-20 02:50:20 +00:00
#endif
2022-10-08 16:15:12 +00:00
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 )
2023-03-02 02:09:56 +00:00
let title = oldValue ? " Error Unreblogging " : " Error Reblogging "
2022-10-08 16:15:12 +00:00
let config = ToastConfiguration ( from : error , with : title , in : presenter ) { toast in
toast . dismissToast ( animated : true )
await self . toggleReblog ( )
}
presenter . showToast ( configuration : config , animated : true )
2023-10-20 02:50:20 +00:00
#if ! os ( visionOS )
2022-10-08 16:15:12 +00:00
if hapticFeedback {
UINotificationFeedbackGenerator ( ) . notificationOccurred ( . error )
}
2023-10-20 02:50:20 +00:00
#endif
2022-10-08 16:15:12 +00:00
}
}
}