mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-10-31 08:15:24 +00:00
6efa8743ff
* Adjust login flow to exclusively use the ServerSelectionScreen * Move async code to server selection vm * ServerSelection supports pro picker options * Use homeserver address for both confirmation and picker modes * rename ServerSelectionScreenMode * remove ServerConfirmationScreen It's been superseded by the ServerSelectionScreen * rename userInput * Update strings with latest design strings * Add server input autocompletion * Store previous servers in AppSettings and autofill on server signin * Audit changes for logging * Enforce lowercase server history storage * Update tests * Update Xcode project * PR review fixups * Add HomeserverHistoryManager * Review fixups 2 * Review fixups 3
101 lines
4.1 KiB
Swift
101 lines
4.1 KiB
Swift
//
|
|
// Copyright 2026 Element Creations Ltd.
|
|
//
|
|
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
|
// Please see LICENSE files in the repository root for full details.
|
|
//
|
|
|
|
import Combine
|
|
import UIKit
|
|
|
|
/// When leveraging introspection, this allows intercepting UITextFieldDelegate calls
|
|
class TextFieldAdapter: NSObject, UITextFieldDelegate {
|
|
var textField: UITextField? {
|
|
didSet {
|
|
oldValue?.delegate = nil
|
|
passthroughDelegate = textField?.delegate
|
|
textField?.delegate = self
|
|
}
|
|
}
|
|
|
|
/// the original swiftui delegate
|
|
private var passthroughDelegate: UITextFieldDelegate?
|
|
|
|
private let keystrokeSubject = PassthroughSubject<String, Never>()
|
|
/// fires when keystrokes are made. does not fire for deletions or programmatic text changes
|
|
var keystrokePublisher: AnyPublisher<String, Never> {
|
|
keystrokeSubject.eraseToAnyPublisher()
|
|
}
|
|
|
|
func textField(_ textField: UITextField, shouldChangeCharactersInRanges ranges: [NSValue], replacementString string: String) -> Bool {
|
|
guard let range = ranges.first?.rangeValue else { return true }
|
|
if string.isEmpty == false { // don't fire for backspaces
|
|
let previousText = textField.text ?? ""
|
|
|
|
let completeString = (previousText as NSString).replacingCharacters(in: range, with: string)
|
|
|
|
keystrokeSubject.send(completeString)
|
|
}
|
|
return true
|
|
}
|
|
|
|
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
|
|
self.textField(textField, shouldChangeCharactersInRanges: [NSValue(range: range)], replacementString: string)
|
|
}
|
|
|
|
// MARK: - Passthrough
|
|
|
|
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
|
|
passthroughDelegate?.textFieldShouldBeginEditing?(textField) ?? true
|
|
}
|
|
|
|
func textFieldDidBeginEditing(_ textField: UITextField) {
|
|
passthroughDelegate?.textFieldDidBeginEditing?(textField)
|
|
}
|
|
|
|
func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
|
|
passthroughDelegate?.textFieldShouldEndEditing?(textField) ?? true
|
|
}
|
|
|
|
func textFieldDidEndEditing(_ textField: UITextField, reason: UITextField.DidEndEditingReason) {
|
|
passthroughDelegate?.textFieldDidEndEditing?(textField, reason: reason)
|
|
}
|
|
|
|
func textFieldDidEndEditing(_ textField: UITextField) {
|
|
passthroughDelegate?.textFieldDidEndEditing?(textField)
|
|
}
|
|
|
|
func textFieldShouldClear(_ textField: UITextField) -> Bool {
|
|
passthroughDelegate?.textFieldShouldClear?(textField) ?? true
|
|
}
|
|
|
|
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
|
|
passthroughDelegate?.textFieldShouldReturn?(textField) ?? true
|
|
}
|
|
|
|
func textFieldDidChangeSelection(_ textField: UITextField) {
|
|
passthroughDelegate?.textFieldDidChangeSelection?(textField)
|
|
}
|
|
|
|
@available(iOS 26.0, *)
|
|
func textField(_ textField: UITextField, editMenuForCharactersInRanges ranges: [NSValue], suggestedActions: [UIMenuElement]) -> UIMenu? {
|
|
passthroughDelegate?.textField?(textField, editMenuForCharactersInRanges: ranges, suggestedActions: suggestedActions)
|
|
}
|
|
|
|
func textField(_ textField: UITextField, editMenuForCharactersIn range: NSRange, suggestedActions: [UIMenuElement]) -> UIMenu? {
|
|
passthroughDelegate?.textField?(textField, editMenuForCharactersIn: range, suggestedActions: suggestedActions)
|
|
}
|
|
|
|
func textField(_ textField: UITextField, willPresentEditMenuWith animator: any UIEditMenuInteractionAnimating) {
|
|
passthroughDelegate?.textField?(textField, willPresentEditMenuWith: animator)
|
|
}
|
|
|
|
func textField(_ textField: UITextField, willDismissEditMenuWith animator: any UIEditMenuInteractionAnimating) {
|
|
passthroughDelegate?.textField?(textField, willDismissEditMenuWith: animator)
|
|
}
|
|
|
|
func textField(_ textField: UITextField, insertInputSuggestion inputSuggestion: UIInputSuggestion) {
|
|
passthroughDelegate?.textField?(textField, insertInputSuggestion: inputSuggestion)
|
|
}
|
|
}
|