mirror of
https://github.com/ichmagmaus111/ghostgram.git
synced 2026-11-03 14:17:19 +01:00
Ghostgram for iOS, rebuilt from scratch on Telegram iOS 13.0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
159 lines
6.9 KiB
Swift
159 lines
6.9 KiB
Swift
import Foundation
|
|
import UIKit
|
|
import Display
|
|
import ComponentFlow
|
|
import SwiftSignalKit
|
|
import TelegramPresentationData
|
|
import AlertComponent
|
|
import MediaEditor
|
|
|
|
final class MediaEditorDraftSaveAlert: AlertScreen {
|
|
var requestClose: (() -> Bool)?
|
|
private var allowDismiss = false
|
|
|
|
override func dismiss(completion: (() -> Void)? = nil) {
|
|
guard self.allowDismiss || (self.requestClose?() ?? true) else {
|
|
return
|
|
}
|
|
super.dismiss(completion: completion)
|
|
}
|
|
|
|
func close(completion: (() -> Void)? = nil) {
|
|
self.allowDismiss = true
|
|
self.dismiss(completion: completion)
|
|
}
|
|
}
|
|
|
|
extension MediaEditorScreenImpl {
|
|
func prepareCollageMedia(_ collage: MediaEditorCollage, completion: @escaping (Bool) -> Void) {
|
|
guard collage.isVideo else {
|
|
completion(true)
|
|
return
|
|
}
|
|
guard self.collageMediaAlert == nil else {
|
|
completion(false)
|
|
return
|
|
}
|
|
let presentationData = self.context.sharedContext.currentPresentationData.with { $0 }.withUpdated(theme: defaultDarkPresentationTheme)
|
|
var finished = false
|
|
weak var weakAlert: MediaEditorDraftSaveAlert?
|
|
let finish: (Bool, Bool) -> Void = { [weak self] success, cancelled in
|
|
guard let self, !finished else {
|
|
return
|
|
}
|
|
finished = true
|
|
self.collageMediaDisposable.set(nil)
|
|
self.collageMediaAlert = nil
|
|
weakAlert?.close(completion: { [weak self] in
|
|
if !success && !cancelled {
|
|
self?.presentCollageAlert(text: presentationData.strings.Login_UnknownError, completion: { completion(false) })
|
|
} else {
|
|
completion(success)
|
|
}
|
|
})
|
|
}
|
|
let alert = MediaEditorDraftSaveAlert(
|
|
configuration: AlertScreen.Configuration(actionAlignment: .vertical, dismissOnOutsideTap: false),
|
|
contentSignal: .single([]),
|
|
actionsSignal: .single([
|
|
AlertScreen.Action(title: presentationData.strings.Channel_NotificationLoading, action: {}, autoDismiss: false, isEnabled: .single(false), progress: .single(true)),
|
|
AlertScreen.Action(title: presentationData.strings.Common_Cancel, action: { finish(false, true) }, autoDismiss: false)
|
|
]),
|
|
updatedPresentationData: (initial: presentationData, signal: self.context.sharedContext.presentationData |> map { $0.withUpdated(theme: defaultDarkPresentationTheme) })
|
|
)
|
|
weakAlert = alert
|
|
alert.requestClose = {
|
|
finish(false, true)
|
|
return false
|
|
}
|
|
self.collageMediaAlert = alert
|
|
self.present(alert, in: .window(.root))
|
|
self.collageMediaDisposable.set((collage.prepareVideoSources() |> take(1) |> deliverOnMainQueue).start(next: { success in
|
|
finish(success, false)
|
|
}))
|
|
}
|
|
|
|
func presentCollageDraftSaveAlert(title: String, text: String, saveTitle: String) {
|
|
guard self.collageSaveAlert == nil else {
|
|
return
|
|
}
|
|
let presentationData = self.context.sharedContext.currentPresentationData.with { $0 }.withUpdated(theme: defaultDarkPresentationTheme)
|
|
let progress = ValuePromise<Bool>(false, ignoreRepeated: true)
|
|
let enabled = progress.get() |> map { !$0 }
|
|
let message = ValuePromise<String>(text, ignoreRepeated: true)
|
|
var isSaving = false
|
|
weak var weakAlert: MediaEditorDraftSaveAlert?
|
|
let close: () -> Bool = { [weak self] in
|
|
guard let self else {
|
|
return true
|
|
}
|
|
if isSaving && !self.cancelCollageDraftSave() {
|
|
return false
|
|
}
|
|
isSaving = false
|
|
self.collageSaveAlert = nil
|
|
return true
|
|
}
|
|
let alert = MediaEditorDraftSaveAlert(
|
|
configuration: AlertScreen.Configuration(actionAlignment: .vertical, dismissOnOutsideTap: false),
|
|
contentSignal: message.get() |> map { message in
|
|
return [
|
|
AnyComponentWithIdentity(id: "title", component: AnyComponent(AlertTitleComponent(title: title))),
|
|
AnyComponentWithIdentity(id: "text", component: AnyComponent(AlertTextComponent(content: .plain(message))))
|
|
]
|
|
},
|
|
actionsSignal: .single([
|
|
AlertScreen.Action(title: presentationData.strings.Story_Editor_DraftDiscard, type: .destructive, action: { [weak self] in
|
|
guard let self, !isSaving else {
|
|
return
|
|
}
|
|
self.collageSaveAlert = nil
|
|
weakAlert?.close(completion: { [weak self] in
|
|
self?.requestDismiss(saveDraft: false, animated: true)
|
|
})
|
|
}, autoDismiss: false, isEnabled: enabled),
|
|
AlertScreen.Action(title: saveTitle, action: { [weak self] in
|
|
guard let self, !isSaving else {
|
|
return
|
|
}
|
|
isSaving = true
|
|
progress.set(true)
|
|
message.set(text)
|
|
self.saveCollageDraft(id: nil, completion: { [weak self] result in
|
|
guard let self else {
|
|
return
|
|
}
|
|
isSaving = false
|
|
progress.set(false)
|
|
switch result {
|
|
case .success:
|
|
self.collageSaveAlert = nil
|
|
weakAlert?.close(completion: { [weak self] in
|
|
self?.requestDismiss(saveDraft: true, animated: true, draftSaved: true)
|
|
})
|
|
case let .failure(error):
|
|
switch error {
|
|
case .cancelled:
|
|
self.collageSaveAlert = nil
|
|
weakAlert?.close()
|
|
case .mediaUnavailable, .storage:
|
|
message.set(presentationData.strings.Login_UnknownError)
|
|
}
|
|
}
|
|
})
|
|
}, autoDismiss: false, isEnabled: enabled, progress: progress.get()),
|
|
AlertScreen.Action(title: presentationData.strings.Common_Cancel, action: {
|
|
if close() {
|
|
weakAlert?.close()
|
|
}
|
|
}, autoDismiss: false)
|
|
]),
|
|
updatedPresentationData: (initial: presentationData, signal: self.context.sharedContext.presentationData |> map { $0.withUpdated(theme: defaultDarkPresentationTheme) })
|
|
)
|
|
weakAlert = alert
|
|
alert.requestClose = close
|
|
self.collageSaveAlert = alert
|
|
self.present(alert, in: .window(.root))
|
|
}
|
|
}
|