[WIP] Stickers editor

This commit is contained in:
Ilya Laktyushin 2024-04-06 19:53:19 +04:00
parent 7c6651db34
commit ee2b7be5e2
19 changed files with 263 additions and 65 deletions

View File

@ -1024,7 +1024,7 @@ public protocol SharedAccountContext: AnyObject {
func makeStickerMediaPickerScreen(context: AccountContext, getSourceRect: @escaping () -> CGRect, completion: @escaping (Any?, UIView?, CGRect, UIImage?, @escaping (Bool?) -> (UIView, CGRect)?, @escaping () -> Void) -> Void, dismissed: @escaping () -> Void) -> ViewController
func makeStoryMediaPickerScreen(context: AccountContext, getSourceRect: @escaping () -> CGRect, completion: @escaping (Any, UIView, CGRect, UIImage?, @escaping (Bool?) -> (UIView, CGRect)?, @escaping () -> Void) -> Void, dismissed: @escaping () -> Void, groupsPresented: @escaping () -> Void) -> ViewController
func makeStickerPickerScreen(context: AccountContext, inputData: Promise<StickerPickerInput>, completion: @escaping (TelegramMediaFile) -> Void) -> ViewController
func makeStickerPickerScreen(context: AccountContext, inputData: Promise<StickerPickerInput>, completion: @escaping (FileMediaReference) -> Void) -> ViewController
func makeProxySettingsController(sharedContext: SharedAccountContext, account: UnauthorizedAccount) -> ViewController

View File

@ -189,7 +189,7 @@ public class DrawingReactionEntityView: DrawingStickerEntityView {
}
if case let .file(_, type) = self.stickerEntity.content, case let .reaction(_, style) = type {
self.stickerEntity.content = .file(animation, .reaction(updateReaction.reaction, style))
self.stickerEntity.content = .file(.standalone(media: animation), .reaction(updateReaction.reaction, style))
}
var nodeToTransitionOut: ASDisplayNode?

View File

@ -2893,13 +2893,13 @@ public class DrawingScreen: ViewController, TGPhotoDrawingInterfaceController, U
for entity in self.entitiesView.entities {
if let sticker = entity as? DrawingStickerEntity, case let .file(file, _) = sticker.content {
let coder = PostboxEncoder()
coder.encodeRootObject(file)
coder.encodeRootObject(file.media)
stickers.append(coder.makeData())
} else if let text = entity as? DrawingTextEntity, let subEntities = text.renderSubEntities {
for sticker in subEntities {
if let sticker = sticker as? DrawingStickerEntity, case let .file(file, _) = sticker.content {
let coder = PostboxEncoder()
coder.encodeRootObject(file)
coder.encodeRootObject(file.media)
stickers.append(coder.makeData())
}
}

View File

@ -118,7 +118,7 @@ public class DrawingStickerEntityView: DrawingEntityView {
private var file: TelegramMediaFile? {
if case let .file(file, _) = self.stickerEntity.content {
return file
return file.media
} else {
return nil
}
@ -158,7 +158,7 @@ public class DrawingStickerEntityView: DrawingEntityView {
private var dimensions: CGSize {
switch self.stickerEntity.content {
case let .file(file, _):
return file.dimensions?.cgSize ?? CGSize(width: 512.0, height: 512.0)
return file.media.dimensions?.cgSize ?? CGSize(width: 512.0, height: 512.0)
case let .image(image, _):
return image.size
case let .animatedImage(_, thumbnailImage):
@ -174,7 +174,7 @@ public class DrawingStickerEntityView: DrawingEntityView {
private func updateAnimationColor() {
let color: UIColor?
if case let .file(file, type) = self.stickerEntity.content, file.isCustomTemplateEmoji {
if case let .file(file, type) = self.stickerEntity.content, file.media.isCustomTemplateEmoji {
if case let .reaction(_, style) = type {
if case .white = style {
color = UIColor(rgb: 0x000000)

View File

@ -725,7 +725,7 @@ public final class DrawingTextEntityView: DrawingEntityView, UITextViewDelegate
let itemSize: CGFloat = floor(24.0 * fontSize * 0.78 / 17.0)
let emojiTextPosition = emojiRect.center.offsetBy(dx: -textSize.width / 2.0, dy: -textSize.height / 2.0)
let entity = DrawingStickerEntity(content: .file(file, .sticker))
let entity = DrawingStickerEntity(content: .file(.standalone(media: file), .sticker))
entity.referenceDrawingSize = CGSize(width: itemSize * 4.0, height: itemSize * 4.0)
entity.scale = scale
entity.position = textPosition.offsetBy(

View File

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

View File

@ -102,7 +102,8 @@ private class LegacyPaintStickerEntity: LegacyPaintEntity {
self.animated = entity.isAnimated
switch entity.content {
case let .file(file, _):
case let .file(fileReference, _):
let file = fileReference.media
self.file = file
if file.isAnimatedSticker || file.isVideoSticker || file.mimeType == "video/webm" {
self.source = AnimatedStickerResourceSource(postbox: postbox, resource: file.resource, isVideo: file.isVideoSticker || file.mimeType == "video/webm")

View File

@ -25,6 +25,8 @@ import Pasteboard
import StickerPackEditTitleController
import EntityKeyboard
private let maxStickersCount = 120
private enum StickerPackPreviewGridEntry: Comparable, Identifiable {
case sticker(index: Int, stableId: Int, stickerItem: StickerPackItem?, isEmpty: Bool, isPremium: Bool, isLocked: Bool, isEditing: Bool, isAdd: Bool)
case add
@ -1251,7 +1253,7 @@ private final class StickerPackContainer: ASDisplayNode {
completion: { file, emoji, commit in
dismissImpl?()
let sticker = ImportSticker(
resource: file.resource,
resource: .standalone(resource: file.resource),
emojis: emoji,
dimensions: file.dimensions ?? PixelDimensions(width: 512, height: 512),
mimeType: file.mimeType,
@ -1292,18 +1294,18 @@ private final class StickerPackContainer: ASDisplayNode {
let context = self.context
let controller = self.context.sharedContext.makeStickerPickerScreen(context: self.context, inputData: self.stickerPickerInputData, completion: { file in
var emoji = "🫥"
for attribute in file.attributes {
if case let .Sticker(displayText, _, _) = attribute {
for attribute in file.media.attributes {
if case let .Sticker(displayText, _, _) = attribute, !displayText.isEmpty {
emoji = displayText
break
}
}
let sticker = ImportSticker(
resource: file.resource,
resource: file.resourceReference(file.media.resource),
emojis: [emoji],
dimensions: file.dimensions ?? PixelDimensions(width: 512, height: 512),
mimeType: file.mimeType,
dimensions: file.media.dimensions ?? PixelDimensions(width: 512, height: 512),
mimeType: file.media.mimeType,
keywords: ""
)
let packReference: StickerPackReference = .id(id: info.id.id, accessHash: info.accessHash)
@ -1313,7 +1315,7 @@ private final class StickerPackContainer: ASDisplayNode {
(navigationController?.viewControllers.last as? ViewController)?.present(packController, in: .window(.root))
Queue.mainQueue().after(0.1) {
packController.present(UndoOverlayController(presentationData: presentationData, content: .sticker(context: context, file: file, loop: true, title: nil, text: "Sticker added to **\(info.title)** sticker set.", undoText: nil, customAction: nil), elevatedLayout: false, action: { _ in return false }), in: .current)
packController.present(UndoOverlayController(presentationData: presentationData, content: .sticker(context: context, file: file.media, loop: true, title: nil, text: "Sticker added to **\(info.title)** sticker set.", undoText: nil, customAction: nil), elevatedLayout: false, action: { _ in return false }), in: .current)
}
})
})
@ -1342,7 +1344,7 @@ private final class StickerPackContainer: ASDisplayNode {
transitionArguments: nil,
completion: { file, emoji, commit in
let sticker = ImportSticker(
resource: file.resource,
resource: .standalone(resource: file.resource),
emojis: emoji,
dimensions: file.dimensions ?? PixelDimensions(width: 512, height: 512),
mimeType: file.mimeType,
@ -1787,7 +1789,7 @@ private final class StickerPackContainer: ASDisplayNode {
self.updateButton(count: count)
}
if GlobalExperimentalSettings.enableWIPStickers && info.flags.contains(.isCreator) && !info.flags.contains(.isEmoji) {
if GlobalExperimentalSettings.enableWIPStickers && info.flags.contains(.isCreator) && !info.flags.contains(.isEmoji) && entries.count < maxStickersCount {
entries.append(.add)
}
}
@ -1883,7 +1885,9 @@ private final class StickerPackContainer: ASDisplayNode {
}
}
if entries.count < maxStickersCount {
entries.append(.add)
}
self.currentEntries = entries

View File

@ -299,6 +299,8 @@ private enum MediaReferenceRevalidationKey: Hashable {
case webPage(webPage: WebpageReference)
case stickerPack(stickerPack: StickerPackReference)
case savedGifs
case savedStickers
case recentStickers
case peer(peer: PeerReference)
case wallpaper(wallpaper: WallpaperReference)
case wallpapers
@ -544,6 +546,66 @@ final class MediaReferenceRevalidationContext {
}
}
func savedStickers(postbox: Postbox, network: Network, background: Bool) -> Signal<[TelegramMediaFile], RevalidateMediaReferenceError> {
return self.genericItem(key: .savedStickers, background: background, request: { next, error in
let loadSavedStickers: Signal<[TelegramMediaFile], NoError> = postbox.transaction { transaction -> [TelegramMediaFile] in
return transaction.getOrderedListItems(collectionId: Namespaces.OrderedItemList.CloudSavedStickers).compactMap({ item -> TelegramMediaFile? in
if let contents = item.contents.get(RecentMediaItem.self) {
let file = contents.media
return file
}
return nil
})
}
return (managedSavedStickers(postbox: postbox, network: network, forceFetch: true)
|> mapToSignal { _ -> Signal<[TelegramMediaFile], NoError> in
return .complete()
}
|> then(loadSavedStickers)
|> castError(RevalidateMediaReferenceError.self)).start(next: { value in
next(value)
}, error: { _ in
error(.generic)
})
}) |> mapToSignal { next -> Signal<[TelegramMediaFile], RevalidateMediaReferenceError> in
if let next = next as? [TelegramMediaFile] {
return .single(next)
} else {
return .fail(.generic)
}
}
}
func recentStickers(postbox: Postbox, network: Network, background: Bool) -> Signal<[TelegramMediaFile], RevalidateMediaReferenceError> {
return self.genericItem(key: .recentStickers, background: background, request: { next, error in
let loadRecentStickers: Signal<[TelegramMediaFile], NoError> = postbox.transaction { transaction -> [TelegramMediaFile] in
return transaction.getOrderedListItems(collectionId: Namespaces.OrderedItemList.CloudRecentStickers).compactMap({ item -> TelegramMediaFile? in
if let contents = item.contents.get(RecentMediaItem.self) {
let file = contents.media
return file
}
return nil
})
}
return (managedRecentStickers(postbox: postbox, network: network, forceFetch: true)
|> mapToSignal { _ -> Signal<[TelegramMediaFile], NoError> in
return .complete()
}
|> then(loadRecentStickers)
|> castError(RevalidateMediaReferenceError.self)).start(next: { value in
next(value)
}, error: { _ in
error(.generic)
})
}) |> mapToSignal { next -> Signal<[TelegramMediaFile], RevalidateMediaReferenceError> in
if let next = next as? [TelegramMediaFile] {
return .single(next)
} else {
return .fail(.generic)
}
}
}
func peer(accountPeerId: PeerId, postbox: Postbox, network: Network, background: Bool, peer: PeerReference) -> Signal<Peer, RevalidateMediaReferenceError> {
return self.genericItem(key: .peer(peer: peer), background: background, request: { next, error in
return (_internal_updatedRemotePeer(accountPeerId: accountPeerId, postbox: postbox, network: network, peer: peer)
@ -811,6 +873,30 @@ func revalidateMediaResourceReference(accountPeerId: PeerId, postbox: Postbox, n
}
return .fail(.generic)
}
case let .savedSticker(media):
return revalidationContext.savedStickers(postbox: postbox, network: network, background: info.preferBackgroundReferenceRevalidation)
|> mapToSignal { result -> Signal<RevalidatedMediaResource, RevalidateMediaReferenceError> in
for file in result {
if media.id != nil && file.id == media.id {
if let updatedResource = findUpdatedMediaResource(media: file, previousMedia: media, resource: resource) {
return .single(RevalidatedMediaResource(updatedResource: updatedResource, updatedReference: nil))
}
}
}
return .fail(.generic)
}
case let .recentSticker(media):
return revalidationContext.recentStickers(postbox: postbox, network: network, background: info.preferBackgroundReferenceRevalidation)
|> mapToSignal { result -> Signal<RevalidatedMediaResource, RevalidateMediaReferenceError> in
for file in result {
if media.id != nil && file.id == media.id {
if let updatedResource = findUpdatedMediaResource(media: file, previousMedia: media, resource: resource) {
return .single(RevalidatedMediaResource(updatedResource: updatedResource, updatedReference: nil))
}
}
}
return .fail(.generic)
}
case let .avatarList(peer, media):
return revalidationContext.peerAvatars(accountPeerId: accountPeerId, postbox: postbox, network: network, background: info.preferBackgroundReferenceRevalidation, peer: peer)
|> mapToSignal { result -> Signal<RevalidatedMediaResource, RevalidateMediaReferenceError> in

View File

@ -42,8 +42,8 @@ private func managedRecentMedia(postbox: Postbox, network: Network, collectionId
} |> switchToLatest
}
func managedRecentStickers(postbox: Postbox, network: Network) -> Signal<Void, NoError> {
return managedRecentMedia(postbox: postbox, network: network, collectionId: Namespaces.OrderedItemList.CloudRecentStickers, extractItemId: { RecentMediaItemId($0).mediaId.id }, reverseHashOrder: false, forceFetch: false, fetch: { hash in
func managedRecentStickers(postbox: Postbox, network: Network, forceFetch: Bool = false) -> Signal<Void, NoError> {
return managedRecentMedia(postbox: postbox, network: network, collectionId: Namespaces.OrderedItemList.CloudRecentStickers, extractItemId: { RecentMediaItemId($0).mediaId.id }, reverseHashOrder: false, forceFetch: forceFetch, fetch: { hash in
return network.request(Api.functions.messages.getRecentStickers(flags: 0, hash: hash))
|> retryRequest
|> mapToSignal { result -> Signal<[OrderedItemListEntry]?, NoError> in
@ -88,8 +88,8 @@ func managedRecentGifs(postbox: Postbox, network: Network, forceFetch: Bool = fa
})
}
func managedSavedStickers(postbox: Postbox, network: Network) -> Signal<Void, NoError> {
return managedRecentMedia(postbox: postbox, network: network, collectionId: Namespaces.OrderedItemList.CloudSavedStickers, extractItemId: { RecentMediaItemId($0).mediaId.id }, reverseHashOrder: true, forceFetch: false, fetch: { hash in
func managedSavedStickers(postbox: Postbox, network: Network, forceFetch: Bool = false) -> Signal<Void, NoError> {
return managedRecentMedia(postbox: postbox, network: network, collectionId: Namespaces.OrderedItemList.CloudSavedStickers, extractItemId: { RecentMediaItemId($0).mediaId.id }, reverseHashOrder: true, forceFetch: forceFetch, fetch: { hash in
return network.request(Api.functions.messages.getFavedStickers(hash: hash))
|> retryRequest
|> mapToSignal { result -> Signal<[OrderedItemListEntry]?, NoError> in

View File

@ -262,6 +262,8 @@ public enum AnyMediaReference: Equatable {
case webPage(webPage: WebpageReference, media: Media)
case stickerPack(stickerPack: StickerPackReference, media: Media)
case savedGif(media: Media)
case savedSticker(media: Media)
case recentSticker(media: Media)
case avatarList(peer: PeerReference, media: Media)
case attachBot(peer: PeerReference, media: Media)
case customEmoji(media: Media)
@ -299,6 +301,18 @@ public enum AnyMediaReference: Equatable {
} else {
return false
}
case let .savedSticker(lhsMedia):
if case let .savedSticker(rhsMedia) = rhs, lhsMedia.isEqual(to: rhsMedia) {
return true
} else {
return false
}
case let .recentSticker(lhsMedia):
if case let .recentSticker(rhsMedia) = rhs, lhsMedia.isEqual(to: rhsMedia) {
return true
} else {
return false
}
case let .avatarList(lhsPeer, lhsMedia):
if case let .avatarList(rhsPeer, rhsMedia) = rhs, lhsPeer == rhsPeer, lhsMedia.isEqual(to: rhsMedia) {
return true
@ -338,6 +352,10 @@ public enum AnyMediaReference: Equatable {
return .stickerPack(stickerPack: stickerPack)
case .savedGif:
return .savedGif
case .savedSticker:
return .savedSticker
case .recentSticker:
return .recentSticker
case .avatarList:
return nil
case .attachBot:
@ -371,6 +389,14 @@ public enum AnyMediaReference: Equatable {
if let media = media as? T {
return .savedGif(media: media)
}
case let .savedSticker(media):
if let media = media as? T {
return .savedSticker(media: media)
}
case let .recentSticker(media):
if let media = media as? T {
return .recentSticker(media: media)
}
case let .avatarList(peer, media):
if let media = media as? T {
return .avatarList(peer: peer, media: media)
@ -403,6 +429,10 @@ public enum AnyMediaReference: Equatable {
return media
case let .savedGif(media):
return media
case let .savedSticker(media):
return media
case let .recentSticker(media):
return media
case let .avatarList(_, media):
return media
case let .attachBot(_, media):
@ -425,12 +455,16 @@ public enum PartialMediaReference: Equatable {
case webPage
case stickerPack
case savedGif
case savedSticker
case recentSticker
}
case message(message: MessageReference)
case webPage(webPage: WebpageReference)
case stickerPack(stickerPack: StickerPackReference)
case savedGif
case savedSticker
case recentSticker
public init?(decoder: PostboxDecoder) {
guard let caseIdValue = decoder.decodeOptionalInt32ForKey("_r"), let caseId = CodingCase(rawValue: caseIdValue) else {
@ -448,6 +482,10 @@ public enum PartialMediaReference: Equatable {
self = .stickerPack(stickerPack: stickerPack)
case .savedGif:
self = .savedGif
case .savedSticker:
self = .savedSticker
case .recentSticker:
self = .recentSticker
}
}
@ -464,6 +502,10 @@ public enum PartialMediaReference: Equatable {
encoder.encodeObject(stickerPack, forKey: "spk")
case .savedGif:
encoder.encodeInt32(CodingCase.savedGif.rawValue, forKey: "_r")
case .savedSticker:
encoder.encodeInt32(CodingCase.savedSticker.rawValue, forKey: "_r")
case .recentSticker:
encoder.encodeInt32(CodingCase.recentSticker.rawValue, forKey: "_r")
}
}
@ -477,6 +519,10 @@ public enum PartialMediaReference: Equatable {
return .stickerPack(stickerPack: stickerPack, media: media)
case .savedGif:
return .savedGif(media: media)
case .savedSticker:
return .savedSticker(media: media)
case .recentSticker:
return .recentSticker(media: media)
}
}
}
@ -488,6 +534,8 @@ public enum MediaReference<T: Media> {
case webPage
case stickerPack
case savedGif
case savedSticker
case recentSticker
case avatarList
case attachBot
case customEmoji
@ -499,6 +547,8 @@ public enum MediaReference<T: Media> {
case webPage(webPage: WebpageReference, media: T)
case stickerPack(stickerPack: StickerPackReference, media: T)
case savedGif(media: T)
case savedSticker(media: T)
case recentSticker(media: T)
case avatarList(peer: PeerReference, media: T)
case attachBot(peer: PeerReference, media: T)
case customEmoji(media: T)
@ -537,6 +587,16 @@ public enum MediaReference<T: Media> {
return nil
}
self = .savedGif(media: media)
case .savedSticker:
guard let media = decoder.decodeObjectForKey("m") as? T else {
return nil
}
self = .savedSticker(media: media)
case .recentSticker:
guard let media = decoder.decodeObjectForKey("m") as? T else {
return nil
}
self = .recentSticker(media: media)
case .avatarList:
let peer = decoder.decodeObjectForKey("pr", decoder: { PeerReference(decoder: $0) }) as! PeerReference
guard let media = decoder.decodeObjectForKey("m") as? T else {
@ -584,6 +644,12 @@ public enum MediaReference<T: Media> {
case let .savedGif(media):
encoder.encodeInt32(CodingCase.savedGif.rawValue, forKey: "_r")
encoder.encodeObject(media, forKey: "m")
case let .savedSticker(media):
encoder.encodeInt32(CodingCase.savedSticker.rawValue, forKey: "_r")
encoder.encodeObject(media, forKey: "m")
case let .recentSticker(media):
encoder.encodeInt32(CodingCase.recentSticker.rawValue, forKey: "_r")
encoder.encodeObject(media, forKey: "m")
case let .avatarList(peer, media):
encoder.encodeInt32(CodingCase.avatarList.rawValue, forKey: "_r")
encoder.encodeObject(peer, forKey: "pr")
@ -615,6 +681,10 @@ public enum MediaReference<T: Media> {
return .stickerPack(stickerPack: stickerPack, media: media)
case let .savedGif(media):
return .savedGif(media: media)
case let .savedSticker(media):
return .savedSticker(media: media)
case let .recentSticker(media):
return .recentSticker(media: media)
case let .avatarList(peer, media):
return .avatarList(peer: peer, media: media)
case let .attachBot(peer, media):
@ -642,6 +712,10 @@ public enum MediaReference<T: Media> {
return media
case let .savedGif(media):
return media
case let .savedSticker(media):
return media
case let .recentSticker(media):
return media
case let .avatarList(_, media):
return media
case let .attachBot(_, media):

View File

@ -2,7 +2,7 @@ import Foundation
import Postbox
import SwiftSignalKit
import TelegramApi
import MtProtoKit
public enum UploadStickerStatus {
case progress(Float)
@ -77,13 +77,13 @@ public enum CreateStickerSetError {
}
public struct ImportSticker {
public let resource: MediaResource
public let resource: MediaResourceReference
let emojis: [String]
public let dimensions: PixelDimensions
public let mimeType: String
public let keywords: String
public init(resource: MediaResource, emojis: [String], dimensions: PixelDimensions, mimeType: String, keywords: String) {
public init(resource: MediaResourceReference, emojis: [String], dimensions: PixelDimensions, mimeType: String, keywords: String) {
self.resource = resource
self.emojis = emojis
self.dimensions = dimensions
@ -94,7 +94,7 @@ public struct ImportSticker {
public extension ImportSticker {
var stickerPackItem: StickerPackItem? {
guard let resource = self.resource as? TelegramMediaResource else {
guard let resource = self.resource.resource as? TelegramMediaResource else {
return nil
}
var fileAttributes: [TelegramMediaFileAttribute] = []
@ -150,10 +150,10 @@ func _internal_createStickerSet(account: Account, title: String, shortName: Stri
stickers.append(thumbnail)
}
for sticker in stickers {
if let resource = sticker.resource as? CloudDocumentMediaResource {
if let resource = sticker.resource.resource as? CloudDocumentMediaResource {
uploadStickers.append(.single(.complete(resource, sticker.mimeType)))
} else {
uploadStickers.append(_internal_uploadSticker(account: account, peer: peer, resource: sticker.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, mimeType: sticker.mimeType)
|> mapError { _ -> CreateStickerSetError in
return .generic
})
@ -294,13 +294,13 @@ public enum AddStickerToSetError {
func _internal_addStickerToStickerSet(account: Account, packReference: StickerPackReference, sticker: ImportSticker) -> Signal<Bool, AddStickerToSetError> {
let uploadSticker: Signal<UploadStickerStatus, AddStickerToSetError>
if let resource = sticker.resource as? CloudDocumentMediaResource {
if let resource = sticker.resource.resource as? CloudDocumentMediaResource {
uploadSticker = .single(.complete(resource, sticker.mimeType))
} else {
uploadSticker = account.postbox.loadedPeerWithId(account.peerId)
|> castError(AddStickerToSetError.self)
|> mapToSignal { peer in
return _internal_uploadSticker(account: account, peer: peer, resource: sticker.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, mimeType: sticker.mimeType)
|> mapError { _ -> AddStickerToSetError in
return .generic
}
@ -319,6 +319,25 @@ func _internal_addStickerToStickerSet(account: Account, packReference: StickerPa
let inputSticker: Api.InputStickerSetItem = .inputStickerSetItem(flags: flags, document: .inputDocument(id: resource.fileId, accessHash: resource.accessHash, fileReference: Buffer(data: resource.fileReference ?? Data())), emoji: sticker.emojis.joined(), maskCoords: nil, keywords: sticker.keywords)
return account.network.request(Api.functions.stickers.addStickerToSet(stickerset: packReference.apiInputStickerSet, sticker: inputSticker))
|> `catch` { error -> Signal<Api.messages.StickerSet, MTRpcError> in
if error.errorDescription == "FILE_REFERENCE_EXPIRED" {
return revalidateMediaResourceReference(accountPeerId: account.peerId, postbox: account.postbox, network: account.network, revalidationContext: account.mediaReferenceRevalidationContext, info: TelegramCloudMediaResourceFetchInfo(reference: sticker.resource, preferBackgroundReferenceRevalidation: false, continueInBackground: false), resource: sticker.resource.resource)
|> mapError { _ -> MTRpcError in
return MTRpcError(errorCode: 500, errorDescription: "Internal")
}
|> mapToSignal { result -> Signal<Api.messages.StickerSet, MTRpcError> in
guard let resource = result.updatedResource as? CloudDocumentMediaResource else {
return .fail(MTRpcError(errorCode: 500, errorDescription: "Internal"))
}
let inputSticker: Api.InputStickerSetItem = .inputStickerSetItem(flags: flags, document: .inputDocument(id: resource.fileId, accessHash: resource.accessHash, fileReference: Buffer(data: resource.fileReference)), emoji: sticker.emojis.joined(), maskCoords: nil, keywords: sticker.keywords)
return account.network.request(Api.functions.stickers.addStickerToSet(stickerset: packReference.apiInputStickerSet, sticker: inputSticker))
}
} else {
return .fail(error)
}
}
|> mapError { error -> AddStickerToSetError in
return .generic
}
@ -403,13 +422,13 @@ func _internal_replaceSticker(account: Account, previousSticker: FileMediaRefere
}
let uploadSticker: Signal<UploadStickerStatus, ReplaceStickerError>
if let resource = sticker.resource as? CloudDocumentMediaResource {
if let resource = sticker.resource.resource as? CloudDocumentMediaResource {
uploadSticker = .single(.complete(resource, sticker.mimeType))
} else {
uploadSticker = account.postbox.loadedPeerWithId(account.peerId)
|> castError(ReplaceStickerError.self)
|> mapToSignal { peer in
return _internal_uploadSticker(account: account, peer: peer, resource: sticker.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, mimeType: sticker.mimeType)
|> mapError { _ -> ReplaceStickerError in
return .generic
}

View File

@ -1401,7 +1401,7 @@ final class AvatarEditorScreenComponent: Component {
try? backgroundImage.jpegData(compressionQuality: 0.8)?.write(to: tempUrl)
let drawingSize = CGSize(width: 1920.0, height: 1920.0)
let entity = DrawingStickerEntity(content: .file(file, .sticker))
let entity = DrawingStickerEntity(content: .file(.standalone(media: file), .sticker))
entity.referenceDrawingSize = drawingSize
entity.position = CGPoint(x: drawingSize.width / 2.0, y: drawingSize.height / 2.0)
entity.scale = 3.3
@ -1409,7 +1409,8 @@ final class AvatarEditorScreenComponent: Component {
var fileId: Int64 = 0
var stickerPackId: Int64 = 0
var stickerPackAccessHash: Int64 = 0
if case let .file(file, _) = entity.content {
if case let .file(fileReference, _) = entity.content {
let file = fileReference.media
if file.isCustomEmoji {
fileId = file.fileId.id
} else if file.isAnimatedSticker {

View File

@ -1195,7 +1195,16 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode {
if let id = groupId.base as? ItemCollectionId, context.sharedContext.currentStickerSettings.with({ $0 }).dynamicPackOrder {
bubbleUpEmojiOrStickersets.append(id)
}
let _ = interaction.sendSticker(.standalone(media: file), false, false, nil, false, view, rect, layer, bubbleUpEmojiOrStickersets)
let reference: FileMediaReference
if groupId == AnyHashable("saved") {
reference = .savedSticker(media: file)
} else if groupId == AnyHashable("recent") {
reference = .recentSticker(media: file)
} else {
reference = .standalone(media: file)
}
let _ = interaction.sendSticker(reference, false, false, nil, false, view, rect, layer, bubbleUpEmojiOrStickersets)
}
})
},

View File

@ -32,7 +32,7 @@ public final class DrawingStickerEntity: DrawingEntity, Codable {
case sticker
case reaction(MessageReaction.Reaction, ReactionStyle)
}
case file(TelegramMediaFile, FileType)
case file(FileMediaReference, FileType)
case image(UIImage, ImageType)
case animatedImage(Data, UIImage)
case video(TelegramMediaFile)
@ -43,7 +43,7 @@ public final class DrawingStickerEntity: DrawingEntity, Codable {
switch lhs {
case let .file(lhsFile, lhsFileType):
if case let .file(rhsFile, rhsFileType) = rhs {
return lhsFile.fileId == rhsFile.fileId && lhsFileType == rhsFileType
return lhsFile.media.fileId == rhsFile.media.fileId && lhsFileType == rhsFileType
} else {
return false
}
@ -152,7 +152,7 @@ public final class DrawingStickerEntity: DrawingEntity, Codable {
if case .reaction = type {
dimensions = CGSize(width: 512.0, height: 512.0)
} else {
dimensions = file.dimensions?.cgSize ?? CGSize(width: 512.0, height: 512.0)
dimensions = file.media.dimensions?.cgSize ?? CGSize(width: 512.0, height: 512.0)
}
case let .video(file):
dimensions = file.dimensions?.cgSize ?? CGSize(width: 512.0, height: 512.0)
@ -176,7 +176,7 @@ public final class DrawingStickerEntity: DrawingEntity, Codable {
case .reaction:
return false
default:
return file.isAnimatedSticker || file.isVideoSticker || file.mimeType == "video/webm"
return file.media.isAnimatedSticker || file.media.isVideoSticker || file.media.mimeType == "video/webm"
}
}
case .image:
@ -248,7 +248,7 @@ public final class DrawingStickerEntity: DrawingEntity, Codable {
} else {
fileType = .sticker
}
self.content = .file(file, fileType)
self.content = .file(.standalone(media: file), fileType)
} else if let imagePath = try container.decodeIfPresent(String.self, forKey: .imagePath), let image = UIImage(contentsOfFile: fullEntityMediaPath(imagePath)) {
let isRectangle = try container.decodeIfPresent(Bool.self, forKey: .isRectangle) ?? false
let isDualPhoto = try container.decodeIfPresent(Bool.self, forKey: .isDualPhoto) ?? false
@ -290,7 +290,7 @@ public final class DrawingStickerEntity: DrawingEntity, Codable {
try container.encode(self.uuid, forKey: .uuid)
switch self.content {
case let .file(file, fileType):
try container.encode(file, forKey: .file)
try container.encode(file.media, forKey: .file)
switch fileType {
case let .reaction(reaction, reactionStyle):
try container.encode(reaction, forKey: .reaction)

View File

@ -69,7 +69,7 @@ func composerEntitiesForDrawingEntity(postbox: Postbox, textScale: CGFloat, enti
let content: MediaEditorComposerStickerEntity.Content
switch entity.content {
case let .file(file, _):
content = .file(file)
content = .file(file.media)
case let .image(image, _):
content = .image(image)
case let .animatedImage(data, _):

View File

@ -3051,7 +3051,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
})
} else if case let .sticker(sticker, emoji) = effectiveSubject {
controller.stickerSelectedEmoji = emoji
let stickerEntity = DrawingStickerEntity(content: .file(sticker, .sticker))
let stickerEntity = DrawingStickerEntity(content: .file(.standalone(media: sticker), .sticker))
stickerEntity.referenceDrawingSize = storyDimensions
stickerEntity.scale = 4.0
stickerEntity.position = CGPoint(x: storyDimensions.width / 2.0, y: storyDimensions.height / 2.0)
@ -4382,7 +4382,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
if let reaction = self.availableReactions.first(where: { reaction in
return reaction.reaction.rawValue == .builtin(heart)
}) {
let stickerEntity = DrawingStickerEntity(content: .file(reaction.stillAnimation, .reaction(.builtin(heart), .white)))
let stickerEntity = DrawingStickerEntity(content: .file(.standalone(media: reaction.stillAnimation), .reaction(.builtin(heart), .white)))
self.interaction?.insertEntity(stickerEntity, scale: 1.175)
}
@ -4530,11 +4530,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
if let self {
if let content {
if case let .file(file, _) = content {
if file.isCustomEmoji {
self.defaultToEmoji = true
} else {
self.defaultToEmoji = false
}
self.defaultToEmoji = file.media.isCustomEmoji
}
let stickerEntity = DrawingStickerEntity(content: content)
@ -5823,7 +5819,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
let entities = self.node.entitiesView.entities.filter { !($0 is DrawingMediaEntity) }
for entity in entities {
if let stickerEntity = entity as? DrawingStickerEntity, case let .file(file, type) = stickerEntity.content, case let .reaction(reaction, _) = type, case .custom = reaction {
self.presentUnavailableReactionPremiumSuggestion(file: file)
self.presentUnavailableReactionPremiumSuggestion(file: file.media)
return false
}
}
@ -5879,13 +5875,13 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
switch entity {
case let .sticker(stickerEntity):
if case let .file(file, fileType) = stickerEntity.content, case .sticker = fileType {
stickers.append(file)
stickers.append(file.media)
}
case let .text(textEntity):
if let subEntities = textEntity.renderSubEntities {
for entity in subEntities {
if let stickerEntity = entity as? DrawingStickerEntity, case let .file(file, fileType) = stickerEntity.content, case .sticker = fileType {
stickers.append(file)
stickers.append(file.media)
}
}
}
@ -6467,7 +6463,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
shortName: "",
stickers: [
ImportSticker(
resource: file.resource,
resource: .standalone(resource: file.resource),
emojis: self.effectiveStickerEmoji(),
dimensions: PixelDimensions(width: 512, height: 512),
mimeType: "image/webp",
@ -6602,7 +6598,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
}
case let .createStickerPack(title):
let sticker = ImportSticker(
resource: resource,
resource: .standalone(resource: resource),
emojis: self.effectiveStickerEmoji(),
dimensions: dimensions,
mimeType: mimeType,
@ -6621,7 +6617,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
}
case let .addToStickerPack(pack, _):
let sticker = ImportSticker(
resource: resource,
resource: .standalone(resource: resource),
emojis: self.effectiveStickerEmoji(),
dimensions: dimensions,
mimeType: mimeType,

View File

@ -147,7 +147,7 @@ private final class StickerSelectionComponent: Component {
c.dismiss(animated: true)
}
})
if controller.completion(.file(file.media, .sticker)) {
if controller.completion(.file(file, .sticker)) {
controller.dismiss(animated: true)
}
}
@ -884,7 +884,7 @@ public class StickerPickerScreen: ViewController {
})
})
} else if let file = item.itemFile {
if controller.completion(.file(file, .sticker)) {
if controller.completion(.file(.standalone(media: file), .sticker)) {
controller.dismiss(animated: true)
}
} else if case let .staticEmoji(emoji) = item.content {
@ -1299,7 +1299,7 @@ public class StickerPickerScreen: ViewController {
guard let self, let controller = self.controller else {
return false
}
if controller.completion(.file(fileReference.media, .sticker)) {
if controller.completion(.file(fileReference, .sticker)) {
controller.dismiss(animated: true)
}
return true
@ -1311,7 +1311,15 @@ public class StickerPickerScreen: ViewController {
}
})
} else {
let _ = controller.completion(.file(file, .sticker))
let reference: FileMediaReference
if groupId == AnyHashable("saved") {
reference = .savedSticker(media: file)
} else if groupId == AnyHashable("recent") {
reference = .recentSticker(media: file)
} else {
reference = .standalone(media: file)
}
let _ = controller.completion(.file(reference, .sticker))
controller.dismiss(animated: true)
}
},

View File

@ -2421,7 +2421,7 @@ public final class SharedAccountContextImpl: SharedAccountContext {
return stickerMediaPickerController(context: context, getSourceRect: getSourceRect, completion: completion, dismissed: dismissed)
}
public func makeStickerPickerScreen(context: AccountContext, inputData: Promise<StickerPickerInput>, completion: @escaping (TelegramMediaFile) -> Void) -> ViewController {
public func makeStickerPickerScreen(context: AccountContext, inputData: Promise<StickerPickerInput>, completion: @escaping (FileMediaReference) -> Void) -> ViewController {
let controller = StickerPickerScreen(context: context, inputData: inputData.get(), expanded: true, hasGifs: false, hasInteractiveStickers: false)
controller.completion = { content in
if let content, case let .file(file, _) = content {