diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index b5d1141306..fd056f9e9a 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -5630,6 +5630,7 @@ Sorry for the inconvenience."; "Conversation.ContextMenuOpenProfile" = "Open Profile"; "Conversation.ContextMenuSendMessage" = "Send Message"; "Conversation.ContextMenuMention" = "Mention"; +"Conversation.ContextMenuSearchMessages" = "Search Messages"; "Conversation.ContextMenuOpenChannelProfile" = "Open Profile"; "Conversation.ContextMenuOpenChannel" = "Open Channel"; @@ -12047,6 +12048,7 @@ Sorry for the inconvenience."; "MediaEditor.CreateNewPack" = "New Sticker Set"; "MediaEditor.ReplaceSticker" = "Replace Sticker"; "MediaEditor.AddToStickerPack" = "Add to Sticker Set"; +"MediaEditor.SetAsIntroSticker" = "Set as Greeting Sticker"; "MediaEditor.NewStickerPack.Title" = "New Sticker Set"; "MediaEditor.NewStickerPack.Text" = "Choose a name for your sticker set."; @@ -12182,3 +12184,9 @@ Sorry for the inconvenience."; "Chat.NextSuggestedChannelSwipeAction" = "Release to go to the next channel"; "Chat.NextUnreadTopicSwipeProgress" = "Pull up to go to the next topic"; "Chat.NextUnreadTopicSwipeAction" = "Release to go to the next topic"; + +"EmojiPacksSettings.ArchivedPacks" = "Archived Stickers"; +"EmojiPacksSettings.ArchivedPacks.Info" = "You can have up to 200 sticker sets installed.\nUnused stickers are archived when you add more."; + +"EmojiPacks.UnarchiveEmojiPacksConfirmation_1" = "Unarchive %@ Pack"; +"EmojiPacks.UnarchiveEmojiPacksConfirmation_any" = "Unarchive %@ Packs"; diff --git a/submodules/AccountContext/Sources/AccountContext.swift b/submodules/AccountContext/Sources/AccountContext.swift index fb56d8a454..7b045f2c18 100644 --- a/submodules/AccountContext/Sources/AccountContext.swift +++ b/submodules/AccountContext/Sources/AccountContext.swift @@ -990,7 +990,7 @@ public protocol SharedAccountContext: AnyObject { func navigateToChatController(_ params: NavigateToChatControllerParams) func navigateToForumChannel(context: AccountContext, peerId: EnginePeer.Id, navigationController: NavigationController) - func navigateToForumThread(context: AccountContext, peerId: EnginePeer.Id, threadId: Int64, messageId: EngineMessage.Id?, navigationController: NavigationController, activateInput: ChatControllerActivateInput?, keepStack: NavigateToChatKeepStack) -> Signal + func navigateToForumThread(context: AccountContext, peerId: EnginePeer.Id, threadId: Int64, messageId: EngineMessage.Id?, navigationController: NavigationController, activateInput: ChatControllerActivateInput?, scrollToEndIfExists: Bool, keepStack: NavigateToChatKeepStack) -> Signal func chatControllerForForumThread(context: AccountContext, peerId: EnginePeer.Id, threadId: Int64) -> Signal func openStorageUsage(context: AccountContext) func openLocationScreen(context: AccountContext, messageId: MessageId, navigationController: NavigationController) @@ -1019,11 +1019,11 @@ public protocol SharedAccountContext: AnyObject { func makePremiumPrivacyControllerController(context: AccountContext, subject: PremiumPrivacySubject, peerId: EnginePeer.Id) -> ViewController func makePremiumBoostLevelsController(context: AccountContext, peerId: EnginePeer.Id, subject: BoostSubject, boostStatus: ChannelBoostStatus, myBoostStatus: MyBoostStatus, forceDark: Bool, openStats: (() -> Void)?) -> ViewController - func makeStickerPackScreen(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)?, mainStickerPack: StickerPackReference, stickerPacks: [StickerPackReference], loadedStickerPacks: [LoadedStickerPack], isEditing: Bool, expandIfNeeded: Bool, parentNavigationController: NavigationController?, sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)?) -> ViewController + func makeStickerPackScreen(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)?, mainStickerPack: StickerPackReference, stickerPacks: [StickerPackReference], loadedStickerPacks: [LoadedStickerPack], isEditing: Bool, expandIfNeeded: Bool, parentNavigationController: NavigationController?, sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)?, actionPerformed: ((Bool) -> Void)?) -> ViewController func makeMediaPickerScreen(context: AccountContext, hasSearch: Bool, completion: @escaping (Any) -> Void) -> ViewController - func makeStickerEditorScreen(context: AccountContext, source: Any?, transitionArguments: (UIView, CGRect, UIImage?)?, completion: @escaping (TelegramMediaFile, [String], @escaping () -> Void) -> Void, cancelled: @escaping () -> Void) -> ViewController + func makeStickerEditorScreen(context: AccountContext, source: Any?, intro: Bool, transitionArguments: (UIView, CGRect, UIImage?)?, completion: @escaping (TelegramMediaFile, [String], @escaping () -> Void) -> Void, cancelled: @escaping () -> Void) -> ViewController func makeStickerMediaPickerScreen(context: AccountContext, getSourceRect: @escaping () -> CGRect?, completion: @escaping (Any?, UIView?, CGRect, UIImage?, Bool, @escaping (Bool?) -> (UIView, CGRect)?, @escaping () -> Void) -> Void, dismissed: @escaping () -> Void) -> ViewController func makeStoryMediaPickerScreen(context: AccountContext, getSourceRect: @escaping () -> CGRect, completion: @escaping (Any, UIView, CGRect, UIImage?, @escaping (Bool?) -> (UIView, CGRect)?, @escaping () -> Void) -> Void, dismissed: @escaping () -> Void, groupsPresented: @escaping () -> Void) -> ViewController diff --git a/submodules/AttachmentUI/Sources/AttachmentContainer.swift b/submodules/AttachmentUI/Sources/AttachmentContainer.swift index ace93ca1d4..6c4d3c4f85 100644 --- a/submodules/AttachmentUI/Sources/AttachmentContainer.swift +++ b/submodules/AttachmentUI/Sources/AttachmentContainer.swift @@ -473,9 +473,7 @@ final class AttachmentContainer: ASDisplayNode, ASGestureRecognizerDelegate { if let statusBarHeight = layout.statusBarHeight { containerTopInset += statusBarHeight } - - let effectiveStatusBarHeight: CGFloat? = nil - + var safeInsets = layout.safeInsets safeInsets.left += overflowInset safeInsets.right += overflowInset @@ -487,7 +485,7 @@ final class AttachmentContainer: ASDisplayNode, ASGestureRecognizerDelegate { var additionalInsets = layout.additionalInsets additionalInsets.bottom = topInset - containerLayout = ContainerViewLayout(size: CGSize(width: layout.size.width + overflowInset * 2.0, height: layout.size.height - containerTopInset), metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, intrinsicInsets: UIEdgeInsets(top: 0.0, left: intrinsicInsets.left, bottom: intrinsicInsets.bottom, right: intrinsicInsets.right), safeInsets: UIEdgeInsets(top: 0.0, left: safeInsets.left, bottom: safeInsets.bottom, right: safeInsets.right), additionalInsets: additionalInsets, statusBarHeight: effectiveStatusBarHeight, inputHeight: layout.inputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging, inVoiceOver: layout.inVoiceOver) + containerLayout = ContainerViewLayout(size: CGSize(width: layout.size.width + overflowInset * 2.0, height: layout.size.height - containerTopInset), metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, intrinsicInsets: UIEdgeInsets(top: 0.0, left: intrinsicInsets.left, bottom: intrinsicInsets.bottom, right: intrinsicInsets.right), safeInsets: UIEdgeInsets(top: 0.0, left: safeInsets.left, bottom: safeInsets.bottom, right: safeInsets.right), additionalInsets: additionalInsets, statusBarHeight: nil, inputHeight: layout.inputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging, inVoiceOver: layout.inVoiceOver) let unscaledFrame = CGRect(origin: CGPoint(x: 0.0, y: containerTopInset - coveredByModalTransition * 10.0), size: containerLayout.size) let maxScale: CGFloat = (containerLayout.size.width - 16.0 * 2.0) / containerLayout.size.width containerScale = 1.0 * (1.0 - coveredByModalTransition) + maxScale * coveredByModalTransition diff --git a/submodules/AttachmentUI/Sources/AttachmentController.swift b/submodules/AttachmentUI/Sources/AttachmentController.swift index a343b776ab..30c441ba9a 100644 --- a/submodules/AttachmentUI/Sources/AttachmentController.swift +++ b/submodules/AttachmentUI/Sources/AttachmentController.swift @@ -691,7 +691,7 @@ public class AttachmentController: ViewController { } else { ContainedViewLayoutTransition.animated(duration: 0.3, curve: .linear).updateAlpha(node: self.dim, alpha: 1.0) - let targetPosition = CGPoint(x: layout.size.width / 2.0, y: layout.size.height / 2.0) + let targetPosition = self.container.position let startPosition = targetPosition.offsetBy(dx: 0.0, dy: layout.size.height) self.container.position = startPosition diff --git a/submodules/ChatListUI/Sources/ChatListController.swift b/submodules/ChatListUI/Sources/ChatListController.swift index fd94633a75..cbcc97d831 100644 --- a/submodules/ChatListUI/Sources/ChatListController.swift +++ b/submodules/ChatListUI/Sources/ChatListController.swift @@ -1054,7 +1054,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController } if case let .channel(channel) = peer, channel.flags.contains(.isForum), let threadId { - let _ = self.context.sharedContext.navigateToForumThread(context: self.context, peerId: peer.id, threadId: threadId, messageId: nil, navigationController: navigationController, activateInput: nil, keepStack: .never).startStandalone() + let _ = self.context.sharedContext.navigateToForumThread(context: self.context, peerId: peer.id, threadId: threadId, messageId: nil, navigationController: navigationController, activateInput: nil, scrollToEndIfExists: scrollToEndIfExists, keepStack: .never).startStandalone() self.chatListDisplayNode.clearHighlightAnimated(true) } else { var navigationAnimationOptions: NavigationAnimationOptions = [] @@ -1201,7 +1201,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController navigationAnimationOptions = .removeOnMasterDetails } if case let .channel(channel) = actualPeer, channel.flags.contains(.isForum), let threadId { - let _ = strongSelf.context.sharedContext.navigateToForumThread(context: strongSelf.context, peerId: peer.id, threadId: threadId, messageId: messageId, navigationController: navigationController, activateInput: nil, keepStack: .never).startStandalone() + let _ = strongSelf.context.sharedContext.navigateToForumThread(context: strongSelf.context, peerId: peer.id, threadId: threadId, messageId: messageId, navigationController: navigationController, activateInput: nil, scrollToEndIfExists: false, keepStack: .never).startStandalone() } else { strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(actualPeer), subject: .message(id: .id(messageId), highlight: ChatControllerSubject.MessageHighlight(quote: nil), timecode: nil), purposefulAction: { if deactivateOnAction { @@ -1234,7 +1234,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController navigationAnimationOptions = .removeOnMasterDetails } if case let .channel(channel) = peer, channel.flags.contains(.isForum), let threadId { - let _ = strongSelf.context.sharedContext.navigateToForumThread(context: strongSelf.context, peerId: peer.id, threadId: threadId, messageId: nil, navigationController: navigationController, activateInput: nil, keepStack: .never).startStandalone() + let _ = strongSelf.context.sharedContext.navigateToForumThread(context: strongSelf.context, peerId: peer.id, threadId: threadId, messageId: nil, navigationController: navigationController, activateInput: nil, scrollToEndIfExists: false, keepStack: .never).startStandalone() } else { strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer), purposefulAction: { [weak self] in self?.deactivateSearch(animated: false) @@ -1312,7 +1312,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController let _ = (context.engine.peers.createForumChannelTopic(id: peerId, title: title, iconColor: iconColor, iconFileId: fileId) |> deliverOnMainQueue).startStandalone(next: { topicId in - let _ = context.sharedContext.navigateToForumThread(context: context, peerId: peerId, threadId: topicId, messageId: nil, navigationController: navigationController, activateInput: .text, keepStack: .never).startStandalone() + let _ = context.sharedContext.navigateToForumThread(context: context, peerId: peerId, threadId: topicId, messageId: nil, navigationController: navigationController, activateInput: .text, scrollToEndIfExists: false, keepStack: .never).startStandalone() }, error: { _ in controller?.isInProgress = false }) @@ -3566,7 +3566,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController let _ = (context.engine.peers.createForumChannelTopic(id: peerId, title: title, iconColor: iconColor, iconFileId: fileId) |> deliverOnMainQueue).startStandalone(next: { topicId in if let navigationController = (sourceController.navigationController as? NavigationController) { - let _ = context.sharedContext.navigateToForumThread(context: context, peerId: peerId, threadId: topicId, messageId: nil, navigationController: navigationController, activateInput: .text, keepStack: .never).startStandalone() + let _ = context.sharedContext.navigateToForumThread(context: context, peerId: peerId, threadId: topicId, messageId: nil, navigationController: navigationController, activateInput: .text, scrollToEndIfExists: false, keepStack: .never).startStandalone() } }, error: { _ in controller?.isInProgress = false diff --git a/submodules/ChatListUI/Sources/Node/ChatListItem.swift b/submodules/ChatListUI/Sources/Node/ChatListItem.swift index 74b30b4d92..3d4d0dde25 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListItem.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListItem.swift @@ -3049,9 +3049,11 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode { isFirstForumThreadSelectable = forumThread.isUnread forumThreads.append((id: forumThread.id, title: NSAttributedString(string: forumThread.title, font: textFont, textColor: forumThread.isUnread || isSearching ? theme.authorNameColor : theme.messageTextColor), iconId: forumThread.iconId, iconColor: forumThread.iconColor)) } - for item in topForumTopicItems { - if forumThread?.id != item.id { - forumThreads.append((id: item.id, title: NSAttributedString(string: item.title, font: textFont, textColor: item.isUnread || isSearching ? theme.authorNameColor : theme.messageTextColor), iconId: item.iconFileId, iconColor: item.iconColor)) + for topicItem in topForumTopicItems { + if case let .peer(peer) = item.content, peer.peer.peerId.id._internalGetInt64Value() == topicItem.id { + + } else if forumThread?.id != topicItem.id { + forumThreads.append((id: topicItem.id, title: NSAttributedString(string: topicItem.title, font: textFont, textColor: topicItem.isUnread || isSearching ? theme.authorNameColor : theme.messageTextColor), iconId: topicItem.iconFileId, iconColor: topicItem.iconColor)) } } @@ -4060,7 +4062,6 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode { strongSelf.textNode.textNode.alpha = 0.0 strongSelf.authorNode.alpha = 0.0 strongSelf.compoundHighlightingNode?.alpha = 0.0 - strongSelf.dustNode?.alpha = 0.0 strongSelf.forwardedIconNode.alpha = 0.0 if animated || animateContent { @@ -4072,13 +4073,13 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode { strongSelf.forwardedIconNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15) } } + strongSelf.dustNode?.alpha = 0.0 } else { if !strongSelf.inputActivitiesNode.alpha.isZero { strongSelf.inputActivitiesNode.alpha = 0.0 strongSelf.textNode.textNode.alpha = 1.0 strongSelf.authorNode.alpha = 1.0 strongSelf.compoundHighlightingNode?.alpha = 1.0 - strongSelf.dustNode?.alpha = 1.0 strongSelf.forwardedIconNode.alpha = 1.0 if animated || animateContent { strongSelf.inputActivitiesNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, completion: { value in @@ -4095,6 +4096,7 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode { strongSelf.inputActivitiesNode.removeFromSupernode() } } + strongSelf.dustNode?.alpha = 1.0 } if let inputActivitiesSize = inputActivitiesSize { let inputActivitiesFrame = CGRect(origin: CGPoint(x: contentRect.minX, y: authorNodeFrame.minY + UIScreenPixel), size: inputActivitiesSize) diff --git a/submodules/LegacyMediaPickerUI/Sources/LegacyAttachmentMenu.swift b/submodules/LegacyMediaPickerUI/Sources/LegacyAttachmentMenu.swift index 6f668dfad3..52cbe8cf30 100644 --- a/submodules/LegacyMediaPickerUI/Sources/LegacyAttachmentMenu.swift +++ b/submodules/LegacyMediaPickerUI/Sources/LegacyAttachmentMenu.swift @@ -469,7 +469,7 @@ public func legacyAttachmentMenu(context: AccountContext, peer: Peer?, threadTit present(legacyController, nil) - TGPhotoVideoEditor.present(with: legacyController.context, controller: emptyController, caption: NSAttributedString(), withItem: item, paint: false, adjustments: false, recipientName: recipientName, stickersContext: paintStickersContext, from: .zero, mainSnapshot: nil, snapshots: [], immediate: false, appeared: { + TGPhotoVideoEditor.present(with: legacyController.context, controller: emptyController, caption: initialCaption, withItem: item, paint: false, adjustments: false, recipientName: recipientName, stickersContext: paintStickersContext, from: .zero, mainSnapshot: nil, snapshots: [], immediate: false, appeared: { }, completion: { result, editingContext in let nativeGenerator = legacyAssetPickerItemGenerator() var selectableResult: TGMediaSelectableItem? diff --git a/submodules/LegacyMediaPickerUI/Sources/LegacyMediaPickers.swift b/submodules/LegacyMediaPickerUI/Sources/LegacyMediaPickers.swift index 14b8218342..f787ceccee 100644 --- a/submodules/LegacyMediaPickerUI/Sources/LegacyMediaPickers.swift +++ b/submodules/LegacyMediaPickerUI/Sources/LegacyMediaPickers.swift @@ -758,10 +758,20 @@ public func legacyAssetPickerEnqueueMessages(context: AccountContext, account: A fileAttributes.append(.Animated) } } + + if estimatedSize > 10 * 1024 * 1024 { + fileAttributes.append(.hintFileIsLarge) + } + } else { + if case let .asset(asset) = data, let phAsset = asset.backingAsset, let resource = PHAssetResource.assetResources(for: phAsset).last, let sizeValue = resource.value(forKey: "fileSize") as? CLong, sizeValue > 0 { + let size = Int64(bitPattern: UInt64(sizeValue)) + + if size > 10 * 1024 * 1024 { + fileAttributes.append(.hintFileIsLarge) + } + } } - if estimatedSize > 10 * 1024 * 1024 { - fileAttributes.append(.hintFileIsLarge) - } + var attributes: [MessageAttribute] = [] diff --git a/submodules/PeerInfoUI/Sources/ChannelAdminController.swift b/submodules/PeerInfoUI/Sources/ChannelAdminController.swift index 42a9faa2f3..b45a71658b 100644 --- a/submodules/PeerInfoUI/Sources/ChannelAdminController.swift +++ b/submodules/PeerInfoUI/Sources/ChannelAdminController.swift @@ -1715,7 +1715,9 @@ public func channelAdminController(context: AccountContext, updatedPresentationD return false }) if let resultItemNode = resultItemNode { - controller.ensureItemNodeVisible(resultItemNode) + Queue.mainQueue().after(0.1) { + controller.ensureItemNodeVisible(resultItemNode, atTop: true) + } } }) } diff --git a/submodules/PhotoResources/Sources/PhotoResources.swift b/submodules/PhotoResources/Sources/PhotoResources.swift index cfe948a294..8507e3456b 100644 --- a/submodules/PhotoResources/Sources/PhotoResources.swift +++ b/submodules/PhotoResources/Sources/PhotoResources.swift @@ -914,7 +914,7 @@ public func chatMessagePhotoThumbnail(account: Account, userLocation: MediaResou var blurredThumbnailImage: CGImage? if let thumbnailImage = thumbnailImage { - if thumbnailIsBlurred { + if thumbnailIsBlurred || blurred { let thumbnailSize = CGSize(width: thumbnailImage.width, height: thumbnailImage.height) let thumbnailContextSize = thumbnailSize.aspectFitted(blurred ? CGSize(width: 50.0, height: 50.0) : CGSize(width: 150.0, height: 150.0)) if let thumbnailContext = DrawingContext(size: thumbnailContextSize, scale: 1.0) { @@ -925,6 +925,10 @@ public func chatMessagePhotoThumbnail(account: Account, userLocation: MediaResou imageFastBlur(Int32(thumbnailContextSize.width), Int32(thumbnailContextSize.height), Int32(thumbnailContext.bytesPerRow), thumbnailContext.bytes) if blurred { + if !thumbnailIsBlurred { + telegramFastBlurMore(Int32(thumbnailContextSize.width), Int32(thumbnailContextSize.height), Int32(thumbnailContext.bytesPerRow), thumbnailContext.bytes) + telegramFastBlurMore(Int32(thumbnailContextSize.width), Int32(thumbnailContextSize.height), Int32(thumbnailContext.bytesPerRow), thumbnailContext.bytes) + } imageFastBlur(Int32(thumbnailContextSize.width), Int32(thumbnailContextSize.height), Int32(thumbnailContext.bytesPerRow), thumbnailContext.bytes) adjustSaturationInContext(context: thumbnailContext, saturation: 1.7) } diff --git a/submodules/PremiumUI/Sources/PremiumIntroScreen.swift b/submodules/PremiumUI/Sources/PremiumIntroScreen.swift index eb1a927e2d..521ad43d0a 100644 --- a/submodules/PremiumUI/Sources/PremiumIntroScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumIntroScreen.swift @@ -1805,7 +1805,9 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent { } }, tapAction: { _, _ in - shareLink(link) + if !link.isEmpty { + shareLink(link) + } } ), environment: {}, @@ -3161,6 +3163,8 @@ private final class PremiumIntroScreenComponent: CombinedComponent { let bottomSeparator = Child(Rectangle.self) let button = Child(SolidRoundedButtonComponent.self) + var updatedInstalled: Bool? + return { context in let environment = context.environment[EnvironmentType.self].value let state = context.state @@ -3368,8 +3372,15 @@ 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], loadedStickerPacks: loadedEmojiPack.flatMap { [$0] } ?? [], isEditing: false, expandIfNeeded: false, parentNavigationController: navigationController, sendSticker: { _, _, _ in + var loadedPack: LoadedStickerPack? + if let loadedEmojiPack, case let .result(info, items, installed) = loadedEmojiPack { + loadedPack = .result(info: info, items: items, installed: updatedInstalled ?? installed) + } + + let controller = accountContext.sharedContext.makeStickerPackScreen(context: accountContext, updatedPresentationData: nil, mainStickerPack: packReference, stickerPacks: [packReference], loadedStickerPacks: loadedPack.flatMap { [$0] } ?? [], isEditing: false, expandIfNeeded: false, parentNavigationController: navigationController, sendSticker: { _, _, _ in return false + }, actionPerformed: { added in + updatedInstalled = added }) presentController(controller) break diff --git a/submodules/PresentationDataUtils/Sources/OpenUrl.swift b/submodules/PresentationDataUtils/Sources/OpenUrl.swift index 6a7a7a52b6..31f70d75d2 100644 --- a/submodules/PresentationDataUtils/Sources/OpenUrl.swift +++ b/submodules/PresentationDataUtils/Sources/OpenUrl.swift @@ -5,11 +5,15 @@ import Postbox import AccountContext import OverlayStatusController import UrlWhitelist +import TelegramPresentationData -public func openUserGeneratedUrl(context: AccountContext, peerId: PeerId?, url: String, concealed: Bool, skipUrlAuth: Bool = false, skipConcealedAlert: Bool = false, present: @escaping (ViewController) -> Void, openResolved: @escaping (ResolvedUrl) -> Void, progress: Promise? = nil) -> Disposable { +public func openUserGeneratedUrl(context: AccountContext, peerId: PeerId?, url: String, concealed: Bool, skipUrlAuth: Bool = false, skipConcealedAlert: Bool = false, forceDark: Bool = false, present: @escaping (ViewController) -> Void, openResolved: @escaping (ResolvedUrl) -> Void, progress: Promise? = nil, alertDisplayUpdated: ((ViewController?) -> Void)? = nil) -> Disposable { var concealed = concealed - let presentationData = context.sharedContext.currentPresentationData.with { $0 } + var presentationData = context.sharedContext.currentPresentationData.with { $0 } + if forceDark { + presentationData = presentationData.withUpdated(theme: defaultDarkColorPresentationTheme) + } let openImpl: () -> Disposable = { let disposable = MetaDisposable() @@ -87,9 +91,15 @@ public func openUserGeneratedUrl(context: AccountContext, peerId: PeerId?, url: var displayUrl = rawDisplayUrl displayUrl = displayUrl.replacingOccurrences(of: "\u{202e}", with: "") let disposable = MetaDisposable() - present(textAlertController(context: context, title: nil, text: presentationData.strings.Generic_OpenHiddenLinkAlert(displayUrl).string, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Common_No, action: {}), TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Yes, action: { + + let alertController = textAlertController(context: context, forceTheme: forceDark ? presentationData.theme : nil, title: nil, text: presentationData.strings.Generic_OpenHiddenLinkAlert(displayUrl).string, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Common_No, action: {}), TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Yes, action: { disposable.set(openImpl()) - })])) + })]) + alertController.dismissed = { _ in + alertDisplayUpdated?(nil) + } + present(alertController) + alertDisplayUpdated?(alertController) return disposable } else { return openImpl() diff --git a/submodules/ReactionSelectionNode/Sources/ReactionContextNode.swift b/submodules/ReactionSelectionNode/Sources/ReactionContextNode.swift index 753c2ead47..1493695ac3 100644 --- a/submodules/ReactionSelectionNode/Sources/ReactionContextNode.swift +++ b/submodules/ReactionSelectionNode/Sources/ReactionContextNode.swift @@ -2187,6 +2187,12 @@ public final class ReactionContextNode: ASDisplayNode, ASScrollViewDelegate { continue } itemNode.layer.animateAlpha(from: itemNode.alpha, to: 0.0, duration: 0.2, removeOnCompletion: false) + if let selectionView = itemNode.selectionView { + selectionView.layer.animateAlpha(from: selectionView.alpha, to: 0.0, duration: 0.2, removeOnCompletion: false) + } + if let selectionTintView = itemNode.selectionTintView { + selectionTintView.layer.animateAlpha(from: selectionTintView.alpha, to: 0.0, duration: 0.2, removeOnCompletion: false) + } } if let titleLabelView = self.titleLabelView { diff --git a/submodules/SettingsUI/Sources/Stickers/ArchivedStickerPacksController.swift b/submodules/SettingsUI/Sources/Stickers/ArchivedStickerPacksController.swift index 7cb21fde38..9639d7bfce 100644 --- a/submodules/SettingsUI/Sources/Stickers/ArchivedStickerPacksController.swift +++ b/submodules/SettingsUI/Sources/Stickers/ArchivedStickerPacksController.swift @@ -210,11 +210,18 @@ private struct ArchivedStickerPacksControllerState: Equatable { } } -private func archivedStickerPacksControllerEntries(context: AccountContext, presentationData: PresentationData, state: ArchivedStickerPacksControllerState, packs: [ArchivedStickerPackItem]?, installedView: CombinedView, stickerSettings: StickerSettings) -> [ArchivedStickerPacksEntry] { +private func archivedStickerPacksControllerEntries(context: AccountContext, mode: ArchivedStickerPacksControllerMode, presentationData: PresentationData, state: ArchivedStickerPacksControllerState, packs: [ArchivedStickerPackItem]?, installedView: CombinedView, stickerSettings: StickerSettings) -> [ArchivedStickerPacksEntry] { var entries: [ArchivedStickerPacksEntry] = [] if let packs = packs { - entries.append(.info(presentationData.theme, presentationData.strings.StickerPacksSettings_ArchivedPacks_Info + "\n\n")) + let info: String + switch mode { + case .emoji: + info = presentationData.strings.EmojiPacksSettings_ArchivedPacks_Info + default: + info = presentationData.strings.StickerPacksSettings_ArchivedPacks_Info + } + entries.append(.info(presentationData.theme, info + "\n\n")) var installedIds = Set() if let view = installedView.views[.itemCollectionIds(namespaces: [Namespaces.ItemCollection.CloudStickerPacks])] as? ItemCollectionIdsView, let ids = view.idsByNamespace[Namespaces.ItemCollection.CloudStickerPacks] { @@ -340,7 +347,18 @@ public func archivedStickerPacksController(context: AccountContext, mode: Archiv } } - presentControllerImpl?(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 + let title: String + let text: String + switch mode { + case .emoji: + title = presentationData.strings.EmojiPackActionInfo_AddedTitle + text = presentationData.strings.EmojiPackActionInfo_AddedText(info.title).string + default: + title = presentationData.strings.StickerPackActionInfo_AddedTitle + text = presentationData.strings.StickerPackActionInfo_AddedText(info.title).string + } + + presentControllerImpl?(UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: title, text: text, undo: false, info: info, topItem: items.first, context: context), elevatedLayout: false, animateInAsReplacement: animateInAsReplacement, action: { _ in return true }), nil) @@ -495,8 +513,17 @@ public func archivedStickerPacksController(context: AccountContext, mode: Archiv presentControllerImpl?(actionSheet, nil) }), .init(title: presentationData.strings.StickerPacks_ActionUnarchive, isEnabled: selectedCount > 0, action: { let actionSheet = ActionSheetController(presentationData: presentationData) + + let text: String + switch mode { + case .emoji: + text = presentationData.strings.EmojiPacks_UnarchiveEmojiPacksConfirmation(selectedCount) + default: + text = presentationData.strings.StickerPacks_UnarchiveStickerPacksConfirmation(selectedCount) + } + var items: [ActionSheetItem] = [] - items.append(ActionSheetButtonItem(title: presentationData.strings.StickerPacks_UnarchiveStickerPacksConfirmation(selectedCount), color: .destructive, action: { [weak actionSheet] in + items.append(ActionSheetButtonItem(title: text, color: .destructive, action: { [weak actionSheet] in actionSheet?.dismissAnimated() updateState { @@ -550,9 +577,17 @@ public func archivedStickerPacksController(context: AccountContext, mode: Archiv emptyStateItem = ItemListLoadingIndicatorEmptyStateItem(theme: presentationData.theme) } - let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.StickerPacksSettings_ArchivedPacks), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true) + let title: String + switch mode { + case .emoji: + title = presentationData.strings.EmojiPacksSettings_ArchivedPacks + default: + title = presentationData.strings.StickerPacksSettings_ArchivedPacks + } - let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: archivedStickerPacksControllerEntries(context: context, presentationData: presentationData, state: state, packs: packs, installedView: installedView, stickerSettings: stickerSettings), style: .blocks, emptyStateItem: emptyStateItem, toolbarItem: toolbarItem, animateChanges: previous != nil && packs != nil && (previous! != 0 && previous! >= packs!.count - 10)) + let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(title), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true) + + let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: archivedStickerPacksControllerEntries(context: context, mode: mode, presentationData: presentationData, state: state, packs: packs, installedView: installedView, stickerSettings: stickerSettings), style: .blocks, emptyStateItem: emptyStateItem, toolbarItem: toolbarItem, animateChanges: previous != nil && packs != nil && (previous! != 0 && previous! >= packs!.count - 10)) return (controllerState, (listState, arguments)) } |> afterDisposed { actionsDisposable.dispose() diff --git a/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift b/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift index 34f54d709c..5ff3bdd2ad 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift @@ -1257,6 +1257,7 @@ private final class StickerPackContainer: ASDisplayNode { let editorController = context.sharedContext.makeStickerEditorScreen( context: context, source: result, + intro: false, transitionArguments: transitionView.flatMap { ($0, transitionRect, transitionImage) }, completion: { file, emoji, commit in dismissImpl?() @@ -1361,6 +1362,7 @@ private final class StickerPackContainer: ASDisplayNode { let controller = context.sharedContext.makeStickerEditorScreen( context: context, source: (initialFile, emoji), + intro: false, transitionArguments: nil, completion: { file, emoji, commit in let sticker = ImportSticker( diff --git a/submodules/TelegramUI/Components/Chat/ChatInlineSearchResultsListComponent/Sources/ChatInlineSearchResultsListComponent.swift b/submodules/TelegramUI/Components/Chat/ChatInlineSearchResultsListComponent/Sources/ChatInlineSearchResultsListComponent.swift index d82c7bd409..dff94d1759 100644 --- a/submodules/TelegramUI/Components/Chat/ChatInlineSearchResultsListComponent/Sources/ChatInlineSearchResultsListComponent.swift +++ b/submodules/TelegramUI/Components/Chat/ChatInlineSearchResultsListComponent/Sources/ChatInlineSearchResultsListComponent.swift @@ -239,6 +239,13 @@ public final class ChatInlineSearchResultsListComponent: Component { super.init(frame: frame) self.addSubnode(self.listNode) + + self.listNode.beganInteractiveDragging = { [weak self] _ in + guard let self else { + return + } + self.window?.endEditing(true) + } } required public init?(coder: NSCoder) { diff --git a/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsControllerNode.swift b/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsControllerNode.swift index 7b87ad7533..a20a910b94 100644 --- a/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsControllerNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsControllerNode.swift @@ -304,7 +304,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode { }, navigateToMessageStandalone: { _ in }, navigateToThreadMessage: { [weak self] peerId, threadId, _ in if let context = self?.context, let navigationController = self?.getNavigationController() { - let _ = context.sharedContext.navigateToForumThread(context: context, peerId: peerId, threadId: threadId, messageId: nil, navigationController: navigationController, activateInput: nil, keepStack: .always).startStandalone() + let _ = context.sharedContext.navigateToForumThread(context: context, peerId: peerId, threadId: threadId, messageId: nil, navigationController: navigationController, activateInput: nil, scrollToEndIfExists: false, keepStack: .always).startStandalone() } }, tapMessage: nil, clickThroughMessage: { }, toggleMessagesSelection: { _, _ in }, sendCurrentMessage: { _ in }, sendMessage: { _ in }, sendSticker: { _, _, _, _, _, _, _, _, _ in return false }, sendEmoji: { _, _, _ in }, sendGif: { _, _, _, _, _ in return false }, sendBotContextResultAsGif: { _, _, _, _, _, _ in return false }, requestMessageActionCallback: { [weak self] messageId, _, _, _ in @@ -1181,7 +1181,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode { } case let .replyThread(messageId): if let navigationController = strongSelf.getNavigationController() { - let _ = strongSelf.context.sharedContext.navigateToForumThread(context: strongSelf.context, peerId: messageId.peerId, threadId: Int64(messageId.id), messageId: nil, navigationController: navigationController, activateInput: nil, keepStack: .always).startStandalone() + let _ = strongSelf.context.sharedContext.navigateToForumThread(context: strongSelf.context, peerId: messageId.peerId, threadId: Int64(messageId.id), messageId: nil, navigationController: navigationController, activateInput: nil, scrollToEndIfExists: false, keepStack: .always).startStandalone() } case let .stickerPack(name, type): let _ = type diff --git a/submodules/TelegramUI/Components/ChatEntityKeyboardInputNode/Sources/ChatEntityKeyboardInputNode.swift b/submodules/TelegramUI/Components/ChatEntityKeyboardInputNode/Sources/ChatEntityKeyboardInputNode.swift index 81555f268c..fa47f65448 100644 --- a/submodules/TelegramUI/Components/ChatEntityKeyboardInputNode/Sources/ChatEntityKeyboardInputNode.swift +++ b/submodules/TelegramUI/Components/ChatEntityKeyboardInputNode/Sources/ChatEntityKeyboardInputNode.swift @@ -208,6 +208,7 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode { hasTrending: hasTrending, forceHasPremium: false, hasEdit: hasEdit, + hasAdd: hasEdit, subject: .chatStickers, hideBackground: hideBackground ) @@ -1397,7 +1398,8 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode { parentNavigationController: interaction.getNavigationController(), sendSticker: { [weak interaction] fileReference, sourceView, sourceRect in return interaction?.sendSticker(fileReference, false, false, nil, false, sourceView, sourceRect, nil, []) ?? false - } + }, + actionPerformed: nil ) interaction.presentController(controller, nil) }) @@ -2880,7 +2882,7 @@ public final class EmojiContentPeekBehaviorImpl: EmojiContentPeekBehavior { let controller = strongSelf.context.sharedContext.makeStickerPackScreen(context: context, updatedPresentationData: nil, mainStickerPack: packReference, stickerPacks: [packReference], loadedStickerPacks: [], isEditing: false, expandIfNeeded: false, parentNavigationController: interaction.navigationController(), sendSticker: { file, sourceView, sourceRect in sendSticker(file, false, false, nil, false, sourceView, sourceRect, nil) return true - }) + }, actionPerformed: nil) interaction.navigationController()?.view.window?.endEditing(true) interaction.presentController(controller, nil) diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentSignals.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentSignals.swift index d02f26e64f..33bf1a054c 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentSignals.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentSignals.swift @@ -1607,6 +1607,7 @@ public extension EmojiPagerContentComponent { hasTrending: Bool, forceHasPremium: Bool, hasEdit: Bool = false, + hasAdd: Bool = false, searchIsPlaceholderOnly: Bool = true, subject: StickersSubject = .chatStickers, hideBackground: Bool = false @@ -1890,7 +1891,7 @@ public extension EmojiPagerContentComponent { } } - if hasEdit && !addedCreateStickerButton, let groupIndex = itemGroupIndexById[groupId] { + if hasAdd && !addedCreateStickerButton, let groupIndex = itemGroupIndexById[groupId] { let resultItem = EmojiPagerContentComponent.Item( animationData: nil, content: .icon(.add), diff --git a/submodules/TelegramUI/Components/MediaEditorScreen/BUILD b/submodules/TelegramUI/Components/MediaEditorScreen/BUILD index 3227264f2d..d4939961f7 100644 --- a/submodules/TelegramUI/Components/MediaEditorScreen/BUILD +++ b/submodules/TelegramUI/Components/MediaEditorScreen/BUILD @@ -59,6 +59,7 @@ swift_library( "//submodules/TelegramUI/Components/StickerPickerScreen", "//submodules/UIKitRuntimeUtils", "//submodules/TelegramUI/Components/MediaEditor/ImageObjectSeparation", + "//submodules/Components/HierarchyTrackingLayer", ], visibility = [ "//visibility:public", diff --git a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift index d09be9b218..9df94346e4 100644 --- a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift +++ b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift @@ -2410,6 +2410,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate case generic case addingToPack case editing + case businessIntro } case storyEditor @@ -6494,6 +6495,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate var file = stickerFile(resource: resource, thumbnailResource: thumbnailResource, size: Int64(0), dimensions: PixelDimensions(image.size), duration: self.preferredStickerDuration(), isVideo: isVideo) var menuItems: [ContextMenuItem] = [] + var hasEmojiSelection = true if case let .stickerEditor(mode) = self.mode { switch mode { case .generic: @@ -6652,6 +6654,24 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate } f(.default) + let _ = (imagesReady.get() + |> filter { $0 } + |> take(1) + |> deliverOnMainQueue).start(next: { [weak self] _ in + guard let self else { + return + } + self.uploadSticker(file, action: .upload) + }) + }))) + case .businessIntro: + hasEmojiSelection = false + menuItems.append(.action(ContextMenuActionItem(text: presentationData.strings.MediaEditor_SetAsIntroSticker, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Sticker"), color: theme.contextMenu.primaryColor) }, action: { [weak self] c, f in + guard let self else { + return + } + f(.default) + let _ = (imagesReady.get() |> filter { $0 } |> take(1) @@ -6682,14 +6702,14 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate theme: presentationData.theme, strings: presentationData.strings, item: .portal(portalView), - isCreating: true, + isCreating: hasEmojiSelection, selectedEmoji: self.stickerSelectedEmoji, selectedEmojiUpdated: { [weak self] selectedEmoji in if let self { self.stickerSelectedEmoji = selectedEmoji } }, - recommendedEmoji: stickerRecommendedEmoji, + recommendedEmoji: self.stickerRecommendedEmoji, menu: menuItems, openPremiumIntro: {} ), @@ -6936,7 +6956,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate case .addToStickerPack, .createStickerPack: if let (packReference, packTitle) = packReferenceAndTitle, let navigationController = self.navigationController as? NavigationController { Queue.mainQueue().after(0.2) { - let controller = self.context.sharedContext.makeStickerPackScreen(context: self.context, updatedPresentationData: nil, mainStickerPack: packReference, stickerPacks: [packReference], loadedStickerPacks: [], isEditing: false, expandIfNeeded: true, parentNavigationController: navigationController, sendSticker: self.sendSticker) + let controller = self.context.sharedContext.makeStickerPackScreen(context: self.context, updatedPresentationData: nil, mainStickerPack: packReference, stickerPacks: [packReference], loadedStickerPacks: [], isEditing: false, expandIfNeeded: true, parentNavigationController: navigationController, sendSticker: self.sendSticker, actionPerformed: nil) (navigationController.viewControllers.last as? ViewController)?.present(controller, in: .window(.root)) Queue.mainQueue().after(0.1) { diff --git a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/StickerCutoutOutlineView.swift b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/StickerCutoutOutlineView.swift index df26149917..c0f5a74ee8 100644 --- a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/StickerCutoutOutlineView.swift +++ b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/StickerCutoutOutlineView.swift @@ -135,10 +135,7 @@ final class StickerCutoutOutlineView: UIView { private func animateBump(path: BezierPath) { let boundingBox = path.path.cgPath.boundingBox let pathCenter = CGPoint(x: boundingBox.midX, y: boundingBox.midY) - -// let originalPosition = self.imageLayer.position -// let originalAnchorPoint = self.imageLayer.anchorPoint - + let layerPathCenter = self.imageLayer.convert(pathCenter, from: self.imageLayer.superlayer) self.imageLayer.anchorPoint = CGPoint(x: layerPathCenter.x / layer.bounds.width, y: layerPathCenter.y / layer.bounds.height) self.imageLayer.position = layerPathCenter diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoData.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoData.swift index cb7022db28..1736295a98 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoData.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoData.swift @@ -898,7 +898,7 @@ func peerInfoScreenSettingsData(context: AccountContext, peerId: EnginePeer.Id, } } -func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, isSettings: Bool, isMyProfile: Bool, hintGroupInCommon: PeerId?, existingRequestsContext: PeerInvitationImportersContext?, chatLocation: ChatLocation, chatLocationContextHolder: Atomic) -> Signal { +func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, isSettings: Bool, isMyProfile: Bool, hintGroupInCommon: PeerId?, existingRequestsContext: PeerInvitationImportersContext?, chatLocation: ChatLocation, chatLocationContextHolder: Atomic, privacySettings: Signal) -> Signal { return peerInfoScreenInputData(context: context, peerId: peerId, isSettings: isSettings) |> mapToSignal { inputData -> Signal in let wasUpgradedGroup = Atomic(value: nil) @@ -1162,9 +1162,10 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen hasSavedMessagesChats, hasSavedMessages, hasSavedMessageTags, - peerInfoPersonalChannel(context: context, peerId: peerId, isSettings: false) + peerInfoPersonalChannel(context: context, peerId: peerId, isSettings: false), + privacySettings ) - |> map { peerView, availablePanes, globalNotificationSettings, encryptionKeyFingerprint, status, hasStories, hasStoryArchive, accountIsPremium, savedMessagesPeer, hasSavedMessagesChats, hasSavedMessages, hasSavedMessageTags, personalChannel -> PeerInfoScreenData in + |> map { peerView, availablePanes, globalNotificationSettings, encryptionKeyFingerprint, status, hasStories, hasStoryArchive, accountIsPremium, savedMessagesPeer, hasSavedMessagesChats, hasSavedMessages, hasSavedMessageTags, personalChannel, privacySettings -> PeerInfoScreenData in var availablePanes = availablePanes if isMyProfile { @@ -1205,6 +1206,32 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen let peer = peerView.peers[userPeerId] + var globalSettings: TelegramGlobalSettings? + if let privacySettings { + globalSettings = TelegramGlobalSettings( + suggestPhoneNumberConfirmation: false, + suggestPasswordConfirmation: false, + suggestPasswordSetup: false, + premiumGracePeriod: false, + accountsAndPeers: [], + activeSessionsContext: nil, + webSessionsContext: nil, + otherSessionsCount: nil, + proxySettings: ProxySettings(enabled: false, servers: [], activeServer: nil, useForCalls: false), + notificationAuthorizationStatus: .notDetermined, + notificationWarningSuppressed: false, + notificationExceptions: nil, + inAppNotificationSettings: InAppNotificationSettings(playSounds: false, vibrate: false, displayPreviews: false, totalUnreadCountDisplayStyle: .filtered, totalUnreadCountDisplayCategory: .chats, totalUnreadCountIncludeTags: .all, displayNameOnLockscreen: false, displayNotificationsFromAllAccounts: false, customSound: nil), + privacySettings: privacySettings, + unreadTrendingStickerPacks: 0, + archivedStickerPacks: nil, + userLimits: context.userLimits, + bots: [], + hasPassport: false, + hasWatchApp: false, + enableQRLogin: false) + } + return PeerInfoScreenData( peer: peer, chatPeer: peerView.peers[peerId], @@ -1222,7 +1249,7 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen storyListContext: storyListContext, storyArchiveListContext: storyArchiveListContext, encryptionKeyFingerprint: encryptionKeyFingerprint, - globalSettings: nil, + globalSettings: globalSettings, invitations: nil, requests: nil, requestsContext: nil, diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift index 0b639069fc..e2ff5e91fb 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift @@ -2846,7 +2846,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro c.dismiss(completion: { if let strongSelf = self, let currentPeer = strongSelf.data?.peer, let navigationController = strongSelf.controller?.navigationController as? NavigationController { if let channel = currentPeer as? TelegramChannel, channel.flags.contains(.isForum), let threadId = message.threadId { - let _ = strongSelf.context.sharedContext.navigateToForumThread(context: strongSelf.context, peerId: currentPeer.id, threadId: threadId, messageId: message.id, navigationController: navigationController, activateInput: nil, keepStack: .default).startStandalone() + let _ = strongSelf.context.sharedContext.navigateToForumThread(context: strongSelf.context, peerId: currentPeer.id, threadId: threadId, messageId: message.id, navigationController: navigationController, activateInput: nil, scrollToEndIfExists: false, keepStack: .default).startStandalone() } else { let targetLocation: NavigateToChatControllerParams.Location if case let .replyThread(message) = strongSelf.chatLocation { @@ -3008,7 +3008,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro c.dismiss(completion: { if let strongSelf = self, let currentPeer = strongSelf.data?.peer, let navigationController = strongSelf.controller?.navigationController as? NavigationController { if let channel = currentPeer as? TelegramChannel, channel.flags.contains(.isForum), let threadId = message.threadId { - let _ = strongSelf.context.sharedContext.navigateToForumThread(context: strongSelf.context, peerId: currentPeer.id, threadId: threadId, messageId: message.id, navigationController: navigationController, activateInput: nil, keepStack: .default).startStandalone() + let _ = strongSelf.context.sharedContext.navigateToForumThread(context: strongSelf.context, peerId: currentPeer.id, threadId: threadId, messageId: message.id, navigationController: navigationController, activateInput: nil, scrollToEndIfExists: false, keepStack: .default).startStandalone() } else { let targetLocation: NavigateToChatControllerParams.Location if case let .replyThread(message) = strongSelf.chatLocation { @@ -4251,7 +4251,13 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro strongSelf.controller?.present(emojiStatusSelectionController, in: .window(.root)) } } else { - screenData = peerInfoScreenData(context: context, peerId: peerId, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, isSettings: self.isSettings, isMyProfile: self.isMyProfile, hintGroupInCommon: hintGroupInCommon, existingRequestsContext: requestsContext, chatLocation: self.chatLocation, chatLocationContextHolder: self.chatLocationContextHolder) + if peerId == context.account.peerId { + self.privacySettings.set(.single(nil) |> then(context.engine.privacy.requestAccountPrivacySettings() |> map(Optional.init))) + } else { + self.privacySettings.set(.single(nil)) + } + + screenData = peerInfoScreenData(context: context, peerId: peerId, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, isSettings: self.isSettings, isMyProfile: self.isMyProfile, hintGroupInCommon: hintGroupInCommon, existingRequestsContext: requestsContext, chatLocation: self.chatLocation, chatLocationContextHolder: self.chatLocationContextHolder, privacySettings: self.privacySettings.get()) var previousTimestamp: Double? self.headerNode.displayPremiumIntro = { [weak self] sourceView, peerStatus, emojiStatusFileAndPack, white in diff --git a/submodules/TelegramUI/Components/Settings/BusinessIntroSetupScreen/BUILD b/submodules/TelegramUI/Components/Settings/BusinessIntroSetupScreen/BUILD index 02989c42f4..024c651c5b 100644 --- a/submodules/TelegramUI/Components/Settings/BusinessIntroSetupScreen/BUILD +++ b/submodules/TelegramUI/Components/Settings/BusinessIntroSetupScreen/BUILD @@ -41,6 +41,7 @@ swift_library( "//submodules/TelegramUI/Components/PeerAllowedReactionsScreen", "//submodules/TelegramUI/Components/EmojiActionIconComponent", "//submodules/TelegramUI/Components/TextFieldComponent", + "//submodules/TelegramUI/Components/CameraScreen", ], visibility = [ "//visibility:public", diff --git a/submodules/TelegramUI/Components/Settings/BusinessIntroSetupScreen/Sources/BusinessIntroSetupScreen.swift b/submodules/TelegramUI/Components/Settings/BusinessIntroSetupScreen/Sources/BusinessIntroSetupScreen.swift index b06da137cc..439834ef2f 100644 --- a/submodules/TelegramUI/Components/Settings/BusinessIntroSetupScreen/Sources/BusinessIntroSetupScreen.swift +++ b/submodules/TelegramUI/Components/Settings/BusinessIntroSetupScreen/Sources/BusinessIntroSetupScreen.swift @@ -22,6 +22,7 @@ import EntityKeyboard import PeerAllowedReactionsScreen import EmojiActionIconComponent import TextFieldComponent +import CameraScreen final class BusinessIntroSetupScreenComponent: Component { typealias EnvironmentType = ViewControllerComponentContainer.Environment @@ -161,6 +162,56 @@ final class BusinessIntroSetupScreenComponent: Component { return true } + func openStickerEditor() { + guard let component = self.component, let environment = self.environment, let controller = environment.controller() as? BusinessIntroSetupScreen else { + return + } + + let context = component.context + let navigationController = controller.navigationController as? NavigationController + + var dismissImpl: (() -> Void)? + let mainController = context.sharedContext.makeStickerMediaPickerScreen( + context: context, + getSourceRect: { return .zero }, + completion: { result, transitionView, transitionRect, transitionImage, fromCamera, completion, cancelled in + let editorController = context.sharedContext.makeStickerEditorScreen( + context: context, + source: result, + intro: true, + transitionArguments: transitionView.flatMap { ($0, transitionRect, transitionImage) }, + completion: { [weak self] file, emoji, commit in + dismissImpl?() + + guard let self else { + return + } + + self.stickerFile = file + if !self.isUpdating { + self.state?.updated(transition: .spring(duration: 0.4)) + } + + commit() + }, + cancelled: cancelled + ) + navigationController?.pushViewController(editorController) + }, + dismissed: {} + ) + dismissImpl = { [weak mainController] in + if let mainController, let navigationController = mainController.navigationController { + var viewControllers = navigationController.viewControllers + viewControllers = viewControllers.filter { c in + return !(c is CameraScreen) && c !== mainController + } + navigationController.setViewControllers(viewControllers, animated: false) + } + } + navigationController?.pushViewController(mainController) + } + func scrollViewDidScroll(_ scrollView: UIScrollView) { if !self.ignoreScrolling { self.updateScrolling(transition: .immediate) @@ -229,6 +280,7 @@ final class BusinessIntroSetupScreenComponent: Component { hasSearch: true, hasTrending: false, forceHasPremium: true, + hasAdd: true, searchIsPlaceholderOnly: false, subject: .greetingStickers ) @@ -245,6 +297,13 @@ final class BusinessIntroSetupScreenComponent: Component { return } guard let itemFile = item.itemFile else { + if case .icon(.add) = item.content { + self.openStickerEditor() + self.displayStickerInput = false + if !self.isUpdating { + self.state?.updated(transition: .spring(duration: 0.4)) + } + } return } diff --git a/submodules/TelegramUI/Components/Settings/WallpaperGridScreen/Sources/ThemeGridControllerNode.swift b/submodules/TelegramUI/Components/Settings/WallpaperGridScreen/Sources/ThemeGridControllerNode.swift index 25fc99f957..1f32b66fb4 100644 --- a/submodules/TelegramUI/Components/Settings/WallpaperGridScreen/Sources/ThemeGridControllerNode.swift +++ b/submodules/TelegramUI/Components/Settings/WallpaperGridScreen/Sources/ThemeGridControllerNode.swift @@ -825,7 +825,7 @@ final class ThemeGridControllerNode: ASDisplayNode { if let makeGalleryIconLayout, let galleryItem = self.galleryItem as? ItemListPeerActionItem { (galleryLayout, galleryApply) = makeGalleryIconLayout(galleryItem, params, ItemListNeighbors(top: isChannel ? .none : .sameSection(alwaysPlain: false), bottom: .sameSection(alwaysPlain: !hasCustomWallpaper))) } else if let makeGalleryLayout, let galleryItem = self.galleryItem as? ItemListActionItem { - (galleryLayout, galleryApply) = makeGalleryLayout(galleryItem, params, ItemListNeighbors(top: isChannel ? .none : .sameSection(alwaysPlain: false), bottom: .sameSection(alwaysPlain: false))) + (galleryLayout, galleryApply) = makeGalleryLayout(galleryItem, params, ItemListNeighbors(top: isChannel ? .none : .sameSection(alwaysPlain: false), bottom: .sameSection(alwaysPlain: true))) } else { fatalError() } diff --git a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryContainerScreen.swift b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryContainerScreen.swift index 9d200b7a99..2be200e643 100644 --- a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryContainerScreen.swift +++ b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryContainerScreen.swift @@ -974,6 +974,13 @@ private final class StoryContainerScreenComponent: Component { } } else { if let result = subview.hitTest(self.convert(self.convert(point, to: subview), to: subview), with: event) { + if let environment = self.environment, case .regular = environment.metrics.widthClass { + if result.isDescendant(of: self.backgroundEffectView) { + if let stateValue = self.stateValue, let slice = stateValue.slice, let itemSetView = self.visibleItemSetViews[slice.peer.id] { + return itemSetView.view.view + } + } + } return result } } diff --git a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemContentComponent.swift b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemContentComponent.swift index 01cc825f96..2fab648f95 100644 --- a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemContentComponent.swift +++ b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemContentComponent.swift @@ -569,7 +569,7 @@ final class StoryItemContentComponent: Component { return } if apply { - videoNode.seek(timestamp) + videoNode.seek(min(timestamp, self.effectiveDuration - 0.3)) } self.isSeeking = true self.updateVideoPlaybackProgress(timestamp) diff --git a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift index 1bfe74f35d..a0219c6ba5 100644 --- a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift +++ b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift @@ -4231,7 +4231,7 @@ public final class StoryItemSetContainerComponent: Component { } switch action { case let .url(url, concealed): - let _ = openUserGeneratedUrl(context: component.context, peerId: component.slice.peer.id, url: url, concealed: concealed, skipUrlAuth: false, skipConcealedAlert: false, present: { [weak self] c in + let _ = openUserGeneratedUrl(context: component.context, peerId: component.slice.peer.id, url: url, concealed: concealed, skipUrlAuth: false, skipConcealedAlert: false, forceDark: true, present: { [weak self] c in guard let self, let component = self.component, let controller = component.controller() else { return } @@ -4241,6 +4241,12 @@ public final class StoryItemSetContainerComponent: Component { return } self.sendMessageContext.openResolved(view: self, result: resolved, forceExternal: false, concealed: concealed) + }, alertDisplayUpdated: { [weak self] alertController in + guard let self else { + return + } + self.sendMessageContext.statusController = alertController + self.updateIsProgressPaused() }) case let .textMention(value): self.sendMessageContext.openPeerMention(view: self, name: value) @@ -4376,6 +4382,12 @@ public final class StoryItemSetContainerComponent: Component { let captionFrame = CGRect(origin: CGPoint(x: 0.0, y: contentFrame.height - captionSize.height), size: captionSize) if let captionItemView = captionItem.view.view { if captionItemView.superview == nil { + if case .regular = component.metrics.widthClass { + self.topContentGradientView.layer.cornerRadius = 12.0 + self.topContentGradientView.clipsToBounds = true + captionItemView.layer.cornerRadius = 12.0 + captionItemView.clipsToBounds = true + } self.controlsContainerView.insertSubview(captionItemView, aboveSubview: self.contentDimView) } captionItemTransition.setFrame(view: captionItemView, frame: captionFrame) diff --git a/submodules/TelegramUI/Sources/Chat/ChatControllerLoadDisplayNode.swift b/submodules/TelegramUI/Sources/Chat/ChatControllerLoadDisplayNode.swift index a1eee5093b..35ae3b57a3 100644 --- a/submodules/TelegramUI/Sources/Chat/ChatControllerLoadDisplayNode.swift +++ b/submodules/TelegramUI/Sources/Chat/ChatControllerLoadDisplayNode.swift @@ -1217,14 +1217,7 @@ extension ChatControllerImpl { } } - let transformedMessages: [EnqueueMessage] - if let silentPosting = silentPosting { - transformedMessages = strongSelf.transformEnqueueMessages(messages, silentPosting: silentPosting, scheduleTime: scheduleTime) - } else if let scheduleTime = scheduleTime { - transformedMessages = strongSelf.transformEnqueueMessages(messages, silentPosting: false, scheduleTime: scheduleTime) - } else { - transformedMessages = strongSelf.transformEnqueueMessages(messages) - } + let transformedMessages = strongSelf.transformEnqueueMessages(messages, silentPosting: silentPosting ?? false, scheduleTime: scheduleTime) var forwardedMessages: [[EnqueueMessage]] = [] var forwardSourcePeerIds = Set() diff --git a/submodules/TelegramUI/Sources/Chat/ChatMessageActionOptions.swift b/submodules/TelegramUI/Sources/Chat/ChatMessageActionOptions.swift index 2e09f56eae..469ed2498e 100644 --- a/submodules/TelegramUI/Sources/Chat/ChatMessageActionOptions.swift +++ b/submodules/TelegramUI/Sources/Chat/ChatMessageActionOptions.swift @@ -149,13 +149,14 @@ private func chatForwardOptions(selfController: ChatControllerImpl, sourceNode: for media in message.media { if let media = media as? TelegramMediaFile, media.isMusic { isMusic = true + if !message.text.isEmpty { + hasCaptions = true + } } else if media is TelegramMediaDice { isDice = true - } else { + } else if media is TelegramMediaImage || media is TelegramMediaFile { if !message.text.isEmpty { - if media is TelegramMediaImage || media is TelegramMediaFile { - hasCaptions = true - } + hasCaptions = true } } } diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index 4e5b6dd269..866f086247 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -180,8 +180,12 @@ func isTopmostChatController(_ controller: ChatControllerImpl) -> Bool { if let _ = controller.navigationController { var hasOther = false controller.window?.forEachController({ c in - if c is ChatControllerImpl && controller !== c { - hasOther = true + if c is ChatControllerImpl { + if controller !== c { + hasOther = true + } else { + hasOther = false + } } }) if hasOther { @@ -1702,7 +1706,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G self?.navigateToMessage(from: nil, to: .id(id, NavigateToMessageParams(timestamp: nil, quote: nil)), forceInCurrentChat: false) }, navigateToThreadMessage: { [weak self] peerId, threadId, messageId in if let context = self?.context, let navigationController = self?.effectiveNavigationController { - let _ = context.sharedContext.navigateToForumThread(context: context, peerId: peerId, threadId: threadId, messageId: messageId, navigationController: navigationController, activateInput: nil, keepStack: .always).startStandalone() + let _ = context.sharedContext.navigateToForumThread(context: context, peerId: peerId, threadId: threadId, messageId: messageId, navigationController: navigationController, activateInput: nil, scrollToEndIfExists: false, keepStack: .always).startStandalone() } }, tapMessage: nil, clickThroughMessage: { [weak self] in self?.chatDisplayNode.dismissInput() @@ -3648,6 +3652,18 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G }, delay: true) }))) } + if !isChannel { + items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.Conversation_ContextMenuSearchMessages, icon: { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Search"), color: theme.actionSheet.primaryTextColor) + }, action: { _, f in + f(.dismissWithoutContent) + + guard let strongSelf = self else { + return + } + strongSelf.activateSearch(domain: .member(peer._asPeer())) + }))) + } strongSelf.chatDisplayNode.messageTransitionNode.dismissMessageReactionContexts() diff --git a/submodules/TelegramUI/Sources/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index 3cd21174f2..2e36be9e48 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -446,7 +446,7 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate { var messageMedia = message.media var hasDice = false - if hideNames { + if hideNames || options.hideCaptions { for media in message.media { if options.hideCaptions { if media is TelegramMediaImage || media is TelegramMediaFile { diff --git a/submodules/TelegramUI/Sources/NavigateToChatController.swift b/submodules/TelegramUI/Sources/NavigateToChatController.swift index e9ced9f7f3..f99072a72a 100644 --- a/submodules/TelegramUI/Sources/NavigateToChatController.swift +++ b/submodules/TelegramUI/Sources/NavigateToChatController.swift @@ -354,7 +354,7 @@ public func isOverlayControllerForChatNotificationOverlayPresentation(_ controll return false } -public func navigateToForumThreadImpl(context: AccountContext, peerId: EnginePeer.Id, threadId: Int64, messageId: EngineMessage.Id?, navigationController: NavigationController, activateInput: ChatControllerActivateInput?, keepStack: NavigateToChatKeepStack) -> Signal { +public func navigateToForumThreadImpl(context: AccountContext, peerId: EnginePeer.Id, threadId: Int64, messageId: EngineMessage.Id?, navigationController: NavigationController, activateInput: ChatControllerActivateInput?, scrollToEndIfExists: Bool, keepStack: NavigateToChatKeepStack) -> Signal { return fetchAndPreloadReplyThreadInfo(context: context, subject: .groupMessage(MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadId))), atMessageId: messageId, preload: false) |> deliverOnMainQueue |> beforeNext { [weak context, weak navigationController] result in @@ -375,7 +375,9 @@ public func navigateToForumThreadImpl(context: AccountContext, peerId: EnginePee chatLocationContextHolder: result.contextHolder, subject: messageId.flatMap { .message(id: .id($0), highlight: ChatControllerSubject.MessageHighlight(quote: nil), timecode: nil) }, activateInput: actualActivateInput, - keepStack: keepStack + keepStack: keepStack, + scrollToEndIfExists: scrollToEndIfExists, + animated: !scrollToEndIfExists ) ) } diff --git a/submodules/TelegramUI/Sources/OpenChatMessage.swift b/submodules/TelegramUI/Sources/OpenChatMessage.swift index b22296c21a..b3534e55db 100644 --- a/submodules/TelegramUI/Sources/OpenChatMessage.swift +++ b/submodules/TelegramUI/Sources/OpenChatMessage.swift @@ -186,7 +186,7 @@ func openChatMessageImpl(_ params: OpenChatMessageParams) -> Bool { if actions.count > 1, let first = actions.first { if case .add = first.2 { - params.navigationController?.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.EmojiPackActionInfo_AddedTitle, text: presentationData.strings.EmojiPackActionInfo_MultipleAddedText(Int32(actions.count)), undo: false, info: first.0, topItem: first.1.first, context: params.context), elevatedLayout: true, animateInAsReplacement: false, action: { _ in + params.navigationController?.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.EmojiPackActionInfo_AddedTitle, text: presentationData.strings.EmojiPackActionInfo_MultipleAddedText(Int32(actions.count)), undo: false, info: first.0, topItem: first.1.first, context: params.context), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return true })) } @@ -204,16 +204,18 @@ func openChatMessageImpl(_ params: OpenChatMessageParams) -> Bool { } 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 + let 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: false, animateInAsReplacement: animateInAsReplacement, action: { _ in return true - })) + }) + (params.navigationController?.topViewController as? ViewController)?.present(controller, in: .current) 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 + let 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: false, animateInAsReplacement: animateInAsReplacement, action: { action in if case .undo = action { let _ = params.context.engine.stickers.addStickerPackInteractively(info: info, items: items, positionInList: positionInList).startStandalone() } return true - })) + }) + (params.navigationController?.topViewController as? ViewController)?.present(controller, in: .current) } } }, getSourceRect: params.getSourceRect) diff --git a/submodules/TelegramUI/Sources/OpenResolvedUrl.swift b/submodules/TelegramUI/Sources/OpenResolvedUrl.swift index cc4f13a668..10da2f4eca 100644 --- a/submodules/TelegramUI/Sources/OpenResolvedUrl.swift +++ b/submodules/TelegramUI/Sources/OpenResolvedUrl.swift @@ -216,7 +216,7 @@ func openResolvedUrlImpl( } case let .replyThread(messageId): if let navigationController = navigationController { - let _ = context.sharedContext.navigateToForumThread(context: context, peerId: messageId.peerId, threadId: Int64(messageId.id), messageId: nil, navigationController: navigationController, activateInput: nil, keepStack: .always).startStandalone() + let _ = context.sharedContext.navigateToForumThread(context: context, peerId: messageId.peerId, threadId: Int64(messageId.id), messageId: nil, navigationController: navigationController, activateInput: nil, scrollToEndIfExists: false, keepStack: .always).startStandalone() } case let .stickerPack(name, _): dismissInput() @@ -233,11 +233,11 @@ func openResolvedUrlImpl( 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 + 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: false, 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 + 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: false, animateInAsReplacement: false, action: { action in if case .undo = action { let _ = context.engine.stickers.addStickerPackInteractively(info: info, items: items, positionInList: positionInList).startStandalone() } diff --git a/submodules/TelegramUI/Sources/SharedAccountContext.swift b/submodules/TelegramUI/Sources/SharedAccountContext.swift index 2ef573b55b..a5da8cbfb9 100644 --- a/submodules/TelegramUI/Sources/SharedAccountContext.swift +++ b/submodules/TelegramUI/Sources/SharedAccountContext.swift @@ -1526,8 +1526,8 @@ public final class SharedAccountContextImpl: SharedAccountContext { navigateToForumChannelImpl(context: context, peerId: peerId, navigationController: navigationController) } - public func navigateToForumThread(context: AccountContext, peerId: EnginePeer.Id, threadId: Int64, messageId: EngineMessage.Id?, navigationController: NavigationController, activateInput: ChatControllerActivateInput?, keepStack: NavigateToChatKeepStack) -> Signal { - return navigateToForumThreadImpl(context: context, peerId: peerId, threadId: threadId, messageId: messageId, navigationController: navigationController, activateInput: activateInput, keepStack: keepStack) + public func navigateToForumThread(context: AccountContext, peerId: EnginePeer.Id, threadId: Int64, messageId: EngineMessage.Id?, navigationController: NavigationController, activateInput: ChatControllerActivateInput?, scrollToEndIfExists: Bool, keepStack: NavigateToChatKeepStack) -> Signal { + return navigateToForumThreadImpl(context: context, peerId: peerId, threadId: threadId, messageId: messageId, navigationController: navigationController, activateInput: activateInput, scrollToEndIfExists: scrollToEndIfExists, keepStack: keepStack) } public func chatControllerForForumThread(context: AccountContext, peerId: EnginePeer.Id, threadId: Int64) -> Signal { @@ -2481,13 +2481,22 @@ public final class SharedAccountContextImpl: SharedAccountContext { return controller } - public func makeStickerPackScreen(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)?, mainStickerPack: StickerPackReference, stickerPacks: [StickerPackReference], loadedStickerPacks: [LoadedStickerPack], isEditing: Bool, expandIfNeeded: Bool, parentNavigationController: NavigationController?, sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)?) -> ViewController { - return StickerPackScreen(context: context, updatedPresentationData: updatedPresentationData, mainStickerPack: mainStickerPack, stickerPacks: stickerPacks, loadedStickerPacks: loadedStickerPacks, isEditing: isEditing, expandIfNeeded: expandIfNeeded, parentNavigationController: parentNavigationController, sendSticker: sendSticker) + public func makeStickerPackScreen(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)?, mainStickerPack: StickerPackReference, stickerPacks: [StickerPackReference], loadedStickerPacks: [LoadedStickerPack], isEditing: Bool, expandIfNeeded: Bool, parentNavigationController: NavigationController?, sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)?, actionPerformed: ((Bool) -> Void)?) -> ViewController { + return StickerPackScreen(context: context, updatedPresentationData: updatedPresentationData, mainStickerPack: mainStickerPack, stickerPacks: stickerPacks, loadedStickerPacks: loadedStickerPacks, isEditing: isEditing, expandIfNeeded: expandIfNeeded, parentNavigationController: parentNavigationController, sendSticker: sendSticker, actionPerformed: { actions in + if let (_, _, action) = actions.first { + switch action { + case .add: + actionPerformed?(true) + case .remove: + actionPerformed?(false) + } + } + }) } - public func makeStickerEditorScreen(context: AccountContext, source: Any?, transitionArguments: (UIView, CGRect, UIImage?)?, completion: @escaping (TelegramMediaFile, [String], @escaping () -> Void) -> Void, cancelled: @escaping () -> Void) -> ViewController { + public func makeStickerEditorScreen(context: AccountContext, source: Any?, intro: Bool, transitionArguments: (UIView, CGRect, UIImage?)?, completion: @escaping (TelegramMediaFile, [String], @escaping () -> Void) -> Void, cancelled: @escaping () -> Void) -> ViewController { let subject: Signal - let mode: MediaEditorScreen.Mode.StickerEditorMode + var mode: MediaEditorScreen.Mode.StickerEditorMode var fromCamera = false if let (file, emoji) = source as? (TelegramMediaFile, [String]) { subject = .single(.sticker(file, emoji)) @@ -2516,6 +2525,9 @@ public final class SharedAccountContextImpl: SharedAccountContext { subject = .single(.empty(PixelDimensions(width: 1080, height: 1920))) mode = .addingToPack } + if intro { + mode = .businessIntro + } let editorController = MediaEditorScreen( context: context, mode: .stickerEditor(mode: mode), diff --git a/submodules/TelegramUI/Sources/TextLinkHandling.swift b/submodules/TelegramUI/Sources/TextLinkHandling.swift index d5a30fff0e..3dbfd4f567 100644 --- a/submodules/TelegramUI/Sources/TextLinkHandling.swift +++ b/submodules/TelegramUI/Sources/TextLinkHandling.swift @@ -82,7 +82,7 @@ func handleTextLinkActionImpl(context: AccountContext, peerId: EnginePeer.Id?, n } case let .replyThread(messageId): if let navigationController = controller.navigationController as? NavigationController { - let _ = context.sharedContext.navigateToForumThread(context: context, peerId: messageId.peerId, threadId: Int64(messageId.id), messageId: nil, navigationController: navigationController, activateInput: nil, keepStack: .always).start() + let _ = context.sharedContext.navigateToForumThread(context: context, peerId: messageId.peerId, threadId: Int64(messageId.id), messageId: nil, navigationController: navigationController, activateInput: nil, scrollToEndIfExists: false, keepStack: .always).start() } case let .stickerPack(name, _): let packReference: StickerPackReference = .name(name) diff --git a/submodules/UrlHandling/Sources/UrlHandling.swift b/submodules/UrlHandling/Sources/UrlHandling.swift index e55b397eec..5b9c30e7d5 100644 --- a/submodules/UrlHandling/Sources/UrlHandling.swift +++ b/submodules/UrlHandling/Sources/UrlHandling.swift @@ -1204,7 +1204,11 @@ public func resolveUrlImpl(context: AccountContext, peerId: PeerId?, url: String var url = url let lowercasedUrl = url.lowercased() if (lowercasedUrl.hasPrefix(scheme) && (lowercasedUrl.hasSuffix(".\(basePath)") || lowercasedUrl.contains(".\(basePath)/") || lowercasedUrl.contains(".\(basePath)?"))) { - url = basePrefix + String(url[scheme.endIndex...]).replacingOccurrences(of: ".\(basePath)/", with: "").replacingOccurrences(of: ".\(basePath)", with: "") + let restUrl = String(url[scheme.endIndex...]) + if let slashRange = restUrl.range(of: "/"), let baseRange = restUrl.range(of: basePath), slashRange.lowerBound < baseRange.lowerBound { + } else { + url = basePrefix + restUrl.replacingOccurrences(of: ".\(basePath)/", with: "/").replacingOccurrences(of: ".\(basePath)", with: "") + } } if url.lowercased().hasPrefix(basePrefix) { if let internalUrl = parseInternalUrl(sharedContext: context.sharedContext, query: String(url[basePrefix.endIndex...])) {