[WIP] Stickers editor

This commit is contained in:
Ilya Laktyushin 2024-04-06 23:08:44 +04:00
parent ee2b7be5e2
commit a6b5f0f96e
7 changed files with 80 additions and 41 deletions

View File

@ -89,7 +89,7 @@ public final class ImportStickerPackController: ViewController, StandalonePresen
var signals: [Signal<(UUID, StickerVerificationStatus, EngineMediaResource?), NoError>] = [] var signals: [Signal<(UUID, StickerVerificationStatus, EngineMediaResource?), NoError>] = []
for sticker in strongSelf.stickerPack.stickers { for sticker in strongSelf.stickerPack.stickers {
if let resource = strongSelf.controllerNode.stickerResources[sticker.uuid] { if let resource = strongSelf.controllerNode.stickerResources[sticker.uuid] {
signals.append(strongSelf.context.engine.stickers.uploadSticker(peer: peer, resource: resource._asResource(), alt: sticker.emojis.first ?? "", dimensions: PixelDimensions(width: 512, height: 512), mimeType: sticker.mimeType) signals.append(strongSelf.context.engine.stickers.uploadSticker(peer: peer, resource: resource._asResource(), alt: sticker.emojis.first ?? "", dimensions: PixelDimensions(width: 512, height: 512), duration: nil, mimeType: sticker.mimeType)
|> map { result -> (UUID, StickerVerificationStatus, EngineMediaResource?) in |> map { result -> (UUID, StickerVerificationStatus, EngineMediaResource?) in
switch result { switch result {
case .progress: case .progress:

View File

@ -625,9 +625,9 @@ final class ImportStickerPackControllerNode: ViewControllerTracingNode, ASScroll
if let localResource = item.stickerItem.resource { if let localResource = item.stickerItem.resource {
self.context.account.postbox.mediaBox.copyResourceData(from: localResource._asResource().id, to: resource._asResource().id) self.context.account.postbox.mediaBox.copyResourceData(from: localResource._asResource().id, to: resource._asResource().id)
} }
stickers.append(ImportSticker(resource: .standalone(resource: resource._asResource()), emojis: item.stickerItem.emojis, dimensions: dimensions, mimeType: item.stickerItem.mimeType, keywords: item.stickerItem.keywords)) stickers.append(ImportSticker(resource: .standalone(resource: resource._asResource()), emojis: item.stickerItem.emojis, dimensions: dimensions, duration: nil, mimeType: item.stickerItem.mimeType, keywords: item.stickerItem.keywords))
} else if let resource = item.stickerItem.resource { } else if let resource = item.stickerItem.resource {
stickers.append(ImportSticker(resource: .standalone(resource: resource._asResource()), emojis: item.stickerItem.emojis, dimensions: dimensions, mimeType: item.stickerItem.mimeType, keywords: item.stickerItem.keywords)) stickers.append(ImportSticker(resource: .standalone(resource: resource._asResource()), emojis: item.stickerItem.emojis, dimensions: dimensions, duration: nil, mimeType: item.stickerItem.mimeType, keywords: item.stickerItem.keywords))
} }
} }
var thumbnailSticker: ImportSticker? var thumbnailSticker: ImportSticker?
@ -638,7 +638,7 @@ final class ImportStickerPackControllerNode: ViewControllerTracingNode, ASScroll
} }
let resource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max)) let resource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max))
self.context.account.postbox.mediaBox.storeResourceData(resource.id, data: thumbnail.data) self.context.account.postbox.mediaBox.storeResourceData(resource.id, data: thumbnail.data)
thumbnailSticker = ImportSticker(resource: .standalone(resource: resource), emojis: [], dimensions: dimensions, mimeType: thumbnail.mimeType, keywords: thumbnail.keywords) thumbnailSticker = ImportSticker(resource: .standalone(resource: resource), emojis: [], dimensions: dimensions, duration: nil, mimeType: thumbnail.mimeType, keywords: thumbnail.keywords)
} }
let firstStickerItem = thumbnailSticker ?? stickers.first let firstStickerItem = thumbnailSticker ?? stickers.first

View File

