-
Notifications
You must be signed in to change notification settings - Fork 384
/
Copy pathSettingsInputCell.swift
133 lines (105 loc) · 3.82 KB
/
SettingsInputCell.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
//
// SettingsInputCell.swift
// MullvadVPN
//
// Created by Jon Petersson on 2023-05-05.
// Copyright © 2023 Mullvad VPN AB. All rights reserved.
//
import UIKit
class SettingsInputCell: SelectableSettingsCell {
let textField = CustomTextField(frame: CGRect(origin: .zero, size: CGSize(width: 100, height: 30)))
var toolbarDoneButton = UIBarButtonItem()
var isValidInput: Bool {
didSet {
updateTextFieldInputValidity()
}
}
var inputDidChange: ((String) -> Void)?
var inputWasConfirmed: ((String) -> Void)?
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
isValidInput = true
super.init(style: style, reuseIdentifier: reuseIdentifier)
toolbarDoneButton = UIBarButtonItem(
title: NSLocalizedString(
"INPUT_CELL_TOOLBAR_BUTTON_DONE",
tableName: "VPNSettings",
value: "Done",
comment: ""
),
style: .done,
target: self,
action: #selector(confirmInput)
)
accessoryView = textField
setUpTextField()
setUpTextFieldToolbar()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func prepareForReuse() {
super.prepareForReuse()
reset()
}
func reset() {
textField.text = nil
UITextField.SearchTextFieldAppearance.inactive.apply(to: textField)
}
func setInput(_ text: String) {
textField.text = text
textFieldDidChange(textField)
}
@objc func confirmInput() {
_ = textFieldShouldReturn(textField)
}
@objc private func textFieldDidChange(_ textField: UITextField) {
if let text = textField.text {
inputDidChange?(text)
toolbarDoneButton.isEnabled = isValidInput
}
}
private func setUpTextField() {
textField.borderStyle = .none
textField.layer.cornerRadius = 4
textField.font = .preferredFont(forTextStyle: .body)
textField.textAlignment = .right
textField.delegate = self
textField.keyboardType = .numberPad
textField.returnKeyType = .done
textField.textMargins = UIMetrics.SettingsCell.inputCellTextFieldLayoutMargins
textField.addTarget(self, action: #selector(textFieldDidChange), for: .editingChanged)
UITextField.SearchTextFieldAppearance.inactive.apply(to: textField)
}
private func setUpTextFieldToolbar() {
let toolbar = UIToolbar(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 44))
toolbar.items = [
UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: self, action: nil),
toolbarDoneButton,
]
toolbar.sizeToFit()
textField.inputAccessoryView = toolbar
}
private func updateTextFieldInputValidity() {
if isValidInput {
textField.textColor = textField.isEditing ? .SearchTextField.textColor : .SearchTextField.inactiveTextColor
} else {
textField.textColor = UIColor.TextField.invalidInputTextColor
}
}
}
extension SettingsInputCell: UITextFieldDelegate {
func textFieldDidBeginEditing(_ textField: UITextField) {
inputDidChange?(textField.text ?? "")
toolbarDoneButton.isEnabled = isValidInput
UITextField.SearchTextFieldAppearance.active.apply(to: textField)
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
guard isValidInput else { return false }
inputWasConfirmed?(textField.text ?? "")
textField.resignFirstResponder()
return true
}
func textFieldDidEndEditing(_ textField: UITextField) {
UITextField.SearchTextFieldAppearance.inactive.apply(to: textField)
}
}