diff --git a/submodules/TelegramPresentationData/Sources/DefaultDarkAccentPresentationTheme.swift b/submodules/TelegramPresentationData/Sources/DefaultDarkAccentPresentationTheme.swift index ec501447e5..598099f46d 100644 --- a/submodules/TelegramPresentationData/Sources/DefaultDarkAccentPresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/DefaultDarkAccentPresentationTheme.swift @@ -118,7 +118,8 @@ private let list = PresentationThemeList( ), mediaPlaceholderColor: UIColor(rgb: 0x1e2c3a), scrollIndicatorColor: UIColor(white: 1.0, alpha: 0.3), - pageIndicatorInactiveColor: UIColor(rgb: 0xDBF5FF, alpha: 0.4) + pageIndicatorInactiveColor: UIColor(rgb: 0xDBF5FF, alpha: 0.4), + inputClearButtonColor: UIColor(rgb: 0x8B9197) ) private let chatList = PresentationThemeChatList( diff --git a/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift b/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift index 33f1543c78..e5fe40e107 100644 --- a/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift @@ -116,7 +116,8 @@ private let list = PresentationThemeList( ), mediaPlaceholderColor: UIColor(rgb: 0x1c1c1d), scrollIndicatorColor: UIColor(white: 1.0, alpha: 0.3), - pageIndicatorInactiveColor: UIColor(white: 1.0, alpha: 0.3) + pageIndicatorInactiveColor: UIColor(white: 1.0, alpha: 0.3), + inputClearButtonColor: UIColor(rgb: 0x8B9197) ) private let chatList = PresentationThemeChatList( diff --git a/submodules/TelegramPresentationData/Sources/DefaultPresentationTheme.swift b/submodules/TelegramPresentationData/Sources/DefaultPresentationTheme.swift index 68f6c6bfbe..f711b1764d 100644 --- a/submodules/TelegramPresentationData/Sources/DefaultPresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/DefaultPresentationTheme.swift @@ -116,7 +116,8 @@ private func makeDefaultPresentationTheme(accentColor: UIColor, serviceBackgroun ), mediaPlaceholderColor: UIColor(rgb: 0xe4e4e4), scrollIndicatorColor: UIColor(white: 0.0, alpha: 0.3), - pageIndicatorInactiveColor: UIColor(rgb: 0xe3e3e7) + pageIndicatorInactiveColor: UIColor(rgb: 0xe3e3e7), + inputClearButtonColor: UIColor(rgb: 0xcccccc) ) let chatList = PresentationThemeChatList( diff --git a/submodules/TelegramPresentationData/Sources/PresentationTheme.swift b/submodules/TelegramPresentationData/Sources/PresentationTheme.swift index f931624977..cb9955f7b6 100644 --- a/submodules/TelegramPresentationData/Sources/PresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/PresentationTheme.swift @@ -331,8 +331,9 @@ public final class PresentationThemeList { public let mediaPlaceholderColor: UIColor public let scrollIndicatorColor: UIColor public let pageIndicatorInactiveColor: UIColor + public let inputClearButtonColor: UIColor - public init(blocksBackgroundColor: UIColor, plainBackgroundColor: UIColor, itemPrimaryTextColor: UIColor, itemSecondaryTextColor: UIColor, itemDisabledTextColor: UIColor, itemAccentColor: UIColor, itemHighlightedColor: UIColor, itemDestructiveColor: UIColor, itemPlaceholderTextColor: UIColor, itemBlocksBackgroundColor: UIColor, itemHighlightedBackgroundColor: UIColor, itemBlocksSeparatorColor: UIColor, itemPlainSeparatorColor: UIColor, disclosureArrowColor: UIColor, sectionHeaderTextColor: UIColor, freeTextColor: UIColor, freeTextErrorColor: UIColor, freeTextSuccessColor: UIColor, freeMonoIcon: UIColor, itemSwitchColors: PresentationThemeSwitch, itemDisclosureActions: PresentationThemeItemDisclosureActions, itemCheckColors: PresentationThemeCheck, controlSecondaryColor: UIColor, freeInputField: PresentationInputFieldTheme, mediaPlaceholderColor: UIColor, scrollIndicatorColor: UIColor, pageIndicatorInactiveColor: UIColor) { + public init(blocksBackgroundColor: UIColor, plainBackgroundColor: UIColor, itemPrimaryTextColor: UIColor, itemSecondaryTextColor: UIColor, itemDisabledTextColor: UIColor, itemAccentColor: UIColor, itemHighlightedColor: UIColor, itemDestructiveColor: UIColor, itemPlaceholderTextColor: UIColor, itemBlocksBackgroundColor: UIColor, itemHighlightedBackgroundColor: UIColor, itemBlocksSeparatorColor: UIColor, itemPlainSeparatorColor: UIColor, disclosureArrowColor: UIColor, sectionHeaderTextColor: UIColor, freeTextColor: UIColor, freeTextErrorColor: UIColor, freeTextSuccessColor: UIColor, freeMonoIcon: UIColor, itemSwitchColors: PresentationThemeSwitch, itemDisclosureActions: PresentationThemeItemDisclosureActions, itemCheckColors: PresentationThemeCheck, controlSecondaryColor: UIColor, freeInputField: PresentationInputFieldTheme, mediaPlaceholderColor: UIColor, scrollIndicatorColor: UIColor, pageIndicatorInactiveColor: UIColor, inputClearButtonColor: UIColor) { self.blocksBackgroundColor = blocksBackgroundColor self.plainBackgroundColor = plainBackgroundColor self.itemPrimaryTextColor = itemPrimaryTextColor @@ -360,6 +361,7 @@ public final class PresentationThemeList { self.mediaPlaceholderColor = mediaPlaceholderColor self.scrollIndicatorColor = scrollIndicatorColor self.pageIndicatorInactiveColor = pageIndicatorInactiveColor + self.inputClearButtonColor = inputClearButtonColor } } @@ -500,7 +502,7 @@ public func bubbleColorComponents(theme: PresentationTheme, incoming: Bool, wall public func bubbleVariableColor(variableColor: PresentationThemeVariableColor, wallpaper: TelegramWallpaper) -> UIColor { switch wallpaper { - case .builtin, .color(0xffffff): + case .color(0xffffff): return variableColor.withoutWallpaper default: return variableColor.withWallpaper @@ -708,7 +710,7 @@ public func serviceMessageColorComponents(theme: PresentationTheme, wallpaper: T public func serviceMessageColorComponents(chatTheme: PresentationThemeChat, wallpaper: TelegramWallpaper) -> PresentationThemeServiceMessageColorComponents { switch wallpaper { - case .builtin, .color(0xffffff): + case .color(0xffffff): return chatTheme.serviceMessage.components.withDefaultWallpaper default: return chatTheme.serviceMessage.components.withCustomWallpaper diff --git a/submodules/TelegramUI/TelegramUI/ChannelVisibilityController.swift b/submodules/TelegramUI/TelegramUI/ChannelVisibilityController.swift index 02e771e0af..753c31f8df 100644 --- a/submodules/TelegramUI/TelegramUI/ChannelVisibilityController.swift +++ b/submodules/TelegramUI/TelegramUI/ChannelVisibilityController.swift @@ -280,7 +280,7 @@ private enum ChannelVisibilityEntry: ItemListNodeEntry { } }, tag: ChannelVisibilityEntryTag.privateLink) case let .editablePublicLink(theme, placeholder, currentText): - return ItemListSingleLineInputItem(theme: theme, title: NSAttributedString(string: "t.me/", textColor: theme.list.itemPrimaryTextColor), text: currentText, placeholder: placeholder, tag: ChannelVisibilityEntryTag.publicLink, sectionId: self.section, textUpdated: { updatedText in + return ItemListSingleLineInputItem(theme: theme, title: NSAttributedString(string: "t.me/", textColor: theme.list.itemPrimaryTextColor), text: currentText, placeholder: placeholder, type: .regular(capitalization: false, autocorrection: false), clearButton: true, tag: ChannelVisibilityEntryTag.publicLink, sectionId: self.section, textUpdated: { updatedText in arguments.updatePublicLinkText(currentText, updatedText) }, receivedFocus: { arguments.scrollToPublicLinkText() diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageBubbleItemNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageBubbleItemNode.swift index 0f6374c802..faf31a4887 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageBubbleItemNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageBubbleItemNode.swift @@ -1849,7 +1849,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView { if item.effectiveAuthorId?.namespace == Namespaces.Peer.Empty { item.controllerInteraction.displayMessageTooltip(item.content.firstMessage.id, item.presentationData.strings.Conversation_ForwardAuthorHiddenTooltip, self, avatarNode.frame) } else { - if let channel = item.content.firstMessage.forwardInfo?.author as? TelegramChannel, channel.username == nil { + if item.message.id.peerId == item.context.account.peerId, let channel = item.content.firstMessage.forwardInfo?.author as? TelegramChannel, channel.username == nil { if case .member = channel.participationStatus { } else { item.controllerInteraction.displayMessageTooltip(item.message.id, item.presentationData.strings.Conversation_PrivateChannelTooltip, self, avatarNode.frame) diff --git a/submodules/TelegramUI/TelegramUI/ChatPresentationData.swift b/submodules/TelegramUI/TelegramUI/ChatPresentationData.swift index 9852172a21..9971681d4e 100644 --- a/submodules/TelegramUI/TelegramUI/ChatPresentationData.swift +++ b/submodules/TelegramUI/TelegramUI/ChatPresentationData.swift @@ -1,5 +1,6 @@ import Foundation import UIKit +import Display import TelegramCore import TelegramPresentationData import TelegramUIPreferences @@ -28,7 +29,7 @@ extension PresentationFontSize { extension TelegramWallpaper { var isEmpty: Bool { switch self { - case .builtin, .image: + case .image: return false case let .file(file): if file.isPattern, file.settings.color == 0xffffff { @@ -38,6 +39,8 @@ extension TelegramWallpaper { } case let .color(color): return color == 0xffffff + default: + return false } } var isBuiltin: Bool { @@ -79,6 +82,7 @@ public final class ChatPresentationData { let messageEmojiFont3: UIFont let messageBoldFont: UIFont let messageItalicFont: UIFont + let messageBoldItalicFont: UIFont let messageFixedFont: UIFont init(theme: ChatPresentationThemeData, fontSize: PresentationFontSize, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, disableAnimations: Bool, largeEmoji: Bool) { @@ -97,6 +101,7 @@ public final class ChatPresentationData { self.messageEmojiFont3 = UIFont.systemFont(ofSize: 24.0) self.messageBoldFont = UIFont.boldSystemFont(ofSize: baseFontSize) self.messageItalicFont = UIFont.italicSystemFont(ofSize: baseFontSize) + self.messageBoldItalicFont = Font.semiboldItalic(baseFontSize) self.messageFixedFont = UIFont(name: "Menlo-Regular", size: baseFontSize - 1.0) ?? UIFont.systemFont(ofSize: baseFontSize) } } diff --git a/submodules/TelegramUI/TelegramUI/ItemListAvatarAndNameItem.swift b/submodules/TelegramUI/TelegramUI/ItemListAvatarAndNameItem.swift index f265a1e277..ecfc4dacee 100644 --- a/submodules/TelegramUI/TelegramUI/ItemListAvatarAndNameItem.swift +++ b/submodules/TelegramUI/TelegramUI/ItemListAvatarAndNameItem.swift @@ -9,6 +9,10 @@ import TelegramPresentationData private let updatingAvatarOverlayImage = generateFilledCircleImage(diameter: 66.0, color: UIColor(white: 0.0, alpha: 0.4), backgroundColor: nil) +private func generateClearIcon(color: UIColor) -> UIImage? { + return generateTintedImage(image: UIImage(bundleImageName: "Components/Search Bar/Clear"), color: color) +} + enum ItemListAvatarAndNameInfoItemTitleType { case group case channel @@ -164,6 +168,7 @@ class ItemListAvatarAndNameInfoItem: ListViewItem, ItemListItem { let sectionId: ItemListSectionId let style: ItemListAvatarAndNameInfoItemStyle let editingNameUpdated: (ItemListAvatarAndNameInfoItemName) -> Void + let editingNameCompleted: () -> Void let avatarTapped: () -> Void let context: ItemListAvatarAndNameInfoItemContext? let updatingImage: ItemListAvatarAndNameInfoItemUpdatingAvatar? @@ -174,7 +179,7 @@ class ItemListAvatarAndNameInfoItem: ListViewItem, ItemListItem { let selectable: Bool - init(account: Account, theme: PresentationTheme, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, mode: ItemListAvatarAndNameInfoItemMode, peer: Peer?, presence: PeerPresence?, label: String? = nil, cachedData: CachedPeerData?, state: ItemListAvatarAndNameInfoItemState, sectionId: ItemListSectionId, style: ItemListAvatarAndNameInfoItemStyle, editingNameUpdated: @escaping (ItemListAvatarAndNameInfoItemName) -> Void, avatarTapped: @escaping () -> Void, context: ItemListAvatarAndNameInfoItemContext? = nil, updatingImage: ItemListAvatarAndNameInfoItemUpdatingAvatar? = nil, call: (() -> Void)? = nil, action: (() -> Void)? = nil, longTapAction: (() -> Void)? = nil, tag: ItemListItemTag? = nil) { + init(account: Account, theme: PresentationTheme, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, mode: ItemListAvatarAndNameInfoItemMode, peer: Peer?, presence: PeerPresence?, label: String? = nil, cachedData: CachedPeerData?, state: ItemListAvatarAndNameInfoItemState, sectionId: ItemListSectionId, style: ItemListAvatarAndNameInfoItemStyle, editingNameUpdated: @escaping (ItemListAvatarAndNameInfoItemName) -> Void, editingNameCompleted: @escaping () -> Void = {}, avatarTapped: @escaping () -> Void, context: ItemListAvatarAndNameInfoItemContext? = nil, updatingImage: ItemListAvatarAndNameInfoItemUpdatingAvatar? = nil, call: (() -> Void)? = nil, action: (() -> Void)? = nil, longTapAction: (() -> Void)? = nil, tag: ItemListItemTag? = nil) { self.account = account self.theme = theme self.strings = strings @@ -188,6 +193,7 @@ class ItemListAvatarAndNameInfoItem: ListViewItem, ItemListItem { self.sectionId = sectionId self.style = style self.editingNameUpdated = editingNameUpdated + self.editingNameCompleted = editingNameCompleted self.avatarTapped = avatarTapped self.context = context self.updatingImage = updatingImage @@ -248,7 +254,7 @@ private let avatarFont = UIFont(name: ".SFCompactRounded-Semibold", size: 28.0)! private let nameFont = Font.medium(19.0) private let statusFont = Font.regular(15.0) -class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNode, ItemListItemFocusableNode { +class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNode, ItemListItemFocusableNode, UITextFieldDelegate { private let backgroundNode: ASDisplayNode private let highlightedBackgroundNode: ASDisplayNode private let topStripeNode: ASDisplayNode @@ -270,6 +276,9 @@ class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNode, Ite private var inputFirstField: UITextField? private var inputSecondField: UITextField? + private var inputFirstClearButton: HighlightableButtonNode? + private var inputSecondClearButton: HighlightableButtonNode? + private var item: ItemListAvatarAndNameInfoItem? private var layoutWidthAndNeighbors: (width: ListViewItemLayoutParams, neighbors: ItemListNeighbors)? private var peerPresenceManager: PeerPresenceStatusManager? @@ -547,6 +556,9 @@ class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNode, Ite strongSelf.inputSeparator?.backgroundColor = itemSeparatorColor strongSelf.callButton.setImage(PresentationResourcesChat.chatInfoCallButtonImage(item.theme), for: []) + strongSelf.inputFirstClearButton?.setImage(generateClearIcon(color: item.theme.list.inputClearButtonColor), for: []) + strongSelf.inputSecondClearButton?.setImage(generateClearIcon(color: item.theme.list.inputClearButtonColor), for: []) + updatedArrowImage = PresentationResourcesItemList.disclosureArrowImage(item.theme) } @@ -708,6 +720,7 @@ class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNode, Ite if strongSelf.inputFirstField == nil { let inputFirstField = TextFieldNodeView() + inputFirstField.delegate = self inputFirstField.font = Font.regular(17.0) inputFirstField.autocorrectionType = .no inputFirstField.returnKeyType = .next @@ -725,8 +738,20 @@ class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNode, Ite strongSelf.inputFirstField?.keyboardAppearance = keyboardAppearance } + if strongSelf.inputFirstClearButton == nil { + strongSelf.inputFirstClearButton = HighlightableButtonNode() + strongSelf.inputFirstClearButton?.imageNode.displaysAsynchronously = false + strongSelf.inputFirstClearButton?.imageNode.displayWithoutProcessing = true + strongSelf.inputFirstClearButton?.displaysAsynchronously = false + strongSelf.inputFirstClearButton?.setImage(generateClearIcon(color: item.theme.list.inputClearButtonColor), for: []) + strongSelf.inputFirstClearButton?.addTarget(strongSelf, action: #selector(strongSelf.firstClearPressed), forControlEvents: .touchUpInside) + strongSelf.inputFirstClearButton?.isHidden = true + strongSelf.addSubnode(strongSelf.inputFirstClearButton!) + } + if strongSelf.inputSecondField == nil { let inputSecondField = TextFieldNodeView() + inputSecondField.delegate = self inputSecondField.font = Font.regular(17.0) inputSecondField.autocorrectionType = .no inputSecondField.returnKeyType = .done @@ -744,9 +769,27 @@ class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNode, Ite strongSelf.inputSecondField?.keyboardAppearance = keyboardAppearance } + if strongSelf.inputSecondClearButton == nil { + strongSelf.inputSecondClearButton = HighlightableButtonNode() + strongSelf.inputSecondClearButton?.imageNode.displaysAsynchronously = false + strongSelf.inputSecondClearButton?.imageNode.displayWithoutProcessing = true + strongSelf.inputSecondClearButton?.displaysAsynchronously = false + strongSelf.inputSecondClearButton?.setImage(generateClearIcon(color: item.theme.list.inputClearButtonColor), for: []) + strongSelf.inputSecondClearButton?.addTarget(strongSelf, action: #selector(strongSelf.secondClearPressed), forControlEvents: .touchUpInside) + strongSelf.inputSecondClearButton?.isHidden = true + strongSelf.addSubnode(strongSelf.inputSecondClearButton!) + } + strongSelf.inputSeparator?.frame = CGRect(origin: CGPoint(x: params.leftInset + 100.0, y: 46.0), size: CGSize(width: params.width - params.leftInset - params.rightInset - 100.0, height: separatorHeight)) - strongSelf.inputFirstField?.frame = CGRect(origin: CGPoint(x: params.leftInset + 111.0, y: 12.0), size: CGSize(width: params.width - params.leftInset - params.rightInset - 111.0 - 8.0, height: 30.0)) - strongSelf.inputSecondField?.frame = CGRect(origin: CGPoint(x: params.leftInset + 111.0, y: 52.0), size: CGSize(width: params.width - params.leftInset - params.rightInset - 111.0 - 8.0, height: 30.0)) + strongSelf.inputFirstField?.frame = CGRect(origin: CGPoint(x: params.leftInset + 111.0, y: 12.0), size: CGSize(width: params.width - params.leftInset - params.rightInset - 111.0 - 36.0, height: 30.0)) + strongSelf.inputSecondField?.frame = CGRect(origin: CGPoint(x: params.leftInset + 111.0, y: 52.0), size: CGSize(width: params.width - params.leftInset - params.rightInset - 111.0 - 36.0, height: 30.0)) + + if let image = strongSelf.inputFirstClearButton?.image(for: []), let inputFieldFrame = strongSelf.inputFirstField?.frame { + strongSelf.inputFirstClearButton?.frame = CGRect(origin: CGPoint(x: inputFieldFrame.maxX, y: inputFieldFrame.minY + floor((inputFieldFrame.size.height - image.size.height) / 2.0) - 1.0 + UIScreenPixel), size: image.size) + } + if let image = strongSelf.inputSecondClearButton?.image(for: []), let inputFieldFrame = strongSelf.inputSecondField?.frame { + strongSelf.inputSecondClearButton?.frame = CGRect(origin: CGPoint(x: inputFieldFrame.maxX, y: inputFieldFrame.minY + floor((inputFieldFrame.size.height - image.size.height) / 2.0) - 1.0 + UIScreenPixel), size: image.size) + } if animated && animateIn { strongSelf.inputSeparator?.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3) @@ -764,6 +807,7 @@ class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNode, Ite if strongSelf.inputFirstField == nil { let inputFirstField = TextFieldNodeView() + inputFirstField.delegate = self inputFirstField.font = Font.regular(17.0) inputFirstField.autocorrectionType = .no inputFirstField.attributedText = NSAttributedString(string: title, font: Font.regular(19.0), textColor: item.theme.list.itemPrimaryTextColor) @@ -786,8 +830,23 @@ class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNode, Ite strongSelf.inputFirstField?.keyboardAppearance = keyboardAppearance } + if strongSelf.inputFirstClearButton == nil { + strongSelf.inputFirstClearButton = HighlightableButtonNode() + strongSelf.inputFirstClearButton?.imageNode.displaysAsynchronously = false + strongSelf.inputFirstClearButton?.imageNode.displayWithoutProcessing = true + strongSelf.inputFirstClearButton?.displaysAsynchronously = false + strongSelf.inputFirstClearButton?.setImage(generateClearIcon(color: item.theme.list.inputClearButtonColor), for: []) + strongSelf.inputFirstClearButton?.addTarget(strongSelf, action: #selector(strongSelf.firstClearPressed), forControlEvents: .touchUpInside) + strongSelf.inputFirstClearButton?.isHidden = true + strongSelf.addSubnode(strongSelf.inputFirstClearButton!) + } + strongSelf.inputSeparator?.frame = CGRect(origin: CGPoint(x: params.leftInset + 100.0, y: 62.0), size: CGSize(width: params.width - params.leftInset - params.rightInset - 100.0, height: separatorHeight)) - strongSelf.inputFirstField?.frame = CGRect(origin: CGPoint(x: params.leftInset + 102.0, y: 26.0), size: CGSize(width: params.width - params.leftInset - params.rightInset - 102.0 - 8.0, height: 35.0)) + strongSelf.inputFirstField?.frame = CGRect(origin: CGPoint(x: params.leftInset + 111.0, y: 26.0), size: CGSize(width: params.width - params.leftInset - params.rightInset - 111.0 - 36.0, height: 35.0)) + + if let image = strongSelf.inputFirstClearButton?.image(for: []), let inputFieldFrame = strongSelf.inputFirstField?.frame { + strongSelf.inputFirstClearButton?.frame = CGRect(origin: CGPoint(x: inputFieldFrame.maxX, y: inputFieldFrame.minY + floor((inputFieldFrame.size.height - image.size.height) / 2.0) - 1.0 + UIScreenPixel), size: image.size) + } if animated && animateIn { strongSelf.inputSeparator?.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3) @@ -835,6 +894,17 @@ class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNode, Ite } else { inputFirstField.removeFromSuperview() } + + if let inputFirstClearButton = strongSelf.inputFirstClearButton { + strongSelf.inputFirstClearButton = nil + if animated { + inputFirstClearButton.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak inputFirstClearButton] _ in + inputFirstClearButton?.removeFromSupernode() + }) + } else { + inputFirstClearButton.removeFromSupernode() + } + } } if let inputSecondField = strongSelf.inputSecondField { strongSelf.inputSecondField = nil @@ -845,6 +915,17 @@ class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNode, Ite } else { inputSecondField.removeFromSuperview() } + + if let inputSecondClearButton = strongSelf.inputSecondClearButton { + strongSelf.inputSecondClearButton = nil + if animated { + inputSecondClearButton.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak inputSecondClearButton] _ in + inputSecondClearButton?.removeFromSupernode() + }) + } else { + inputSecondClearButton.removeFromSupernode() + } + } } if animated && animateOut { strongSelf.statusNode.layer.animateAlpha(from: CGFloat(strongSelf.statusNode.layer.opacity), to: 1.0, duration: 0.3) @@ -928,6 +1009,13 @@ class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNode, Ite } } + private func updateClearButtonVisibility(_ button: HighlightableButtonNode?, textField: UITextField?) { + guard let button = button, let textField = textField else { + return + } + button.isHidden = !textField.isFirstResponder || (textField.text?.isEmpty ?? true) + } + @objc func textFieldDidChange(_ inputField: UITextField) { if let item = self.item, let currentEditingName = item.state.editingName { var editingName: ItemListAvatarAndNameInfoItemName? @@ -942,6 +1030,41 @@ class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNode, Ite item.editingNameUpdated(editingName) } } + + if inputField == self.inputFirstField { + self.updateClearButtonVisibility(self.inputFirstClearButton, textField: inputField) + } else if inputField == self.inputSecondField { + self.updateClearButtonVisibility(self.inputSecondClearButton, textField: inputField) + } + } + + func textFieldDidBeginEditing(_ textField: UITextField) { + if textField == self.inputFirstField { + self.updateClearButtonVisibility(self.inputFirstClearButton, textField: textField) + } else if textField == self.inputSecondField { + self.updateClearButtonVisibility(self.inputSecondClearButton, textField: textField) + } + } + + func textFieldDidEndEditing(_ textField: UITextField) { + if textField == self.inputFirstField { + self.updateClearButtonVisibility(self.inputFirstClearButton, textField: textField) + } else if textField == self.inputSecondField { + self.updateClearButtonVisibility(self.inputSecondClearButton, textField: textField) + } + } + + func textFieldShouldReturn(_ textField: UITextField) -> Bool { + if textField == self.inputFirstField { + if let inputSecondField = self.inputSecondField { + inputSecondField.becomeFirstResponder() + } else { + self.item?.editingNameCompleted() + } + } else if textField == self.inputSecondField { + self.item?.editingNameCompleted() + } + return true } @objc func avatarTapGesture(_ recognizer: UITapGestureRecognizer) { @@ -975,6 +1098,16 @@ class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNode, Ite self.item?.call?() } + @objc func firstClearPressed() { + self.inputFirstField?.text = nil + self.updateClearButtonVisibility(self.inputFirstClearButton, textField: self.inputFirstField) + } + + @objc func secondClearPressed() { + self.inputSecondField?.text = nil + self.updateClearButtonVisibility(self.inputSecondClearButton, textField: self.inputSecondField) + } + func focus() { self.inputFirstField?.becomeFirstResponder() } diff --git a/submodules/TelegramUI/TelegramUI/PresentationResourcesItemList.swift b/submodules/TelegramUI/TelegramUI/PresentationResourcesItemList.swift index b8bb44f926..73faca85b1 100644 --- a/submodules/TelegramUI/TelegramUI/PresentationResourcesItemList.swift +++ b/submodules/TelegramUI/TelegramUI/PresentationResourcesItemList.swift @@ -136,7 +136,7 @@ struct PresentationResourcesItemList { static func itemListClearInputIcon(_ theme: PresentationTheme) -> UIImage? { return theme.image(PresentationResourceKey.itemListClearInputIcon.rawValue, { theme in - return generateTintedImage(image: UIImage(bundleImageName: "Components/Search Bar/Clear"), color: theme.rootController.activeNavigationSearchBar.inputIconColor) + return generateTintedImage(image: UIImage(bundleImageName: "Components/Search Bar/Clear"), color: theme.list.inputClearButtonColor) }) } diff --git a/submodules/TelegramUI/TelegramUI/ProxyServerSettingsController.swift b/submodules/TelegramUI/TelegramUI/ProxyServerSettingsController.swift index 1cecc7b627..8b91ef36ba 100644 --- a/submodules/TelegramUI/TelegramUI/ProxyServerSettingsController.swift +++ b/submodules/TelegramUI/TelegramUI/ProxyServerSettingsController.swift @@ -138,7 +138,7 @@ private enum ProxySettingsEntry: ItemListNodeEntry { case let .connectionHeader(theme, text): return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section) case let .connectionServer(theme, placeholder, text): - return ItemListSingleLineInputItem(theme: theme, title: NSAttributedString(), text: text, placeholder: placeholder, sectionId: self.section, textUpdated: { value in + return ItemListSingleLineInputItem(theme: theme, title: NSAttributedString(), text: text, placeholder: placeholder, type: .regular(capitalization: false, autocorrection: false), sectionId: self.section, textUpdated: { value in arguments.updateState { current in var state = current state.host = value diff --git a/submodules/TelegramUI/TelegramUI/SinglePhoneInputNode.swift b/submodules/TelegramUI/TelegramUI/SinglePhoneInputNode.swift index b43bfe867b..62689797e2 100644 --- a/submodules/TelegramUI/TelegramUI/SinglePhoneInputNode.swift +++ b/submodules/TelegramUI/TelegramUI/SinglePhoneInputNode.swift @@ -92,6 +92,8 @@ final class SinglePhoneInputNode: ASDisplayNode, UITextFieldDelegate { } } var numberUpdated: ((String) -> Void)? + var beginEditing: (() -> Void)? + var endEditing: (() -> Void)? private let phoneFormatter = InteractivePhoneFormatter() @@ -131,6 +133,14 @@ final class SinglePhoneInputNode: ASDisplayNode, UITextFieldDelegate { return self.enableEditing } + func textFieldDidBeginEditing(_ textField: UITextField) { + self.beginEditing?() + } + + func textFieldDidEndEditing(_ textField: UITextField) { + self.endEditing?() + } + private func updateNumberFromTextFields() { guard let numberField = self.numberField else { return diff --git a/submodules/TelegramUI/TelegramUI/UserInfoEditingPhoneItem.swift b/submodules/TelegramUI/TelegramUI/UserInfoEditingPhoneItem.swift index 20ea365af6..0e923545a4 100644 --- a/submodules/TelegramUI/TelegramUI/UserInfoEditingPhoneItem.swift +++ b/submodules/TelegramUI/TelegramUI/UserInfoEditingPhoneItem.swift @@ -5,6 +5,10 @@ import AsyncDisplayKit import SwiftSignalKit import TelegramPresentationData +private func generateClearIcon(color: UIColor) -> UIImage? { + return generateTintedImage(image: UIImage(bundleImageName: "Components/Search Bar/Clear"), color: color) +} + struct UserInfoEditingPhoneItemEditing { let editable: Bool let hasActiveRevealControls: Bool @@ -87,6 +91,7 @@ class UserInfoEditingPhoneItemNode: ItemListRevealOptionsItemNode, ItemListItemN private let editableControlNode: ItemListEditableControlNode private let labelSeparatorNode: ASDisplayNode private let phoneNode: SinglePhoneInputNode + private let clearButton: HighlightableButtonNode private var item: UserInfoEditingPhoneItem? private var layoutParams: ListViewItemLayoutParams? @@ -120,6 +125,12 @@ class UserInfoEditingPhoneItemNode: ItemListRevealOptionsItemNode, ItemListItemN self.phoneNode = SinglePhoneInputNode(fontSize: 17.0) + self.clearButton = HighlightableButtonNode() + self.clearButton.imageNode.displaysAsynchronously = false + self.clearButton.imageNode.displayWithoutProcessing = true + self.clearButton.displaysAsynchronously = false + self.clearButton.isHidden = true + super.init(layerBacked: false, dynamicBounce: false, rotated: false, seeThrough: false) self.addSubnode(self.editableControlNode) @@ -127,6 +138,7 @@ class UserInfoEditingPhoneItemNode: ItemListRevealOptionsItemNode, ItemListItemN self.addSubnode(self.labelButtonNode) self.addSubnode(self.labelSeparatorNode) self.addSubnode(self.phoneNode) + self.addSubnode(self.clearButton) self.labelButtonNode.highligthedChanged = { [weak self] highlighted in if let strongSelf = self { @@ -150,7 +162,18 @@ class UserInfoEditingPhoneItemNode: ItemListRevealOptionsItemNode, ItemListItemN self.phoneNode.numberUpdated = { [weak self] number in self?.item?.updated(number) + self?.updateClearButtonVisibility() } + + self.phoneNode.beginEditing = { [weak self] in + self?.updateClearButtonVisibility() + } + + self.phoneNode.endEditing = { [weak self] in + self?.updateClearButtonVisibility() + } + + self.clearButton.addTarget(self, action: #selector(self.clearPressed), forControlEvents: .touchUpInside) } override func didLoad() { @@ -208,6 +231,8 @@ class UserInfoEditingPhoneItemNode: ItemListRevealOptionsItemNode, ItemListItemN strongSelf.phoneNode.numberField?.textField.textColor = updatedTheme.list.itemPrimaryTextColor strongSelf.phoneNode.numberField?.textField.keyboardAppearance = updatedTheme.chatList.searchBarKeyboardColor.keyboardAppearance + + strongSelf.clearButton.setImage(generateClearIcon(color: updatedTheme.list.inputClearButtonColor), for: []) } let revealOffset = strongSelf.revealOffset @@ -246,6 +271,10 @@ class UserInfoEditingPhoneItemNode: ItemListRevealOptionsItemNode, ItemListItemN strongSelf.phoneNode.updateLayout(size: phoneFrame.size) strongSelf.phoneNode.number = item.value + if let image = strongSelf.clearButton.image(for: []) { + strongSelf.clearButton.frame = CGRect(origin: CGPoint(x: phoneFrame.maxX - image.size.width - 23.0, y: phoneFrame.minY + floor((phoneFrame.size.height - image.size.height) / 2.0) - 1.0 + UIScreenPixel), size: image.size) + } + strongSelf.updateLayout(size: layout.contentSize, leftInset: params.leftInset, rightInset: params.rightInset) strongSelf.setRevealOptions((left: [], right: [ItemListRevealOption(key: 0, title: item.strings.Common_Delete, icon: .none, color: item.theme.list.itemDisclosureActions.destructive.fillColor, textColor: item.theme.list.itemDisclosureActions.destructive.foregroundColor)])) @@ -297,6 +326,17 @@ class UserInfoEditingPhoneItemNode: ItemListRevealOptionsItemNode, ItemListItemN self.item?.selectLabel?() } + @objc func clearPressed() { + self.phoneNode.numberField?.textField.text = "+" + self.updateClearButtonVisibility() + } + + private func updateClearButtonVisibility() { + let text = self.phoneNode.numberField?.textField.text ?? "" + let isEmpty = text.isEmpty || text == "+" + self.clearButton.isHidden = isEmpty || !(self.phoneNode.numberField?.textField.isFirstResponder ?? false) + } + func focus() { self.phoneNode.numberField?.becomeFirstResponder() } diff --git a/submodules/TelegramUI/TelegramUI/UsernameSetupController.swift b/submodules/TelegramUI/TelegramUI/UsernameSetupController.swift index e87caa8845..9655809d31 100644 --- a/submodules/TelegramUI/TelegramUI/UsernameSetupController.swift +++ b/submodules/TelegramUI/TelegramUI/UsernameSetupController.swift @@ -89,7 +89,7 @@ private enum UsernameSetupEntry: ItemListNodeEntry { func item(_ arguments: UsernameSetupControllerArguments) -> ListViewItem { switch self { case let .editablePublicLink(theme, prefix, currentText, text): - return ItemListSingleLineInputItem(theme: theme, title: NSAttributedString(string: prefix, textColor: theme.list.itemPrimaryTextColor), text: text, placeholder: "", type: .username, spacing: 10.0, tag: UsernameEntryTag.username, sectionId: self.section, textUpdated: { updatedText in + return ItemListSingleLineInputItem(theme: theme, title: NSAttributedString(string: prefix, textColor: theme.list.itemPrimaryTextColor), text: text, placeholder: "", type: .username, spacing: 10.0, clearButton: true, tag: UsernameEntryTag.username, sectionId: self.section, textUpdated: { updatedText in arguments.updatePublicLinkText(currentText, updatedText) }, action: { })