Added clear buttons for name/username/phone input fields

This commit is contained in:
Ilya Laktyushin 2019-06-25 23:56:15 +02:00
parent 3310461737
commit dc46a8e786
13 changed files with 210 additions and 17 deletions

View File

@ -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(

View File

@ -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(

View File

@ -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(

View File

@ -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

View File

@ -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()

View File

@ -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)

View File

@ -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)
}
}

View File

@ -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()
}

View File

@ -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)
})
}

View File

@ -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

View File

@ -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

View File

@ -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()
}

View File

@ -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: {
})