diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 93ac3ed360..ff971f1ef1 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -8079,3 +8079,4 @@ Sorry for the inconvenience."; "PeerInfo.LabelAllReactions" = "All Reactions"; +"TextFormat.Format" = "Format"; diff --git a/submodules/AsyncDisplayKit/Source/ASEditableTextNode.mm b/submodules/AsyncDisplayKit/Source/ASEditableTextNode.mm index b9a977c80e..9dbdff9cee 100644 --- a/submodules/AsyncDisplayKit/Source/ASEditableTextNode.mm +++ b/submodules/AsyncDisplayKit/Source/ASEditableTextNode.mm @@ -1203,4 +1203,12 @@ return 0; } +- (UIMenu *)textView:(UITextView *)textView editMenuForTextInRange:(NSRange)range suggestedActions:(NSArray *)suggestedActions API_AVAILABLE(ios(16.0)) { + if ([_delegate respondsToSelector:@selector(editableTextNodeMenu:forTextRange:suggestedActions:)]) { + return [_delegate editableTextNodeMenu:self forTextRange:range suggestedActions:suggestedActions]; + } else { + return [UIMenu menuWithChildren:suggestedActions]; + } +} + @end diff --git a/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASEditableTextNode.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASEditableTextNode.h index b30969e3f1..3dd542d7af 100644 --- a/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASEditableTextNode.h +++ b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASEditableTextNode.h @@ -221,6 +221,9 @@ NS_ASSUME_NONNULL_BEGIN - (BOOL)editableTextNodeShouldReturn:(ASEditableTextNode *)editableTextNode; - (void)editableTextNodeBackspaceWhileEmpty:(ASEditableTextNode *)editableTextNode; + +- (UIMenu *)editableTextNodeMenu:(ASEditableTextNode *)editableTextNode forTextRange:(NSRange)textRange suggestedActions:(NSArray *)suggestedActions API_AVAILABLE(ios(16.0)); + @end NS_ASSUME_NONNULL_END diff --git a/submodules/AttachmentTextInputPanelNode/Sources/AttachmentTextInputPanelNode.swift b/submodules/AttachmentTextInputPanelNode/Sources/AttachmentTextInputPanelNode.swift index 23beb07c7a..8b3028fd82 100644 --- a/submodules/AttachmentTextInputPanelNode/Sources/AttachmentTextInputPanelNode.swift +++ b/submodules/AttachmentTextInputPanelNode/Sources/AttachmentTextInputPanelNode.swift @@ -1422,13 +1422,17 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS else if action == makeSelectorFromString("_accessibilitySpeakLanguageSelection:") || action == makeSelectorFromString("_accessibilityPauseSpeaking:") || action == makeSelectorFromString("_accessibilitySpeakSentence:") { return ASEditableTextNodeTargetForAction(target: nil) } else if action == makeSelectorFromString("_showTextStyleOptions:") { - if case .general = self.inputMenu.state { - if let textInputNode = self.textInputNode, textInputNode.attributedText == nil || textInputNode.attributedText!.length == 0 || textInputNode.selectedRange.length == 0 { + if #available(iOS 16.0, *) { + return ASEditableTextNodeTargetForAction(target: nil) + } else { + if case .general = self.inputMenu.state { + if let textInputNode = self.textInputNode, textInputNode.attributedText == nil || textInputNode.attributedText!.length == 0 || textInputNode.selectedRange.length == 0 { + return ASEditableTextNodeTargetForAction(target: nil) + } + return ASEditableTextNodeTargetForAction(target: self) + } else { return ASEditableTextNodeTargetForAction(target: nil) } - return ASEditableTextNodeTargetForAction(target: self) - } else { - return ASEditableTextNodeTargetForAction(target: nil) } } else if action == #selector(self.formatAttributesBold(_:)) || action == #selector(self.formatAttributesItalic(_:)) || action == #selector(self.formatAttributesMonospace(_:)) || action == #selector(self.formatAttributesLink(_:)) || action == #selector(self.formatAttributesStrikethrough(_:)) || action == #selector(self.formatAttributesUnderline(_:)) || action == #selector(self.formatAttributesSpoiler(_:)) { if case .format = self.inputMenu.state { @@ -1443,6 +1447,65 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS return nil } + @available(iOS 16.0, *) + public func editableTextNodeMenu(_ editableTextNode: ASEditableTextNode, forTextRange textRange: NSRange, suggestedActions: [UIMenuElement]) -> UIMenu { + var actions = suggestedActions + + if editableTextNode.attributedText == nil || editableTextNode.attributedText!.length == 0 || editableTextNode.selectedRange.length == 0 { + + } else { + var children: [UIAction] = [ + UIAction(title: self.strings?.TextFormat_Bold ?? "Bold", image: nil) { [weak self] (action) in + if let strongSelf = self { + strongSelf.formatAttributesBold(strongSelf) + } + }, + UIAction(title: self.strings?.TextFormat_Italic ?? "Italic", image: nil) { [weak self] (action) in + if let strongSelf = self { + strongSelf.formatAttributesItalic(strongSelf) + } + }, + UIAction(title: self.strings?.TextFormat_Monospace ?? "Monospace", image: nil) { [weak self] (action) in + if let strongSelf = self { + strongSelf.formatAttributesMonospace(strongSelf) + } + }, + UIAction(title: self.strings?.TextFormat_Link ?? "Link", image: nil) { [weak self] (action) in + if let strongSelf = self { + strongSelf.formatAttributesLink(strongSelf) + } + }, + UIAction(title: self.strings?.TextFormat_Strikethrough ?? "Strikethrough", image: nil) { [weak self] (action) in + if let strongSelf = self { + strongSelf.formatAttributesStrikethrough(strongSelf) + } + }, + UIAction(title: self.strings?.TextFormat_Underline ?? "Underline", image: nil) { [weak self] (action) in + if let strongSelf = self { + strongSelf.formatAttributesUnderline(strongSelf) + } + } + ] + + var hasSpoilers = true + if self.presentationInterfaceState?.chatLocation.peerId?.namespace == Namespaces.Peer.SecretChat { + hasSpoilers = false + } + + if hasSpoilers { + children.append(UIAction(title: self.strings?.TextFormat_Spoiler ?? "Spoiler", image: nil) { [weak self] (action) in + if let strongSelf = self { + strongSelf.formatAttributesSpoiler(strongSelf) + } + }) + } + + let formatMenu = UIMenu(title: self.strings?.TextFormat_Format ?? "Format", image: nil, children: children) + actions.insert(formatMenu, at: 3) + } + return UIMenu(children: actions) + } + @objc func _accessibilitySpeak(_ sender: Any) { var text = "" self.interfaceInteraction?.updateTextInputStateAndMode { current, inputMode in diff --git a/submodules/AuthorizationUI/Sources/AuthorizationSequenceController.swift b/submodules/AuthorizationUI/Sources/AuthorizationSequenceController.swift index e11f73e1cb..aba53912c3 100644 --- a/submodules/AuthorizationUI/Sources/AuthorizationSequenceController.swift +++ b/submodules/AuthorizationUI/Sources/AuthorizationSequenceController.swift @@ -155,8 +155,8 @@ public final class AuthorizationSequenceController: NavigationController, MFMail let _ = TelegramEngineUnauthorized(account: strongSelf.account).auth.setState(state: UnauthorizedAccountState(isTestingEnvironment: strongSelf.account.testingEnvironment, masterDatacenterId: strongSelf.account.masterDatacenterId, contents: .empty)).start() } }) - if let splahController = splashController { - controller.animateWithSplashController(splahController) + if let splashController = splashController { + controller.animateWithSplashController(splashController) } controller.accountUpdated = { [weak self] updatedAccount in guard let strongSelf = self else { @@ -1033,6 +1033,11 @@ public final class AuthorizationSequenceController: NavigationController, MFMail break } } + + if let validLayout = self.validLayout, case .tablet = validLayout.deviceMetrics.type { + previousSplashController = nil + } + controllers.append(self.phoneEntryController(countryCode: countryCode, number: number, splashController: previousSplashController)) self.setViewControllers(controllers, animated: !self.viewControllers.isEmpty && (previousSplashController == nil || self.viewControllers.count > 2)) case let .confirmationCodeEntry(number, type, _, timeout, nextType, _): diff --git a/submodules/AuthorizationUI/Sources/AuthorizationSequencePhoneEntryControllerNode.swift b/submodules/AuthorizationUI/Sources/AuthorizationSequencePhoneEntryControllerNode.swift index 61253ca197..1f0358fdf0 100644 --- a/submodules/AuthorizationUI/Sources/AuthorizationSequencePhoneEntryControllerNode.swift +++ b/submodules/AuthorizationUI/Sources/AuthorizationSequencePhoneEntryControllerNode.swift @@ -426,7 +426,7 @@ final class AuthorizationSequencePhoneEntryControllerNode: ASDisplayNode { } self.animationNode.completed = { [weak self] _ in - self?.animationNode.isHidden = true + self?.animationNode.removeFromSupernode() self?.managedAnimationNode.isHidden = false } } diff --git a/submodules/ChatListUI/Sources/Node/ChatListItem.swift b/submodules/ChatListUI/Sources/Node/ChatListItem.swift index 4bd2b35f9e..3cd9dd81a6 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListItem.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListItem.swift @@ -1741,7 +1741,6 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { if let _ = updatedTheme { strongSelf.separatorNode.backgroundColor = item.presentationData.theme.chatList.itemSeparatorColor - strongSelf.highlightedBackgroundNode.backgroundColor = item.presentationData.theme.chatList.itemHighlightedBackgroundColor } let revealOffset = strongSelf.revealOffset @@ -2115,22 +2114,28 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { transition.updateFrame(node: strongSelf.backgroundNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: layout.contentSize.width, height: itemHeight))) let backgroundColor: UIColor + let highlightedBackgroundColor: UIColor if item.selected { backgroundColor = theme.itemSelectedBackgroundColor + highlightedBackgroundColor = theme.itemHighlightedBackgroundColor } else if item.index.pinningIndex != nil { if case let .groupReference(_, _, _, _, hiddenByDefault) = item.content, hiddenByDefault { backgroundColor = theme.itemBackgroundColor + highlightedBackgroundColor = theme.itemHighlightedBackgroundColor } else { backgroundColor = theme.pinnedItemBackgroundColor + highlightedBackgroundColor = theme.pinnedItemHighlightedBackgroundColor } } else { backgroundColor = theme.itemBackgroundColor + highlightedBackgroundColor = theme.itemHighlightedBackgroundColor } if animated { transition.updateBackgroundColor(node: strongSelf.backgroundNode, color: backgroundColor) } else { strongSelf.backgroundNode.backgroundColor = backgroundColor } + strongSelf.highlightedBackgroundNode.backgroundColor = highlightedBackgroundColor let topNegativeInset: CGFloat = 0.0 strongSelf.highlightedBackgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: layoutOffset - separatorHeight - topNegativeInset), size: CGSize(width: layout.contentSize.width, height: layout.contentSize.height + separatorHeight + topNegativeInset)) diff --git a/submodules/ComposePollUI/Sources/CreatePollTextInputItem.swift b/submodules/ComposePollUI/Sources/CreatePollTextInputItem.swift index 20481f84aa..b08ccbddb6 100644 --- a/submodules/ComposePollUI/Sources/CreatePollTextInputItem.swift +++ b/submodules/ComposePollUI/Sources/CreatePollTextInputItem.swift @@ -426,14 +426,18 @@ public class CreatePollTextInputItemNode: ListViewItemNode, ASEditableTextNodeDe public func editableTextNodeTarget(forAction action: Selector) -> ASEditableTextNodeTargetForAction? { if action == makeSelectorFromString("_showTextStyleOptions:") { - if case .general = self.inputMenu.state { - if self.textNode.attributedText == nil || self.textNode.attributedText!.length == 0 || self.textNode.selectedRange.length == 0 { - return ASEditableTextNodeTargetForAction(target: nil) - } - return ASEditableTextNodeTargetForAction(target: self) - } else { - return ASEditableTextNodeTargetForAction(target: nil) - } + if #available(iOS 16.0, *) { + return ASEditableTextNodeTargetForAction(target: nil) + } else { + if case .general = self.inputMenu.state { + if self.textNode.attributedText == nil || self.textNode.attributedText!.length == 0 || self.textNode.selectedRange.length == 0 { + return ASEditableTextNodeTargetForAction(target: nil) + } + return ASEditableTextNodeTargetForAction(target: self) + } else { + return ASEditableTextNodeTargetForAction(target: nil) + } + } } else if action == #selector(self.formatAttributesBold(_:)) || action == #selector(self.formatAttributesItalic(_:)) || action == #selector(self.formatAttributesMonospace(_:)) || action == #selector(self.formatAttributesLink(_:)) || action == #selector(self.formatAttributesStrikethrough(_:)) || action == #selector(self.formatAttributesUnderline(_:)) { if case .format = self.inputMenu.state { return ASEditableTextNodeTargetForAction(target: self) @@ -451,6 +455,58 @@ public class CreatePollTextInputItemNode: ListViewItemNode, ASEditableTextNodeDe self.inputMenu.format(view: self.textNode.view, rect: self.textNode.selectionRect.offsetBy(dx: 0.0, dy: -self.textNode.textView.contentOffset.y).insetBy(dx: 0.0, dy: -1.0)) } + @available(iOS 16.0, *) + public func editableTextNodeMenu(_ editableTextNode: ASEditableTextNode, forTextRange textRange: NSRange, suggestedActions: [UIMenuElement]) -> UIMenu { + var actions = suggestedActions + + if editableTextNode.attributedText == nil || editableTextNode.attributedText!.length == 0 || editableTextNode.selectedRange.length == 0 { + + } else if let strings = self.item?.presentationData.strings { + let children: [UIAction] = [ + UIAction(title: strings.TextFormat_Bold, image: nil) { [weak self] (action) in + if let strongSelf = self { + strongSelf.formatAttributesBold(strongSelf) + } + }, + UIAction(title: strings.TextFormat_Italic, image: nil) { [weak self] (action) in + if let strongSelf = self { + strongSelf.formatAttributesItalic(strongSelf) + } + }, + UIAction(title: strings.TextFormat_Monospace, image: nil) { [weak self] (action) in + if let strongSelf = self { + strongSelf.formatAttributesMonospace(strongSelf) + } + }, + UIAction(title: strings.TextFormat_Link, image: nil) { [weak self] (action) in + if let strongSelf = self { + strongSelf.formatAttributesLink(strongSelf) + } + }, + UIAction(title: strings.TextFormat_Strikethrough, image: nil) { [weak self] (action) in + if let strongSelf = self { + strongSelf.formatAttributesStrikethrough(strongSelf) + } + }, + UIAction(title: strings.TextFormat_Underline, image: nil) { [weak self] (action) in + if let strongSelf = self { + strongSelf.formatAttributesUnderline(strongSelf) + } + }, + UIAction(title: strings.TextFormat_Spoiler, image: nil) { [weak self] (action) in + if let strongSelf = self { + strongSelf.formatAttributesSpoiler(strongSelf) + } + } + ] + + let formatMenu = UIMenu(title: strings.TextFormat_Format, image: nil, children: children) + actions.insert(formatMenu, at: 3) + } + + return UIMenu(children: actions) + } + @objc func formatAttributesBold(_ sender: Any) { self.inputMenu.back() if let item = self.item { @@ -491,6 +547,13 @@ public class CreatePollTextInputItemNode: ListViewItemNode, ASEditableTextNodeDe } } + @objc func formatAttributesSpoiler(_ sender: Any) { + self.inputMenu.back() + if let item = self.item { + chatTextInputAddFormattingAttribute(item: item, textNode: self.textNode, theme: item.presentationData.theme, attribute: ChatTextInputAttributes.spoiler) + } + } + public func editableTextNode(_ editableTextNode: ASEditableTextNode, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { if let item = self.item { if text.count > 1, let processPaste = item.processPaste { diff --git a/submodules/Display/Source/Navigation/NavigationController.swift b/submodules/Display/Source/Navigation/NavigationController.swift index 5dacbdd5ea..3d73f0c733 100644 --- a/submodules/Display/Source/Navigation/NavigationController.swift +++ b/submodules/Display/Source/Navigation/NavigationController.swift @@ -158,7 +158,7 @@ open class NavigationController: UINavigationController, ContainableController, private var globalOverlayContainerParent: GlobalOverlayContainerParent? public var globalOverlayControllersUpdated: (() -> Void)? - private var validLayout: ContainerViewLayout? + public private(set) var validLayout: ContainerViewLayout? private var validStatusBarStyle: NavigationStatusBarStyle? private var validStatusBarHidden: Bool = false @@ -1309,6 +1309,18 @@ open class NavigationController: UINavigationController, ContainableController, completion() } + public func updateContainerPulled(_ pushed: Bool) { + guard self.modalContainers.isEmpty else { + return + } + if let rootContainer = self.rootContainer, case let .flat(container) = rootContainer { + let scale: CGFloat = pushed ? 1.06 : 1.0 + + container.view.layer.transform = CATransform3DMakeScale(scale, scale, 1.0) + container.view.layer.animateScale(from: pushed ? 1.0 : 1.06, to: scale, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring) + } + } + open override func pushViewController(_ viewController: UIViewController, animated: Bool) { var controllers = self.viewControllers controllers.append(viewController) diff --git a/submodules/GalleryUI/Sources/Items/ChatImageGalleryItem.swift b/submodules/GalleryUI/Sources/Items/ChatImageGalleryItem.swift index e78b5bc6fc..fe075fecb1 100644 --- a/submodules/GalleryUI/Sources/Items/ChatImageGalleryItem.swift +++ b/submodules/GalleryUI/Sources/Items/ChatImageGalleryItem.swift @@ -240,6 +240,8 @@ final class ChatImageGalleryItemNode: ZoomableContentGalleryItemNode { super.init() + self.clipsToBounds = true + self.imageNode.imageUpdated = { [weak self] _ in self?._ready.set(.single(Void())) } @@ -290,6 +292,11 @@ final class ChatImageGalleryItemNode: ZoomableContentGalleryItemNode { return self._ready.get() } + override func screenFrameUpdated(_ frame: CGRect) { + let center = frame.midX - self.frame.width / 2.0 + self.subnodeTransform = CATransform3DMakeTranslation(-center * 0.16, 0.0, 0.0) + } + override func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition) { super.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, transition: transition) diff --git a/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift b/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift index 9f148ea62b..4e933489c2 100644 --- a/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift +++ b/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift @@ -814,6 +814,8 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { super.init() + self.clipsToBounds = true + self.moreBarButton.addTarget(self, action: #selector(self.moreButtonPressed), forControlEvents: .touchUpInside) self.footerContentNode.interacting = { [weak self] value in @@ -966,6 +968,12 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { return self._ready.get() } + + override func screenFrameUpdated(_ frame: CGRect) { + let center = frame.midX - self.frame.width / 2.0 + self.subnodeTransform = CATransform3DMakeTranslation(-center * 0.16, 0.0, 0.0) + } + override func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition) { if let _ = self.customUnembedWhenPortrait, layout.size.width < layout.size.height { self.expandIntoCustomPiP() diff --git a/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift b/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift index 2c1b4d04cb..e499ffd7c9 100644 --- a/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift @@ -465,7 +465,8 @@ public func makeDefaultDarkPresentationTheme(extendingThemeReference: Presentati itemSeparatorColor: UIColor(rgb: 0x545458, alpha: 0.55), itemBackgroundColor: UIColor(rgb: 0x000000), pinnedItemBackgroundColor: UIColor(rgb: 0x1c1c1d), - itemHighlightedBackgroundColor: UIColor(rgb: 0x191919), + itemHighlightedBackgroundColor: UIColor(rgb: 0xffffff, alpha: 0.07), + pinnedItemHighlightedBackgroundColor: UIColor(rgb: 0xffffff, alpha: 0.07), itemSelectedBackgroundColor: UIColor(rgb: 0x191919), titleColor: UIColor(rgb: 0xffffff), secretTitleColor: UIColor(rgb: 0x00b12c), diff --git a/submodules/TelegramPresentationData/Sources/DefaultDarkTintedPresentationTheme.swift b/submodules/TelegramPresentationData/Sources/DefaultDarkTintedPresentationTheme.swift index 493e917ec9..7aa97959c7 100644 --- a/submodules/TelegramPresentationData/Sources/DefaultDarkTintedPresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/DefaultDarkTintedPresentationTheme.swift @@ -685,6 +685,7 @@ public func makeDefaultDarkTintedPresentationTheme(extendingThemeReference: Pres itemBackgroundColor: additionalBackgroundColor, pinnedItemBackgroundColor: mainBackgroundColor, itemHighlightedBackgroundColor: mainSelectionColor, + pinnedItemHighlightedBackgroundColor: mainSelectionColor, itemSelectedBackgroundColor: mainSelectionColor, titleColor: UIColor(rgb: 0xffffff), secretTitleColor: UIColor(rgb: 0x89df9e), diff --git a/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift b/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift index 1d24f2c939..812ade905a 100644 --- a/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift @@ -526,6 +526,7 @@ public func makeDefaultDayPresentationTheme(extendingThemeReference: Presentatio itemBackgroundColor: UIColor(rgb: 0xffffff), pinnedItemBackgroundColor: UIColor(rgb: 0xf7f7f7), itemHighlightedBackgroundColor: UIColor(rgb: 0xe5e5ea), + pinnedItemHighlightedBackgroundColor: UIColor(rgb: 0xe5e5ea), itemSelectedBackgroundColor: UIColor(rgb: 0xe9f0fa), titleColor: UIColor(rgb: 0x000000), secretTitleColor: UIColor(rgb: 0x00b12c), diff --git a/submodules/TelegramPresentationData/Sources/PresentationTheme.swift b/submodules/TelegramPresentationData/Sources/PresentationTheme.swift index c8a62f43f5..62091d16bc 100644 --- a/submodules/TelegramPresentationData/Sources/PresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/PresentationTheme.swift @@ -561,6 +561,7 @@ public final class PresentationThemeChatList { public let itemBackgroundColor: UIColor public let pinnedItemBackgroundColor: UIColor public let itemHighlightedBackgroundColor: UIColor + public let pinnedItemHighlightedBackgroundColor: UIColor public let itemSelectedBackgroundColor: UIColor public let titleColor: UIColor public let secretTitleColor: UIColor @@ -597,6 +598,7 @@ public final class PresentationThemeChatList { itemBackgroundColor: UIColor, pinnedItemBackgroundColor: UIColor, itemHighlightedBackgroundColor: UIColor, + pinnedItemHighlightedBackgroundColor: UIColor, itemSelectedBackgroundColor: UIColor, titleColor: UIColor, secretTitleColor: UIColor, @@ -632,6 +634,7 @@ public final class PresentationThemeChatList { self.itemBackgroundColor = itemBackgroundColor self.pinnedItemBackgroundColor = pinnedItemBackgroundColor self.itemHighlightedBackgroundColor = itemHighlightedBackgroundColor + self.pinnedItemHighlightedBackgroundColor = pinnedItemHighlightedBackgroundColor self.itemSelectedBackgroundColor = itemSelectedBackgroundColor self.titleColor = titleColor self.secretTitleColor = secretTitleColor @@ -669,6 +672,7 @@ public final class PresentationThemeChatList { itemBackgroundColor: UIColor? = nil, pinnedItemBackgroundColor: UIColor? = nil, itemHighlightedBackgroundColor: UIColor? = nil, + pinnedItemHighlightedBackgroundColor: UIColor? = nil, itemSelectedBackgroundColor: UIColor? = nil, titleColor: UIColor? = nil, secretTitleColor: UIColor? = nil, @@ -705,6 +709,7 @@ public final class PresentationThemeChatList { itemBackgroundColor: itemBackgroundColor ?? self.itemBackgroundColor, pinnedItemBackgroundColor: pinnedItemBackgroundColor ?? self.pinnedItemBackgroundColor, itemHighlightedBackgroundColor: itemHighlightedBackgroundColor ?? self.itemHighlightedBackgroundColor, + pinnedItemHighlightedBackgroundColor: pinnedItemHighlightedBackgroundColor ?? self.pinnedItemHighlightedBackgroundColor, itemSelectedBackgroundColor: itemSelectedBackgroundColor ?? self.itemSelectedBackgroundColor, titleColor: titleColor ?? self.titleColor, secretTitleColor: secretTitleColor ?? self.secretTitleColor, diff --git a/submodules/TelegramPresentationData/Sources/PresentationThemeCodable.swift b/submodules/TelegramPresentationData/Sources/PresentationThemeCodable.swift index 5ee859af80..5f2e8ca37b 100644 --- a/submodules/TelegramPresentationData/Sources/PresentationThemeCodable.swift +++ b/submodules/TelegramPresentationData/Sources/PresentationThemeCodable.swift @@ -966,6 +966,7 @@ extension PresentationThemeChatList: Codable { case itemBg case pinnedItemBg case itemHighlightedBg + case pinnedItemHighlightedBg case itemSelectedBg case title case secretTitle @@ -1005,6 +1006,7 @@ extension PresentationThemeChatList: Codable { itemBackgroundColor: try decodeColor(values, .itemBg), pinnedItemBackgroundColor: try decodeColor(values, .pinnedItemBg), itemHighlightedBackgroundColor: try decodeColor(values, .itemHighlightedBg), + pinnedItemHighlightedBackgroundColor: try decodeColor(values, .pinnedItemHighlightedBg, fallbackKey: "\(codingPath).itemHighlightedBg"), itemSelectedBackgroundColor: try decodeColor(values, .itemSelectedBg), titleColor: try decodeColor(values, .title), secretTitleColor: try decodeColor(values, .secretTitle), diff --git a/submodules/TelegramUI/Sources/ChatMessageAttachedContentNode.swift b/submodules/TelegramUI/Sources/ChatMessageAttachedContentNode.swift index a9e8769513..66635312fe 100644 --- a/submodules/TelegramUI/Sources/ChatMessageAttachedContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageAttachedContentNode.swift @@ -853,7 +853,43 @@ final class ChatMessageAttachedContentNode: ASDisplayNode { } adjustedBoundingSize.width = max(boundingWidth, adjustedBoundingSize.width) - + + var contentMediaHeight: CGFloat? + if let (contentImageSize, _) = contentImageSizeAndApply { + contentMediaHeight = contentImageSize.height + } + + if let (contentFileSize, _) = contentFileSizeAndApply { + contentMediaHeight = contentFileSize.height + } + + if let (videoLayout, _) = contentInstantVideoSizeAndApply { + contentMediaHeight = videoLayout.contentSize.height + } + + var textVerticalOffset: CGFloat = 0.0 + if let contentMediaHeight = contentMediaHeight, let (_, flags) = mediaAndFlags, flags.contains(.preferMediaBeforeText) { + textVerticalOffset = contentMediaHeight + 7.0 + } + let adjustedTextFrame = textFrame.offsetBy(dx: 0.0, dy: textVerticalOffset) + + var statusFrame: CGRect? + if let statusSizeAndApply = statusSizeAndApply { + var finalStatusFrame = CGRect(origin: CGPoint(x: adjustedTextFrame.minX, y: adjustedTextFrame.maxY), size: statusSizeAndApply.0) + if let imageFrame = imageFrame { + if finalStatusFrame.maxY < imageFrame.maxY + 10.0 { + finalStatusFrame.origin.y = max(finalStatusFrame.minY, imageFrame.maxY + 2.0) + if finalStatusFrame.height == 0.0 { + finalStatusFrame.origin.y += 14.0 + + adjustedBoundingSize.height += 14.0 + adjustedLineHeight += 14.0 + } + } + } + statusFrame = finalStatusFrame + } + return (adjustedBoundingSize, { [weak self] animation, synchronousLoads, applyInfo in if let strongSelf = self { strongSelf.context = context @@ -900,12 +936,8 @@ final class ChatMessageAttachedContentNode: ASDisplayNode { } else if strongSelf.inlineImageNode.supernode != nil { strongSelf.inlineImageNode.removeFromSupernode() } - - var contentMediaHeight: CGFloat? - + if let (contentImageSize, contentImageApply) = contentImageSizeAndApply { - contentMediaHeight = contentImageSize.height - let contentImageNode = contentImageApply(animation, synchronousLoads) if strongSelf.contentImageNode !== contentImageNode { strongSelf.contentImageNode = contentImageNode @@ -960,8 +992,6 @@ final class ChatMessageAttachedContentNode: ASDisplayNode { } if let (contentFileSize, contentFileApply) = contentFileSizeAndApply { - contentMediaHeight = contentFileSize.height - let contentFileNode = contentFileApply(synchronousLoads, animation, applyInfo) if strongSelf.contentFileNode !== contentFileNode { strongSelf.contentFileNode = contentFileNode @@ -988,7 +1018,6 @@ final class ChatMessageAttachedContentNode: ASDisplayNode { } if let (videoLayout, apply) = contentInstantVideoSizeAndApply { - contentMediaHeight = videoLayout.contentSize.height let contentInstantVideoNode = apply(.unconstrained(width: boundingWidth - insets.left - insets.right), animation) if strongSelf.contentInstantVideoNode !== contentInstantVideoNode { strongSelf.contentInstantVideoNode = contentInstantVideoNode @@ -1003,23 +1032,9 @@ final class ChatMessageAttachedContentNode: ASDisplayNode { contentInstantVideoNode.removeFromSupernode() strongSelf.contentInstantVideoNode = nil } - - var textVerticalOffset: CGFloat = 0.0 - if let contentMediaHeight = contentMediaHeight, let (_, flags) = mediaAndFlags, flags.contains(.preferMediaBeforeText) { - textVerticalOffset = contentMediaHeight + 7.0 - } - - strongSelf.textNode.textNode.frame = textFrame.offsetBy(dx: 0.0, dy: textVerticalOffset) - if let statusSizeAndApply = statusSizeAndApply { - var statusFrame = CGRect(origin: CGPoint(x: strongSelf.textNode.textNode.frame.minX, y: strongSelf.textNode.textNode.frame.maxY), size: statusSizeAndApply.0) - if let imageFrame = imageFrame { - if statusFrame.maxY < imageFrame.maxY + 10.0 { - statusFrame.origin.y = max(statusFrame.minY, imageFrame.maxY + 2.0) - if statusFrame.height == 0.0 { - statusFrame.origin.y += 14.0 - } - } - } + + strongSelf.textNode.textNode.frame = adjustedTextFrame + if let statusSizeAndApply = statusSizeAndApply, let statusFrame = statusFrame { if strongSelf.statusNode.supernode == nil { strongSelf.addSubnode(strongSelf.statusNode) strongSelf.statusNode.frame = statusFrame diff --git a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift index 5e9e72e469..90f226dbb3 100644 --- a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift @@ -2997,13 +2997,17 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { else if action == makeSelectorFromString("_accessibilitySpeakLanguageSelection:") || action == makeSelectorFromString("_accessibilityPauseSpeaking:") || action == makeSelectorFromString("_accessibilitySpeakSentence:") { return ASEditableTextNodeTargetForAction(target: nil) } else if action == makeSelectorFromString("_showTextStyleOptions:") { - if case .general = self.inputMenu.state { - if let textInputNode = self.textInputNode, textInputNode.attributedText == nil || textInputNode.attributedText!.length == 0 || textInputNode.selectedRange.length == 0 { + if #available(iOS 16.0, *) { + return ASEditableTextNodeTargetForAction(target: nil) + } else { + if case .general = self.inputMenu.state { + if let textInputNode = self.textInputNode, textInputNode.attributedText == nil || textInputNode.attributedText!.length == 0 || textInputNode.selectedRange.length == 0 { + return ASEditableTextNodeTargetForAction(target: nil) + } + return ASEditableTextNodeTargetForAction(target: self) + } else { return ASEditableTextNodeTargetForAction(target: nil) } - return ASEditableTextNodeTargetForAction(target: self) - } else { - return ASEditableTextNodeTargetForAction(target: nil) } } else if action == #selector(self.formatAttributesBold(_:)) || action == #selector(self.formatAttributesItalic(_:)) || action == #selector(self.formatAttributesMonospace(_:)) || action == #selector(self.formatAttributesLink(_:)) || action == #selector(self.formatAttributesStrikethrough(_:)) || action == #selector(self.formatAttributesUnderline(_:)) || action == #selector(self.formatAttributesSpoiler(_:)) { if case .format = self.inputMenu.state { @@ -3044,6 +3048,65 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { return nil } + @available(iOS 16.0, *) + func editableTextNodeMenu(_ editableTextNode: ASEditableTextNode, forTextRange textRange: NSRange, suggestedActions: [UIMenuElement]) -> UIMenu { + var actions = suggestedActions + + if editableTextNode.attributedText == nil || editableTextNode.attributedText!.length == 0 || editableTextNode.selectedRange.length == 0 { + + } else { + var children: [UIAction] = [ + UIAction(title: self.strings?.TextFormat_Bold ?? "Bold", image: nil) { [weak self] (action) in + if let strongSelf = self { + strongSelf.formatAttributesBold(strongSelf) + } + }, + UIAction(title: self.strings?.TextFormat_Italic ?? "Italic", image: nil) { [weak self] (action) in + if let strongSelf = self { + strongSelf.formatAttributesItalic(strongSelf) + } + }, + UIAction(title: self.strings?.TextFormat_Monospace ?? "Monospace", image: nil) { [weak self] (action) in + if let strongSelf = self { + strongSelf.formatAttributesMonospace(strongSelf) + } + }, + UIAction(title: self.strings?.TextFormat_Link ?? "Link", image: nil) { [weak self] (action) in + if let strongSelf = self { + strongSelf.formatAttributesLink(strongSelf) + } + }, + UIAction(title: self.strings?.TextFormat_Strikethrough ?? "Strikethrough", image: nil) { [weak self] (action) in + if let strongSelf = self { + strongSelf.formatAttributesStrikethrough(strongSelf) + } + }, + UIAction(title: self.strings?.TextFormat_Underline ?? "Underline", image: nil) { [weak self] (action) in + if let strongSelf = self { + strongSelf.formatAttributesUnderline(strongSelf) + } + } + ] + + var hasSpoilers = true + if self.presentationInterfaceState?.chatLocation.peerId?.namespace == Namespaces.Peer.SecretChat { + hasSpoilers = false + } + + if hasSpoilers { + children.append(UIAction(title: self.strings?.TextFormat_Spoiler ?? "Spoiler", image: nil) { [weak self] (action) in + if let strongSelf = self { + strongSelf.formatAttributesSpoiler(strongSelf) + } + }) + } + + let formatMenu = UIMenu(title: self.strings?.TextFormat_Format ?? "Format", image: nil, children: children) + actions.insert(formatMenu, at: 3) + } + return UIMenu(children: actions) + } + @objc func _accessibilitySpeak(_ sender: Any) { var text = "" self.interfaceInteraction?.updateTextInputStateAndMode { current, inputMode in diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoPaneContainerNode.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoPaneContainerNode.swift index 3899c04ca0..1633da1ec1 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoPaneContainerNode.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoPaneContainerNode.swift @@ -745,7 +745,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat transition.updateAlpha(node: self.coveringBackgroundNode, alpha: expansionFraction) - self.backgroundColor = presentationData.theme.list.itemBlocksBackgroundColor + self.backgroundColor = presentationData.theme.list.plainBackgroundColor self.coveringBackgroundNode.updateColor(color: presentationData.theme.rootController.navigationBar.opaqueBackgroundColor, transition: .immediate) self.separatorNode.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor self.tabsSeparatorNode.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor