forked from shadowfacts/Tusker
parent
33c641cd85
commit
1d193dec0f
@ -25,9 +25,9 @@ final class PostService: ObservableObject {
|
||||
self.draft = draft
|
||||
}
|
||||
|
||||
func post() async throws(Error) {
|
||||
func post() async throws(Error) -> Status {
|
||||
guard draft.hasContent || draft.editedStatusID != nil else {
|
||||
return
|
||||
throw .noContent
|
||||
}
|
||||
|
||||
// save before posting, so if a crash occurs during network request, the status won't be lost
|
||||
@ -105,7 +105,7 @@ final class PostService: ObservableObject {
|
||||
do {
|
||||
let (status, _) = try await mastodonController.run(request)
|
||||
currentStep += 1
|
||||
mastodonController.storeCreatedStatus(status)
|
||||
return status
|
||||
} catch {
|
||||
throw Error.posting(error)
|
||||
}
|
||||
@ -197,6 +197,7 @@ final class PostService: ObservableObject {
|
||||
}
|
||||
|
||||
enum Error: Swift.Error, LocalizedError {
|
||||
case noContent
|
||||
case attachmentData(index: Int, cause: DraftAttachment.ExportError)
|
||||
case attachmentMissingMimeType(index: Int, type: UTType)
|
||||
case attachmentUpload(index: Int, cause: Client.Error)
|
||||
@ -204,6 +205,8 @@ final class PostService: ObservableObject {
|
||||
|
||||
var localizedDescription: String {
|
||||
switch self {
|
||||
case .noContent:
|
||||
return "No content"
|
||||
case let .attachmentData(index: index, cause: cause):
|
||||
return "Attachment \(index + 1): \(cause.localizedDescription)"
|
||||
case let .attachmentMissingMimeType(index: index, type: type):
|
||||
|
@ -26,7 +26,5 @@ public protocol ComposeMastodonContext {
|
||||
@MainActor
|
||||
func searchCachedHashtags(query: String) -> [Hashtag]
|
||||
|
||||
func storeCreatedStatus(_ status: Status)
|
||||
|
||||
func fetchStatus(id: String) -> (any StatusProtocol)?
|
||||
}
|
||||
|
@ -6,7 +6,10 @@
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Pachyderm
|
||||
|
||||
public enum DismissMode {
|
||||
case cancel, post
|
||||
case cancel
|
||||
case edit(Status)
|
||||
case post(Status)
|
||||
}
|
||||
|
@ -223,7 +223,7 @@ private struct ComposeViewBody: View {
|
||||
state.poster = poster
|
||||
|
||||
do {
|
||||
try await poster.post()
|
||||
let status = try await poster.post()
|
||||
|
||||
isDismissing = true
|
||||
state.didPostSuccessfully = true
|
||||
@ -233,7 +233,11 @@ private struct ComposeViewBody: View {
|
||||
|
||||
// don't unset the poster, so the ui remains disabled while dismissing
|
||||
|
||||
config.dismiss(.post)
|
||||
if draft.editedStatusID != nil {
|
||||
config.dismiss(.edit(status))
|
||||
} else {
|
||||
config.dismiss(.post(status))
|
||||
}
|
||||
} catch {
|
||||
self.postError = error
|
||||
state.poster = nil
|
||||
|
@ -74,7 +74,7 @@ class ShareHostingController: UIHostingController<ShareHostingController.View> {
|
||||
switch mode {
|
||||
case .cancel:
|
||||
extensionContext.cancelRequest(withError: Error.cancelled)
|
||||
case .post:
|
||||
case .post(_), .edit(_):
|
||||
extensionContext.completeRequest(returningItems: nil)
|
||||
}
|
||||
}
|
||||
|
@ -72,9 +72,6 @@ final class ShareMastodonContext: ComposeMastodonContext, ObservableObject, Send
|
||||
return []
|
||||
}
|
||||
|
||||
func storeCreatedStatus(_ status: Status) {
|
||||
}
|
||||
|
||||
func fetchStatus(id: String) -> (any StatusProtocol)? {
|
||||
return nil
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ extension ComposeSceneDelegate: ComposeHostingControllerDelegate {
|
||||
switch mode {
|
||||
case .cancel:
|
||||
animation = .decline
|
||||
case .post:
|
||||
case .post(_), .edit(_):
|
||||
animation = .commit
|
||||
}
|
||||
closeWindow(animation: animation)
|
||||
|
@ -145,10 +145,41 @@ class ComposeHostingController: UIHostingController<ComposeHostingController.Vie
|
||||
if delegate?.dismissCompose(mode: mode) == true {
|
||||
return
|
||||
} else {
|
||||
switch mode {
|
||||
case .edit(let status), .post(let status):
|
||||
if let presentingViewController,
|
||||
let host = findNavDelegate(in: presentingViewController) {
|
||||
mastodonController.persistentContainer.addOrUpdateOnViewContext(status: status)
|
||||
var config = ToastConfiguration(title: "Posted Successfully")
|
||||
config.actionTitle = "View"
|
||||
config.systemImageName = "checkmark"
|
||||
config.action = { toast in
|
||||
host.selected(status: status.id)
|
||||
toast.dismissToast(animated: true)
|
||||
}
|
||||
host.showToast(configuration: config, animated: true)
|
||||
}
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
dismiss(animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
private func findNavDelegate(in vc: UIViewController) -> (any TuskerNavigationDelegate)? {
|
||||
if let toastable = vc as? any TuskerNavigationDelegate {
|
||||
return toastable
|
||||
} else {
|
||||
for child in vc.children {
|
||||
if let navDelegate = findNavDelegate(in: child) {
|
||||
return navDelegate
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
private func presentAssetPicker(completion: @MainActor @escaping ([PHPickerResult]) -> Void) {
|
||||
self.assetPickerCompletion = completion
|
||||
|
||||
@ -280,10 +311,6 @@ extension MastodonController: ComposeMastodonContext {
|
||||
return results
|
||||
}
|
||||
|
||||
func storeCreatedStatus(_ status: Status) {
|
||||
persistentContainer.addOrUpdate(status: status)
|
||||
}
|
||||
|
||||
func fetchStatus(id: String) -> (any StatusProtocol)? {
|
||||
return persistentContainer.status(for: id)
|
||||
}
|
||||
|
@ -178,9 +178,8 @@ extension BaseMainTabBarViewController: StateRestorableViewController {
|
||||
var activity: NSUserActivity?
|
||||
if let presentedNav = presentedViewController as? UINavigationController,
|
||||
let compose = presentedNav.viewControllers.first as? ComposeHostingController {
|
||||
// TODO: this
|
||||
// let draft = compose.controller.draft
|
||||
// activity = UserActivityManager.editDraftActivity(id: draft.id, accountID: draft.accountID)
|
||||
let draft = compose.state.draft
|
||||
activity = UserActivityManager.editDraftActivity(id: draft.id, accountID: draft.accountID)
|
||||
} else if let vc = (selectedViewController as? any NavigationControllerProtocol)?.topViewController as? StateRestorableViewController {
|
||||
activity = vc.stateRestorationActivity()
|
||||
}
|
||||
|
@ -354,6 +354,9 @@ extension ProfileViewController: TuskerNavigationDelegate {
|
||||
}
|
||||
|
||||
extension ProfileViewController: ToastableViewController {
|
||||
var toastScrollView: UIScrollView? {
|
||||
currentViewController.collectionView
|
||||
}
|
||||
}
|
||||
|
||||
extension ProfileViewController: ProfileHeaderViewDelegate {
|
||||
|
@ -723,7 +723,7 @@ class TimelineViewController: UIViewController, TimelineLikeCollectionViewContro
|
||||
} else {
|
||||
var config = ToastConfiguration(title: "Sync Position")
|
||||
config.edge = .top
|
||||
config.dismissAutomaticallyAfter = 5
|
||||
config.dismissAutomaticallyAfter = 2
|
||||
config.systemImageName = "arrow.triangle.2.circlepath"
|
||||
config.action = { [unowned self] toast in
|
||||
toast.isUserInteractionEnabled = false
|
||||
@ -861,7 +861,7 @@ class TimelineViewController: UIViewController, TimelineLikeCollectionViewContro
|
||||
var config = ToastConfiguration(title: "Jump to Present")
|
||||
config.edge = .top
|
||||
config.systemImageName = "arrow.up"
|
||||
config.dismissAutomaticallyAfter = 4
|
||||
config.dismissAutomaticallyAfter = 2
|
||||
config.action = { [unowned self] toast in
|
||||
toast.dismissToast(animated: true)
|
||||
|
||||
|
@ -106,3 +106,23 @@ extension ToastableViewController {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension UITabBarController: ToastableViewController {
|
||||
var toastParentView: UIView {
|
||||
(selectedViewController as? ToastableViewController)?.toastParentView ?? self.view
|
||||
}
|
||||
|
||||
var toastScrollView: UIScrollView? {
|
||||
(selectedViewController as? ToastableViewController)?.toastScrollView
|
||||
}
|
||||
}
|
||||
|
||||
extension UINavigationController: ToastableViewController {
|
||||
var toastParentView: UIView {
|
||||
(topViewController as? ToastableViewController)?.toastParentView ?? self.view
|
||||
}
|
||||
|
||||
var toastScrollView: UIScrollView? {
|
||||
(topViewController as? ToastableViewController)?.toastScrollView
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user