Various fixes

This commit is contained in:
Ilya Laktyushin
2024-03-25 01:09:45 +04:00
parent 75070e2aa7
commit b7c18980f6
12 changed files with 225 additions and 137 deletions

View File

@@ -4596,11 +4596,11 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
init(
media: MediaResult?,
mediaAreas: [MediaArea],
caption: NSAttributedString,
options: MediaEditorResultPrivacy,
stickers: [TelegramMediaFile],
randomId: Int64
mediaAreas: [MediaArea] = [],
caption: NSAttributedString = NSAttributedString(),
options: MediaEditorResultPrivacy = MediaEditorResultPrivacy(sendAsPeerId: nil, privacy: EngineStoryPrivacy(base: .everyone, additionallyIncludePeers: []), timeout: 0, isForwardingDisabled: false, pin: false),
stickers: [TelegramMediaFile] = [],
randomId: Int64 = 0
) {
self.media = media
self.mediaAreas = mediaAreas
@@ -5755,24 +5755,13 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
let values = mediaEditor.values.withUpdatedQualityPreset(.sticker)
makeEditorImageComposition(context: self.node.ciContext, postbox: self.context.account.postbox, inputImage: image, dimensions: storyDimensions, outputDimensions: CGSize(width: 512, height: 512), values: values, time: .zero, textScale: 2.0, completion: { [weak self] resultImage in
if let self, let resultImage {
// let dimensions = CGSize(width: 512, height: 512)
// let scaledImage = generateImage(dimensions, contextGenerator: { size, context in
// context.clear(CGRect(origin: CGPoint(), size: size))
//
// context.addPath(CGPath(roundedRect: CGRect(origin: .zero, size: size), cornerWidth: size.width / 8.0, cornerHeight: size.width / 8.0, transform: nil))
// context.clip()
//
// let scaledSize = resultImage.size.aspectFilled(size)
// context.draw(resultImage.cgImage!, in: CGRect(origin: CGPoint(x: floor((size.width - scaledSize.width) / 2.0), y: floor((size.height - scaledSize.height) / 2.0)), size: scaledSize))
// }, opaque: false, scale: 1.0)!
self.presentStickerPreview(image: resultImage)
}
})
}
}
private weak var resultController: PeekController?
func presentStickerPreview(image: UIImage) {
guard let mediaEditor = self.node.mediaEditor else {
return
@@ -5783,7 +5772,6 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
var isVideo = false
if mediaEditor.resultIsVideo {
isVideo = true
self.performSave(toStickerResource: resource)
} else {
Queue.concurrentDefaultQueue().async {
if let data = try? WebP.convert(toWebP: image, quality: 97.0) {
@@ -5804,26 +5792,29 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
guard let self else {
return
}
if self.videoExport != nil {
return
}
f(.default)
self.completion(MediaEditorScreen.Result(
media: .sticker(file: file),
mediaAreas: [],
caption: NSAttributedString(),
options: MediaEditorResultPrivacy(sendAsPeerId: nil, privacy: EngineStoryPrivacy(base: .everyone, additionallyIncludePeers: []), timeout: 0, isForwardingDisabled: false, pin: false),
stickers: [],
randomId: 0
), { [weak self] finished in
self?.node.animateOut(finished: true, saveDraft: false, completion: { [weak self] in
self?.dismiss()
Queue.mainQueue().justDispatch {
finished()
}
if isVideo {
self.uploadSticker(file, action: .send)
} else {
self.resultController?.disappeared = nil
self.completion(MediaEditorScreen.Result(
media: .sticker(file: file),
mediaAreas: [],
caption: NSAttributedString(),
options: MediaEditorResultPrivacy(sendAsPeerId: nil, privacy: EngineStoryPrivacy(base: .everyone, additionallyIncludePeers: []), timeout: 0, isForwardingDisabled: false, pin: false),
stickers: [],
randomId: 0
), { [weak self] finished in
self?.node.animateOut(finished: true, saveDraft: false, completion: { [weak self] in
self?.dismiss()
Queue.mainQueue().justDispatch {
finished()
}
})
})
})
}
f(.default)
})))
menuItems.append(.action(ContextMenuActionItem(text: presentationData.strings.Stickers_AddToFavorites, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Fave"), color: theme.contextMenu.primaryColor) }, action: { [weak self] _, f in
f(.default)
@@ -5899,6 +5890,10 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
}
}
Queue.mainQueue().justDispatch {
self.node.entitiesView.selectEntity(nil)
}
let peekController = PeekController(
presentationData: presentationData,
content: StickerPreviewPeekContent(
@@ -5934,6 +5929,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
self.node.previewView.alpha = 1.0
}
}
self.resultController = peekController
self.present(peekController, in: .window(.root))
}
@@ -5942,6 +5938,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
case createStickerPack(title: String)
case addToStickerPack(pack: StickerPackReference, title: String)
case upload
case send
}
private func presentCreateStickerPack(file: TelegramMediaFile, completion: @escaping () -> Void) {
@@ -6014,69 +6011,118 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
let context = self.context
let dimensions = PixelDimensions(width: 512, height: 512)
let mimeType = file.mimeType
let isVideo = file.mimeType == "video/webm"
self.updateEditProgress(0.0, cancel: { [weak self] in
self?.stickerUploadDisposable.set(nil)
})
enum PrepareStickerStatus {
case progress(Float)
case complete(TelegramMediaResource)
case failed
}
let resourceSignal: Signal<PrepareStickerStatus, UploadStickerError>
if isVideo {
self.performSave(toStickerResource: file.resource)
resourceSignal = self.videoExportPromise.get()
|> castError(UploadStickerError.self)
|> filter { $0 != nil }
|> take(1)
|> mapToSignal { videoExport -> Signal<PrepareStickerStatus, UploadStickerError> in
guard let videoExport else {
return .complete()
}
return videoExport.status
|> castError(UploadStickerError.self)
|> mapToSignal { status -> Signal<PrepareStickerStatus, UploadStickerError> in
switch status {
case .unknown:
return .single(.progress(0.0))
case let .progress(progress):
return .single(.progress(progress))
case .completed:
return .single(.complete(file.resource))
|> delay(0.05, queue: Queue.mainQueue())
case .failed:
return .single(.failed)
}
}
}
} else {
resourceSignal = .single(.complete(file.resource))
}
let signal = context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId))
|> castError(UploadStickerError.self)
|> mapToSignal { peer -> Signal<UploadStickerStatus, UploadStickerError> in
guard let peer else {
return .complete()
}
return context.engine.stickers.uploadSticker(peer: peer._asPeer(), resource: file.resource, alt: "", dimensions: dimensions, mimeType: mimeType)
|> mapToSignal { status -> Signal<UploadStickerStatus, UploadStickerError> in
switch status {
case .progress:
return .single(status)
case let .complete(resource, _):
let file = stickerFile(resource: resource, size: file.size ?? 0, dimensions: dimensions, isVideo: file.mimeType == "video/webm")
switch action {
case .addToFavorites:
return context.engine.stickers.toggleStickerSaved(file: file, saved: true)
|> `catch` { _ -> Signal<SavedStickerResult, UploadStickerError> in
return .fail(.generic)
}
|> map { _ in
return status
}
case let .createStickerPack(title):
let sticker = ImportSticker(
resource: resource,
emojis: ["😀😂"],
dimensions: dimensions,
mimeType: mimeType,
keywords: ""
)
return context.engine.stickers.createStickerSet(title: title, shortName: "", stickers: [sticker], thumbnail: nil, type: .stickers(content: .image), software: nil)
|> `catch` { _ -> Signal<CreateStickerSetStatus, UploadStickerError> in
return .fail(.generic)
}
|> mapToSignal { innerStatus in
if case .complete = innerStatus {
return resourceSignal
|> mapToSignal { result -> Signal<UploadStickerStatus, UploadStickerError> in
switch result {
case .failed:
return .fail(.generic)
case let .progress(progress):
return .single(.progress(progress * 0.5))
case let .complete(resource):
return context.engine.stickers.uploadSticker(peer: peer._asPeer(), resource: resource, alt: "", dimensions: dimensions, mimeType: mimeType)
|> mapToSignal { status -> Signal<UploadStickerStatus, UploadStickerError> in
switch status {
case let .progress(progress):
return .single(.progress(isVideo ? 0.5 + progress * 0.5 : progress))
case let .complete(resource, _):
let file = stickerFile(resource: resource, size: file.size ?? 0, dimensions: dimensions, isVideo: isVideo)
switch action {
case .send:
return .single(status)
case .addToFavorites:
return context.engine.stickers.toggleStickerSaved(file: file, saved: true)
|> `catch` { _ -> Signal<SavedStickerResult, UploadStickerError> in
return .fail(.generic)
}
|> map { _ in
return status
}
case let .createStickerPack(title):
let sticker = ImportSticker(
resource: resource,
emojis: ["😀😂"],
dimensions: dimensions,
mimeType: mimeType,
keywords: ""
)
return context.engine.stickers.createStickerSet(title: title, shortName: "", stickers: [sticker], thumbnail: nil, type: .stickers(content: .image), software: nil)
|> `catch` { _ -> Signal<CreateStickerSetStatus, UploadStickerError> in
return .fail(.generic)
}
|> mapToSignal { innerStatus in
if case .complete = innerStatus {
return .single(status)
} else {
return .complete()
}
}
case let .addToStickerPack(pack, _):
let sticker = ImportSticker(
resource: resource,
emojis: ["😀😂"],
dimensions: dimensions,
mimeType: mimeType,
keywords: ""
)
return context.engine.stickers.addStickerToStickerSet(packReference: pack, sticker: sticker)
|> `catch` { _ -> Signal<Bool, UploadStickerError> in
return .fail(.generic)
}
|> map { _ in
return status
}
case .upload:
return .single(status)
} else {
return .complete()
}
}
case let .addToStickerPack(pack, _):
let sticker = ImportSticker(
resource: resource,
emojis: ["😀😂"],
dimensions: dimensions,
mimeType: mimeType,
keywords: ""
)
return context.engine.stickers.addStickerToStickerSet(packReference: pack, sticker: sticker)
|> `catch` { _ -> Signal<Bool, UploadStickerError> in
return .fail(.generic)
}
|> map { _ in
return status
}
case .upload:
return .single(status)
}
}
}
@@ -6090,26 +6136,23 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
switch status {
case let .progress(progress):
self.updateEditProgress(progress, cancel: { [weak self] in
self?.videoExport?.cancel()
self?.videoExport = nil
self?.exportDisposable.set(nil)
self?.stickerUploadDisposable.set(nil)
})
case let .complete(resource, _):
let navigationController = self.navigationController as? NavigationController
let result: MediaEditorScreen.Result
if case .upload = action {
let file = stickerFile(resource: resource, size: resource.size ?? 0, dimensions: dimensions, isVideo: file.mimeType == "video/webm")
result = MediaEditorScreen.Result(
media: .sticker(file: file),
mediaAreas: [],
caption: NSAttributedString(),
options: MediaEditorResultPrivacy(sendAsPeerId: nil, privacy: EngineStoryPrivacy(base: .everyone, additionallyIncludePeers: []), timeout: 0, isForwardingDisabled: false, pin: false),
stickers: [],
randomId: 0
)
} else {
switch action {
case .upload, .send:
let file = stickerFile(resource: resource, size: resource.size ?? 0, dimensions: dimensions, isVideo: isVideo)
result = MediaEditorScreen.Result(media: .sticker(file: file))
default:
result = MediaEditorScreen.Result()
}
self.completion(result, { [weak self] finished in
self?.node.animateOut(finished: true, saveDraft: false, completion: { [weak self] in
guard let self else {
@@ -6147,7 +6190,12 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
}))
}
private var videoExport: MediaEditorVideoExport?
private var videoExport: MediaEditorVideoExport? {
didSet {
self.videoExportPromise.set(.single(self.videoExport))
}
}
private var videoExportPromise = Promise<MediaEditorVideoExport?>(nil)
private var exportDisposable = MetaDisposable()
fileprivate var isSavingAvailable = false
@@ -6178,7 +6226,6 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
mediaEditor.setDrawingAndEntities(data: nil, image: mediaEditor.values.drawing, entities: codableEntities)
let isSticker = toStickerResource != nil
if !isSticker {
self.previousSavedValues = mediaEditor.values
self.isSavingAvailable = false
@@ -6207,8 +6254,10 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
}
if mediaEditor.resultIsVideo {
mediaEditor.maybePauseVideo()
self.node.entitiesView.pause()
if !isSticker {
mediaEditor.maybePauseVideo()
self.node.entitiesView.pause()
}
let exportSubject: Signal<MediaEditorVideoExport.Subject, NoError>
switch subject {
@@ -6293,8 +6342,10 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
switch status {
case .completed:
self.videoExport = nil
if let toStickerResource, let data = try? Data(contentsOf: URL(fileURLWithPath: outputPath)) {
self.context.account.postbox.mediaBox.storeResourceData(toStickerResource.id, data: data)
if let toStickerResource {
if let data = try? Data(contentsOf: URL(fileURLWithPath: outputPath)) {
self.context.account.postbox.mediaBox.storeResourceData(toStickerResource.id, data: data, synchronous: true)
}
} else {
saveToPhotos(outputPath, true)
self.node.presentSaveTooltip()
@@ -6337,16 +6388,18 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
}
fileprivate func cancelVideoExport() {
if let videoExport = self.videoExport {
self.previousSavedValues = nil
videoExport.cancel()
self.videoExport = nil
self.exportDisposable.set(nil)
self.node.mediaEditor?.play()
self.node.entitiesView.play()
guard let videoExport = self.videoExport else {
return
}
videoExport.cancel()
self.videoExport = nil
self.exportDisposable.set(nil)
self.previousSavedValues = nil
self.node.mediaEditor?.play()
self.node.entitiesView.play()
}
public func updateEditProgress(_ progress: Float, cancel: @escaping () -> Void) {