@ -717,6 +717,16 @@ private final class StickerPackContainer: ASDisplayNode {
if let reorderPosition = self.reorderPosition, let file = itemNode.stickerPackItem?.file { if let reorderPosition = self.reorderPosition, let file = itemNode.stickerPackItem?.file {
let _ = self.context.engine.stickers.reorderSticker(sticker: .standalone(media: file), position: reorderPosition).startStandalone() let _ = self.context.engine.stickers.reorderSticker(sticker: .standalone(media: file), position: reorderPosition).startStandalone()
if let (info, items, isInstalled) = self.currentStickerPack {
var updatedItems = items
if let index = items.firstIndex(where: { $0.file.fileId == file.fileId }) {
let item = items[index]
updatedItems.remove(at: index)
updatedItems.insert(item, at: reorderPosition)
}
self.currentStickerPack = (info, updatedItems, isInstalled)
}
} }
} else { } else {
reorderNode.removeFromSupernode() reorderNode.removeFromSupernode()
@ -1256,6 +1266,7 @@ private final class StickerPackContainer: ASDisplayNode {
resource: .standalone(resource: file.resource), resource: .standalone(resource: file.resource),
emojis: emoji, emojis: emoji,
dimensions: file.dimensions ?? PixelDimensions(width: 512, height: 512), dimensions: file.dimensions ?? PixelDimensions(width: 512, height: 512),
duration: file.duration,
mimeType: file.mimeType, mimeType: file.mimeType,
keywords: "" keywords: ""
) )
@ -1305,6 +1316,7 @@ private final class StickerPackContainer: ASDisplayNode {
resource: file.resourceReference(file.media.resource), resource: file.resourceReference(file.media.resource),
emojis: [emoji], emojis: [emoji],
dimensions: file.media.dimensions ?? PixelDimensions(width: 512, height: 512), dimensions: file.media.dimensions ?? PixelDimensions(width: 512, height: 512),
duration: file.media.duration,
mimeType: file.media.mimeType, mimeType: file.media.mimeType,
keywords: "" keywords: ""
) )
@ -1347,6 +1359,7 @@ private final class StickerPackContainer: ASDisplayNode {
resource: .standalone(resource: file.resource), resource: .standalone(resource: file.resource),
emojis: emoji, emojis: emoji,
dimensions: file.dimensions ?? PixelDimensions(width: 512, height: 512), dimensions: file.dimensions ?? PixelDimensions(width: 512, height: 512),
duration: file.duration,
mimeType: file.mimeType, mimeType: file.mimeType,
keywords: "" keywords: ""
) )
@ -1856,12 +1869,14 @@ private final class StickerPackContainer: ASDisplayNode {
entries.append(.sticker(index: entries.count, stableId: resolvedStableId, stickerItem: item, isEmpty: false, isPremium: isPremium, isLocked: isLocked, isEditing: false, isAdd: false)) entries.append(.sticker(index: entries.count, stableId: resolvedStableId, stickerItem: item, isEmpty: false, isPremium: isPremium, isLocked: isLocked, isEditing: false, isAdd: false))
} }
var addedReorderItem = false
var currentIndex: Int = 0 var currentIndex: Int = 0
for item in generalItems { for item in generalItems {
if self.isReordering, let reorderNode = self.reorderNode, let reorderItem = reorderNode.itemNode?.stickerPackItem, let reorderPosition = self.reorderPosition { if self.isReordering, let reorderItem = self.reorderNode?.itemNode?.stickerPackItem, let reorderPosition = self.reorderPosition {
if currentIndex == reorderPosition { if currentIndex == reorderPosition {
addItem(reorderItem, false, false) addItem(reorderItem, false, false)
currentIndex += 1 currentIndex += 1
addedReorderItem = true
} }
if item.file.fileId == reorderItem.file.fileId { if item.file.fileId == reorderItem.file.fileId {
@ -1875,6 +1890,11 @@ private final class StickerPackContainer: ASDisplayNode {
currentIndex += 1 currentIndex += 1
} }
} }
if !addedReorderItem, let reorderItem = self.reorderNode?.itemNode?.stickerPackItem, let reorderPosition = self.reorderPosition, currentIndex == reorderPosition {
addItem(reorderItem, false, false)
currentIndex += 1
addedReorderItem = true
}
if !premiumConfiguration.isPremiumDisabled { if !premiumConfiguration.isPremiumDisabled {
if !premiumItems.isEmpty { if !premiumItems.isEmpty {

View File

@ -33,7 +33,7 @@ private func uploadedSticker(postbox: Postbox, network: Network, resource: Media
} }
} }
func _internal_uploadSticker(account: Account, peer: Peer, resource: MediaResource, alt: String, dimensions: PixelDimensions, mimeType: String) -> Signal<UploadStickerStatus, UploadStickerError> { func _internal_uploadSticker(account: Account, peer: Peer, resource: MediaResource, alt: String, dimensions: PixelDimensions, duration: Double?, mimeType: String) -> Signal<UploadStickerStatus, UploadStickerError> {
guard let inputPeer = apiInputPeer(peer) else { guard let inputPeer = apiInputPeer(peer) else {
return .fail(.generic) return .fail(.generic)
} }
@ -51,6 +51,9 @@ func _internal_uploadSticker(account: Account, peer: Peer, resource: MediaResour
let flags: Int32 = 0 let flags: Int32 = 0
var attributes: [Api.DocumentAttribute] = [] var attributes: [Api.DocumentAttribute] = []
attributes.append(.documentAttributeSticker(flags: 0, alt: alt, stickerset: .inputStickerSetEmpty, maskCoords: nil)) attributes.append(.documentAttributeSticker(flags: 0, alt: alt, stickerset: .inputStickerSetEmpty, maskCoords: nil))
if let duration {
attributes.append(.documentAttributeVideo(flags: 0, duration: duration, w: dimensions.width, h: dimensions.height, preloadPrefixSize: nil))
}
attributes.append(.documentAttributeImageSize(w: dimensions.width, h: dimensions.height)) attributes.append(.documentAttributeImageSize(w: dimensions.width, h: dimensions.height))
return account.network.request(Api.functions.messages.uploadMedia(flags: 0, businessConnectionId: nil, peer: inputPeer, media: Api.InputMedia.inputMediaUploadedDocument(flags: flags, file: file, thumb: nil, mimeType: mimeType, attributes: attributes, stickers: nil, ttlSeconds: nil))) return account.network.request(Api.functions.messages.uploadMedia(flags: 0, businessConnectionId: nil, peer: inputPeer, media: Api.InputMedia.inputMediaUploadedDocument(flags: flags, file: file, thumb: nil, mimeType: mimeType, attributes: attributes, stickers: nil, ttlSeconds: nil)))
|> mapError { _ -> UploadStickerError in return .generic } |> mapError { _ -> UploadStickerError in return .generic }
@ -80,13 +83,15 @@ public struct ImportSticker {
public let resource: MediaResourceReference public let resource: MediaResourceReference
let emojis: [String] let emojis: [String]
public let dimensions: PixelDimensions public let dimensions: PixelDimensions
public let duration: Double?
public let mimeType: String public let mimeType: String
public let keywords: String public let keywords: String
public init(resource: MediaResourceReference, emojis: [String], dimensions: PixelDimensions, mimeType: String, keywords: String) { public init(resource: MediaResourceReference, emojis: [String], dimensions: PixelDimensions, duration: Double?, mimeType: String, keywords: String) {
self.resource = resource self.resource = resource
self.emojis = emojis self.emojis = emojis
self.dimensions = dimensions self.dimensions = dimensions
self.duration = duration
self.mimeType = mimeType self.mimeType = mimeType
self.keywords = keywords self.keywords = keywords
} }
@ -102,6 +107,7 @@ public extension ImportSticker {
fileAttributes.append(.FileName(fileName: "sticker.webm")) fileAttributes.append(.FileName(fileName: "sticker.webm"))
fileAttributes.append(.Animated) fileAttributes.append(.Animated)
fileAttributes.append(.Sticker(displayText: "", packReference: nil, maskData: nil)) fileAttributes.append(.Sticker(displayText: "", packReference: nil, maskData: nil))
fileAttributes.append(.Video(duration: self.duration ?? 3.0, size: self.dimensions, flags: [], preloadSize: nil))
} else if self.mimeType == "application/x-tgsticker" { } else if self.mimeType == "application/x-tgsticker" {
fileAttributes.append(.FileName(fileName: "sticker.tgs")) fileAttributes.append(.FileName(fileName: "sticker.tgs"))
fileAttributes.append(.Animated) fileAttributes.append(.Animated)
@ -153,7 +159,7 @@ func _internal_createStickerSet(account: Account, title: String, shortName: Stri
if let resource = sticker.resource.resource as? CloudDocumentMediaResource { if let resource = sticker.resource.resource as? CloudDocumentMediaResource {
uploadStickers.append(.single(.complete(resource, sticker.mimeType))) uploadStickers.append(.single(.complete(resource, sticker.mimeType)))
} else { } else {
uploadStickers.append(_internal_uploadSticker(account: account, peer: peer, resource: sticker.resource.resource, alt: sticker.emojis.first ?? "", dimensions: sticker.dimensions, mimeType: sticker.mimeType) uploadStickers.append(_internal_uploadSticker(account: account, peer: peer, resource: sticker.resource.resource, alt: sticker.emojis.first ?? "", dimensions: sticker.dimensions, duration: sticker.duration, mimeType: sticker.mimeType)
|> mapError { _ -> CreateStickerSetError in |> mapError { _ -> CreateStickerSetError in
return .generic return .generic
}) })
@ -300,7 +306,7 @@ func _internal_addStickerToStickerSet(account: Account, packReference: StickerPa
uploadSticker = account.postbox.loadedPeerWithId(account.peerId) uploadSticker = account.postbox.loadedPeerWithId(account.peerId)
|> castError(AddStickerToSetError.self) |> castError(AddStickerToSetError.self)
|> mapToSignal { peer in |> mapToSignal { peer in
return _internal_uploadSticker(account: account, peer: peer, resource: sticker.resource.resource, alt: sticker.emojis.first ?? "", dimensions: sticker.dimensions, mimeType: sticker.mimeType) return _internal_uploadSticker(account: account, peer: peer, resource: sticker.resource.resource, alt: sticker.emojis.first ?? "", dimensions: sticker.dimensions, duration: sticker.duration, mimeType: sticker.mimeType)
|> mapError { _ -> AddStickerToSetError in |> mapError { _ -> AddStickerToSetError in
return .generic return .generic
} }
@ -428,7 +434,7 @@ func _internal_replaceSticker(account: Account, previousSticker: FileMediaRefere
uploadSticker = account.postbox.loadedPeerWithId(account.peerId) uploadSticker = account.postbox.loadedPeerWithId(account.peerId)
|> castError(ReplaceStickerError.self) |> castError(ReplaceStickerError.self)
|> mapToSignal { peer in |> mapToSignal { peer in
return _internal_uploadSticker(account: account, peer: peer, resource: sticker.resource.resource, alt: sticker.emojis.first ?? "", dimensions: sticker.dimensions, mimeType: sticker.mimeType) return _internal_uploadSticker(account: account, peer: peer, resource: sticker.resource.resource, alt: sticker.emojis.first ?? "", dimensions: sticker.dimensions, duration: sticker.duration, mimeType: sticker.mimeType)
|> mapError { _ -> ReplaceStickerError in |> mapError { _ -> ReplaceStickerError in
return .generic return .generic
} }

View File

@ -78,8 +78,8 @@ public extension TelegramEngine {
return _internal_stickerPacksAttachedToMedia(account: self.account, media: media) return _internal_stickerPacksAttachedToMedia(account: self.account, media: media)
} }
public func uploadSticker(peer: Peer, resource: MediaResource, alt: String, dimensions: PixelDimensions, mimeType: String) -> Signal<UploadStickerStatus, UploadStickerError> { public func uploadSticker(peer: Peer, resource: MediaResource, alt: String, dimensions: PixelDimensions, duration: Double?, mimeType: String) -> Signal<UploadStickerStatus, UploadStickerError> {
return _internal_uploadSticker(account: self.account, peer: peer, resource: resource, alt: alt, dimensions: dimensions, mimeType: mimeType) return _internal_uploadSticker(account: self.account, peer: peer, resource: resource, alt: alt, dimensions: dimensions, duration: duration, mimeType: mimeType)
} }
public func createStickerSet(title: String, shortName: String, stickers: [ImportSticker], thumbnail: ImportSticker?, type: CreateStickerSetType, software: String?) -> Signal<CreateStickerSetStatus, CreateStickerSetError> { public func createStickerSet(title: String, shortName: String, stickers: [ImportSticker], thumbnail: ImportSticker?, type: CreateStickerSetType, software: String?) -> Signal<CreateStickerSetStatus, CreateStickerSetError> {

View File

@ -6231,6 +6231,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
private var stickerRecommendedEmoji: [String] = [] private var stickerRecommendedEmoji: [String] = []
private var stickerSelectedEmoji: [String] = [] private var stickerSelectedEmoji: [String] = []
private func effectiveStickerEmoji() -> [String] { private func effectiveStickerEmoji() -> [String] {
let filtered = self.stickerSelectedEmoji.filter { !$0.isEmpty } let filtered = self.stickerSelectedEmoji.filter { !$0.isEmpty }
guard !filtered.isEmpty else { guard !filtered.isEmpty else {
@ -6238,6 +6239,23 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
} }
return filtered return filtered
} }
private func preferredStickerDuration() -> Double {
var duration: Double = 3.0
var stickerDurations: [Double] = []
self.node.entitiesView.eachView { entityView in
if let stickerEntityView = entityView as? DrawingStickerEntityView {
if let duration = stickerEntityView.duration, duration > 0.0 {
stickerDurations.append(duration)
}
}
}
if !stickerDurations.isEmpty {
duration = stickerDurations.max() ?? 3.0
}
return duration
}
private weak var stickerResultController: PeekController? private weak var stickerResultController: PeekController?
func presentStickerPreview(image: UIImage) { func presentStickerPreview(image: UIImage) {
guard let mediaEditor = self.node.mediaEditor else { guard let mediaEditor = self.node.mediaEditor else {
@ -6257,8 +6275,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
self.context.account.postbox.mediaBox.storeResourceData(isVideo ? thumbnailResource.id : resource.id, data: data) self.context.account.postbox.mediaBox.storeResourceData(isVideo ? thumbnailResource.id : resource.id, data: data)
} }
} }
var file = stickerFile(resource: resource, thumbnailResource: thumbnailResource, size: Int64(0), dimensions: PixelDimensions(image.size), isVideo: isVideo) var file = stickerFile(resource: resource, thumbnailResource: thumbnailResource, size: Int64(0), dimensions: PixelDimensions(image.size), duration: self.preferredStickerDuration(), isVideo: isVideo)
let emoji = self.stickerSelectedEmoji
var menuItems: [ContextMenuItem] = [] var menuItems: [ContextMenuItem] = []
if case let .stickerEditor(mode) = self.mode { if case let .stickerEditor(mode) = self.mode {
@ -6274,7 +6291,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
} else { } else {
self.stickerResultController?.disappeared = nil self.stickerResultController?.disappeared = nil
self.completion(MediaEditorScreen.Result( self.completion(MediaEditorScreen.Result(
media: .sticker(file: file, emoji: emoji), media: .sticker(file: file, emoji: self.effectiveStickerEmoji()),
mediaAreas: [], mediaAreas: [],
caption: NSAttributedString(), caption: NSAttributedString(),
options: MediaEditorResultPrivacy(sendAsPeerId: nil, privacy: EngineStoryPrivacy(base: .everyone, additionallyIncludePeers: []), timeout: 0, isForwardingDisabled: false, pin: false), options: MediaEditorResultPrivacy(sendAsPeerId: nil, privacy: EngineStoryPrivacy(base: .everyone, additionallyIncludePeers: []), timeout: 0, isForwardingDisabled: false, pin: false),
@ -6465,8 +6482,9 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
ImportSticker( ImportSticker(
resource: .standalone(resource: file.resource), resource: .standalone(resource: file.resource),
emojis: self.effectiveStickerEmoji(), emojis: self.effectiveStickerEmoji(),
dimensions: PixelDimensions(width: 512, height: 512), dimensions: file.dimensions ?? PixelDimensions(width: 512, height: 512),
mimeType: "image/webp", duration: file.duration,
mimeType: file.mimeType,
keywords: "" keywords: ""
) )
], ],
@ -6512,9 +6530,10 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
private func uploadSticker(_ file: TelegramMediaFile, action: StickerAction) { private func uploadSticker(_ file: TelegramMediaFile, action: StickerAction) {
let context = self.context let context = self.context
let dimensions = PixelDimensions(width: 512, height: 512) let dimensions = PixelDimensions(width: 512, height: 512)
let duration = file.duration
let mimeType = file.mimeType let mimeType = file.mimeType
let isVideo = file.mimeType == "video/webm" let isVideo = file.mimeType == "video/webm"
let emoji = self.stickerSelectedEmoji let emojis = self.effectiveStickerEmoji()
var isUpdate = false var isUpdate = false
if case .update = action { if case .update = action {
@ -6578,13 +6597,13 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
if let resource = resource as? CloudDocumentMediaResource { if let resource = resource as? CloudDocumentMediaResource {
return .single(.progress(1.0)) |> then(.single(.complete(resource, mimeType))) return .single(.progress(1.0)) |> then(.single(.complete(resource, mimeType)))
} else { } else {
return context.engine.stickers.uploadSticker(peer: peer._asPeer(), resource: resource, alt: "", dimensions: dimensions, mimeType: mimeType) return context.engine.stickers.uploadSticker(peer: peer._asPeer(), resource: resource, alt: "", dimensions: dimensions, duration: duration, mimeType: mimeType)
|> mapToSignal { status -> Signal<UploadStickerStatus, UploadStickerError> in |> mapToSignal { status -> Signal<UploadStickerStatus, UploadStickerError> in
switch status { switch status {
case let .progress(progress): case let .progress(progress):
return .single(.progress(isVideo ? 0.5 + progress * 0.5 : progress)) return .single(.progress(isVideo ? 0.5 + progress * 0.5 : progress))
case let .complete(resource, _): case let .complete(resource, _):
let file = stickerFile(resource: resource, thumbnailResource: file.previewRepresentations.first?.resource, size: file.size ?? 0, dimensions: dimensions, isVideo: isVideo) let file = stickerFile(resource: resource, thumbnailResource: file.previewRepresentations.first?.resource, size: file.size ?? 0, dimensions: dimensions, duration: file.duration, isVideo: isVideo)
switch action { switch action {
case .send: case .send:
return .single(status) return .single(status)
@ -6599,8 +6618,9 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
case let .createStickerPack(title): case let .createStickerPack(title):
let sticker = ImportSticker( let sticker = ImportSticker(
resource: .standalone(resource: resource), resource: .standalone(resource: resource),
emojis: self.effectiveStickerEmoji(), emojis: emojis,
dimensions: dimensions, dimensions: dimensions,
duration: duration,
mimeType: mimeType, mimeType: mimeType,
keywords: "" keywords: ""
) )
@ -6618,8 +6638,9 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
case let .addToStickerPack(pack, _): case let .addToStickerPack(pack, _):
let sticker = ImportSticker( let sticker = ImportSticker(
resource: .standalone(resource: resource), resource: .standalone(resource: resource),
emojis: self.effectiveStickerEmoji(), emojis: emojis,
dimensions: dimensions, dimensions: dimensions,
duration: duration,
mimeType: mimeType, mimeType: mimeType,
keywords: "" keywords: ""
) )
@ -6659,10 +6680,10 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
let result: MediaEditorScreen.Result let result: MediaEditorScreen.Result
switch action { switch action {
case .update: case .update:
result = MediaEditorScreen.Result(media: .sticker(file: file, emoji: emoji)) result = MediaEditorScreen.Result(media: .sticker(file: file, emoji: emojis))
case .upload, .send: case .upload, .send:
let file = stickerFile(resource: resource, thumbnailResource: file.previewRepresentations.first?.resource, size: resource.size ?? 0, dimensions: dimensions, isVideo: isVideo) let file = stickerFile(resource: resource, thumbnailResource: file.previewRepresentations.first?.resource, size: resource.size ?? 0, dimensions: dimensions, duration: self.preferredStickerDuration(), isVideo: isVideo)
result = MediaEditorScreen.Result(media: .sticker(file: file, emoji: emoji)) result = MediaEditorScreen.Result(media: .sticker(file: file, emoji: emojis))
default: default:
result = MediaEditorScreen.Result() result = MediaEditorScreen.Result()
} }
@ -6844,18 +6865,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
duration = video.duration.seconds duration = video.duration.seconds
} }
if isSticker { if isSticker {
duration = 3.0 duration = self.preferredStickerDuration()
var stickerDurations: [Double] = []
self.node.entitiesView.eachView { entityView in
if let stickerEntityView = entityView as? DrawingStickerEntityView {
if let duration = stickerEntityView.duration, duration > 0.0 {
stickerDurations.append(duration)
}
}
}
if !stickerDurations.isEmpty {
duration = stickerDurations.max() ?? 3.0
}
} }
let configuration = recommendedVideoExportConfiguration(values: mediaEditor.values, duration: duration, forceFullHd: true, frameRate: 60.0, isSticker: isSticker) let configuration = recommendedVideoExportConfiguration(values: mediaEditor.values, duration: duration, forceFullHd: true, frameRate: 60.0, isSticker: isSticker)
let outputPath = NSTemporaryDirectory() + "\(Int64.random(in: 0 ..< .max)).\(fileExtension)" let outputPath = NSTemporaryDirectory() + "\(Int64.random(in: 0 ..< .max)).\(fileExtension)"
@ -7610,12 +7620,15 @@ extension MediaScrubberComponent.Track {
} }
} }
private func stickerFile(resource: TelegramMediaResource, thumbnailResource: TelegramMediaResource?, size: Int64, dimensions: PixelDimensions, isVideo: Bool) -> TelegramMediaFile { private func stickerFile(resource: TelegramMediaResource, thumbnailResource: TelegramMediaResource?, size: Int64, dimensions: PixelDimensions, duration: Double?, isVideo: Bool) -> TelegramMediaFile {
var fileAttributes: [TelegramMediaFileAttribute] = [] var fileAttributes: [TelegramMediaFileAttribute] = []
fileAttributes.append(.FileName(fileName: isVideo ? "sticker.webm" : "sticker.webp")) fileAttributes.append(.FileName(fileName: isVideo ? "sticker.webm" : "sticker.webp"))
fileAttributes.append(.Sticker(displayText: "", packReference: nil, maskData: nil)) fileAttributes.append(.Sticker(displayText: "", packReference: nil, maskData: nil))
fileAttributes.append(.ImageSize(size: dimensions)) if isVideo {
fileAttributes.append(.Video(duration: duration ?? 3.0, size: dimensions, flags: [], preloadSize: nil))
} else {
fileAttributes.append(.ImageSize(size: dimensions))
}
var previewRepresentations: [TelegramMediaImageRepresentation] = [] var previewRepresentations: [TelegramMediaImageRepresentation] = []
if let thumbnailResource { if let thumbnailResource {
previewRepresentations.append(TelegramMediaImageRepresentation(dimensions: dimensions, resource: thumbnailResource, progressiveSizes: [], immediateThumbnailData: nil)) previewRepresentations.append(TelegramMediaImageRepresentation(dimensions: dimensions, resource: thumbnailResource, progressiveSizes: [], immediateThumbnailData: nil))

View File

@ -761,7 +761,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
if file.isAnimatedSticker { if file.isAnimatedSticker {
thumbnailItem = .animated(EngineMediaResource(file.resource)) thumbnailItem = .animated(EngineMediaResource(file.resource))
resourceReference = MediaResourceReference.media(media: .standalone(media: file), resource: file.resource) resourceReference = MediaResourceReference.media(media: .standalone(media: file), resource: file.resource)
} else if let dimensions = file.dimensions, let resource = chatMessageStickerResource(file: file, small: true) as? TelegramMediaResource { } else if let dimensions = file.dimensions, let resource = chatMessageStickerResource(file: file, small: false) as? TelegramMediaResource {
thumbnailItem = .still(TelegramMediaImageRepresentation(dimensions: dimensions, resource: resource, progressiveSizes: [], immediateThumbnailData: nil, hasVideo: false, isPersonal: false)) thumbnailItem = .still(TelegramMediaImageRepresentation(dimensions: dimensions, resource: resource, progressiveSizes: [], immediateThumbnailData: nil, hasVideo: false, isPersonal: false))
resourceReference = MediaResourceReference.media(media: .standalone(media: file), resource: resource) resourceReference = MediaResourceReference.media(media: .standalone(media: file), resource: resource)
} }