mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
[WIP] Stickers editor
This commit is contained in:
parent
ff5307a254
commit
70eef8ecac
@ -11904,3 +11904,5 @@ Sorry for the inconvenience.";
|
|||||||
|
|
||||||
"Conversation.ViewStickers" = "VIEW STICKERS";
|
"Conversation.ViewStickers" = "VIEW STICKERS";
|
||||||
"Conversation.ViewEmojis" = "VIEW EMOJIS";
|
"Conversation.ViewEmojis" = "VIEW EMOJIS";
|
||||||
|
|
||||||
|
"MediaEditor.StickersTooMuch" = "Sorry, you've reached the maximum number of stickers in this set. Try a different one.";
|
||||||
|
@ -314,7 +314,7 @@ final class StickerPackPreviewGridItemNode: GridItemNode {
|
|||||||
if stickerItem.file.isAnimatedSticker || stickerItem.file.isVideoSticker {
|
if stickerItem.file.isAnimatedSticker || stickerItem.file.isVideoSticker {
|
||||||
let dimensions = stickerItem.file.dimensions ?? PixelDimensions(width: 512, height: 512)
|
let dimensions = stickerItem.file.dimensions ?? PixelDimensions(width: 512, height: 512)
|
||||||
if stickerItem.file.isVideoSticker {
|
if stickerItem.file.isVideoSticker {
|
||||||
self.imageNode.setSignal(chatMessageSticker(account: context.account, userLocation: .other, file: stickerItem.file, small: true))
|
self.imageNode.setSignal(chatMessageSticker(account: context.account, userLocation: .other, file: stickerItem.file, small: true, fetched: true))
|
||||||
} else {
|
} else {
|
||||||
self.imageNode.setSignal(chatMessageAnimatedSticker(postbox: context.account.postbox, userLocation: .other, file: stickerItem.file, small: false, size: dimensions.cgSize.aspectFitted(CGSize(width: 160.0, height: 160.0))))
|
self.imageNode.setSignal(chatMessageAnimatedSticker(postbox: context.account.postbox, userLocation: .other, file: stickerItem.file, small: false, size: dimensions.cgSize.aspectFitted(CGSize(width: 160.0, height: 160.0))))
|
||||||
}
|
}
|
||||||
|
@ -1250,6 +1250,7 @@ private final class StickerPackContainer: ASDisplayNode {
|
|||||||
let presentationData = self.presentationData
|
let presentationData = self.presentationData
|
||||||
let updatedPresentationData = self.controller?.updatedPresentationData
|
let updatedPresentationData = self.controller?.updatedPresentationData
|
||||||
let navigationController = self.controller?.parentNavigationController as? NavigationController
|
let navigationController = self.controller?.parentNavigationController as? NavigationController
|
||||||
|
let sendSticker = self.controller?.sendSticker
|
||||||
|
|
||||||
var dismissImpl: (() -> Void)?
|
var dismissImpl: (() -> Void)?
|
||||||
let mainController = context.sharedContext.makeStickerMediaPickerScreen(
|
let mainController = context.sharedContext.makeStickerMediaPickerScreen(
|
||||||
@ -1275,7 +1276,7 @@ private final class StickerPackContainer: ASDisplayNode {
|
|||||||
|> deliverOnMainQueue).start(completed: {
|
|> deliverOnMainQueue).start(completed: {
|
||||||
commit()
|
commit()
|
||||||
|
|
||||||
let packController = StickerPackScreen(context: context, updatedPresentationData: updatedPresentationData, mainStickerPack: packReference, stickerPacks: [packReference], loadedStickerPacks: [], expandIfNeeded: true, parentNavigationController: navigationController, sendSticker: nil, sendEmoji: nil, actionPerformed: nil, dismissed: nil, getSourceRect: nil)
|
let packController = StickerPackScreen(context: context, updatedPresentationData: updatedPresentationData, mainStickerPack: packReference, stickerPacks: [packReference], loadedStickerPacks: [], expandIfNeeded: true, parentNavigationController: navigationController, sendSticker: sendSticker, sendEmoji: nil, actionPerformed: nil, dismissed: nil, getSourceRect: nil)
|
||||||
(navigationController?.viewControllers.last as? ViewController)?.present(packController, in: .window(.root))
|
(navigationController?.viewControllers.last as? ViewController)?.present(packController, in: .window(.root))
|
||||||
|
|
||||||
Queue.mainQueue().after(0.1) {
|
Queue.mainQueue().after(0.1) {
|
||||||
@ -1301,6 +1302,7 @@ private final class StickerPackContainer: ASDisplayNode {
|
|||||||
let presentationData = self.presentationData
|
let presentationData = self.presentationData
|
||||||
let updatedPresentationData = self.controller?.updatedPresentationData
|
let updatedPresentationData = self.controller?.updatedPresentationData
|
||||||
let navigationController = self.controller?.parentNavigationController as? NavigationController
|
let navigationController = self.controller?.parentNavigationController as? NavigationController
|
||||||
|
let sendSticker = self.controller?.sendSticker
|
||||||
|
|
||||||
let context = self.context
|
let context = self.context
|
||||||
let controller = self.context.sharedContext.makeStickerPickerScreen(context: self.context, inputData: self.stickerPickerInputData, completion: { file in
|
let controller = self.context.sharedContext.makeStickerPickerScreen(context: self.context, inputData: self.stickerPickerInputData, completion: { file in
|
||||||
@ -1323,7 +1325,7 @@ private final class StickerPackContainer: ASDisplayNode {
|
|||||||
let packReference: StickerPackReference = .id(id: info.id.id, accessHash: info.accessHash)
|
let packReference: StickerPackReference = .id(id: info.id.id, accessHash: info.accessHash)
|
||||||
let _ = (context.engine.stickers.addStickerToStickerSet(packReference: packReference, sticker: sticker)
|
let _ = (context.engine.stickers.addStickerToStickerSet(packReference: packReference, sticker: sticker)
|
||||||
|> deliverOnMainQueue).start(completed: {
|
|> deliverOnMainQueue).start(completed: {
|
||||||
let packController = StickerPackScreen(context: context, updatedPresentationData: updatedPresentationData, mainStickerPack: packReference, stickerPacks: [packReference], loadedStickerPacks: [], expandIfNeeded: true, parentNavigationController: navigationController, sendSticker: nil, sendEmoji: nil, actionPerformed: nil, dismissed: nil, getSourceRect: nil)
|
let packController = StickerPackScreen(context: context, updatedPresentationData: updatedPresentationData, mainStickerPack: packReference, stickerPacks: [packReference], loadedStickerPacks: [], expandIfNeeded: true, parentNavigationController: navigationController, sendSticker: sendSticker, sendEmoji: nil, actionPerformed: nil, dismissed: nil, getSourceRect: nil)
|
||||||
(navigationController?.viewControllers.last as? ViewController)?.present(packController, in: .window(.root))
|
(navigationController?.viewControllers.last as? ViewController)?.present(packController, in: .window(.root))
|
||||||
|
|
||||||
Queue.mainQueue().after(0.1) {
|
Queue.mainQueue().after(0.1) {
|
||||||
@ -1345,8 +1347,10 @@ private final class StickerPackContainer: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let context = self.context
|
let context = self.context
|
||||||
|
let presentationData = self.presentationData
|
||||||
let updatedPresentationData = self.controller?.updatedPresentationData
|
let updatedPresentationData = self.controller?.updatedPresentationData
|
||||||
let navigationController = self.controller?.parentNavigationController as? NavigationController
|
let navigationController = self.controller?.parentNavigationController as? NavigationController
|
||||||
|
let sendSticker = self.controller?.sendSticker
|
||||||
|
|
||||||
self.controller?.dismiss()
|
self.controller?.dismiss()
|
||||||
|
|
||||||
@ -1369,8 +1373,12 @@ private final class StickerPackContainer: ASDisplayNode {
|
|||||||
|> deliverOnMainQueue).start(completed: {
|
|> deliverOnMainQueue).start(completed: {
|
||||||
commit()
|
commit()
|
||||||
|
|
||||||
let packController = StickerPackScreen(context: context, updatedPresentationData: updatedPresentationData, mainStickerPack: packReference, stickerPacks: [packReference], loadedStickerPacks: [], expandIfNeeded: true, parentNavigationController: navigationController, sendSticker: nil, sendEmoji: nil, actionPerformed: nil, dismissed: nil, getSourceRect: nil)
|
let packController = StickerPackScreen(context: context, updatedPresentationData: updatedPresentationData, mainStickerPack: packReference, stickerPacks: [packReference], loadedStickerPacks: [], expandIfNeeded: true, parentNavigationController: navigationController, sendSticker: sendSticker, sendEmoji: nil, actionPerformed: nil, dismissed: nil, getSourceRect: nil)
|
||||||
(navigationController?.viewControllers.last as? ViewController)?.present(packController, in: .window(.root))
|
(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 updated.", undoText: nil, customAction: nil), elevatedLayout: false, action: { _ in return false }), in: .current)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -2645,7 +2653,7 @@ public final class StickerPackScreenImpl: ViewController, StickerPackScreen {
|
|||||||
|
|
||||||
private let initialSelectedStickerPackIndex: Int
|
private let initialSelectedStickerPackIndex: Int
|
||||||
fileprivate weak var parentNavigationController: NavigationController?
|
fileprivate weak var parentNavigationController: NavigationController?
|
||||||
private let sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)?
|
fileprivate let sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)?
|
||||||
private let sendEmoji: ((String, ChatTextInputTextCustomEmojiAttribute) -> Void)?
|
private let sendEmoji: ((String, ChatTextInputTextCustomEmojiAttribute) -> Void)?
|
||||||
|
|
||||||
fileprivate var controllerNode: StickerPackScreenNode {
|
fileprivate var controllerNode: StickerPackScreenNode {
|
||||||
|
@ -162,7 +162,7 @@ public final class ChatMessageAttachedContentNode: ASDisplayNode {
|
|||||||
self.activateBadgeAction?()
|
self.activateBadgeAction?()
|
||||||
}
|
}
|
||||||
|
|
||||||
public typealias AsyncLayout = (_ presentationData: ChatPresentationData, _ automaticDownloadSettings: MediaAutoDownloadSettings, _ associatedData: ChatMessageItemAssociatedData, _ attributes: ChatMessageEntryAttributes, _ context: AccountContext, _ controllerInteraction: ChatControllerInteraction, _ message: Message, _ messageRead: Bool, _ chatLocation: ChatLocation, _ title: String?, _ titleBadge: String?, _ subtitle: NSAttributedString?, _ text: String?, _ entities: [MessageTextEntity]?, _ media: (Media, ChatMessageAttachedContentNodeMediaFlags)?, _ mediaBadge: String?, _ actionIcon: ChatMessageAttachedContentActionIcon?, _ actionTitle: String?, _ displayLine: Bool, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ constrainedSize: CGSize, _ animationCache: AnimationCache, _ animationRenderer: MultiAnimationRenderer) -> (CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void)))
|
public typealias AsyncLayout = (_ presentationData: ChatPresentationData, _ automaticDownloadSettings: MediaAutoDownloadSettings, _ associatedData: ChatMessageItemAssociatedData, _ attributes: ChatMessageEntryAttributes, _ context: AccountContext, _ controllerInteraction: ChatControllerInteraction, _ message: Message, _ messageRead: Bool, _ chatLocation: ChatLocation, _ title: String?, _ titleBadge: String?, _ subtitle: NSAttributedString?, _ text: String?, _ entities: [MessageTextEntity]?, _ media: ([Media], ChatMessageAttachedContentNodeMediaFlags)?, _ mediaBadge: String?, _ actionIcon: ChatMessageAttachedContentActionIcon?, _ actionTitle: String?, _ displayLine: Bool, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ constrainedSize: CGSize, _ animationCache: AnimationCache, _ animationRenderer: MultiAnimationRenderer) -> (CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void)))
|
||||||
|
|
||||||
public func makeProgress() -> Promise<Bool> {
|
public func makeProgress() -> Promise<Bool> {
|
||||||
let progress = Promise<Bool>()
|
let progress = Promise<Bool>()
|
||||||
@ -302,7 +302,7 @@ public final class ChatMessageAttachedContentNode: ASDisplayNode {
|
|||||||
|
|
||||||
var mediaAndFlags = mediaAndFlags
|
var mediaAndFlags = mediaAndFlags
|
||||||
if let mediaAndFlagsValue = mediaAndFlags {
|
if let mediaAndFlagsValue = mediaAndFlags {
|
||||||
if mediaAndFlagsValue.0 is TelegramMediaStory || mediaAndFlagsValue.0 is WallpaperPreviewMedia {
|
if mediaAndFlagsValue.0.first is TelegramMediaStory || mediaAndFlagsValue.0.first is WallpaperPreviewMedia {
|
||||||
var flags = mediaAndFlagsValue.1
|
var flags = mediaAndFlagsValue.1
|
||||||
flags.remove(.preferMediaInline)
|
flags.remove(.preferMediaInline)
|
||||||
mediaAndFlags = (mediaAndFlagsValue.0, flags)
|
mediaAndFlags = (mediaAndFlagsValue.0, flags)
|
||||||
@ -315,50 +315,52 @@ public final class ChatMessageAttachedContentNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
var contentMediaInline = false
|
var contentMediaInline = false
|
||||||
|
|
||||||
if let (media, flags) = mediaAndFlags {
|
if let (mediaArray, flags) = mediaAndFlags {
|
||||||
contentMediaInline = flags.contains(.preferMediaInline)
|
contentMediaInline = flags.contains(.preferMediaInline)
|
||||||
|
|
||||||
if let file = media as? TelegramMediaFile {
|
if let media = mediaArray.first {
|
||||||
if file.mimeType == "application/x-tgtheme-ios", let size = file.size, size < 16 * 1024 {
|
if let file = media as? TelegramMediaFile {
|
||||||
contentMediaValue = file
|
if file.mimeType == "application/x-tgtheme-ios", let size = file.size, size < 16 * 1024 {
|
||||||
} else if file.isInstantVideo {
|
contentMediaValue = file
|
||||||
contentMediaValue = file
|
} else if file.isInstantVideo {
|
||||||
} else if file.isVideo {
|
contentMediaValue = file
|
||||||
contentMediaValue = file
|
} else if file.isVideo {
|
||||||
} else if file.isSticker || file.isAnimatedSticker {
|
contentMediaValue = file
|
||||||
contentMediaValue = file
|
} else if file.isSticker || file.isAnimatedSticker {
|
||||||
} else {
|
contentMediaValue = file
|
||||||
contentFileValue = file
|
|
||||||
}
|
|
||||||
|
|
||||||
if shouldDownloadMediaAutomatically(settings: automaticDownloadSettings, peerType: associatedData.automaticDownloadPeerType, networkType: associatedData.automaticDownloadNetworkType, authorPeerId: message.author?.id, contactsPeerIds: associatedData.contactsPeerIds, media: file) {
|
|
||||||
contentMediaAutomaticDownload = .full
|
|
||||||
} else if shouldPredownloadMedia(settings: automaticDownloadSettings, peerType: associatedData.automaticDownloadPeerType, networkType: associatedData.automaticDownloadNetworkType, media: file) {
|
|
||||||
contentMediaAutomaticDownload = .prefetch
|
|
||||||
}
|
|
||||||
|
|
||||||
if file.isAnimated {
|
|
||||||
contentMediaAutomaticPlayback = context.sharedContext.energyUsageSettings.autoplayGif
|
|
||||||
} else if file.isVideo && context.sharedContext.energyUsageSettings.autoplayVideo {
|
|
||||||
var willDownloadOrLocal = false
|
|
||||||
if case .full = contentMediaAutomaticDownload {
|
|
||||||
willDownloadOrLocal = true
|
|
||||||
} else {
|
} else {
|
||||||
willDownloadOrLocal = context.account.postbox.mediaBox.completedResourcePath(file.resource) != nil
|
contentFileValue = file
|
||||||
}
|
}
|
||||||
if willDownloadOrLocal {
|
|
||||||
contentMediaAutomaticPlayback = true
|
if shouldDownloadMediaAutomatically(settings: automaticDownloadSettings, peerType: associatedData.automaticDownloadPeerType, networkType: associatedData.automaticDownloadNetworkType, authorPeerId: message.author?.id, contactsPeerIds: associatedData.contactsPeerIds, media: file) {
|
||||||
contentMediaAspectFilled = true
|
contentMediaAutomaticDownload = .full
|
||||||
|
} else if shouldPredownloadMedia(settings: automaticDownloadSettings, peerType: associatedData.automaticDownloadPeerType, networkType: associatedData.automaticDownloadNetworkType, media: file) {
|
||||||
|
contentMediaAutomaticDownload = .prefetch
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if file.isAnimated {
|
||||||
|
contentMediaAutomaticPlayback = context.sharedContext.energyUsageSettings.autoplayGif
|
||||||
|
} else if file.isVideo && context.sharedContext.energyUsageSettings.autoplayVideo {
|
||||||
|
var willDownloadOrLocal = false
|
||||||
|
if case .full = contentMediaAutomaticDownload {
|
||||||
|
willDownloadOrLocal = true
|
||||||
|
} else {
|
||||||
|
willDownloadOrLocal = context.account.postbox.mediaBox.completedResourcePath(file.resource) != nil
|
||||||
|
}
|
||||||
|
if willDownloadOrLocal {
|
||||||
|
contentMediaAutomaticPlayback = true
|
||||||
|
contentMediaAspectFilled = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if let _ = media as? TelegramMediaImage {
|
||||||
|
contentMediaValue = media
|
||||||
|
} else if let _ = media as? TelegramMediaWebFile {
|
||||||
|
contentMediaValue = media
|
||||||
|
} else if let _ = media as? WallpaperPreviewMedia {
|
||||||
|
contentMediaValue = media
|
||||||
|
} else if let _ = media as? TelegramMediaStory {
|
||||||
|
contentMediaValue = media
|
||||||
}
|
}
|
||||||
} else if let _ = media as? TelegramMediaImage {
|
|
||||||
contentMediaValue = media
|
|
||||||
} else if let _ = media as? TelegramMediaWebFile {
|
|
||||||
contentMediaValue = media
|
|
||||||
} else if let _ = media as? WallpaperPreviewMedia {
|
|
||||||
contentMediaValue = media
|
|
||||||
} else if let _ = media as? TelegramMediaStory {
|
|
||||||
contentMediaValue = media
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -939,7 +941,7 @@ public final class ChatMessageAttachedContentNode: ASDisplayNode {
|
|||||||
|
|
||||||
self.context = context
|
self.context = context
|
||||||
self.message = message
|
self.message = message
|
||||||
self.media = mediaAndFlags?.0
|
self.media = mediaAndFlags?.0.first
|
||||||
self.theme = presentationData.theme
|
self.theme = presentationData.theme
|
||||||
self.mainColor = mainColor
|
self.mainColor = mainColor
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ public final class ChatMessageEventLogPreviousDescriptionContentNode: ChatMessag
|
|||||||
} else {
|
} else {
|
||||||
text = item.message.text
|
text = item.message.text
|
||||||
}
|
}
|
||||||
let mediaAndFlags: (Media, ChatMessageAttachedContentNodeMediaFlags)? = nil
|
let mediaAndFlags: ([Media], ChatMessageAttachedContentNodeMediaFlags)? = nil
|
||||||
|
|
||||||
let (initialWidth, continueLayout) = contentNodeLayout(item.presentationData, item.controllerInteraction.automaticMediaDownloadSettings, item.associatedData, item.attributes, item.context, item.controllerInteraction, item.message, true, .peer(id: item.message.id.peerId), title, nil, nil, text, messageEntities, mediaAndFlags, nil, nil, nil, true, layoutConstants, preparePosition, constrainedSize, item.controllerInteraction.presentationContext.animationCache, item.controllerInteraction.presentationContext.animationRenderer)
|
let (initialWidth, continueLayout) = contentNodeLayout(item.presentationData, item.controllerInteraction.automaticMediaDownloadSettings, item.associatedData, item.attributes, item.context, item.controllerInteraction, item.message, true, .peer(id: item.message.id.peerId), title, nil, nil, text, messageEntities, mediaAndFlags, nil, nil, nil, true, layoutConstants, preparePosition, constrainedSize, item.controllerInteraction.presentationContext.animationCache, item.controllerInteraction.presentationContext.animationRenderer)
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ public final class ChatMessageEventLogPreviousLinkContentNode: ChatMessageBubble
|
|||||||
|
|
||||||
let title: String = item.message.text.contains("\n") ? item.presentationData.strings.Channel_AdminLog_MessagePreviousLinks : item.presentationData.strings.Channel_AdminLog_MessagePreviousLink
|
let title: String = item.message.text.contains("\n") ? item.presentationData.strings.Channel_AdminLog_MessagePreviousLinks : item.presentationData.strings.Channel_AdminLog_MessagePreviousLink
|
||||||
let text: String = item.message.text
|
let text: String = item.message.text
|
||||||
let mediaAndFlags: (Media, ChatMessageAttachedContentNodeMediaFlags)? = nil
|
let mediaAndFlags: ([Media], ChatMessageAttachedContentNodeMediaFlags)? = nil
|
||||||
|
|
||||||
let (initialWidth, continueLayout) = contentNodeLayout(item.presentationData, item.controllerInteraction.automaticMediaDownloadSettings, item.associatedData, item.attributes, item.context, item.controllerInteraction, item.message, true, .peer(id: item.message.id.peerId), title, nil, nil, text, messageEntities, mediaAndFlags, nil, nil, nil, true, layoutConstants, preparePosition, constrainedSize, item.controllerInteraction.presentationContext.animationCache, item.controllerInteraction.presentationContext.animationRenderer)
|
let (initialWidth, continueLayout) = contentNodeLayout(item.presentationData, item.controllerInteraction.automaticMediaDownloadSettings, item.associatedData, item.attributes, item.context, item.controllerInteraction, item.message, true, .peer(id: item.message.id.peerId), title, nil, nil, text, messageEntities, mediaAndFlags, nil, nil, nil, true, layoutConstants, preparePosition, constrainedSize, item.controllerInteraction.presentationContext.animationCache, item.controllerInteraction.presentationContext.animationRenderer)
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ public final class ChatMessageEventLogPreviousMessageContentNode: ChatMessageBub
|
|||||||
} else {
|
} else {
|
||||||
text = item.message.text
|
text = item.message.text
|
||||||
}
|
}
|
||||||
let mediaAndFlags: (Media, ChatMessageAttachedContentNodeMediaFlags)? = nil
|
let mediaAndFlags: ([Media], ChatMessageAttachedContentNodeMediaFlags)? = nil
|
||||||
|
|
||||||
let (initialWidth, continueLayout) = contentNodeLayout(item.presentationData, item.controllerInteraction.automaticMediaDownloadSettings, item.associatedData, item.attributes, item.context, item.controllerInteraction, item.message, true, .peer(id: item.message.id.peerId), title, nil, nil, text, messageEntities, mediaAndFlags, nil, nil, nil, true, layoutConstants, preparePosition, constrainedSize, item.controllerInteraction.presentationContext.animationCache, item.controllerInteraction.presentationContext.animationRenderer)
|
let (initialWidth, continueLayout) = contentNodeLayout(item.presentationData, item.controllerInteraction.automaticMediaDownloadSettings, item.associatedData, item.attributes, item.context, item.controllerInteraction, item.message, true, .peer(id: item.message.id.peerId), title, nil, nil, text, messageEntities, mediaAndFlags, nil, nil, nil, true, layoutConstants, preparePosition, constrainedSize, item.controllerInteraction.presentationContext.animationCache, item.controllerInteraction.presentationContext.animationRenderer)
|
||||||
|
|
||||||
|
@ -67,16 +67,16 @@ public final class ChatMessageGameBubbleContentNode: ChatMessageBubbleContentNod
|
|||||||
|
|
||||||
var title: String?
|
var title: String?
|
||||||
var text: String?
|
var text: String?
|
||||||
var mediaAndFlags: (Media, ChatMessageAttachedContentNodeMediaFlags)?
|
var mediaAndFlags: ([Media], ChatMessageAttachedContentNodeMediaFlags)?
|
||||||
|
|
||||||
if let game = game {
|
if let game = game {
|
||||||
title = game.title
|
title = game.title
|
||||||
text = game.description
|
text = game.description
|
||||||
|
|
||||||
if let file = game.file {
|
if let file = game.file {
|
||||||
mediaAndFlags = (file, [.preferMediaBeforeText])
|
mediaAndFlags = ([file], [.preferMediaBeforeText])
|
||||||
} else if let image = game.image {
|
} else if let image = game.image {
|
||||||
mediaAndFlags = (image, [.preferMediaBeforeText])
|
mediaAndFlags = ([image], [.preferMediaBeforeText])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ public final class ChatMessageInvoiceBubbleContentNode: ChatMessageBubbleContent
|
|||||||
var title: String?
|
var title: String?
|
||||||
var subtitle: NSAttributedString? = nil
|
var subtitle: NSAttributedString? = nil
|
||||||
var text: String?
|
var text: String?
|
||||||
var mediaAndFlags: (Media, ChatMessageAttachedContentNodeMediaFlags)?
|
var mediaAndFlags: ([Media], ChatMessageAttachedContentNodeMediaFlags)?
|
||||||
|
|
||||||
var automaticDownloadSettings = item.controllerInteraction.automaticMediaDownloadSettings
|
var automaticDownloadSettings = item.controllerInteraction.automaticMediaDownloadSettings
|
||||||
if let invoice = invoice {
|
if let invoice = invoice {
|
||||||
@ -61,7 +61,7 @@ public final class ChatMessageInvoiceBubbleContentNode: ChatMessageBubbleContent
|
|||||||
|
|
||||||
if let image = invoice.photo {
|
if let image = invoice.photo {
|
||||||
automaticDownloadSettings = MediaAutoDownloadSettings.defaultSettings
|
automaticDownloadSettings = MediaAutoDownloadSettings.defaultSettings
|
||||||
mediaAndFlags = (image, [.preferMediaBeforeText])
|
mediaAndFlags = ([image], [.preferMediaBeforeText])
|
||||||
} else {
|
} else {
|
||||||
let invoiceLabel = item.presentationData.strings.Message_InvoiceLabel
|
let invoiceLabel = item.presentationData.strings.Message_InvoiceLabel
|
||||||
var invoiceText = "\(formatCurrencyAmount(invoice.totalAmount, currency: invoice.currency)) "
|
var invoiceText = "\(formatCurrencyAmount(invoice.totalAmount, currency: invoice.currency)) "
|
||||||
|
@ -242,7 +242,7 @@ public final class ChatMessageWebpageBubbleContentNode: ChatMessageBubbleContent
|
|||||||
var text: String?
|
var text: String?
|
||||||
var entities: [MessageTextEntity]?
|
var entities: [MessageTextEntity]?
|
||||||
var titleBadge: String?
|
var titleBadge: String?
|
||||||
var mediaAndFlags: (Media, ChatMessageAttachedContentNodeMediaFlags)?
|
var mediaAndFlags: ([Media], ChatMessageAttachedContentNodeMediaFlags)?
|
||||||
var badge: String?
|
var badge: String?
|
||||||
|
|
||||||
var actionIcon: ChatMessageAttachedContentActionIcon?
|
var actionIcon: ChatMessageAttachedContentActionIcon?
|
||||||
@ -307,9 +307,9 @@ public final class ChatMessageWebpageBubbleContentNode: ChatMessageBubbleContent
|
|||||||
if let file = mainMedia as? TelegramMediaFile, webpage.type != "telegram_theme" {
|
if let file = mainMedia as? TelegramMediaFile, webpage.type != "telegram_theme" {
|
||||||
if let embedUrl = webpage.embedUrl, !embedUrl.isEmpty {
|
if let embedUrl = webpage.embedUrl, !embedUrl.isEmpty {
|
||||||
if automaticPlayback {
|
if automaticPlayback {
|
||||||
mediaAndFlags = (file, [.preferMediaBeforeText])
|
mediaAndFlags = ([file], [.preferMediaBeforeText])
|
||||||
} else {
|
} else {
|
||||||
mediaAndFlags = (webpage.image ?? file, [.preferMediaBeforeText])
|
mediaAndFlags = ([webpage.image ?? file], [.preferMediaBeforeText])
|
||||||
}
|
}
|
||||||
} else if webpage.type == "telegram_background" {
|
} else if webpage.type == "telegram_background" {
|
||||||
var colors: [UInt32] = []
|
var colors: [UInt32] = []
|
||||||
@ -321,12 +321,12 @@ public final class ChatMessageWebpageBubbleContentNode: ChatMessageBubbleContent
|
|||||||
intensity = intensityValue
|
intensity = intensityValue
|
||||||
}
|
}
|
||||||
let media = WallpaperPreviewMedia(content: .file(file: file, colors: colors, rotation: rotation, intensity: intensity, false, false))
|
let media = WallpaperPreviewMedia(content: .file(file: file, colors: colors, rotation: rotation, intensity: intensity, false, false))
|
||||||
mediaAndFlags = (media, [.preferMediaAspectFilled])
|
mediaAndFlags = ([media], [.preferMediaAspectFilled])
|
||||||
if let fileSize = file.size {
|
if let fileSize = file.size {
|
||||||
badge = dataSizeString(fileSize, formatting: DataSizeStringFormatting(chatPresentationData: item.presentationData))
|
badge = dataSizeString(fileSize, formatting: DataSizeStringFormatting(chatPresentationData: item.presentationData))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mediaAndFlags = (file, [])
|
mediaAndFlags = ([file], [])
|
||||||
}
|
}
|
||||||
} else if let image = mainMedia as? TelegramMediaImage {
|
} else if let image = mainMedia as? TelegramMediaImage {
|
||||||
if let type = webpage.type, ["photo", "video", "embed", "gif", "document", "telegram_album"].contains(type) {
|
if let type = webpage.type, ["photo", "video", "embed", "gif", "document", "telegram_album"].contains(type) {
|
||||||
@ -338,13 +338,13 @@ public final class ChatMessageWebpageBubbleContentNode: ChatMessageBubbleContent
|
|||||||
} else if let embedUrl = webpage.embedUrl, !embedUrl.isEmpty {
|
} else if let embedUrl = webpage.embedUrl, !embedUrl.isEmpty {
|
||||||
flags.insert(.preferMediaBeforeText)
|
flags.insert(.preferMediaBeforeText)
|
||||||
}
|
}
|
||||||
mediaAndFlags = (image, flags)
|
mediaAndFlags = ([image], flags)
|
||||||
} else if let _ = largestImageRepresentation(image.representations)?.dimensions {
|
} else if let _ = largestImageRepresentation(image.representations)?.dimensions {
|
||||||
let flags = ChatMessageAttachedContentNodeMediaFlags()
|
let flags = ChatMessageAttachedContentNodeMediaFlags()
|
||||||
mediaAndFlags = (image, flags)
|
mediaAndFlags = ([image], flags)
|
||||||
}
|
}
|
||||||
} else if let story = mainMedia as? TelegramMediaStory {
|
} else if let story = mainMedia as? TelegramMediaStory {
|
||||||
mediaAndFlags = (story, [.preferMediaBeforeText, .titleBeforeMedia])
|
mediaAndFlags = ([story], [.preferMediaBeforeText, .titleBeforeMedia])
|
||||||
if let storyItem = item.message.associatedStories[story.storyId]?.get(Stories.StoredItem.self), case let .item(itemValue) = storyItem {
|
if let storyItem = item.message.associatedStories[story.storyId]?.get(Stories.StoredItem.self), case let .item(itemValue) = storyItem {
|
||||||
text = itemValue.text
|
text = itemValue.text
|
||||||
entities = itemValue.entities
|
entities = itemValue.entities
|
||||||
@ -372,7 +372,7 @@ public final class ChatMessageWebpageBubbleContentNode: ChatMessageBubbleContent
|
|||||||
}
|
}
|
||||||
if let content = content {
|
if let content = content {
|
||||||
let media = WallpaperPreviewMedia(content: content)
|
let media = WallpaperPreviewMedia(content: content)
|
||||||
mediaAndFlags = (media, [])
|
mediaAndFlags = ([media], [])
|
||||||
}
|
}
|
||||||
} else if type == "telegram_theme" {
|
} else if type == "telegram_theme" {
|
||||||
var file: TelegramMediaFile?
|
var file: TelegramMediaFile?
|
||||||
@ -397,10 +397,10 @@ public final class ChatMessageWebpageBubbleContentNode: ChatMessageBubbleContent
|
|||||||
}
|
}
|
||||||
if let file = file {
|
if let file = file {
|
||||||
let media = WallpaperPreviewMedia(content: .file(file: file, colors: [], rotation: nil, intensity: nil, true, isSupported))
|
let media = WallpaperPreviewMedia(content: .file(file: file, colors: [], rotation: nil, intensity: nil, true, isSupported))
|
||||||
mediaAndFlags = (media, ChatMessageAttachedContentNodeMediaFlags())
|
mediaAndFlags = ([media], ChatMessageAttachedContentNodeMediaFlags())
|
||||||
} else if let settings = settings {
|
} else if let settings = settings {
|
||||||
let media = WallpaperPreviewMedia(content: .themeSettings(settings))
|
let media = WallpaperPreviewMedia(content: .themeSettings(settings))
|
||||||
mediaAndFlags = (media, ChatMessageAttachedContentNodeMediaFlags())
|
mediaAndFlags = ([media], ChatMessageAttachedContentNodeMediaFlags())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -479,6 +479,12 @@ public final class ChatMessageWebpageBubbleContentNode: ChatMessageBubbleContent
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for attribute in webpage.attributes {
|
||||||
|
if case let .stickerPack(stickerPack) = attribute, !stickerPack.files.isEmpty {
|
||||||
|
mediaAndFlags = (stickerPack.files, .preferMediaInline)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if defaultWebpageImageSizeIsSmall(webpage: webpage) {
|
if defaultWebpageImageSizeIsSmall(webpage: webpage) {
|
||||||
mediaAndFlags?.1.insert(.preferMediaInline)
|
mediaAndFlags?.1.insert(.preferMediaInline)
|
||||||
@ -514,7 +520,7 @@ public final class ChatMessageWebpageBubbleContentNode: ChatMessageBubbleContent
|
|||||||
for media in item.message.media {
|
for media in item.message.media {
|
||||||
switch media {
|
switch media {
|
||||||
case _ as TelegramMediaImage, _ as TelegramMediaFile, _ as TelegramMediaStory:
|
case _ as TelegramMediaImage, _ as TelegramMediaFile, _ as TelegramMediaStory:
|
||||||
mediaAndFlags = (media, [.preferMediaInline])
|
mediaAndFlags = ([media], [.preferMediaInline])
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -258,7 +258,7 @@ private final class MediaCutoutScreenComponent: Component {
|
|||||||
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
||||||
let result = super.hitTest(point, with: event)
|
let result = super.hitTest(point, with: event)
|
||||||
if let controller = self.environment?.controller() as? MediaCutoutScreen, [.erase, .restore].contains(controller.mode), result == self.previewContainerView {
|
if let controller = self.environment?.controller() as? MediaCutoutScreen, [.erase, .restore].contains(controller.mode), result == self.previewContainerView {
|
||||||
return nil//controller.previewView.superview
|
return nil
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
@ -2418,7 +2418,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final class Node: ViewControllerTracingNode, ASGestureRecognizerDelegate {
|
final class Node: ViewControllerTracingNode, ASGestureRecognizerDelegate, UIScrollViewDelegate {
|
||||||
private weak var controller: MediaEditorScreen?
|
private weak var controller: MediaEditorScreen?
|
||||||
private let context: AccountContext
|
private let context: AccountContext
|
||||||
fileprivate var interaction: DrawingToolsInteraction?
|
fileprivate var interaction: DrawingToolsInteraction?
|
||||||
@ -2438,6 +2438,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
|||||||
fileprivate let toolValue: ComponentView<Empty>
|
fileprivate let toolValue: ComponentView<Empty>
|
||||||
|
|
||||||
fileprivate let previewContainerView: UIView
|
fileprivate let previewContainerView: UIView
|
||||||
|
fileprivate let previewScrollView: UIScrollView
|
||||||
fileprivate let previewContentContainerView: PortalSourceView
|
fileprivate let previewContentContainerView: PortalSourceView
|
||||||
private var transitionInView: UIImageView?
|
private var transitionInView: UIImageView?
|
||||||
|
|
||||||
@ -2514,7 +2515,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
|||||||
self.componentHost = ComponentView<ViewControllerComponentContainer.Environment>()
|
self.componentHost = ComponentView<ViewControllerComponentContainer.Environment>()
|
||||||
self.storyPreview = ComponentView<Empty>()
|
self.storyPreview = ComponentView<Empty>()
|
||||||
self.toolValue = ComponentView<Empty>()
|
self.toolValue = ComponentView<Empty>()
|
||||||
|
|
||||||
self.previewContainerView = UIView()
|
self.previewContainerView = UIView()
|
||||||
self.previewContainerView.alpha = 0.0
|
self.previewContainerView.alpha = 0.0
|
||||||
self.previewContainerView.clipsToBounds = true
|
self.previewContainerView.clipsToBounds = true
|
||||||
@ -2523,6 +2524,14 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
|||||||
self.previewContainerView.layer.cornerCurve = .continuous
|
self.previewContainerView.layer.cornerCurve = .continuous
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.previewScrollView = UIScrollView()
|
||||||
|
self.previewScrollView.contentInsetAdjustmentBehavior = .never
|
||||||
|
self.previewScrollView.contentInset = .zero
|
||||||
|
self.previewScrollView.showsHorizontalScrollIndicator = false
|
||||||
|
self.previewScrollView.showsVerticalScrollIndicator = false
|
||||||
|
self.previewScrollView.panGestureRecognizer.minimumNumberOfTouches = 2
|
||||||
|
self.previewScrollView.isScrollEnabled = false
|
||||||
|
|
||||||
self.previewContentContainerView = PortalSourceView()
|
self.previewContentContainerView = PortalSourceView()
|
||||||
|
|
||||||
self.gradientView = UIImageView()
|
self.gradientView = UIImageView()
|
||||||
@ -2568,6 +2577,9 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
|||||||
|
|
||||||
self.view.addSubview(self.backgroundDimView)
|
self.view.addSubview(self.backgroundDimView)
|
||||||
self.view.addSubview(self.containerView)
|
self.view.addSubview(self.containerView)
|
||||||
|
|
||||||
|
self.previewScrollView.delegate = self
|
||||||
|
|
||||||
self.containerView.addSubview(self.previewContainerView)
|
self.containerView.addSubview(self.previewContainerView)
|
||||||
|
|
||||||
if case .stickerEditor = controller.mode {
|
if case .stickerEditor = controller.mode {
|
||||||
@ -2597,7 +2609,8 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
|||||||
self.previewContainerView.addSubview(self.gradientView)
|
self.previewContainerView.addSubview(self.gradientView)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.previewContainerView.addSubview(self.previewContentContainerView)
|
self.previewContainerView.addSubview(self.previewScrollView)
|
||||||
|
self.previewScrollView.addSubview(self.previewContentContainerView)
|
||||||
|
|
||||||
self.previewContentContainerView.addSubview(self.previewView)
|
self.previewContentContainerView.addSubview(self.previewView)
|
||||||
self.previewContentContainerView.addSubview(self.entitiesContainerView)
|
self.previewContentContainerView.addSubview(self.entitiesContainerView)
|
||||||
@ -3050,7 +3063,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
|||||||
controller.stickerSelectedEmoji = emoji
|
controller.stickerSelectedEmoji = emoji
|
||||||
let stickerEntity = DrawingStickerEntity(content: .file(.standalone(media: sticker), .sticker))
|
let stickerEntity = DrawingStickerEntity(content: .file(.standalone(media: sticker), .sticker))
|
||||||
stickerEntity.referenceDrawingSize = storyDimensions
|
stickerEntity.referenceDrawingSize = storyDimensions
|
||||||
stickerEntity.scale = 4.0
|
stickerEntity.scale = 4.0 * 0.97
|
||||||
stickerEntity.position = CGPoint(x: storyDimensions.width / 2.0, y: storyDimensions.height / 2.0)
|
stickerEntity.position = CGPoint(x: storyDimensions.width / 2.0, y: storyDimensions.height / 2.0)
|
||||||
self.entitiesView.add(stickerEntity, announce: false)
|
self.entitiesView.add(stickerEntity, announce: false)
|
||||||
}
|
}
|
||||||
@ -3262,6 +3275,10 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Queue.mainQueue().after(0.1) {
|
||||||
|
self.previewScrollView.pinchGestureRecognizer?.isEnabled = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
|
@objc func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
|
||||||
@ -4436,6 +4453,53 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func adjustPreviewZoom(updating: Bool = false) {
|
||||||
|
let minScale: CGFloat = 0.05
|
||||||
|
let maxScale: CGFloat = 3.0
|
||||||
|
|
||||||
|
if self.previewScrollView.minimumZoomScale != minScale {
|
||||||
|
self.previewScrollView.minimumZoomScale = minScale
|
||||||
|
}
|
||||||
|
if self.previewScrollView.maximumZoomScale != maxScale {
|
||||||
|
self.previewScrollView.maximumZoomScale = maxScale
|
||||||
|
}
|
||||||
|
|
||||||
|
let boundsSize = self.previewScrollView.frame.size
|
||||||
|
var contentFrame = self.previewContentContainerView.frame
|
||||||
|
if boundsSize.width > contentFrame.size.width {
|
||||||
|
contentFrame.origin.x = (boundsSize.width - contentFrame.size.width) / 2.0
|
||||||
|
} else {
|
||||||
|
contentFrame.origin.x = 0.0
|
||||||
|
}
|
||||||
|
|
||||||
|
if boundsSize.height > contentFrame.size.height {
|
||||||
|
contentFrame.origin.y = (boundsSize.height - contentFrame.size.height) / 2.0
|
||||||
|
} else {
|
||||||
|
contentFrame.origin.y = 0.0
|
||||||
|
}
|
||||||
|
self.previewContentContainerView.frame = contentFrame
|
||||||
|
|
||||||
|
if !updating {
|
||||||
|
self.stickerMaskDrawingView?.updateZoomScale(self.previewScrollView.zoomScale)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func scrollViewDidZoom(_ scrollView: UIScrollView) {
|
||||||
|
self.adjustPreviewZoom()
|
||||||
|
}
|
||||||
|
|
||||||
|
func scrollViewDidEndZooming(_ scrollView: UIScrollView, with view: UIView?, atScale scale: CGFloat) {
|
||||||
|
self.adjustPreviewZoom()
|
||||||
|
|
||||||
|
if scrollView.zoomScale < 1.0 {
|
||||||
|
scrollView.setZoomScale(1.0, animated: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
|
||||||
|
return self.previewContentContainerView
|
||||||
|
}
|
||||||
|
|
||||||
fileprivate var drawingScreen: DrawingScreen?
|
fileprivate var drawingScreen: DrawingScreen?
|
||||||
fileprivate var stickerScreen: StickerPickerScreen?
|
fileprivate var stickerScreen: StickerPickerScreen?
|
||||||
fileprivate weak var cutoutScreen: MediaCutoutScreen?
|
fileprivate weak var cutoutScreen: MediaCutoutScreen?
|
||||||
@ -4723,6 +4787,12 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
|||||||
guard let mediaEditor = self.mediaEditor, let stickerMaskDrawingView = self.stickerMaskDrawingView, let stickerBackgroundView = self.stickerBackgroundView else {
|
guard let mediaEditor = self.mediaEditor, let stickerMaskDrawingView = self.stickerMaskDrawingView, let stickerBackgroundView = self.stickerBackgroundView else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if [.cutoutErase, .cutoutRestore].contains(mode) {
|
||||||
|
self.previewScrollView.isScrollEnabled = true
|
||||||
|
self.previewScrollView.pinchGestureRecognizer?.isEnabled = true
|
||||||
|
}
|
||||||
|
|
||||||
let cutoutController = MediaCutoutScreen(
|
let cutoutController = MediaCutoutScreen(
|
||||||
context: self.context,
|
context: self.context,
|
||||||
mode: cutoutMode,
|
mode: cutoutMode,
|
||||||
@ -4746,6 +4816,9 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
|||||||
}
|
}
|
||||||
cutoutController.dismissed = { [weak self] in
|
cutoutController.dismissed = { [weak self] in
|
||||||
if let self {
|
if let self {
|
||||||
|
self.previewScrollView.setZoomScale(1.0, animated: true)
|
||||||
|
self.previewScrollView.isScrollEnabled = false
|
||||||
|
self.previewScrollView.pinchGestureRecognizer?.isEnabled = false
|
||||||
self.animateInFromTool(inPlace: true)
|
self.animateInFromTool(inPlace: true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4911,8 +4984,18 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
|||||||
|
|
||||||
let previewFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((layout.size.width - previewSize.width) / 2.0), y: topInset - bottomInputOffset + self.dismissOffset), size: previewSize)
|
let previewFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((layout.size.width - previewSize.width) / 2.0), y: topInset - bottomInputOffset + self.dismissOffset), size: previewSize)
|
||||||
transition.setFrame(view: self.previewContainerView, frame: previewFrame)
|
transition.setFrame(view: self.previewContainerView, frame: previewFrame)
|
||||||
|
transition.setFrame(view: self.previewScrollView, frame: CGRect(origin: .zero, size: previewSize))
|
||||||
|
|
||||||
transition.setFrame(view: self.previewContentContainerView, frame: CGRect(origin: .zero, size: previewSize))
|
if self.previewScrollView.contentSize == .zero {
|
||||||
|
self.previewScrollView.zoomScale = 1.0
|
||||||
|
self.previewScrollView.contentSize = previewSize
|
||||||
|
}
|
||||||
|
|
||||||
|
if abs(self.previewContentContainerView.bounds.width - previewSize.width) > 1.0 {
|
||||||
|
transition.setFrame(view: self.previewContentContainerView, frame: CGRect(origin: .zero, size: previewSize))
|
||||||
|
}
|
||||||
|
|
||||||
|
self.adjustPreviewZoom(updating: true)
|
||||||
transition.setFrame(view: self.previewView, frame: CGRect(origin: .zero, size: previewSize))
|
transition.setFrame(view: self.previewView, frame: CGRect(origin: .zero, size: previewSize))
|
||||||
|
|
||||||
let entitiesViewScale = previewSize.width / storyDimensions.width
|
let entitiesViewScale = previewSize.width / storyDimensions.width
|
||||||
@ -5125,6 +5208,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
|||||||
public var completion: (MediaEditorScreen.Result, @escaping (@escaping () -> Void) -> Void) -> Void = { _, _ in }
|
public var completion: (MediaEditorScreen.Result, @escaping (@escaping () -> Void) -> Void) -> Void = { _, _ in }
|
||||||
public var dismissed: () -> Void = { }
|
public var dismissed: () -> Void = { }
|
||||||
public var willDismiss: () -> Void = { }
|
public var willDismiss: () -> Void = { }
|
||||||
|
public var sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)?
|
||||||
|
|
||||||
private var adminedChannels = Promise<[EnginePeer]>()
|
private var adminedChannels = Promise<[EnginePeer]>()
|
||||||
private var closeFriends = Promise<[EnginePeer]>()
|
private var closeFriends = Promise<[EnginePeer]>()
|
||||||
@ -6367,9 +6451,25 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
|||||||
|
|
||||||
contextItems.append(.custom(StickerPackListContextItem(context: self.context, packs: self.myStickerPacks, packSelected: { [weak self] pack in
|
contextItems.append(.custom(StickerPackListContextItem(context: self.context, packs: self.myStickerPacks, packSelected: { [weak self] pack in
|
||||||
guard let self else {
|
guard let self else {
|
||||||
return
|
return true
|
||||||
|
}
|
||||||
|
if pack.count >= 120 {
|
||||||
|
let controller = UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: presentationData.strings.MediaEditor_StickersTooMuch, timeout: nil, customUndoText: nil), elevatedLayout: false, position: .top, animateInAsReplacement: false, action: { [weak self] action in
|
||||||
|
if case .info = action, let self {
|
||||||
|
let controller = context.sharedContext.makePremiumIntroController(context: context, source: .stories, forceDark: true, dismissed: {
|
||||||
|
|
||||||
|
})
|
||||||
|
self.push(controller)
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
self.hapticFeedback.error()
|
||||||
|
self.present(controller, in: .window(.root))
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
self.uploadSticker(file, action: .addToStickerPack(pack: .id(id: pack.id.id, accessHash: pack.accessHash), title: pack.title))
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
self.uploadSticker(file, action: .addToStickerPack(pack: .id(id: pack.id.id, accessHash: pack.accessHash), title: pack.title))
|
|
||||||
}), false))
|
}), false))
|
||||||
|
|
||||||
let items = ContextController.Items(
|
let items = ContextController.Items(
|
||||||
@ -6552,7 +6652,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
|||||||
}
|
}
|
||||||
self.present(controller, in: .window(.root))
|
self.present(controller, in: .window(.root))
|
||||||
}
|
}
|
||||||
|
|
||||||
private let stickerUploadDisposable = MetaDisposable()
|
private let stickerUploadDisposable = MetaDisposable()
|
||||||
private func uploadSticker(_ file: TelegramMediaFile, action: StickerAction) {
|
private func uploadSticker(_ file: TelegramMediaFile, action: StickerAction) {
|
||||||
let context = self.context
|
let context = self.context
|
||||||
|
@ -13,9 +13,9 @@ import ContextUI
|
|||||||
final class StickerPackListContextItem: ContextMenuCustomItem {
|
final class StickerPackListContextItem: ContextMenuCustomItem {
|
||||||
let context: AccountContext
|
let context: AccountContext
|
||||||
let packs: [(StickerPackCollectionInfo, StickerPackItem?)]
|
let packs: [(StickerPackCollectionInfo, StickerPackItem?)]
|
||||||
let packSelected: (StickerPackCollectionInfo) -> Void
|
let packSelected: (StickerPackCollectionInfo) -> Bool
|
||||||
|
|
||||||
init(context: AccountContext, packs: [(StickerPackCollectionInfo, StickerPackItem?)], packSelected: @escaping (StickerPackCollectionInfo) -> Void) {
|
init(context: AccountContext, packs: [(StickerPackCollectionInfo, StickerPackItem?)], packSelected: @escaping (StickerPackCollectionInfo) -> Bool) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.packs = packs
|
self.packs = packs
|
||||||
self.packSelected = packSelected
|
self.packSelected = packSelected
|
||||||
@ -75,9 +75,9 @@ private final class StickerPackListContextItemNode: ASDisplayNode, ContextMenuCu
|
|||||||
}
|
}
|
||||||
|
|
||||||
let action = ContextMenuActionItem(text: pack.title, textLayout: .singleLine, icon: { _ in nil }, iconSource: thumbnailIconSource, iconPosition: .left, action: { _, f in
|
let action = ContextMenuActionItem(text: pack.title, textLayout: .singleLine, icon: { _ in nil }, iconSource: thumbnailIconSource, iconPosition: .left, action: { _, f in
|
||||||
f(.dismissWithoutContent)
|
if item.packSelected(pack) {
|
||||||
|
f(.dismissWithoutContent)
|
||||||
item.packSelected(pack)
|
}
|
||||||
})
|
})
|
||||||
let actionNode = ContextControllerActionsListActionItemNode(getController: getController, requestDismiss: actionSelected, requestUpdateAction: { _, _ in }, item: action)
|
let actionNode = ContextControllerActionsListActionItemNode(getController: getController, requestDismiss: actionSelected, requestUpdateAction: { _, _ in }, item: action)
|
||||||
actionNodes.append(actionNode)
|
actionNodes.append(actionNode)
|
||||||
|
@ -7642,6 +7642,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
if let editMessage = interfaceState.editMessage, let message = combinedInitialData.initialData?.associatedMessages[editMessage.messageId] {
|
if let editMessage = interfaceState.editMessage, let message = combinedInitialData.initialData?.associatedMessages[editMessage.messageId] {
|
||||||
let (updatedState, updatedPreviewQueryState) = updatedChatEditInterfaceMessageState(context: strongSelf.context, state: updated, message: message)
|
let (updatedState, updatedPreviewQueryState) = updatedChatEditInterfaceMessageState(context: strongSelf.context, state: updated, message: message)
|
||||||
updated = updatedState
|
updated = updatedState
|
||||||
|
strongSelf.editingUrlPreviewQueryState?.1.dispose()
|
||||||
strongSelf.editingUrlPreviewQueryState = updatedPreviewQueryState
|
strongSelf.editingUrlPreviewQueryState = updatedPreviewQueryState
|
||||||
}
|
}
|
||||||
updated = updated.updatedSlowmodeState(slowmodeState)
|
updated = updated.updatedSlowmodeState(slowmodeState)
|
||||||
@ -8979,6 +8980,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
|
|
||||||
let (updatedState, updatedPreviewQueryState) = updatedChatEditInterfaceMessageState(context: strongSelf.context, state: updated, message: message)
|
let (updatedState, updatedPreviewQueryState) = updatedChatEditInterfaceMessageState(context: strongSelf.context, state: updated, message: message)
|
||||||
updated = updatedState
|
updated = updatedState
|
||||||
|
strongSelf.editingUrlPreviewQueryState?.1.dispose()
|
||||||
strongSelf.editingUrlPreviewQueryState = updatedPreviewQueryState
|
strongSelf.editingUrlPreviewQueryState = updatedPreviewQueryState
|
||||||
|
|
||||||
updated = updated.updatedInputMode({ _ in
|
updated = updated.updatedInputMode({ _ in
|
||||||
|
@ -1772,6 +1772,9 @@ extension ChatControllerImpl {
|
|||||||
}
|
}
|
||||||
} as (MediaEditorScreen.Result, @escaping (@escaping () -> Void) -> Void) -> Void
|
} as (MediaEditorScreen.Result, @escaping (@escaping () -> Void) -> Void) -> Void
|
||||||
)
|
)
|
||||||
|
editorController.sendSticker = { [weak self] file, sourceView, sourceRect in
|
||||||
|
return self?.interfaceInteraction?.sendSticker(file, true, sourceView, sourceRect, nil, []) ?? false
|
||||||
|
}
|
||||||
self.push(editorController)
|
self.push(editorController)
|
||||||
},
|
},
|
||||||
dismissed: {}
|
dismissed: {}
|
||||||
|
@ -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: false) as? TelegramMediaResource {
|
} else if let dimensions = file.dimensions, let resource = chatMessageStickerResource(file: file, small: true) 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)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user