From 05f2bf7b850658378f84909d71b997b8f6fc356c Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Mon, 25 Jul 2022 05:36:30 +0300 Subject: [PATCH] Various fixes --- .../Telegram-iOS/en.lproj/Localizable.strings | 6 + .../Sources/Items/ChatImageGalleryItem.swift | 30 +-- .../Items/UniversalVideoGalleryItem.swift | 30 +-- .../ImportStickerPackControllerNode.swift | 2 +- .../PremiumUI/Sources/PremiumGiftScreen.swift | 4 +- .../InstalledStickerPacksController.swift | 52 ++--- .../Sources/StickerPackScreen.swift | 196 +++++++++--------- .../TelegramUI/Sources/ChatController.swift | 33 ++- .../TelegramUI/Sources/OpenChatMessage.swift | 53 +++-- .../TelegramUI/Sources/OpenResolvedUrl.swift | 38 ++-- 10 files changed, 249 insertions(+), 195 deletions(-) diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 1b69ca55e6..9aea810170 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -7886,6 +7886,12 @@ Sorry for the inconvenience."; "EmojiPackActionInfo.ArchivedTitle" = "Emoji Archived"; "EmojiPackActionInfo.RemovedText" = "%@ is no longer in your emoji."; +"EmojiPackActionInfo.MultipleAddedText_1" = "%@ pack has been added to your emoji."; +"EmojiPackActionInfo.MultipleAddedText_any" = "%@ packs have been added to your emoji."; + +"EmojiPackActionInfo.MultipleRemovedText_1" = "%@ pack is no longer in your emoji."; +"EmojiPackActionInfo.MultipleRemovedText_any" = "%@ packs are no longer in your emoji."; + "MaskPackActionInfo.RemovedTitle" = "Masks Removed"; "MaskPackActionInfo.ArchivedTitle" = "Masks Archived"; "MaskPackActionInfo.RemovedText" = "%@ is no longer in your masks."; diff --git a/submodules/GalleryUI/Sources/Items/ChatImageGalleryItem.swift b/submodules/GalleryUI/Sources/Items/ChatImageGalleryItem.swift index edd50e3721..b146287009 100644 --- a/submodules/GalleryUI/Sources/Items/ChatImageGalleryItem.swift +++ b/submodules/GalleryUI/Sources/Items/ChatImageGalleryItem.swift @@ -474,20 +474,22 @@ final class ChatImageGalleryItemNode: ZoomableContentGalleryItemNode { } let baseNavigationController = strongSelf.baseNavigationController() baseNavigationController?.view.endEditing(true) - let controller = StickerPackScreen(context: context, mainStickerPack: packs[0], stickerPacks: packs, sendSticker: nil, actionPerformed: { info, items, action in - let animateInAsReplacement = false - switch action { - case .add: - topController?.present(UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.StickerPackActionInfo_AddedTitle, text: presentationData.strings.StickerPackActionInfo_AddedText(info.title).string, undo: false, info: info, topItem: items.first, context: context), elevatedLayout: true, animateInAsReplacement: animateInAsReplacement, action: { _ in - return true - }), in: .window(.root)) - case let .remove(positionInList): - topController?.present(UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.StickerPackActionInfo_RemovedTitle, text: presentationData.strings.StickerPackActionInfo_RemovedText(info.title).string, undo: true, info: info, topItem: items.first, context: context), elevatedLayout: true, animateInAsReplacement: animateInAsReplacement, action: { action in - if case .undo = action { - let _ = context.engine.stickers.addStickerPackInteractively(info: info, items: items, positionInList: positionInList).start() - } - return true - }), in: .window(.root)) + let controller = StickerPackScreen(context: context, mainStickerPack: packs[0], stickerPacks: packs, sendSticker: nil, actionPerformed: { actions in + if let (info, items, action) = actions.first { + let animateInAsReplacement = false + switch action { + case .add: + topController?.present(UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.StickerPackActionInfo_AddedTitle, text: presentationData.strings.StickerPackActionInfo_AddedText(info.title).string, undo: false, info: info, topItem: items.first, context: context), elevatedLayout: true, animateInAsReplacement: animateInAsReplacement, action: { _ in + return true + }), in: .window(.root)) + case let .remove(positionInList): + topController?.present(UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.StickerPackActionInfo_RemovedTitle, text: presentationData.strings.StickerPackActionInfo_RemovedText(info.title).string, undo: true, info: info, topItem: items.first, context: context), elevatedLayout: true, animateInAsReplacement: animateInAsReplacement, action: { action in + if case .undo = action { + let _ = context.engine.stickers.addStickerPackInteractively(info: info, items: items, positionInList: positionInList).start() + } + return true + }), in: .window(.root)) + } } }) (baseNavigationController?.topViewController as? ViewController)?.present(controller, in: .window(.root), with: nil) diff --git a/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift b/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift index d586315cdc..66b2bbf180 100644 --- a/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift +++ b/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift @@ -2667,20 +2667,22 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { } let baseNavigationController = strongSelf.baseNavigationController() baseNavigationController?.view.endEditing(true) - let controller = StickerPackScreen(context: strongSelf.context, mainStickerPack: packs[0], stickerPacks: Array(packs.prefix(1)), sendSticker: nil, actionPerformed: { info, items, action in - let animateInAsReplacement = false - switch action { - case .add: - topController?.present(UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.StickerPackActionInfo_AddedTitle, text: presentationData.strings.StickerPackActionInfo_AddedText(info.title).string, undo: false, info: info, topItem: items.first, context: context), elevatedLayout: true, animateInAsReplacement: animateInAsReplacement, action: { _ in - return true - }), in: .window(.root)) - case let .remove(positionInList): - topController?.present(UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.StickerPackActionInfo_RemovedTitle, text: presentationData.strings.StickerPackActionInfo_RemovedText(info.title).string, undo: true, info: info, topItem: items.first, context: context), elevatedLayout: true, animateInAsReplacement: animateInAsReplacement, action: { action in - if case .undo = action { - let _ = context.engine.stickers.addStickerPackInteractively(info: info, items: items, positionInList: positionInList).start() - } - return true - }), in: .window(.root)) + let controller = StickerPackScreen(context: strongSelf.context, mainStickerPack: packs[0], stickerPacks: Array(packs.prefix(1)), sendSticker: nil, actionPerformed: { actions in + if let (info, items, action) = actions.first { + let animateInAsReplacement = false + switch action { + case .add: + topController?.present(UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.StickerPackActionInfo_AddedTitle, text: presentationData.strings.StickerPackActionInfo_AddedText(info.title).string, undo: false, info: info, topItem: items.first, context: context), elevatedLayout: true, animateInAsReplacement: animateInAsReplacement, action: { _ in + return true + }), in: .window(.root)) + case let .remove(positionInList): + topController?.present(UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.StickerPackActionInfo_RemovedTitle, text: presentationData.strings.StickerPackActionInfo_RemovedText(info.title).string, undo: true, info: info, topItem: items.first, context: context), elevatedLayout: true, animateInAsReplacement: animateInAsReplacement, action: { action in + if case .undo = action { + let _ = context.engine.stickers.addStickerPackInteractively(info: info, items: items, positionInList: positionInList).start() + } + return true + }), in: .window(.root)) + } } }, dismissed: { [weak self] in self?.isInteractingPromise.set(false) diff --git a/submodules/ImportStickerPackUI/Sources/ImportStickerPackControllerNode.swift b/submodules/ImportStickerPackUI/Sources/ImportStickerPackControllerNode.swift index 25d12f558d..163dadd050 100644 --- a/submodules/ImportStickerPackUI/Sources/ImportStickerPackControllerNode.swift +++ b/submodules/ImportStickerPackUI/Sources/ImportStickerPackControllerNode.swift @@ -694,7 +694,7 @@ final class ImportStickerPackControllerNode: ViewControllerTracingNode, UIScroll } strongSelf.presentInGlobalOverlay?(UndoOverlayController(presentationData: strongSelf.presentationData, content: .stickersModified(title: strongSelf.presentationData.strings.StickerPackActionInfo_AddedTitle, text: strongSelf.presentationData.strings.StickerPackActionInfo_AddedText(info.title).string, undo: false, info: info, topItem: firstItem ?? items.first, context: strongSelf.context), elevatedLayout: false, action: { action in if case .info = action { - (navigationController?.viewControllers.last as? ViewController)?.present(StickerPackScreen(context: context, mode: .settings, mainStickerPack: .id(id: info.id.id, accessHash: info.accessHash), stickerPacks: [], parentNavigationController: navigationController, actionPerformed: { _, _, _ in + (navigationController?.viewControllers.last as? ViewController)?.present(StickerPackScreen(context: context, mode: .settings, mainStickerPack: .id(id: info.id.id, accessHash: info.accessHash), stickerPacks: [], parentNavigationController: navigationController, actionPerformed: { _ in }), in: .window(.root)) } return true diff --git a/submodules/PremiumUI/Sources/PremiumGiftScreen.swift b/submodules/PremiumUI/Sources/PremiumGiftScreen.swift index c85674f73b..f081acd905 100644 --- a/submodules/PremiumUI/Sources/PremiumGiftScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumGiftScreen.swift @@ -820,7 +820,9 @@ private final class PremiumGiftScreenComponent: CombinedComponent { } strongSelf.products = gifts - strongSelf.selectedProductId = strongSelf.products?.first?.id + if strongSelf.selectedProductId == nil { + strongSelf.selectedProductId = strongSelf.products?.first?.id + } strongSelf.peer = peer strongSelf.updated(transition: .immediate) } diff --git a/submodules/SettingsUI/Sources/Stickers/InstalledStickerPacksController.swift b/submodules/SettingsUI/Sources/Stickers/InstalledStickerPacksController.swift index f24eedbc3a..73d10a8f52 100644 --- a/submodules/SettingsUI/Sources/Stickers/InstalledStickerPacksController.swift +++ b/submodules/SettingsUI/Sources/Stickers/InstalledStickerPacksController.swift @@ -1267,7 +1267,7 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta packs.insert(packReference, at: 0) } if let mainStickerPack = mainStickerPack { - presentControllerImpl?(StickerPackScreen(context: context, mode: .settings, mainStickerPack: mainStickerPack, stickerPacks: [mainStickerPack], parentNavigationController: controller?.navigationController as? NavigationController, actionPerformed: { info, items, action in + presentControllerImpl?(StickerPackScreen(context: context, mode: .settings, mainStickerPack: mainStickerPack, stickerPacks: [mainStickerPack], parentNavigationController: controller?.navigationController as? NavigationController, actionPerformed: { actions in let presentationData = context.sharedContext.currentPresentationData.with { $0 } var animateInAsReplacement = false if let navigationController = navigationControllerImpl?() { @@ -1278,31 +1278,33 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta } } } - switch action { - case .add: - navigationControllerImpl?()?.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.StickerPackActionInfo_AddedTitle, text: presentationData.strings.StickerPackActionInfo_AddedText(info.title).string, undo: false, info: info, topItem: items.first, context: context), elevatedLayout: false, animateInAsReplacement: animateInAsReplacement, action: { _ in - return true - })) - case let .remove(positionInList): - let removedTitle: String - let removedText: String - if info.id.namespace == Namespaces.ItemCollection.CloudEmojiPacks { - removedTitle = presentationData.strings.EmojiPackActionInfo_RemovedTitle - removedText = presentationData.strings.EmojiPackActionInfo_RemovedText(info.title).string - } else if info.id.namespace == Namespaces.ItemCollection.CloudMaskPacks { - removedTitle = presentationData.strings.MaskPackActionInfo_RemovedTitle - removedText = presentationData.strings.MaskPackActionInfo_RemovedText(info.title).string - } else { - removedTitle = presentationData.strings.StickerPackActionInfo_RemovedTitle - removedText = presentationData.strings.StickerPackActionInfo_RemovedText(info.title).string - } - - navigationControllerImpl?()?.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: removedTitle, text: removedText, undo: true, info: info, topItem: items.first, context: context), elevatedLayout: false, animateInAsReplacement: animateInAsReplacement, action: { action in - if case .undo = action { - let _ = context.engine.stickers.addStickerPackInteractively(info: info, items: items, positionInList: positionInList).start() + if let (info, items, action) = actions.first { + switch action { + case .add: + navigationControllerImpl?()?.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.StickerPackActionInfo_AddedTitle, text: presentationData.strings.StickerPackActionInfo_AddedText(info.title).string, undo: false, info: info, topItem: items.first, context: context), elevatedLayout: false, animateInAsReplacement: animateInAsReplacement, action: { _ in + return true + })) + case let .remove(positionInList): + let removedTitle: String + let removedText: String + if info.id.namespace == Namespaces.ItemCollection.CloudEmojiPacks { + removedTitle = presentationData.strings.EmojiPackActionInfo_RemovedTitle + removedText = presentationData.strings.EmojiPackActionInfo_RemovedText(info.title).string + } else if info.id.namespace == Namespaces.ItemCollection.CloudMaskPacks { + removedTitle = presentationData.strings.MaskPackActionInfo_RemovedTitle + removedText = presentationData.strings.MaskPackActionInfo_RemovedText(info.title).string + } else { + removedTitle = presentationData.strings.StickerPackActionInfo_RemovedTitle + removedText = presentationData.strings.StickerPackActionInfo_RemovedText(info.title).string } - return true - })) + + navigationControllerImpl?()?.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: removedTitle, text: removedText, undo: true, info: info, topItem: items.first, context: context), elevatedLayout: false, animateInAsReplacement: animateInAsReplacement, action: { action in + if case .undo = action { + let _ = context.engine.stickers.addStickerPackInteractively(info: info, items: items, positionInList: positionInList).start() + } + return true + })) + } } }), nil) } diff --git a/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift b/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift index f3ebc8cbe4..96786183cb 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift @@ -632,14 +632,15 @@ private final class StickerPackContainer: ASDisplayNode { }) } } else { + var installedPacks: [(StickerPackCollectionInfo, [StickerPackItem], StickerPackScreenPerformedAction)] = [] for (info, items, isInstalled) in self.currentStickerPacks { if !isInstalled { + installedPacks.append((info, items, .add)) let _ = self.context.engine.stickers.addStickerPackInteractively(info: info, items: items).start() -// if dismissed { -// actionPerformed?(info, items, .add) -// } } } + + self.controller?.actionPerformed?(installedPacks) } self.requestDismiss() } else if let (info, items, installed) = self.currentStickerPack { @@ -660,13 +661,13 @@ private final class StickerPackContainer: ASDisplayNode { return } if dismissed { - actionPerformed?(info, items, .remove(positionInList: positionInList)) + actionPerformed?([(info, items, .remove(positionInList: positionInList))]) } }) } else { let _ = self.context.engine.stickers.addStickerPackInteractively(info: info, items: items).start() if dismissed { - actionPerformed?(info, items, .add) + actionPerformed?([(info, items, .add)]) } } } else { @@ -1220,7 +1221,6 @@ private final class StickerPackScreenNode: ViewControllerTracingNode { super.didLoad() self.dimNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.dimNodeTapGesture(_:)))) -// self.containerContainingNode.view.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(self.panGesture(_:)))) } func updatePresentationData(_ presentationData: PresentationData) { @@ -1238,11 +1238,7 @@ private final class StickerPackScreenNode: ViewControllerTracingNode { transition.updateFrame(node: self.containerContainingNode, frame: CGRect(origin: CGPoint(), size: layout.size)) let expandProgress: CGFloat = 1.0 -// if self.stickerPacks.count == 1 { -// expandProgress = 1.0 -// } else { -// expandProgress = self.containers[self.selectedStickerPackIndex]?.expandProgress ?? 0.0 -// } + let scaledInset: CGFloat = 12.0 let scaledDistance: CGFloat = 4.0 let minScale = (layout.size.width - scaledInset * 2.0) / layout.size.width @@ -1250,108 +1246,106 @@ private final class StickerPackScreenNode: ViewControllerTracingNode { let containerVerticalOffset: CGFloat = (1.0 - expandProgress) * scaledInset * 2.0 -// for i in 0 ..< self.stickerPacks.count { let i = 0 - let indexOffset = i - self.selectedStickerPackIndex - var scaledOffset: CGFloat = 0.0 - scaledOffset = -CGFloat(indexOffset) * (1.0 - expandProgress) * (scaledInset * 2.0) + CGFloat(indexOffset) * scaledDistance - - if abs(indexOffset) <= 1 { - let containerTransition: ContainedViewLayoutTransition - let container: StickerPackContainer - var wasAdded = false - if let current = self.containers[i] { - containerTransition = transition - container = current - } else { - wasAdded = true - containerTransition = .immediate - let index = i - container = StickerPackContainer(index: index, context: context, presentationData: self.presentationData, stickerPacks: self.stickerPacks, decideNextAction: { [weak self] container, action in - guard let strongSelf = self, let layout = strongSelf.validLayout else { - return .dismiss - } - if index == strongSelf.stickerPacks.count - 1 { - return .dismiss - } else { - switch action { - case .add: - var allAdded = true - for _ in index + 1 ..< strongSelf.stickerPacks.count { - if let container = strongSelf.containers[index], let (_, _, installed) = container.currentStickerPack { - if !installed { - allAdded = false - } - } else { + let indexOffset = i - self.selectedStickerPackIndex + var scaledOffset: CGFloat = 0.0 + scaledOffset = -CGFloat(indexOffset) * (1.0 - expandProgress) * (scaledInset * 2.0) + CGFloat(indexOffset) * scaledDistance + + if abs(indexOffset) <= 1 { + let containerTransition: ContainedViewLayoutTransition + let container: StickerPackContainer + var wasAdded = false + if let current = self.containers[i] { + containerTransition = transition + container = current + } else { + wasAdded = true + containerTransition = .immediate + let index = i + container = StickerPackContainer(index: index, context: context, presentationData: self.presentationData, stickerPacks: self.stickerPacks, decideNextAction: { [weak self] container, action in + guard let strongSelf = self, let layout = strongSelf.validLayout else { + return .dismiss + } + if index == strongSelf.stickerPacks.count - 1 { + return .dismiss + } else { + switch action { + case .add: + var allAdded = true + for _ in index + 1 ..< strongSelf.stickerPacks.count { + if let container = strongSelf.containers[index], let (_, _, installed) = container.currentStickerPack { + if !installed { allAdded = false } - } - if allAdded { - return .dismiss - } - case .remove: - if strongSelf.stickerPacks.count == 1 { - return .dismiss } else { - return .ignored + allAdded = false } } - } - - strongSelf.selectedStickerPackIndex = strongSelf.selectedStickerPackIndex + 1 - strongSelf.containerLayoutUpdated(layout, transition: .animated(duration: 0.3, curve: .spring)) - return .navigatedNext - }, requestDismiss: { [weak self] in - self?.dismiss() - }, expandProgressUpdated: { [weak self] container, transition, expandTransition in - guard let strongSelf = self, let layout = strongSelf.validLayout else { - return - } - if index == strongSelf.selectedStickerPackIndex, let container = strongSelf.containers[strongSelf.selectedStickerPackIndex] { - let modalProgress = container.modalProgress - strongSelf.modalProgressUpdated(modalProgress, transition) - strongSelf.containerLayoutUpdated(layout, transition: expandTransition) - for (_, otherContainer) in strongSelf.containers { - if otherContainer !== container { - otherContainer.syncExpandProgress(expandScrollProgress: container.expandScrollProgress, expandProgress: container.expandProgress, modalProgress: container.modalProgress, transition: expandTransition) - } + if allAdded { + return .dismiss + } + case .remove: + if strongSelf.stickerPacks.count == 1 { + return .dismiss + } else { + return .ignored } } - }, presentInGlobalOverlay: presentInGlobalOverlay, sendSticker: sendSticker, openMention: openMention, controller: self.controller) - container.onReady = { [weak self] in - self?.onReady() } - container.onLoading = { [weak self] in - self?.onLoading() + + strongSelf.selectedStickerPackIndex = strongSelf.selectedStickerPackIndex + 1 + strongSelf.containerLayoutUpdated(layout, transition: .animated(duration: 0.3, curve: .spring)) + return .navigatedNext + }, requestDismiss: { [weak self] in + self?.dismiss() + }, expandProgressUpdated: { [weak self] container, transition, expandTransition in + guard let strongSelf = self, let layout = strongSelf.validLayout else { + return } - container.onError = { [weak self] in - self?.onError() - } - self.containerContainingNode.addSubnode(container) - self.containers[i] = container - } - - let containerFrame = CGRect(origin: CGPoint(x: CGFloat(indexOffset) * layout.size.width + self.relativeToSelectedStickerPackTransition + scaledOffset, y: containerVerticalOffset), size: layout.size) - containerTransition.updateFrame(node: container, frame: containerFrame, beginWithCurrentState: true) - containerTransition.updateSublayerTransformScaleAndOffset(node: container, scale: containerScale, offset: CGPoint(), beginWithCurrentState: true) - if container.validLayout?.0 != layout { - container.updateLayout(layout: layout, transition: containerTransition) - } - - if wasAdded { - if let selectedContainer = self.containers[self.selectedStickerPackIndex] { - if selectedContainer !== container { - container.syncExpandProgress(expandScrollProgress: selectedContainer.expandScrollProgress, expandProgress: selectedContainer.expandProgress, modalProgress: selectedContainer.modalProgress, transition: .immediate) + if index == strongSelf.selectedStickerPackIndex, let container = strongSelf.containers[strongSelf.selectedStickerPackIndex] { + let modalProgress = container.modalProgress + strongSelf.modalProgressUpdated(modalProgress, transition) + strongSelf.containerLayoutUpdated(layout, transition: expandTransition) + for (_, otherContainer) in strongSelf.containers { + if otherContainer !== container { + otherContainer.syncExpandProgress(expandScrollProgress: container.expandScrollProgress, expandProgress: container.expandProgress, modalProgress: container.modalProgress, transition: expandTransition) + } } } + }, presentInGlobalOverlay: presentInGlobalOverlay, sendSticker: sendSticker, openMention: openMention, controller: self.controller) + container.onReady = { [weak self] in + self?.onReady() } - } else { - if let container = self.containers[i] { - container.removeFromSupernode() - self.containers.removeValue(forKey: i) + container.onLoading = { [weak self] in + self?.onLoading() + } + container.onError = { [weak self] in + self?.onError() + } + self.containerContainingNode.addSubnode(container) + self.containers[i] = container + } + + let containerFrame = CGRect(origin: CGPoint(x: CGFloat(indexOffset) * layout.size.width + self.relativeToSelectedStickerPackTransition + scaledOffset, y: containerVerticalOffset), size: layout.size) + containerTransition.updateFrame(node: container, frame: containerFrame, beginWithCurrentState: true) + containerTransition.updateSublayerTransformScaleAndOffset(node: container, scale: containerScale, offset: CGPoint(), beginWithCurrentState: true) + if container.validLayout?.0 != layout { + container.updateLayout(layout: layout, transition: containerTransition) + } + + if wasAdded { + if let selectedContainer = self.containers[self.selectedStickerPackIndex] { + if selectedContainer !== container { + container.syncExpandProgress(expandScrollProgress: selectedContainer.expandScrollProgress, expandProgress: selectedContainer.expandProgress, modalProgress: selectedContainer.modalProgress, transition: .immediate) + } } } -// } + } else { + if let container = self.containers[i] { + container.removeFromSupernode() + self.containers.removeValue(forKey: i) + } + } if firstTime { if !self.containers.isEmpty { @@ -1515,7 +1509,7 @@ public final class StickerPackScreenImpl: ViewController { } public var dismissed: (() -> Void)? - public var actionPerformed: ((StickerPackCollectionInfo, [StickerPackItem], StickerPackScreenPerformedAction) -> Void)? + public var actionPerformed: (([(StickerPackCollectionInfo, [StickerPackItem], StickerPackScreenPerformedAction)]) -> Void)? private let _ready = Promise() override public var ready: Promise { @@ -1530,7 +1524,7 @@ public final class StickerPackScreenImpl: ViewController { let animationCache: AnimationCache let animationRenderer: MultiAnimationRenderer - public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, stickerPacks: [StickerPackReference], selectedStickerPackIndex: Int = 0, parentNavigationController: NavigationController? = nil, sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)? = nil, actionPerformed: ((StickerPackCollectionInfo, [StickerPackItem], StickerPackScreenPerformedAction) -> Void)? = nil) { + public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, stickerPacks: [StickerPackReference], selectedStickerPackIndex: Int = 0, parentNavigationController: NavigationController? = nil, sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)? = nil, actionPerformed: (([(StickerPackCollectionInfo, [StickerPackItem], StickerPackScreenPerformedAction)]) -> Void)? = nil) { self.context = context self.presentationData = updatedPresentationData?.initial ?? context.sharedContext.currentPresentationData.with { $0 } self.stickerPacks = stickerPacks @@ -1709,7 +1703,7 @@ public enum StickerPackScreenPerformedAction { case remove(positionInList: Int) } -public func StickerPackScreen(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, mode: StickerPackPreviewControllerMode = .default, mainStickerPack: StickerPackReference, stickerPacks: [StickerPackReference], parentNavigationController: NavigationController? = nil, sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)? = nil, actionPerformed: ((StickerPackCollectionInfo, [StickerPackItem], StickerPackScreenPerformedAction) -> Void)? = nil, dismissed: (() -> Void)? = nil) -> ViewController { +public func StickerPackScreen(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, mode: StickerPackPreviewControllerMode = .default, mainStickerPack: StickerPackReference, stickerPacks: [StickerPackReference], parentNavigationController: NavigationController? = nil, sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)? = nil, actionPerformed: (([(StickerPackCollectionInfo, [StickerPackItem], StickerPackScreenPerformedAction)]) -> Void)? = nil, dismissed: (() -> Void)? = nil) -> ViewController { //let stickerPacks = [mainStickerPack] let controller = StickerPackScreenImpl(context: context, stickerPacks: stickerPacks, selectedStickerPackIndex: stickerPacks.firstIndex(of: mainStickerPack) ?? 0, parentNavigationController: parentNavigationController, sendSticker: sendSticker, actionPerformed: actionPerformed) controller.dismissed = dismissed diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index a2a53e4bb1..a272a3edce 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -1128,7 +1128,36 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G return } strongSelf.chatDisplayNode.dismissTextInput() - let controller = StickerPackScreen(context: context, updatedPresentationData: strongSelf.updatedPresentationData, mainStickerPack: packReference, stickerPacks: Array(packReferences), parentNavigationController: strongSelf.effectiveNavigationController) + + let presentationData = strongSelf.presentationData + let controller = StickerPackScreen(context: context, updatedPresentationData: strongSelf.updatedPresentationData, mainStickerPack: packReference, stickerPacks: Array(packReferences), parentNavigationController: strongSelf.effectiveNavigationController, actionPerformed: { [weak self] actions in + guard let strongSelf = self else { + return + } + if actions.count > 1, let first = actions.first { + if case .add = first.2 { + strongSelf.presentInGlobalOverlay(UndoOverlayController(presentationData: presentationData, content: .actionSucceeded(title: presentationData.strings.EmojiPackActionInfo_AddedTitle, text: presentationData.strings.EmojiPackActionInfo_MultipleAddedText(Int32(actions.count)), cancel: ""), elevatedLayout: true, animateInAsReplacement: false, action: { _ in + return true + })) + } + } else if let (info, items, action) = actions.first { + let isEmoji = info.id.namespace == Namespaces.ItemCollection.CloudEmojiPacks + + switch action { + case .add: + strongSelf.presentInGlobalOverlay(UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: isEmoji ? presentationData.strings.EmojiPackActionInfo_AddedTitle : presentationData.strings.StickerPackActionInfo_AddedTitle, text: isEmoji ? presentationData.strings.EmojiPackActionInfo_AddedText(info.title).string : presentationData.strings.StickerPackActionInfo_AddedText(info.title).string, undo: false, info: info, topItem: items.first, context: context), elevatedLayout: true, animateInAsReplacement: false, action: { _ in + return true + })) + case let .remove(positionInList): + strongSelf.presentInGlobalOverlay(UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: isEmoji ? presentationData.strings.EmojiPackActionInfo_RemovedTitle : presentationData.strings.StickerPackActionInfo_RemovedTitle, text: isEmoji ? presentationData.strings.EmojiPackActionInfo_RemovedText(info.title).string : presentationData.strings.StickerPackActionInfo_RemovedText(info.title).string, undo: true, info: info, topItem: items.first, context: context), elevatedLayout: true, animateInAsReplacement: false, action: { action in + if case .undo = action { + let _ = context.engine.stickers.addStickerPackInteractively(info: info, items: items, positionInList: positionInList).start() + } + return true + })) + } + } + }) strongSelf.present(controller, in: .window(.root)) } @@ -9412,7 +9441,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } else { canSendMedia = true } - if canSendMedia { + if canSendMedia && self.presentationInterfaceState.voiceMessagesAvailable { let _ = (ApplicationSpecificNotice.getChatMediaMediaRecordingTips(accountManager: self.context.sharedContext.accountManager) |> deliverOnMainQueue).start(next: { [weak self] counter in guard let strongSelf = self else { diff --git a/submodules/TelegramUI/Sources/OpenChatMessage.swift b/submodules/TelegramUI/Sources/OpenChatMessage.swift index 640dce7dfd..09118aa5dc 100644 --- a/submodules/TelegramUI/Sources/OpenChatMessage.swift +++ b/submodules/TelegramUI/Sources/OpenChatMessage.swift @@ -78,31 +78,40 @@ func openChatMessageImpl(_ params: OpenChatMessageParams) -> Bool { params.navigationController?.pushViewController(controller) return true case let .stickerPack(reference): - let controller = StickerPackScreen(context: params.context, updatedPresentationData: params.updatedPresentationData, mainStickerPack: reference, stickerPacks: [reference], parentNavigationController: params.navigationController, sendSticker: params.sendSticker, actionPerformed: { info, items, action in - let isEmoji = info.id.namespace == Namespaces.ItemCollection.CloudEmojiPacks - + let controller = StickerPackScreen(context: params.context, updatedPresentationData: params.updatedPresentationData, mainStickerPack: reference, stickerPacks: [reference], parentNavigationController: params.navigationController, sendSticker: params.sendSticker, actionPerformed: { actions in let presentationData = params.context.sharedContext.currentPresentationData.with { $0 } - var animateInAsReplacement = false - if let navigationController = params.navigationController { - for controller in navigationController.overlayControllers { - if let controller = controller as? UndoOverlayController { - controller.dismissWithCommitActionAndReplacementAnimation() - animateInAsReplacement = true + + if actions.count > 1, let first = actions.first { + if case .add = first.2 { + params.navigationController?.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .actionSucceeded(title: presentationData.strings.EmojiPackActionInfo_AddedTitle, text: presentationData.strings.EmojiPackActionInfo_MultipleAddedText(Int32(actions.count)), cancel: ""), elevatedLayout: true, animateInAsReplacement: false, action: { _ in + return true + })) + } + } else if let (info, items, action) = actions.first { + let isEmoji = info.id.namespace == Namespaces.ItemCollection.CloudEmojiPacks + + var animateInAsReplacement = false + if let navigationController = params.navigationController { + for controller in navigationController.overlayControllers { + if let controller = controller as? UndoOverlayController { + controller.dismissWithCommitActionAndReplacementAnimation() + animateInAsReplacement = true + } } } - } - switch action { - case .add: - params.navigationController?.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: isEmoji ? presentationData.strings.EmojiPackActionInfo_AddedTitle : presentationData.strings.StickerPackActionInfo_AddedTitle, text: isEmoji ? presentationData.strings.EmojiPackActionInfo_AddedText(info.title).string : presentationData.strings.StickerPackActionInfo_AddedText(info.title).string, undo: false, info: info, topItem: items.first, context: params.context), elevatedLayout: true, animateInAsReplacement: animateInAsReplacement, action: { _ in - return true - })) - case let .remove(positionInList): - params.navigationController?.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: isEmoji ? presentationData.strings.EmojiPackActionInfo_RemovedTitle : presentationData.strings.StickerPackActionInfo_RemovedTitle, text: isEmoji ? presentationData.strings.EmojiPackActionInfo_RemovedText(info.title).string : presentationData.strings.StickerPackActionInfo_RemovedText(info.title).string, undo: true, info: info, topItem: items.first, context: params.context), elevatedLayout: true, animateInAsReplacement: animateInAsReplacement, action: { action in - if case .undo = action { - let _ = params.context.engine.stickers.addStickerPackInteractively(info: info, items: items, positionInList: positionInList).start() - } - return true - })) + switch action { + case .add: + params.navigationController?.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: isEmoji ? presentationData.strings.EmojiPackActionInfo_AddedTitle : presentationData.strings.StickerPackActionInfo_AddedTitle, text: isEmoji ? presentationData.strings.EmojiPackActionInfo_AddedText(info.title).string : presentationData.strings.StickerPackActionInfo_AddedText(info.title).string, undo: false, info: info, topItem: items.first, context: params.context), elevatedLayout: true, animateInAsReplacement: animateInAsReplacement, action: { _ in + return true + })) + case let .remove(positionInList): + params.navigationController?.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: isEmoji ? presentationData.strings.EmojiPackActionInfo_RemovedTitle : presentationData.strings.StickerPackActionInfo_RemovedTitle, text: isEmoji ? presentationData.strings.EmojiPackActionInfo_RemovedText(info.title).string : presentationData.strings.StickerPackActionInfo_RemovedText(info.title).string, undo: true, info: info, topItem: items.first, context: params.context), elevatedLayout: true, animateInAsReplacement: animateInAsReplacement, action: { action in + if case .undo = action { + let _ = params.context.engine.stickers.addStickerPackInteractively(info: info, items: items, positionInList: positionInList).start() + } + return true + })) + } } }) params.dismissInput() diff --git a/submodules/TelegramUI/Sources/OpenResolvedUrl.swift b/submodules/TelegramUI/Sources/OpenResolvedUrl.swift index d981e2ffcb..a945582f78 100644 --- a/submodules/TelegramUI/Sources/OpenResolvedUrl.swift +++ b/submodules/TelegramUI/Sources/OpenResolvedUrl.swift @@ -166,21 +166,29 @@ func openResolvedUrlImpl(_ resolvedUrl: ResolvedUrl, context: AccountContext, ur case let .stickerPack(name, _): dismissInput() - let controller = StickerPackScreen(context: context, updatedPresentationData: updatedPresentationData, mainStickerPack: .name(name), stickerPacks: [.name(name)], parentNavigationController: navigationController, sendSticker: sendSticker, actionPerformed: { info, items, action in - let isEmoji = info.id.namespace == Namespaces.ItemCollection.CloudEmojiPacks - - switch action { - case .add: - present(UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: isEmoji ? presentationData.strings.EmojiPackActionInfo_AddedTitle : presentationData.strings.StickerPackActionInfo_AddedTitle, text: isEmoji ? presentationData.strings.EmojiPackActionInfo_AddedText(info.title).string : presentationData.strings.StickerPackActionInfo_AddedText(info.title).string, undo: false, info: info, topItem: items.first, context: context), elevatedLayout: true, animateInAsReplacement: false, action: { _ in - return true - }), nil) - case let .remove(positionInList): - present(UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: isEmoji ? presentationData.strings.EmojiPackActionInfo_RemovedTitle : presentationData.strings.StickerPackActionInfo_RemovedTitle, text: isEmoji ? presentationData.strings.EmojiPackActionInfo_RemovedText(info.title).string : presentationData.strings.StickerPackActionInfo_RemovedText(info.title).string, undo: true, info: info, topItem: items.first, context: context), elevatedLayout: true, animateInAsReplacement: false, action: { action in - if case .undo = action { - let _ = context.engine.stickers.addStickerPackInteractively(info: info, items: items, positionInList: positionInList).start() - } - return true - }), nil) + let controller = StickerPackScreen(context: context, updatedPresentationData: updatedPresentationData, mainStickerPack: .name(name), stickerPacks: [.name(name)], parentNavigationController: navigationController, sendSticker: sendSticker, actionPerformed: { actions in + if actions.count > 1, let first = actions.first { + if case .add = first.2 { + present(UndoOverlayController(presentationData: presentationData, content: .actionSucceeded(title: presentationData.strings.EmojiPackActionInfo_AddedTitle, text: presentationData.strings.EmojiPackActionInfo_MultipleAddedText(Int32(actions.count)), cancel: ""), elevatedLayout: true, animateInAsReplacement: false, action: { _ in + return true + }), nil) + } + } else if let (info, items, action) = actions.first { + let isEmoji = info.id.namespace == Namespaces.ItemCollection.CloudEmojiPacks + + switch action { + case .add: + present(UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: isEmoji ? presentationData.strings.EmojiPackActionInfo_AddedTitle : presentationData.strings.StickerPackActionInfo_AddedTitle, text: isEmoji ? presentationData.strings.EmojiPackActionInfo_AddedText(info.title).string : presentationData.strings.StickerPackActionInfo_AddedText(info.title).string, undo: false, info: info, topItem: items.first, context: context), elevatedLayout: true, animateInAsReplacement: false, action: { _ in + return true + }), nil) + case let .remove(positionInList): + present(UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: isEmoji ? presentationData.strings.EmojiPackActionInfo_RemovedTitle : presentationData.strings.StickerPackActionInfo_RemovedTitle, text: isEmoji ? presentationData.strings.EmojiPackActionInfo_RemovedText(info.title).string : presentationData.strings.StickerPackActionInfo_RemovedText(info.title).string, undo: true, info: info, topItem: items.first, context: context), elevatedLayout: true, animateInAsReplacement: false, action: { action in + if case .undo = action { + let _ = context.engine.stickers.addStickerPackInteractively(info: info, items: items, positionInList: positionInList).start() + } + return true + }), nil) + } } }) present(controller, nil)