diff --git a/submodules/ChatSendMessageActionUI/BUILD b/submodules/ChatSendMessageActionUI/BUILD index f031506ecc..51314b168b 100644 --- a/submodules/ChatSendMessageActionUI/BUILD +++ b/submodules/ChatSendMessageActionUI/BUILD @@ -20,6 +20,7 @@ swift_library( "//submodules/ContextUI:ContextUI", "//submodules/AppBundle:AppBundle", "//submodules/TextFormat:TextFormat", + "//submodules/TelegramUI/Components/EmojiTextAttachmentView:EmojiTextAttachmentView", ], visibility = [ "//visibility:public", diff --git a/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageActionSheetController.swift b/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageActionSheetController.swift index d191144be9..50a0b0858e 100644 --- a/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageActionSheetController.swift +++ b/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageActionSheetController.swift @@ -57,7 +57,9 @@ public final class ChatSendMessageActionSheetController: ViewController { |> deliverOnMainQueue).start(next: { [weak self] presentationData in if let strongSelf = self { strongSelf.presentationData = presentationData - strongSelf.controllerNode.updatePresentationData(presentationData) + if strongSelf.isNodeLoaded { + strongSelf.controllerNode.updatePresentationData(presentationData) + } } }) @@ -93,7 +95,7 @@ public final class ChatSendMessageActionSheetController: ViewController { hasEntityKeyboard = true } - self.displayNode = ChatSendMessageActionSheetControllerNode(context: self.context, presentationData: self.presentationData, reminders: reminders, gesture: gesture, sourceSendButton: self.sourceSendButton, textInputNode: self.textInputNode, attachment: self.attachment, forwardedCount: forwardedCount, hasEntityKeyboard: hasEntityKeyboard, send: { [weak self] in + self.displayNode = ChatSendMessageActionSheetControllerNode(context: self.context, presentationData: self.presentationData, reminders: reminders, gesture: gesture, sourceSendButton: self.sourceSendButton, textInputNode: self.textInputNode, attachment: self.attachment, forwardedCount: forwardedCount, hasEntityKeyboard: hasEntityKeyboard, emojiViewProvider: self.emojiViewProvider, send: { [weak self] in self?.sendMessage(false) self?.dismiss(cancel: false) }, sendSilently: { [weak self] in diff --git a/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageActionSheetControllerNode.swift b/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageActionSheetControllerNode.swift index 8d10ae6b7e..3164dcec7c 100644 --- a/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageActionSheetControllerNode.swift +++ b/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageActionSheetControllerNode.swift @@ -10,6 +10,7 @@ import AccountContext import AppBundle import ContextUI import TextFormat +import EmojiTextAttachmentView private let leftInset: CGFloat = 16.0 private let rightInset: CGFloat = 16.0 @@ -177,6 +178,9 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, private let toMessageTextNode: EditableTextNode private let scrollNode: ASScrollNode + private var fromCustomEmojiContainerView: CustomEmojiContainerView? + private var toCustomEmojiContainerView: CustomEmojiContainerView? + private var validLayout: ContainerViewLayout? private var sendButtonFrame: CGRect { @@ -185,7 +189,9 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, private var animateInputField = false - init(context: AccountContext, presentationData: PresentationData, reminders: Bool, gesture: ContextGesture, sourceSendButton: ASDisplayNode, textInputNode: EditableTextNode, attachment: Bool, forwardedCount: Int?, hasEntityKeyboard: Bool, send: (() -> Void)?, sendSilently: (() -> Void)?, schedule: (() -> Void)?, cancel: (() -> Void)?) { + private var emojiViewProvider: ((ChatTextInputTextCustomEmojiAttribute) -> UIView)? + + init(context: AccountContext, presentationData: PresentationData, reminders: Bool, gesture: ContextGesture, sourceSendButton: ASDisplayNode, textInputNode: EditableTextNode, attachment: Bool, forwardedCount: Int?, hasEntityKeyboard: Bool, emojiViewProvider: ((ChatTextInputTextCustomEmojiAttribute) -> UIView)?, send: (() -> Void)?, sendSilently: (() -> Void)?, schedule: (() -> Void)?, cancel: (() -> Void)?) { self.context = context self.presentationData = presentationData self.sourceSendButton = sourceSendButton @@ -194,6 +200,7 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, self.attachment = attachment self.forwardedCount = forwardedCount self.hasEntityKeyboard = hasEntityKeyboard + self.emojiViewProvider = emojiViewProvider self.send = send self.cancel = cancel @@ -351,6 +358,64 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, } } + func updateTextContents() { + var customEmojiRects: [(CGRect, ChatTextInputTextCustomEmojiAttribute)] = [] + + let textInputNode = self.fromMessageTextNode + if let attributedText = textInputNode.attributedText { + let beginning = textInputNode.textView.beginningOfDocument + attributedText.enumerateAttributes(in: NSMakeRange(0, attributedText.length), options: [], using: { attributes, range, _ in + if let value = attributes[ChatTextInputAttributes.customEmoji] as? ChatTextInputTextCustomEmojiAttribute { + if let start = textInputNode.textView.position(from: beginning, offset: range.location), let end = textInputNode.textView.position(from: start, offset: range.length), let textRange = textInputNode.textView.textRange(from: start, to: end) { + let textRects = textInputNode.textView.selectionRects(for: textRange) + for textRect in textRects { + customEmojiRects.append((textRect.rect, value)) + break + } + } + } + }) + } + + self.updateTextContents(rects: customEmojiRects, textInputNode: self.fromMessageTextNode, from: true) + self.updateTextContents(rects: customEmojiRects, textInputNode: self.toMessageTextNode, from: false) + } + + func updateTextContents(rects: [(CGRect, ChatTextInputTextCustomEmojiAttribute)], textInputNode: EditableTextNode, from: Bool) { + if !rects.isEmpty { + let customEmojiContainerView: CustomEmojiContainerView + if from, let current = self.fromCustomEmojiContainerView { + customEmojiContainerView = current + } else if !from, let current = self.toCustomEmojiContainerView { + customEmojiContainerView = current + } else { + customEmojiContainerView = CustomEmojiContainerView(emojiViewProvider: { [weak self] emoji in + guard let strongSelf = self, let emojiViewProvider = strongSelf.emojiViewProvider else { + return nil + } + return emojiViewProvider(emoji) + }) + customEmojiContainerView.isUserInteractionEnabled = false + textInputNode.textView.addSubview(customEmojiContainerView) + if from { + self.fromCustomEmojiContainerView = customEmojiContainerView + } else { + self.toCustomEmojiContainerView = customEmojiContainerView + } + } + + customEmojiContainerView.update(emojiRects: rects) + } else { + if from, let customEmojiContainerView = self.fromCustomEmojiContainerView { + customEmojiContainerView.removeFromSuperview() + self.fromCustomEmojiContainerView = nil + } else if !from, let customEmojiContainerView = self.toCustomEmojiContainerView { + customEmojiContainerView.removeFromSuperview() + self.fromCustomEmojiContainerView = nil + } + } + } + func updatePresentationData(_ presentationData: PresentationData) { guard presentationData.theme !== self.presentationData.theme else { return @@ -459,6 +524,10 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, let springDamping: CGFloat = 104.0 self.contentContainerNode.layer.animateSpring(from: 0.1 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: springDuration, initialVelocity: 0.0, damping: springDamping) self.contentContainerNode.layer.animateSpring(from: NSValue(cgPoint: contentOffset), to: NSValue(cgPoint: CGPoint()), keyPath: "position", duration: springDuration, initialVelocity: 0.0, damping: springDamping, additive: true) + + Queue.mainQueue().after(0.01, { + self.updateTextContents() + }) } func animateOut(cancel: Bool, completion: @escaping () -> Void) { @@ -692,3 +761,64 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, self.send?() } } + +final class CustomEmojiContainerView: UIView { + private let emojiViewProvider: (ChatTextInputTextCustomEmojiAttribute) -> UIView? + + private var emojiLayers: [InlineStickerItemLayer.Key: UIView] = [:] + + init(emojiViewProvider: @escaping (ChatTextInputTextCustomEmojiAttribute) -> UIView?) { + self.emojiViewProvider = emojiViewProvider + + super.init(frame: CGRect()) + } + + required init(coder: NSCoder) { + preconditionFailure() + } + + func update(emojiRects: [(CGRect, ChatTextInputTextCustomEmojiAttribute)]) { + var nextIndexById: [Int64: Int] = [:] + + var validKeys = Set() + for (rect, emoji) in emojiRects { + let index: Int + if let nextIndex = nextIndexById[emoji.fileId] { + index = nextIndex + } else { + index = 0 + } + nextIndexById[emoji.fileId] = index + 1 + + let key = InlineStickerItemLayer.Key(id: emoji.fileId, index: index) + + let view: UIView + if let current = self.emojiLayers[key] { + view = current + } else if let newView = self.emojiViewProvider(emoji) { + view = newView + self.addSubview(newView) + self.emojiLayers[key] = view + } else { + continue + } + + let size = CGSize(width: 24.0, height: 24.0) + + view.frame = CGRect(origin: CGPoint(x: floor(rect.midX - size.width / 2.0), y: floor(rect.midY - size.height / 2.0)), size: size) + + validKeys.insert(key) + } + + var removeKeys: [InlineStickerItemLayer.Key] = [] + for (key, view) in self.emojiLayers { + if !validKeys.contains(key) { + removeKeys.append(key) + view.removeFromSuperview() + } + } + for key in removeKeys { + self.emojiLayers.removeValue(forKey: key) + } + } +} diff --git a/submodules/Display/Source/GridNode.swift b/submodules/Display/Source/GridNode.swift index 6b833112c1..eef5d88868 100644 --- a/submodules/Display/Source/GridNode.swift +++ b/submodules/Display/Source/GridNode.swift @@ -552,9 +552,9 @@ open class GridNode: GridNodeScroller, UIScrollViewDelegate { } itemSize.height = height } else if let fillsRowWithDynamicHeight = item.fillsRowWithDynamicHeight { - let height = fillsRowWithDynamicHeight(gridLayout.size.width) + let height = fillsRowWithDynamicHeight(gridLayout.size.width - itemInsets.left - itemInsets.right) nextItemOrigin.x = initialSpacing + itemInsets.left - itemSize.width = gridLayout.size.width + itemSize.width = gridLayout.size.width - itemInsets.left - itemInsets.right itemSize.height = height } else if index == 0 { let itemsInRow = max(1, Int(effectiveWidth) / Int(itemSize.width)) diff --git a/submodules/Display/Source/HapticFeedback.swift b/submodules/Display/Source/HapticFeedback.swift index bad8b9c59b..a0a714adaf 100644 --- a/submodules/Display/Source/HapticFeedback.swift +++ b/submodules/Display/Source/HapticFeedback.swift @@ -122,11 +122,12 @@ private final class HapticFeedbackImpl { } func warning() { - if let notificationGenerator = self.notificationGenerator { - notificationGenerator.notificationOccurred(.warning) - } else { - - } + AudioServicesPlaySystemSound(1102) +// if let notificationGenerator = self.notificationGenerator { +// notificationGenerator.notificationOccurred(.warning) +// } else { +// +// } } @objc dynamic func f() { diff --git a/submodules/ItemListUI/Sources/Items/ItemListDisclosureItem.swift b/submodules/ItemListUI/Sources/Items/ItemListDisclosureItem.swift index b233875508..30ba660d9b 100644 --- a/submodules/ItemListUI/Sources/Items/ItemListDisclosureItem.swift +++ b/submodules/ItemListUI/Sources/Items/ItemListDisclosureItem.swift @@ -20,7 +20,7 @@ public enum ItemListDisclosureLabelStyle { case text case detailText case coloredText(UIColor) -// case textWithIcon(UIColor) + case textWithIcon(UIImage) case multilineDetailText case badge(UIColor) case color(UIColor) @@ -236,7 +236,9 @@ public class ItemListDisclosureItemNode: ListViewItemNode, ItemListItemNode { updatedLabelImage = generateFilledCircleImage(diameter: 17.0, color: color) } } - if case let .image(image, _) = item.labelStyle { + if case let .textWithIcon(image) = item.labelStyle { + updatedLabelImage = generateTintedImage(image: image, color: item.presentationData.theme.list.itemSecondaryTextColor) + } else if case let .image(image, _) = item.labelStyle { updatedLabelImage = image } @@ -474,7 +476,18 @@ public class ItemListDisclosureItemNode: ListViewItemNode, ItemListItemNode { } strongSelf.labelNode.frame = labelFrame - if case let .image(_, size) = item.labelStyle { + if case .textWithIcon = item.labelStyle { + if let updatedLabelImage = updatedLabelImage { + strongSelf.labelImageNode.image = updatedLabelImage + } + if strongSelf.labelImageNode.supernode == nil { + strongSelf.addSubnode(strongSelf.labelImageNode) + } + + if let size = strongSelf.labelImageNode.image?.size { + strongSelf.labelImageNode.frame = CGRect(origin: CGPoint(x: labelFrame.minX - size.width - 5.0, y: floor((layout.contentSize.height - size.height) / 2.0) - 1.0), size: size) + } + } else if case let .image(_, size) = item.labelStyle { if let updatedLabelImage = updatedLabelImage { strongSelf.labelImageNode.image = updatedLabelImage } diff --git a/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift b/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift index a20f4fe1d8..95bf79323e 100644 --- a/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift +++ b/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift @@ -83,7 +83,7 @@ private enum PrivacyAndSecurityEntry: ItemListNodeEntry { case voiceCallPrivacy(PresentationTheme, String, String) case forwardPrivacy(PresentationTheme, String, String) case groupPrivacy(PresentationTheme, String, String) - case voiceMessagePrivacy(PresentationTheme, String, String) + case voiceMessagePrivacy(PresentationTheme, String, String, Bool) case selectivePrivacyInfo(PresentationTheme, String) case passcode(PresentationTheme, String, Bool, String) case twoStepVerification(PresentationTheme, String, String, TwoStepVerificationAccessConfiguration?) @@ -209,8 +209,8 @@ private enum PrivacyAndSecurityEntry: ItemListNodeEntry { } else { return false } - case let .voiceMessagePrivacy(lhsTheme, lhsText, lhsValue): - if case let .voiceMessagePrivacy(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue { + case let .voiceMessagePrivacy(lhsTheme, lhsText, lhsValue, lhsLocked): + if case let .voiceMessagePrivacy(rhsTheme, rhsText, rhsValue, rhsLocked) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue, lhsLocked == rhsLocked { return true } else { return false @@ -300,7 +300,7 @@ private enum PrivacyAndSecurityEntry: ItemListNodeEntry { case let .privacyHeader(_, text): return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section) case let .blockedPeers(_, text, value): - return ItemListDisclosureItem(presentationData: presentationData, icon: UIImage(bundleImageName: "Settings/Menu/Blocked")?.precomposed(), title: text, label: value, sectionId: self.section, style: .blocks, action: { + return ItemListDisclosureItem(presentationData: presentationData, icon: UIImage(bundleImageName: "Chat/Stickers/Blocked")?.precomposed(), title: text, label: value, sectionId: self.section, style: .blocks, action: { arguments.openBlockedUsers() }) case let .phoneNumberPrivacy(_, text, value): @@ -323,8 +323,8 @@ private enum PrivacyAndSecurityEntry: ItemListNodeEntry { return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, action: { arguments.openGroupsPrivacy() }) - case let .voiceMessagePrivacy(_, text, value): - return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, action: { + case let .voiceMessagePrivacy(_, text, value, locked): + return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, labelStyle: locked ? .textWithIcon(UIImage(bundleImageName: "Notification/SecretLock")!.precomposed()) : .text, sectionId: self.section, style: .blocks, action: { arguments.openVoiceMessagePrivacy() }) case let .selectivePrivacyInfo(_, text): @@ -411,7 +411,7 @@ private func stringForSelectiveSettings(strings: PresentationStrings, settings: } } -private func privacyAndSecurityControllerEntries(presentationData: PresentationData, state: PrivacyAndSecurityControllerState, privacySettings: AccountPrivacySettings?, accessChallengeData: PostboxAccessChallengeData, blockedPeerCount: Int?, activeWebsitesCount: Int, hasTwoStepAuth: Bool?, twoStepAuthData: TwoStepVerificationAccessConfiguration?, canAutoarchive: Bool) -> [PrivacyAndSecurityEntry] { +private func privacyAndSecurityControllerEntries(presentationData: PresentationData, state: PrivacyAndSecurityControllerState, privacySettings: AccountPrivacySettings?, accessChallengeData: PostboxAccessChallengeData, blockedPeerCount: Int?, activeWebsitesCount: Int, hasTwoStepAuth: Bool?, twoStepAuthData: TwoStepVerificationAccessConfiguration?, canAutoarchive: Bool, isPremium: Bool) -> [PrivacyAndSecurityEntry] { var entries: [PrivacyAndSecurityEntry] = [] entries.append(.blockedPeers(presentationData.theme, presentationData.strings.Settings_BlockedUsers, blockedPeerCount == nil ? "" : (blockedPeerCount == 0 ? presentationData.strings.PrivacySettings_BlockedPeersEmpty : "\(blockedPeerCount!)"))) @@ -449,7 +449,7 @@ private func privacyAndSecurityControllerEntries(presentationData: PresentationD entries.append(.lastSeenPrivacy(presentationData.theme, presentationData.strings.PrivacySettings_LastSeen, stringForSelectiveSettings(strings: presentationData.strings, settings: privacySettings.presence))) entries.append(.profilePhotoPrivacy(presentationData.theme, presentationData.strings.Privacy_ProfilePhoto, stringForSelectiveSettings(strings: presentationData.strings, settings: privacySettings.profilePhoto))) entries.append(.voiceCallPrivacy(presentationData.theme, presentationData.strings.Privacy_Calls, stringForSelectiveSettings(strings: presentationData.strings, settings: privacySettings.voiceCalls))) - entries.append(.voiceMessagePrivacy(presentationData.theme, presentationData.strings.Privacy_VoiceMessages, stringForSelectiveSettings(strings: presentationData.strings, settings: privacySettings.voiceMessages))) + entries.append(.voiceMessagePrivacy(presentationData.theme, presentationData.strings.Privacy_VoiceMessages, stringForSelectiveSettings(strings: presentationData.strings, settings: privacySettings.voiceMessages), !isPremium)) entries.append(.forwardPrivacy(presentationData.theme, presentationData.strings.Privacy_Forwards, stringForSelectiveSettings(strings: presentationData.strings, settings: privacySettings.forwards))) entries.append(.groupPrivacy(presentationData.theme, presentationData.strings.Privacy_GroupsAndChannels, stringForSelectiveSettings(strings: presentationData.strings, settings: privacySettings.groupInvitations))) @@ -458,7 +458,7 @@ private func privacyAndSecurityControllerEntries(presentationData: PresentationD entries.append(.lastSeenPrivacy(presentationData.theme, presentationData.strings.PrivacySettings_LastSeen, presentationData.strings.Channel_NotificationLoading)) entries.append(.profilePhotoPrivacy(presentationData.theme, presentationData.strings.Privacy_ProfilePhoto, presentationData.strings.Channel_NotificationLoading)) entries.append(.voiceCallPrivacy(presentationData.theme, presentationData.strings.Privacy_Calls, presentationData.strings.Channel_NotificationLoading)) - entries.append(.voiceMessagePrivacy(presentationData.theme, presentationData.strings.Privacy_VoiceMessages, presentationData.strings.Channel_NotificationLoading)) + entries.append(.voiceMessagePrivacy(presentationData.theme, presentationData.strings.Privacy_VoiceMessages, presentationData.strings.Channel_NotificationLoading, !isPremium)) entries.append(.forwardPrivacy(presentationData.theme, presentationData.strings.Privacy_Forwards, presentationData.strings.Channel_NotificationLoading)) entries.append(.groupPrivacy(presentationData.theme, presentationData.strings.Privacy_GroupsAndChannels, presentationData.strings.Channel_NotificationLoading)) entries.append(.selectivePrivacyInfo(presentationData.theme, presentationData.strings.PrivacyLastSeenSettings_GroupsAndChannelsHelp)) @@ -944,9 +944,10 @@ public func privacyAndSecurityController(context: AccountContext, initialSetting webSessionsContext.state, context.sharedContext.accountManager.accessChallengeData(), combineLatest(twoStepAuth.get(), twoStepAuthDataValue.get()), - context.engine.data.subscribe(TelegramEngine.EngineData.Item.Configuration.App()) + context.engine.data.subscribe(TelegramEngine.EngineData.Item.Configuration.App()), + context.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId)) ) - |> map { presentationData, state, privacySettings, noticeView, sharedData, recentPeers, blockedPeersState, activeWebsitesState, accessChallengeData, twoStepAuth, appConfiguration -> (ItemListControllerState, (ItemListNodeState, Any)) in + |> map { presentationData, state, privacySettings, noticeView, sharedData, recentPeers, blockedPeersState, activeWebsitesState, accessChallengeData, twoStepAuth, appConfiguration, accountPeer -> (ItemListControllerState, (ItemListNodeState, Any)) in var canAutoarchive = false if let data = appConfiguration.data, let hasAutoarchive = data["autoarchive_setting_available"] as? Bool { canAutoarchive = hasAutoarchive @@ -959,7 +960,9 @@ public func privacyAndSecurityController(context: AccountContext, initialSetting let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.PrivacySettings_Title), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false) - let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: privacyAndSecurityControllerEntries(presentationData: presentationData, state: state, privacySettings: privacySettings, accessChallengeData: accessChallengeData.data, blockedPeerCount: blockedPeersState.totalCount, activeWebsitesCount: activeWebsitesState.sessions.count, hasTwoStepAuth: twoStepAuth.0, twoStepAuthData: twoStepAuth.1, canAutoarchive: canAutoarchive), style: .blocks, ensureVisibleItemTag: focusOnItemTag, animateChanges: false) + let isPremium = accountPeer?.isPremium ?? false + + let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: privacyAndSecurityControllerEntries(presentationData: presentationData, state: state, privacySettings: privacySettings, accessChallengeData: accessChallengeData.data, blockedPeerCount: blockedPeersState.totalCount, activeWebsitesCount: activeWebsitesState.sessions.count, hasTwoStepAuth: twoStepAuth.0, twoStepAuthData: twoStepAuth.1, canAutoarchive: canAutoarchive, isPremium: isPremium), style: .blocks, ensureVisibleItemTag: focusOnItemTag, animateChanges: false) return (controllerState, (listState, arguments)) } diff --git a/submodules/StickerPackPreviewUI/Sources/StickerPackEmojisItem.swift b/submodules/StickerPackPreviewUI/Sources/StickerPackEmojisItem.swift index 41773c8e84..b43be1d5c7 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPackEmojisItem.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPackEmojisItem.swift @@ -103,16 +103,14 @@ final class StickerPackEmojisItem: GridItem { func node(layout: GridNodeLayout, synchronousLoad: Bool) -> GridItemNode { let node = StickerPackEmojisItemNode() - node.setup(item: self) return node } func update(node: GridItemNode) { - guard let node = node as? StickerPackEmojisItemNode else { + guard let _ = node as? StickerPackEmojisItemNode else { assertionFailure() return } - node.setup(item: self) } } @@ -173,7 +171,7 @@ final class StickerPackEmojisItemNode: GridItemNode { let shimmerHostView = PortalSourceView() shimmerHostView.alpha = 0.0 - shimmerHostView.frame = CGRect(origin: CGPoint(), size: self.frame.size) + shimmerHostView.frame = CGRect(origin: CGPoint(), size: self.size) self.view.addSubview(shimmerHostView) self.shimmerHostView = shimmerHostView @@ -194,10 +192,14 @@ final class StickerPackEmojisItemNode: GridItemNode { } self.boundsChangeTrackerLayer = boundsChangeTrackerLayer } - - private var setupTimestamp: Double? - func setup(item: StickerPackEmojisItem) { + + private var size = CGSize() + override func updateLayout(item: GridItem, size: CGSize, isVisible: Bool, synchronousLoads: Bool) { + guard let item = item as? StickerPackEmojisItem else { + return + } self.item = item + self.size = size if let title = item.title { let isInstalled = item.isInstalled ?? false @@ -217,9 +219,9 @@ final class StickerPackEmojisItemNode: GridItemNode { self.setNeedsLayout() } - + func updateVisibleItems(attemptSynchronousLoads: Bool, transition: ContainedViewLayoutTransition) { - guard let item = self.item, !self.frame.width.isZero else { + guard let item = self.item, !self.size.width.isZero else { return } @@ -231,10 +233,10 @@ final class StickerPackEmojisItemNode: GridItemNode { var validIds = Set() let itemLayout: ItemLayout - if let current = self.itemLayout, current.width == self.frame.width && current.itemsCount == items.count && current.hasTitle == (item.title != nil) { + if let current = self.itemLayout, current.width == self.size.width && current.itemsCount == items.count && current.hasTitle == (item.title != nil) { itemLayout = current } else { - itemLayout = ItemLayout(width: self.frame.width, itemsCount: items.count, hasTitle: item.title != nil) + itemLayout = ItemLayout(width: self.size.width, itemsCount: items.count, hasTitle: item.title != nil) self.itemLayout = itemLayout } @@ -368,20 +370,20 @@ final class StickerPackEmojisItemNode: GridItemNode { super.layout() if let _ = self.item { - var buttonSize = self.buttonNode.calculateSizeThatFits(self.frame.size) + var buttonSize = self.buttonNode.calculateSizeThatFits(self.size) buttonSize.width += 24.0 buttonSize.height = 28.0 - let titleSize = self.titleNode.updateLayout(CGSize(width: self.frame.width - 60.0, height: self.frame.height)) - let subtitleSize = self.subtitleNode.updateLayout(CGSize(width: self.frame.width - 60.0, height: self.frame.height)) + let titleSize = self.titleNode.updateLayout(CGSize(width: self.size.width - 60.0, height: self.size.height)) + let subtitleSize = self.subtitleNode.updateLayout(CGSize(width: self.size.width - 60.0, height: self.size.height)) self.titleNode.frame = CGRect(origin: CGPoint(x: 16.0, y: 10.0), size: titleSize) self.subtitleNode.frame = CGRect(origin: CGPoint(x: 16.0, y: 33.0), size: subtitleSize) - self.buttonNode.frame = CGRect(origin: CGPoint(x: self.frame.width - buttonSize.width - 16.0, y: 17.0), size: buttonSize) + self.buttonNode.frame = CGRect(origin: CGPoint(x: self.size.width - buttonSize.width - 16.0, y: 17.0), size: buttonSize) } - self.shimmerHostView?.frame = CGRect(origin: CGPoint(), size: self.frame.size) + self.shimmerHostView?.frame = CGRect(origin: CGPoint(), size: self.size) self.updateVisibleItems(attemptSynchronousLoads: false, transition: .immediate) } diff --git a/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift b/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift index 1401791f68..ef35698c49 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift @@ -911,14 +911,6 @@ private final class StickerPackContainer: ASDisplayNode { } if updateLayout, let (layout, _, _, _) = self.validLayout { - let cancelSize = self.cancelButtonNode.measure(CGSize(width: layout.size.width, height: .greatestFiniteMagnitude)) - self.cancelButtonNode.frame = CGRect(origin: CGPoint(x: layout.safeInsets.left + 16.0, y: 18.0), size: cancelSize) - - let titleSize = self.titleNode.updateLayout(CGSize(width: layout.size.width - cancelSize.width * 2.0 - 40.0, height: .greatestFiniteMagnitude)) - self.titleNode.frame = CGRect(origin: CGPoint(x: floor((-titleSize.width) / 2.0), y: floor((-titleSize.height) / 2.0)), size: titleSize) - - self.moreButtonNode.frame = CGRect(origin: CGPoint(x: layout.size.width - layout.safeInsets.right - 46.0, y: 5.0), size: CGSize(width: 44.0, height: 44.0)) - self.updateLayout(layout: layout, transition: .immediate) } @@ -1050,6 +1042,14 @@ private final class StickerPackContainer: ASDisplayNode { titlePlaceholderNode.updateAbsoluteRect(titlePlaceholderNode.frame.offsetBy(dx: self.titleContainer.frame.minX, dy: self.titleContainer.frame.minY - gridInsets.top - gridFrame.minY), within: gridFrame.size) } + let cancelSize = self.cancelButtonNode.measure(CGSize(width: layout.size.width, height: .greatestFiniteMagnitude)) + self.cancelButtonNode.frame = CGRect(origin: CGPoint(x: layout.safeInsets.left + 16.0, y: 18.0), size: cancelSize) + + let titleSize = self.titleNode.updateLayout(CGSize(width: layout.size.width - cancelSize.width * 2.0 - 40.0, height: .greatestFiniteMagnitude)) + self.titleNode.frame = CGRect(origin: CGPoint(x: floor((-titleSize.width) / 2.0), y: floor((-titleSize.height) / 2.0)), size: titleSize) + + self.moreButtonNode.frame = CGRect(origin: CGPoint(x: layout.size.width - layout.safeInsets.right - 46.0, y: 5.0), size: CGSize(width: 44.0, height: 44.0)) + if firstTime { while !self.enqueuedTransactions.isEmpty { self.dequeueTransaction() diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index 7f5f65bc9d..07e99c1e64 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -3617,7 +3617,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G }, didDismiss: { [weak self] in if let strongSelf = self { let isFocused = strongSelf.chatDisplayNode.textInputPanelNode?.isFocused ?? false - strongSelf.chatDisplayNode.insertSubnode(strongSelf.chatDisplayNode.inputPanelContainerNode, aboveSubnode: strongSelf.chatDisplayNode.historyNodeContainer) + strongSelf.chatDisplayNode.insertSubnode(strongSelf.chatDisplayNode.inputPanelContainerNode, aboveSubnode: strongSelf.chatDisplayNode.inputContextPanelContainer) if isFocused { strongSelf.chatDisplayNode.textInputPanelNode?.ensureFocused() } diff --git a/submodules/TelegramUI/Sources/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index d9ff15c6ca..cb2dbacdf5 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -125,7 +125,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { private var secondaryInputPanelNode: ChatInputPanelNode? private(set) var accessoryPanelNode: AccessoryPanelNode? private var inputContextPanelNode: ChatInputContextPanelNode? - private let inputContextPanelContainer: ChatControllerTitlePanelNodeContainer + let inputContextPanelContainer: ChatControllerTitlePanelNodeContainer private let inputContextOverTextPanelContainer: ChatControllerTitlePanelNodeContainer private var overlayContextPanelNode: ChatInputContextPanelNode? diff --git a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift index a55fcff8de..9a16ad296c 100644 --- a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift @@ -1055,7 +1055,14 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { } if isPremiumLocked { - let controller = PremiumIntroScreen(context: context, source: .stickers) + var replaceImpl: ((ViewController) -> Void)? + let controller = PremiumDemoScreen(context: context, subject: .animatedEmoji, action: { + let controller = PremiumIntroScreen(context: context, source: .animatedEmoji) + replaceImpl?(controller) + }) + replaceImpl = { [weak controller] c in + controller?.replace(with: c) + } controllerInteraction.navigationController()?.pushViewController(controller) return diff --git a/submodules/WebUI/Sources/WebAppController.swift b/submodules/WebUI/Sources/WebAppController.swift index 1e74242bed..e939b3a9d5 100644 --- a/submodules/WebUI/Sources/WebAppController.swift +++ b/submodules/WebUI/Sources/WebAppController.swift @@ -800,39 +800,40 @@ public final class WebAppController: ViewController, AttachmentContainable { self.needDismissConfirmation = needConfirmation } case "web_app_request_phone": - let _ = (self.context.account.postbox.loadedPeerWithId(self.context.account.peerId) - |> deliverOnMainQueue).start(next: { [weak self] accountPeer in - guard let strongSelf = self else { - return - } - guard let user = accountPeer as? TelegramUser, let phoneNumber = user.phone else { - return - } - - let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData) - var items: [ActionSheetItem] = [] - items.append(ActionSheetTextItem(title: strongSelf.presentationData.strings.WebApp_ShareMyPhoneNumberConfirmation(formatPhoneNumber(phoneNumber), strongSelf.controller?.botName ?? "").string, parseMarkdown: true)) - items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.WebApp_ShareMyPhoneNumber, action: { [weak actionSheet] in - actionSheet?.dismissAnimated() - guard let strongSelf = self else { - return - } - - strongSelf.sendPhoneRequestedEvent(phone: phoneNumber) - })) - - actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [ - ActionSheetButtonItem(title: strongSelf.presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in - actionSheet?.dismissAnimated() - guard let strongSelf = self else { - return - } - - strongSelf.sendPhoneRequestedEvent(phone: nil) - }) - ])]) - strongSelf.controller?.present(actionSheet, in: .window(.root)) - }) + break +// let _ = (self.context.account.postbox.loadedPeerWithId(self.context.account.peerId) +// |> deliverOnMainQueue).start(next: { [weak self] accountPeer in +// guard let strongSelf = self else { +// return +// } +// guard let user = accountPeer as? TelegramUser, let phoneNumber = user.phone else { +// return +// } +// +// let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData) +// var items: [ActionSheetItem] = [] +// items.append(ActionSheetTextItem(title: strongSelf.presentationData.strings.WebApp_ShareMyPhoneNumberConfirmation(formatPhoneNumber(phoneNumber), strongSelf.controller?.botName ?? "").string, parseMarkdown: true)) +// items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.WebApp_ShareMyPhoneNumber, action: { [weak actionSheet] in +// actionSheet?.dismissAnimated() +// guard let strongSelf = self else { +// return +// } +// +// strongSelf.sendPhoneRequestedEvent(phone: phoneNumber) +// })) +// +// actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [ +// ActionSheetButtonItem(title: strongSelf.presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in +// actionSheet?.dismissAnimated() +// guard let strongSelf = self else { +// return +// } +// +// strongSelf.sendPhoneRequestedEvent(phone: nil) +// }) +// ])]) +// strongSelf.controller?.present(actionSheet, in: .window(.root)) +// }) default: break }