diff --git a/submodules/AccountContext/Sources/AccountContext.swift b/submodules/AccountContext/Sources/AccountContext.swift index 0e686c05f2..aface6baf1 100644 --- a/submodules/AccountContext/Sources/AccountContext.swift +++ b/submodules/AccountContext/Sources/AccountContext.swift @@ -753,7 +753,7 @@ public protocol SharedAccountContext: AnyObject { func makePremiumIntroController(context: AccountContext, source: PremiumIntroSource) -> ViewController - func makeStickerPackScreen(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)?, mainStickerPack: StickerPackReference, stickerPacks: [StickerPackReference], parentNavigationController: NavigationController?, sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)?) -> ViewController + func makeStickerPackScreen(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)?, mainStickerPack: StickerPackReference, stickerPacks: [StickerPackReference], loadedStickerPacks: [LoadedStickerPack], parentNavigationController: NavigationController?, sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)?) -> ViewController func makeProxySettingsController(sharedContext: SharedAccountContext, account: UnauthorizedAccount) -> ViewController @@ -786,7 +786,7 @@ public enum PremiumIntroSource { case about case deeplink(String?) case profile(PeerId) - case emojiStatus(PeerId, Int64, TelegramMediaFile?, String?) + case emojiStatus(PeerId, Int64, TelegramMediaFile?, LoadedStickerPack?) } #if ENABLE_WALLET diff --git a/submodules/ChatListUI/Sources/Node/ChatListItem.swift b/submodules/ChatListUI/Sources/Node/ChatListItem.swift index 392568bddb..131f630e5c 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListItem.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListItem.swift @@ -2339,7 +2339,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { continue } if let previewNode = self.mediaPreviewNodes[mediaId] { - transition.updateFrame(node: previewNode, frame: CGRect(origin: CGPoint(x: mediaPreviewOffsetX, y: previewNode.frame.minY), size: mediaSize)) + transition.updateFrameAdditive(node: previewNode, frame: CGRect(origin: CGPoint(x: mediaPreviewOffsetX, y: previewNode.frame.minY), size: mediaSize)) } mediaPreviewOffsetX += mediaSize.width + contentImageSpacing } @@ -2358,7 +2358,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { } let mutedIconFrame = self.mutedIconNode.frame - transition.updateFrame(node: self.mutedIconNode, frame: CGRect(origin: CGPoint(x: nextTitleIconOrigin - 5.0, y: mutedIconFrame.minY), size: mutedIconFrame.size)) + transition.updateFrameAdditive(node: self.mutedIconNode, frame: CGRect(origin: CGPoint(x: nextTitleIconOrigin - 5.0, y: mutedIconFrame.minY), size: mutedIconFrame.size)) nextTitleIconOrigin += mutedIconFrame.size.width + 3.0 let badgeFrame = self.badgeNode.frame diff --git a/submodules/Display/Source/ChildWindowHostView.swift b/submodules/Display/Source/ChildWindowHostView.swift index 36dadaac16..f4b7a998b9 100644 --- a/submodules/Display/Source/ChildWindowHostView.swift +++ b/submodules/Display/Source/ChildWindowHostView.swift @@ -1,7 +1,7 @@ import Foundation import UIKit -private final class ChildWindowHostView: UIView, WindowHost { +final class ChildWindowHostView: UIView, WindowHost { var updateSize: ((CGSize) -> Void)? var layoutSubviewsEvent: (() -> Void)? var hitTestImpl: ((CGPoint, UIEvent?) -> UIView?)? @@ -56,6 +56,7 @@ private final class ChildWindowHostView: UIView, WindowHost { } func presentInGlobalOverlay(_ controller: ContainableController) { + self.presentController?(controller, .root, true, {}) } func addGlobalPortalHostView(sourceView: PortalSourceView) { diff --git a/submodules/Display/Source/WindowContent.swift b/submodules/Display/Source/WindowContent.swift index 81f85d0ca3..64ecf7536e 100644 --- a/submodules/Display/Source/WindowContent.swift +++ b/submodules/Display/Source/WindowContent.swift @@ -561,6 +561,10 @@ public class Window1 { } } + if strongSelf.hostView.containerView is ChildWindowHostView, !isTablet { + keyboardHeight += 27.0 + } + print("keyboardHeight: \(keyboardHeight) (raw: \(keyboardFrame))") var duration: Double = (notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0.0 diff --git a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGPhotoCaptionInputMixin.h b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGPhotoCaptionInputMixin.h index 46eda2a6b7..3a155692c6 100644 --- a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGPhotoCaptionInputMixin.h +++ b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGPhotoCaptionInputMixin.h @@ -34,6 +34,6 @@ - (void)setCaptionPanelHidden:(bool)hidden animated:(bool)animated; -- (void)updateLayoutWithFrame:(CGRect)frame edgeInsets:(UIEdgeInsets)edgeInsets; +- (void)updateLayoutWithFrame:(CGRect)frame edgeInsets:(UIEdgeInsets)edgeInsets animated:(bool)animated; @end diff --git a/submodules/LegacyComponents/Sources/TGCameraController.m b/submodules/LegacyComponents/Sources/TGCameraController.m index a5b5238c77..bda7a17602 100644 --- a/submodules/LegacyComponents/Sources/TGCameraController.m +++ b/submodules/LegacyComponents/Sources/TGCameraController.m @@ -2722,10 +2722,14 @@ static CGPoint TGCameraControllerClampPointToScreenSize(__unused id self, __unus default: { + if (widescreenWidth == 932.0f) + return CGRectMake(0, 121, screenSize.width, screenSize.height - 121 - 234); if (widescreenWidth == 926.0f) return CGRectMake(0, 121, screenSize.width, screenSize.height - 121 - 234); - if (widescreenWidth == 896.0f) + else if (widescreenWidth == 896.0f) return CGRectMake(0, 121, screenSize.width, screenSize.height - 121 - 223); + if (widescreenWidth == 852.0f) + return CGRectMake(0, 121, screenSize.width, screenSize.height - 121 - 234); else if (widescreenWidth == 844.0f) return CGRectMake(0, 77, screenSize.width, screenSize.height - 77 - 191); else if (widescreenWidth == 812.0f) diff --git a/submodules/LegacyComponents/Sources/TGCameraMainPhoneView.m b/submodules/LegacyComponents/Sources/TGCameraMainPhoneView.m index c71d45d351..bb1ed48c54 100644 --- a/submodules/LegacyComponents/Sources/TGCameraMainPhoneView.m +++ b/submodules/LegacyComponents/Sources/TGCameraMainPhoneView.m @@ -113,6 +113,17 @@ CGFloat shutterButtonWidth = 66.0f; CGSize screenSize = TGScreenSize(); CGFloat widescreenWidth = MAX(screenSize.width, screenSize.height); + if (widescreenWidth == 932.0f) + { + _topPanelOffset = 34.0f; + _topPanelHeight = 48.0f; + _bottomPanelOffset = 94.0f; + _bottomPanelHeight = 140.0f; + _modeControlOffset = -2.0f; + _modeControlHeight = 66.0f; + _counterOffset = 7.0f; + shutterButtonWidth = 72.0f; + } if (widescreenWidth == 926.0f) { _topPanelOffset = 34.0f; @@ -135,6 +146,17 @@ _counterOffset = 7.0f; shutterButtonWidth = 72.0f; } + else if (widescreenWidth == 852.0f) + { + _topPanelOffset = 33.0f; + _topPanelHeight = 44.0f; + _bottomPanelOffset = 63.0f; + _bottomPanelHeight = 128.0f; + _modeControlOffset = 3.0f; + _modeControlHeight = 40.0f; + _counterOffset = 7.0f; + shutterButtonWidth = 70.0f; + } else if (widescreenWidth == 844.0f) { _topPanelOffset = 33.0f; diff --git a/submodules/LegacyComponents/Sources/TGMediaPickerGalleryInterfaceView.m b/submodules/LegacyComponents/Sources/TGMediaPickerGalleryInterfaceView.m index 12ad1135ac..17f0b3a49b 100644 --- a/submodules/LegacyComponents/Sources/TGMediaPickerGalleryInterfaceView.m +++ b/submodules/LegacyComponents/Sources/TGMediaPickerGalleryInterfaceView.m @@ -1644,7 +1644,7 @@ UIEdgeInsets captionEdgeInsets = screenEdges; captionEdgeInsets.bottom = _portraitToolbarView.frame.size.height; - [_captionMixin updateLayoutWithFrame:self.bounds edgeInsets:captionEdgeInsets]; + [_captionMixin updateLayoutWithFrame:self.bounds edgeInsets:captionEdgeInsets animated:false]; switch (orientation) { diff --git a/submodules/LegacyComponents/Sources/TGMediaPickerLayoutMetrics.m b/submodules/LegacyComponents/Sources/TGMediaPickerLayoutMetrics.m index 14eef45878..9a7b02a269 100644 --- a/submodules/LegacyComponents/Sources/TGMediaPickerLayoutMetrics.m +++ b/submodules/LegacyComponents/Sources/TGMediaPickerLayoutMetrics.m @@ -51,7 +51,16 @@ CGSize itemSize = TGPhotoThumbnailSizeForCurrentScreen(); if ([UIScreen mainScreen].scale >= 2.0f - FLT_EPSILON) { - if (widescreenWidth >= 844.0f - FLT_EPSILON) + if (widescreenWidth >= 852.0f - FLT_EPSILON) + { + metrics->_normalItemSize = itemSize; + metrics->_wideItemSize = itemSize; + metrics->_normalEdgeInsets = UIEdgeInsetsMake(2.0f, 0.0f, 2.0f, 0.0f); + metrics->_wideEdgeInsets = UIEdgeInsetsMake(2.0f, 2.0f, 1.0f, 2.0f); + metrics->_normalLineSpacing = 2.0f; + metrics->_wideLineSpacing = 2.0f; + } + else if (widescreenWidth >= 844.0f - FLT_EPSILON) { metrics->_normalItemSize = itemSize; metrics->_wideItemSize = itemSize; diff --git a/submodules/LegacyComponents/Sources/TGPhotoCaptionInputMixin.m b/submodules/LegacyComponents/Sources/TGPhotoCaptionInputMixin.m index 4014752b9c..d87e86069e 100644 --- a/submodules/LegacyComponents/Sources/TGPhotoCaptionInputMixin.m +++ b/submodules/LegacyComponents/Sources/TGPhotoCaptionInputMixin.m @@ -84,7 +84,7 @@ _inputPanel.heightUpdated = ^(BOOL animated) { __strong TGPhotoCaptionInputMixin *strongSelf = weakSelf; - [strongSelf updateLayoutWithFrame:strongSelf->_currentFrame edgeInsets:strongSelf->_currentEdgeInsets]; + [strongSelf updateLayoutWithFrame:strongSelf->_currentFrame edgeInsets:strongSelf->_currentEdgeInsets animated:animated]; }; _inputPanelView = inputPanel.view; @@ -219,7 +219,7 @@ self.keyboardHeightChanged(keyboardHeight, duration, curve); } -- (void)updateLayoutWithFrame:(CGRect)frame edgeInsets:(UIEdgeInsets)edgeInsets +- (void)updateLayoutWithFrame:(CGRect)frame edgeInsets:(UIEdgeInsets)edgeInsets animated:(bool)animated { _currentFrame = frame; _currentEdgeInsets = edgeInsets; @@ -233,13 +233,20 @@ y = edgeInsets.top + frame.size.height - panelHeight - MAX(edgeInsets.bottom, _keyboardHeight); } - _inputPanelView.frame = CGRectMake(edgeInsets.left, y, frame.size.width, panelHeight); - CGFloat backgroundHeight = panelHeight; if (_keyboardHeight > 0.0) { backgroundHeight += _keyboardHeight - edgeInsets.bottom; } - _backgroundView.frame = CGRectMake(edgeInsets.left, y, frame.size.width, backgroundHeight + 1.0); + + if (animated) { + [UIView animateWithDuration:0.2 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{ + _inputPanelView.frame = CGRectMake(edgeInsets.left, y, frame.size.width, panelHeight); + _backgroundView.frame = CGRectMake(edgeInsets.left, y, frame.size.width, backgroundHeight + 1.0); + } completion:nil]; + } else { + _inputPanelView.frame = CGRectMake(edgeInsets.left, y, frame.size.width, panelHeight); + _backgroundView.frame = CGRectMake(edgeInsets.left, y, frame.size.width, backgroundHeight + 1.0); + } } @end diff --git a/submodules/LegacyComponents/Sources/TGPhotoEditorUtils.m b/submodules/LegacyComponents/Sources/TGPhotoEditorUtils.m index 86298a2ac5..c2dfab89a4 100644 --- a/submodules/LegacyComponents/Sources/TGPhotoEditorUtils.m +++ b/submodules/LegacyComponents/Sources/TGPhotoEditorUtils.m @@ -24,14 +24,22 @@ CGSize TGPhotoThumbnailSizeForCurrentScreen() if ([UIScreen mainScreen].scale >= 2.0f - FLT_EPSILON) { - if (widescreenWidth >= 926.0f - FLT_EPSILON) + if (widescreenWidth >= 932.0f - FLT_EPSILON) { return CGSizeMake(141.0f + TGScreenPixel, 141.0 + TGScreenPixel); } - if (widescreenWidth >= 896.0f - FLT_EPSILON) + else if (widescreenWidth >= 926.0f - FLT_EPSILON) + { + return CGSizeMake(141.0f + TGScreenPixel, 141.0 + TGScreenPixel); + } + else if (widescreenWidth >= 896.0f - FLT_EPSILON) { return CGSizeMake(137.0f - TGScreenPixel, 137.0f - TGScreenPixel); } + else if (widescreenWidth >= 852.0f - FLT_EPSILON) + { + return CGSizeMake(129.0f - TGScreenPixel, 129.0f - TGScreenPixel); + } else if (widescreenWidth >= 844.0f - FLT_EPSILON) { return CGSizeMake(129.0f - TGScreenPixel, 129.0f - TGScreenPixel); diff --git a/submodules/LegacyComponents/Sources/TGViewController.mm b/submodules/LegacyComponents/Sources/TGViewController.mm index 13b9029bf0..a8cf5f5ca7 100644 --- a/submodules/LegacyComponents/Sources/TGViewController.mm +++ b/submodules/LegacyComponents/Sources/TGViewController.mm @@ -1117,7 +1117,7 @@ static id _defaultContext = nil; + (UIEdgeInsets)safeAreaInsetForOrientation:(UIInterfaceOrientation)orientation hasOnScreenNavigation:(bool)hasOnScreenNavigation { int height = (int)TGScreenSize().height; - if (!TGIsPad() && (height != 812 && height != 896 && height != 780 && height != 844 && height != 926) && !hasOnScreenNavigation) + if (!TGIsPad() && (height != 812 && height != 896 && height != 780 && height != 844 && height != 852 && height != 926 && height != 932) && !hasOnScreenNavigation) return UIEdgeInsetsZero; if (TGIsPad()) { diff --git a/submodules/PremiumUI/Sources/PremiumIntroScreen.swift b/submodules/PremiumUI/Sources/PremiumIntroScreen.swift index 2b59f47be8..0cf6a2b3a6 100644 --- a/submodules/PremiumUI/Sources/PremiumIntroScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumIntroScreen.swift @@ -25,6 +25,137 @@ import AnimationCache import MultiAnimationRenderer public enum PremiumSource: Equatable { + public static func == (lhs: PremiumSource, rhs: PremiumSource) -> Bool { + switch lhs { + case .settings: + if case .settings = rhs { + return true + } else { + return false + } + case .stickers: + if case .stickers = rhs { + return true + } else { + return false + } + case .reactions: + if case .reactions = rhs { + return true + } else { + return false + } + case .ads: + if case .ads = rhs { + return true + } else { + return false + } + case .upload: + if case .upload = rhs { + return true + } else { + return false + } + case .groupsAndChannels: + if case .groupsAndChannels = rhs { + return true + } else { + return false + } + case .pinnedChats: + if case .pinnedChats = rhs { + return true + } else { + return false + } + case .publicLinks: + if case .publicLinks = rhs { + return true + } else { + return false + } + case .savedGifs: + if case .savedGifs = rhs { + return true + } else { + return false + } + case .savedStickers: + if case .savedStickers = rhs { + return true + } else { + return false + } + case .folders: + if case .folders = rhs { + return true + } else { + return false + } + case .chatsPerFolder: + if case .chatsPerFolder = rhs { + return true + } else { + return false + } + case .accounts: + if case .accounts = rhs { + return true + } else { + return false + } + case .about: + if case .about = rhs { + return true + } else { + return false + } + case .appIcons: + if case .appIcons = rhs { + return true + } else { + return false + } + case .animatedEmoji: + if case .animatedEmoji = rhs { + return true + } else { + return false + } + case let .deeplink(link): + if case .deeplink(link) = rhs { + return true + } else { + return false + } + case let .profile(peerId): + if case .profile(peerId) = rhs { + return true + } else { + return false + } + case let .emojiStatus(lhsPeerId, lhsFileId, lhsFile, _): + if case let .emojiStatus(rhsPeerId, rhsFileId, rhsFile, _) = rhs { + return lhsPeerId == rhsPeerId && lhsFileId == rhsFileId && lhsFile == rhsFile + } else { + return false + } + case let .gift(from, to, duration): + if case .gift(from, to, duration) = rhs { + return true + } else { + return false + } + case .giftTerms: + if case .giftTerms = rhs { + return true + } else { + return false + } + } + } + case settings case stickers case reactions @@ -43,7 +174,7 @@ public enum PremiumSource: Equatable { case animatedEmoji case deeplink(String?) case profile(PeerId) - case emojiStatus(PeerId, Int64, TelegramMediaFile?, String?) + case emojiStatus(PeerId, Int64, TelegramMediaFile?, LoadedStickerPack?) case gift(from: PeerId, to: PeerId, duration: Int32) case giftTerms @@ -1873,10 +2004,10 @@ private final class PremiumIntroScreenComponent: CombinedComponent { } }) - if case let .emojiStatus(_, emojiFileId, emojiFile, emojiPackTitle) = source { + if case let .emojiStatus(_, emojiFileId, emojiFile, maybeEmojiPack) = source, let emojiPack = maybeEmojiPack, case let .result(info, _, _) = emojiPack { if let emojiFile = emojiFile { self.emojiFile = emojiFile - self.emojiPackTitle = emojiPackTitle + self.emojiPackTitle = info.title self.updated(transition: .immediate) } else { self.emojiFileDisposable = (context.engine.stickers.resolveInlineStickers(fileIds: [emojiFileId]) @@ -2127,7 +2258,7 @@ private final class PremiumIntroScreenComponent: CombinedComponent { var highlightableLinks = false let secondaryTitleText: String if let otherPeerName = state.otherPeerName { - if case let .emojiStatus(_, _, file, emojiPackTitle) = context.component.source { + if case let .emojiStatus(_, _, file, maybeEmojiPack) = context.component.source, let emojiPack = maybeEmojiPack, case let .result(info, _, _) = emojiPack { highlightableLinks = true var packReference: StickerPackReference? @@ -2141,7 +2272,7 @@ private final class PremiumIntroScreenComponent: CombinedComponent { if let packReference = packReference, case let .id(id, _) = packReference, id == 773947703670341676 { secondaryTitleText = environment.strings.Premium_EmojiStatusShortTitle(otherPeerName).string } else { - secondaryTitleText = environment.strings.Premium_EmojiStatusTitle(otherPeerName, emojiPackTitle ?? "").string.replacingOccurrences(of: "#", with: " # ") + secondaryTitleText = environment.strings.Premium_EmojiStatusTitle(otherPeerName, info.title).string.replacingOccurrences(of: "#", with: " # ") } } else if case .profile = context.component.source { secondaryTitleText = environment.strings.Premium_PersonalTitle(otherPeerName).string @@ -2206,7 +2337,7 @@ private final class PremiumIntroScreenComponent: CombinedComponent { if let emojiFile = state?.emojiFile, let controller = environment?.controller() as? PremiumIntroScreen, let navigationController = controller.navigationController as? NavigationController { for attribute in emojiFile.attributes { if case let .CustomEmoji(_, _, packReference) = attribute, let packReference = packReference { - let controller = accountContext.sharedContext.makeStickerPackScreen(context: accountContext, updatedPresentationData: nil, mainStickerPack: packReference, stickerPacks: [packReference], parentNavigationController: navigationController, sendSticker: { _, _, _ in + let controller = accountContext.sharedContext.makeStickerPackScreen(context: accountContext, updatedPresentationData: nil, mainStickerPack: packReference, stickerPacks: [packReference], loadedStickerPacks: [], parentNavigationController: navigationController, sendSticker: { _, _, _ in return false }) presentController(controller) diff --git a/submodules/ShareController/Sources/ShareInputFieldNode.swift b/submodules/ShareController/Sources/ShareInputFieldNode.swift index 47de1c6bc3..5ad9bf6393 100644 --- a/submodules/ShareController/Sources/ShareInputFieldNode.swift +++ b/submodules/ShareController/Sources/ShareInputFieldNode.swift @@ -66,7 +66,7 @@ public final class ShareInputFieldNode: ASDisplayNode, ASEditableTextNodeDelegat public var updateText: ((String) -> Void)? private let backgroundInsets = UIEdgeInsets(top: 16.0, left: 16.0, bottom: 1.0, right: 16.0) - private let inputInsets = UIEdgeInsets(top: 10.0, left: 8.0, bottom: 10.0, right: 16.0) + private let inputInsets = UIEdgeInsets(top: 10.0, left: 8.0, bottom: 10.0, right: 22.0) private let accessoryButtonsWidth: CGFloat = 10.0 private var selectTextOnce: Bool = false diff --git a/submodules/ShareController/Sources/ShareSearchBarNode.swift b/submodules/ShareController/Sources/ShareSearchBarNode.swift index f86602ab93..7c5825a231 100644 --- a/submodules/ShareController/Sources/ShareSearchBarNode.swift +++ b/submodules/ShareController/Sources/ShareSearchBarNode.swift @@ -99,6 +99,11 @@ final class ShareSearchBarNode: ASDisplayNode, UITextFieldDelegate { self.textUpdated?(self.textInputNode.textField.text ?? "") } + func textFieldShouldReturn(_ textField: UITextField) -> Bool { + self.deactivateInput() + return true + } + @objc func clearPressed() { self.textInputNode.textField.text = "" self.textFieldDidChangeText() diff --git a/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift b/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift index f7536d1786..bab1ec6d9e 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift @@ -151,6 +151,7 @@ private final class StickerPackContainer: ASDisplayNode { context: AccountContext, presentationData: PresentationData, stickerPacks: [StickerPackReference], + loadedStickerPacks: [LoadedStickerPack], decideNextAction: @escaping (StickerPackContainer, StickerPackAction) -> StickerPackNextAction, requestDismiss: @escaping () -> Void, expandProgressUpdated: @escaping (StickerPackContainer, ContainedViewLayoutTransition, ContainedViewLayoutTransition) -> Void, @@ -343,11 +344,18 @@ private final class StickerPackContainer: ASDisplayNode { return updatedOffset } - let loadedStickerPacks = combineLatest(stickerPacks.map { - context.engine.stickers.loadedStickerPack(reference: $0, forceActualized: true) + + + let fetchedStickerPacks: Signal<[LoadedStickerPack], NoError> = combineLatest(stickerPacks.map { packReference in + for pack in loadedStickerPacks { + if case let .result(info, _, _) = pack, case let .id(id, _) = packReference, info.id.id == id { + return .single(pack) + } + } + return context.engine.stickers.loadedStickerPack(reference: packReference, forceActualized: true) }) - self.itemsDisposable = combineLatest(queue: Queue.mainQueue(), loadedStickerPacks, context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId))).start(next: { [weak self] contents, peer in + self.itemsDisposable = combineLatest(queue: Queue.mainQueue(), fetchedStickerPacks, context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId))).start(next: { [weak self] contents, peer in guard let strongSelf = self else { return } @@ -1332,7 +1340,7 @@ private final class StickerPackScreenNode: ViewControllerTracingNode { 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 + container = StickerPackContainer(index: index, context: self.context, presentationData: self.presentationData, stickerPacks: self.stickerPacks, loadedStickerPacks: self.controller?.loadedStickerPacks ?? [], decideNextAction: { [weak self] container, action in guard let strongSelf = self, let layout = strongSelf.validLayout else { return .dismiss } @@ -1570,6 +1578,8 @@ public final class StickerPackScreenImpl: ViewController { private var presentationDataDisposable: Disposable? private let stickerPacks: [StickerPackReference] + fileprivate let loadedStickerPacks: [LoadedStickerPack] + private let initialSelectedStickerPackIndex: Int fileprivate weak var parentNavigationController: NavigationController? private let sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)? @@ -1599,6 +1609,7 @@ public final class StickerPackScreenImpl: ViewController { context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, stickerPacks: [StickerPackReference], + loadedStickerPacks: [LoadedStickerPack], selectedStickerPackIndex: Int = 0, parentNavigationController: NavigationController? = nil, sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)? = nil, @@ -1608,6 +1619,7 @@ public final class StickerPackScreenImpl: ViewController { self.context = context self.presentationData = updatedPresentationData?.initial ?? context.sharedContext.currentPresentationData.with { $0 } self.stickerPacks = stickerPacks + self.loadedStickerPacks = loadedStickerPacks self.initialSelectedStickerPackIndex = selectedStickerPackIndex self.parentNavigationController = parentNavigationController self.sendSticker = sendSticker @@ -1820,6 +1832,7 @@ public func StickerPackScreen( mode: StickerPackPreviewControllerMode = .default, mainStickerPack: StickerPackReference, stickerPacks: [StickerPackReference], + loadedStickerPacks: [LoadedStickerPack] = [], parentNavigationController: NavigationController? = nil, sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)? = nil, sendEmoji: ((String, ChatTextInputTextCustomEmojiAttribute) -> Void)? = nil, @@ -1829,6 +1842,7 @@ public func StickerPackScreen( let controller = StickerPackScreenImpl( context: context, stickerPacks: stickerPacks, + loadedStickerPacks: loadedStickerPacks, selectedStickerPackIndex: stickerPacks.firstIndex(of: mainStickerPack) ?? 0, parentNavigationController: parentNavigationController, sendSticker: sendSticker, diff --git a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift index 0a032babec..2cfe3425b4 100644 --- a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift @@ -2305,7 +2305,7 @@ private final class EmojiContentPeekBehaviorImpl: EmojiContentPeekBehavior { switch attribute { case let .CustomEmoji(_, _, packReference), let .Sticker(_, packReference, _): if let packReference = packReference { - let controller = strongSelf.context.sharedContext.makeStickerPackScreen(context: context, updatedPresentationData: nil, mainStickerPack: packReference, stickerPacks: [packReference], parentNavigationController: strongSelf.controllerInteraction.navigationController(), sendSticker: { file, sourceView, sourceRect in + let controller = strongSelf.context.sharedContext.makeStickerPackScreen(context: context, updatedPresentationData: nil, mainStickerPack: packReference, stickerPacks: [packReference], loadedStickerPacks: [], parentNavigationController: strongSelf.controllerInteraction.navigationController(), sendSticker: { file, sourceView, sourceRect in sendSticker(file, false, false, nil, false, sourceView, sourceRect, nil) return true }) diff --git a/submodules/TelegramUI/Sources/ChatInterfaceStateContextMenus.swift b/submodules/TelegramUI/Sources/ChatInterfaceStateContextMenus.swift index eb6ed053bc..c715bc4e72 100644 --- a/submodules/TelegramUI/Sources/ChatInterfaceStateContextMenus.swift +++ b/submodules/TelegramUI/Sources/ChatInterfaceStateContextMenus.swift @@ -1462,6 +1462,19 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState clearCacheAsDelete = true } + + if isReplyThreadHead { + actions.append(.action(ContextMenuActionItem(text: chatPresentationInterfaceState.strings.SharedMedia_ViewInChat, icon: { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/GoToMessage"), color: theme.actionSheet.primaryTextColor) + }, action: { c, _ in + c.dismiss(completion: { + guard let navigationController = controllerInteraction.navigationController() else { + return + } + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: messages[0].id.peerId), subject: .message(id: .id(messages[0].id), highlight: true, timecode: nil), useExisting: true)) + }) + }))) + } if !isReplyThreadHead, (!data.messageActions.options.intersection([.deleteLocally, .deleteGlobally]).isEmpty || clearCacheAsDelete) { var autoremoveDeadline: Int32? diff --git a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift index 90f226dbb3..663e033788 100644 --- a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift @@ -243,7 +243,6 @@ private final class AccessoryItemIconButtonNode: HighlightTrackingButtonNode { } else if case .emoji = previousInputMode { animationName = "input_anim_smileToSticker" animationMode = .animating(loop: false) -// colorKeys = emojiColorKeys } else { animationName = "input_anim_keyToSticker" } @@ -258,7 +257,6 @@ private final class AccessoryItemIconButtonNode: HighlightTrackingButtonNode { } else if case .stickers = previousInputMode { animationName = "input_anim_stickerToSmile" animationMode = .animating(loop: false) -// colorKeys = emojiColorKeys } else { animationName = "input_anim_keyToSmile" } @@ -1085,7 +1083,13 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { let recognizer = TouchDownGestureRecognizer(target: self, action: #selector(self.textInputBackgroundViewTap(_:))) recognizer.touchDown = { [weak self] in if let strongSelf = self { - strongSelf.ensureFocusedOnTap() + if strongSelf.textInputNode?.isFirstResponder() == true { + Queue.mainQueue().after(0.05) { + strongSelf.ensureFocusedOnTap() + } + } else { + strongSelf.ensureFocusedOnTap() + } } } recognizer.waitForTouchUp = { [weak self] in @@ -3397,17 +3401,24 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { self.loadTextInputNode() } - self.textInputNode?.becomeFirstResponder() + if !self.switching { + self.textInputNode?.becomeFirstResponder() + } } + private var switching = false func ensureFocusedOnTap() { if self.textInputNode == nil { self.loadTextInputNode() } - self.textInputNode?.becomeFirstResponder() - - self.switchToTextInputIfNeeded?() + if !self.switching { + self.switching = true + self.textInputNode?.becomeFirstResponder() + + self.switchToTextInputIfNeeded?() + self.switching = false + } } func backwardsDeleteText() { diff --git a/submodules/TelegramUI/Sources/OpenResolvedUrl.swift b/submodules/TelegramUI/Sources/OpenResolvedUrl.swift index 6c32e35454..4424cc560f 100644 --- a/submodules/TelegramUI/Sources/OpenResolvedUrl.swift +++ b/submodules/TelegramUI/Sources/OpenResolvedUrl.swift @@ -579,13 +579,13 @@ func openResolvedUrlImpl(_ resolvedUrl: ResolvedUrl, context: AccountContext, ur if let navigationController = navigationController { let controller = context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams(context: context, updatedPresentationData: updatedPresentationData, filter: filters, hasChatListSelector: true, hasContactSelector: false, title: presentationData.strings.WebApp_SelectChat)) controller.peerSelected = { peer in - let _ = context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: peer.id), attachBotStart: ChatControllerInitialAttachBotStart(botId: bot.peer.id, payload: payload, justInstalled: false), useExisting: true)) + let _ = context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: peer.id), attachBotStart: ChatControllerInitialAttachBotStart(botId: bot.peer.id, payload: payload, justInstalled: false), keepStack: .never, useExisting: true)) } navigationController.pushViewController(controller) } } else { if let navigationController = navigationController, case let .chat(chatPeerId, _) = urlContext { - let _ = context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: chatPeerId), attachBotStart: ChatControllerInitialAttachBotStart(botId: peerId, payload: payload, justInstalled: false), useExisting: true)) + let _ = context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: chatPeerId), attachBotStart: ChatControllerInitialAttachBotStart(botId: peerId, payload: payload, justInstalled: false), keepStack: .never, useExisting: true)) } else { presentError(presentationData.strings.WebApp_AddToAttachmentAlreadyAddedError) } diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoHeaderNode.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoHeaderNode.swift index 2074fd37f0..f89306478e 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoHeaderNode.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoHeaderNode.swift @@ -2023,7 +2023,7 @@ final class PeerInfoHeaderNode: ASDisplayNode { var displayAvatarContextMenu: ((ASDisplayNode, ContextGesture?) -> Void)? var displayCopyContextMenu: ((ASDisplayNode, Bool, Bool) -> Void)? - var displayPremiumIntro: ((UIView, PeerEmojiStatus?, Signal<(TelegramMediaFile, String)?, NoError>, Bool) -> Void)? + var displayPremiumIntro: ((UIView, PeerEmojiStatus?, Signal<(TelegramMediaFile, LoadedStickerPack)?, NoError>, Bool) -> Void)? var navigationTransition: PeerInfoHeaderNavigationTransition? @@ -2034,7 +2034,7 @@ final class PeerInfoHeaderNode: ASDisplayNode { let animationRenderer: MultiAnimationRenderer var emojiStatusPackDisposable = MetaDisposable() - var emojiStatusFileAndPackTitle = Promise<(TelegramMediaFile, String)?>() + var emojiStatusFileAndPackTitle = Promise<(TelegramMediaFile, LoadedStickerPack)?>() init(context: AccountContext, avatarInitiallyExpanded: Bool, isOpenedFromChat: Bool, isMediaOnly: Bool, isSettings: Bool) { self.context = context @@ -2392,9 +2392,9 @@ final class PeerInfoHeaderNode: ASDisplayNode { return false } } - |> mapToSignal { result -> Signal<(TelegramMediaFile, String)?, NoError> in - if case let .result(info, items, _) = result { - return .single(items.first.flatMap { ($0.file, info.title) }) + |> mapToSignal { result -> Signal<(TelegramMediaFile, LoadedStickerPack)?, NoError> in + if case let .result(_, items, _) = result { + return .single(items.first.flatMap { ($0.file, result) }) } else { return .complete() } diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift index af0c8746b6..ce6d41eb5c 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift @@ -3155,7 +3155,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate } else { screenData = peerInfoScreenData(context: context, peerId: peerId, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, isSettings: self.isSettings, hintGroupInCommon: hintGroupInCommon, existingRequestsContext: requestsContext) - self.headerNode.displayPremiumIntro = { [weak self] sourceView, peerStatus, emojiStatusFileAndPackTitle, white in + self.headerNode.displayPremiumIntro = { [weak self] sourceView, peerStatus, emojiStatusFileAndPack, white in guard let strongSelf = self else { return } @@ -3172,11 +3172,11 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate } let source: Signal if let peerStatus = peerStatus { - source = emojiStatusFileAndPackTitle + source = emojiStatusFileAndPack |> take(1) - |> mapToSignal { emojiStatusFileAndPackTitle -> Signal in - if let (file, packTitle) = emojiStatusFileAndPackTitle { - return .single(.emojiStatus(strongSelf.peerId, peerStatus.fileId, file, packTitle)) + |> mapToSignal { emojiStatusFileAndPack -> Signal in + if let (file, pack) = emojiStatusFileAndPack { + return .single(.emojiStatus(strongSelf.peerId, peerStatus.fileId, file, pack)) } else { return .complete() } @@ -3185,7 +3185,8 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate source = .single(.profile(strongSelf.peerId)) } - let _ = source.start(next: { [weak self] source in + let _ = (source + |> deliverOnMainQueue).start(next: { [weak self] source in guard let strongSelf = self else { return } diff --git a/submodules/TelegramUI/Sources/SharedAccountContext.swift b/submodules/TelegramUI/Sources/SharedAccountContext.swift index 3e5c19e099..ef98633a45 100644 --- a/submodules/TelegramUI/Sources/SharedAccountContext.swift +++ b/submodules/TelegramUI/Sources/SharedAccountContext.swift @@ -1507,8 +1507,8 @@ public final class SharedAccountContextImpl: SharedAccountContext { return PremiumIntroScreen(context: context, source: mappedSource) } - public func makeStickerPackScreen(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)?, mainStickerPack: StickerPackReference, stickerPacks: [StickerPackReference], parentNavigationController: NavigationController?, sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)?) -> ViewController { - return StickerPackScreen(context: context, updatedPresentationData: updatedPresentationData, mainStickerPack: mainStickerPack, stickerPacks: stickerPacks, parentNavigationController: parentNavigationController, sendSticker: sendSticker) + public func makeStickerPackScreen(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)?, mainStickerPack: StickerPackReference, stickerPacks: [StickerPackReference], loadedStickerPacks: [LoadedStickerPack], parentNavigationController: NavigationController?, sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)?) -> ViewController { + return StickerPackScreen(context: context, updatedPresentationData: updatedPresentationData, mainStickerPack: mainStickerPack, stickerPacks: stickerPacks, loadedStickerPacks: loadedStickerPacks, parentNavigationController: parentNavigationController, sendSticker: sendSticker) } public func makeProxySettingsController(sharedContext: SharedAccountContext, account: UnauthorizedAccount) -> ViewController {