Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 16 additions & 15 deletions Code/Behavior/ELDefaultTextFieldBehavior.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import Foundation
import UIKit

/// Описывает поведение поля ввода по умолчанию
@MainActor
open class ELDefaultTextFieldBehavior: NSObject, ELTextFieldBehavior {

public let mask: ELTextFieldInputMask
Expand All @@ -30,7 +31,7 @@ open class ELDefaultTextFieldBehavior: NSObject, ELTextFieldBehavior {
private var customRightMode: ELRightViewMode?
private var customLeftMode: ELLeftViewMode?

public var onAction: ((ELBehaviorAction) -> Void)?
public var onAction: (@Sendable (ELBehaviorAction) -> Void)?
public let isEditable: Bool
public weak var containerDelegate: ELContainerDelegate?
public private(set) var textInput: (ELTextInput & ELTextInputConfigurable)?
Expand All @@ -52,9 +53,9 @@ open class ELDefaultTextFieldBehavior: NSObject, ELTextFieldBehavior {
/// - validation: Правило валидации поля
public init(
text: String? = nil,
textMapper: ((String?) -> NSAttributedString?)? = nil,
textMapper: (@Sendable (String?) -> NSAttributedString?)? = nil,
placeholder: String? = nil,
placeholderMapper: ((String?) -> NSAttributedString?)? = nil,
placeholderMapper: (@Sendable (String?) -> NSAttributedString?)? = nil,
isEditable: Bool = true,
leftMode: ELLeftViewMode? = nil,
rightMode: ELRightViewMode? = nil,
Expand All @@ -78,7 +79,7 @@ open class ELDefaultTextFieldBehavior: NSObject, ELTextFieldBehavior {
attributedTextMapper: textMapper
)
}

open func configure(textInput: ELTextInput & ELTextInputConfigurable) {
self.textInput = textInput
textInput.inputView = nil
Expand All @@ -89,7 +90,7 @@ open class ELDefaultTextFieldBehavior: NSObject, ELTextFieldBehavior {
textInput.configureRightItem(with: customRightMode?.initialContainer(textInput: textInput))
textInput.configureLeftItem(with: customLeftMode?.initialContainer(textInput: textInput))
}

open func updateState(_ state: ELTextFieldState) {
viewModel.state = state
textInput?.configureRightItem(
Expand All @@ -107,16 +108,16 @@ open class ELDefaultTextFieldBehavior: NSObject, ELTextFieldBehavior {
textInput?.updateState(viewModel.state)
containerDelegate?.container(self, changedState: state)
}

open func updateText(_ newText: String?) {
updateText(newValue: newText)
}

public func textInputShouldClear(_: ELTextInput) -> Bool {
updateText("")
return true
}

open func textInputShouldBeginEditing(_: ELTextInput) -> Bool {
guard isEditable else {
return false
Expand All @@ -131,7 +132,7 @@ open class ELDefaultTextFieldBehavior: NSObject, ELTextFieldBehavior {
return true
}
}

public func textInputDidBeginEditing(_ textInput: ELTextInput) {
containerDelegate?.startEditing(in: self)
}
Expand All @@ -144,11 +145,11 @@ open class ELDefaultTextFieldBehavior: NSObject, ELTextFieldBehavior {
updateState(.default)
}
}

/// При вводе текста свайпом происходит рекурсивный вызов методов:
/// https://stackoverflow.com/questions/58560843/ios-13-crash-with-swipekeyboard-and-textfieldshouldchangecharactersin
private var lastEntry: String?

open func textInput(
_ textInput: ELTextInput & UITextInput,
shouldChangeCharactersIn range: NSRange,
Expand Down Expand Up @@ -205,7 +206,7 @@ open class ELDefaultTextFieldBehavior: NSObject, ELTextFieldBehavior {
range: range
)
}

private func updateText(newValue: String?) {
textInput?.enteredText = newValue
viewModel.text = newValue.isNilOrEmpty ? nil : newValue
Expand All @@ -225,14 +226,14 @@ open class ELDefaultTextFieldBehavior: NSObject, ELTextFieldBehavior {
}
return true
}

public func textInputShouldReturn(_ textInput: ELTextInput) -> Bool {
onAction?(.return)
containerDelegate?.return(in: self)
textInput.resignFirstResponder()
return true
}

open func textInput(_: ELTextInput, canPerformAction _: Selector, withSender _: Any?) -> Bool {
true
}
Expand Down Expand Up @@ -266,7 +267,7 @@ private extension UITextInput {
offset = range.location
}
}

guard let textPosition = position(from: beginningOfDocument, offset: offset) else {
return
}
Expand Down
7 changes: 4 additions & 3 deletions Code/Behavior/ELTextFieldBehavior.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import Foundation

/// Действия, которые могут произойти с Behavior
public enum ELBehaviorAction {
public enum ELBehaviorAction: Sendable {
/// Текст был изменен
case changed(newValue: String)
/// Ввод завершен
Expand All @@ -18,6 +18,7 @@ public enum ELBehaviorAction {
}

/// Хранит состояние поля ввода
@MainActor
public protocol ELTextFieldBehavior: ELTextInputDelegate {

/// Маска поля ввода
Expand All @@ -34,10 +35,10 @@ public protocol ELTextFieldBehavior: ELTextInputDelegate {
var isValid: Bool { get }

/// Срабатывает при срабатывании событий поля ввода
var onAction: ((ELBehaviorAction) -> Void)? { get set }
var onAction: (@Sendable (ELBehaviorAction) -> Void)? { get set }
/// Используется для обработки дополнительных событий делегата
var containerDelegate: ELContainerDelegate? { get set }

func configure(textInput: ELTextInput & ELTextInputConfigurable)
func updateState(_ state: ELTextFieldState)
func updateText(_ newText: String?)
Expand Down
2 changes: 1 addition & 1 deletion Code/Behavior/ELTextFieldState.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import Foundation

/// Состояние TextField
public enum ELTextFieldState {
public enum ELTextFieldState: Sendable {
/// Не в фокусе
case `default`
/// Ошибка (например, валидации)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import Foundation
import UIKit

/// Конфигурация представления TextInput
@MainActor
public protocol ELTextInputConfigurable: AnyObject {
var textInputDelegate: ELTextInputDelegate? { get set }
var touchesDelegate: ELTouchesDelegate? { get set }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import Foundation

/// Маска для преобразования введенного текста в пользовательское представление и наоборот
public protocol ELTextFieldInputMask {
public protocol ELTextFieldInputMask: Sendable {

/// Возвращает текст для отображения пользователю
///
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import Foundation
import UIKit

/// Содержит все поля, необходимые для настройки ввода
public protocol ELTextFieldInputTraits {
public protocol ELTextFieldInputTraits: Sendable {
var isSecureTextEntry: Bool { get set }
var keyboardType: UIKeyboardType { get set }
var contentType: UITextContentType? { get set }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Foundation
import UIKit

/// Содержит информацию о rightView
public struct ELRightViewContainer {
public struct ELRightViewContainer: Sendable {
let view: UIView?
let rightViewMode: UITextField.ViewMode
let clearButtonMode: UITextField.ViewMode
Expand Down Expand Up @@ -52,7 +52,7 @@ public struct ELRightViewContainer {
}
}

public struct ELLeftViewContainer {
public struct ELLeftViewContainer: Sendable {
let view: UIView?
let leftViewMode: UITextField.ViewMode

Expand Down
2 changes: 2 additions & 0 deletions Code/Configuration/Context/RightView/ELRightViewMode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import Foundation
import UIKit

/// Протокол для создания кастомного поведения правой иконки
@MainActor
public protocol ELRightViewMode: AnyObject {

func initialContainer(textInput: ELTextInput) -> ELRightViewContainer
Expand All @@ -19,6 +20,7 @@ public protocol ELRightViewMode: AnyObject {
}

/// Протокол для создания кастомного поведения левой иконки
@MainActor
public protocol ELLeftViewMode: AnyObject {

func initialContainer(textInput: ELTextInput) -> ELLeftViewContainer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import Foundation
import UIKit

@MainActor
public final class ELSystemActionRightView: ELRightViewMode {

private let view: UIView
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import Foundation

/// Поведение по-умолчанию подразумевает, что поле ввода валидно, если оно не пустое
public class ELDefaultTextFieldValidator: ELTextFieldValidator {
public final class ELDefaultTextFieldValidator: ELTextFieldValidator {

public func isValid(text: String?) -> Bool {
text?.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty == false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import Foundation

/// Валидатор поля e-mail
public class ELMailTextFieldValidator: ELTextFieldValidator {
public final class ELMailTextFieldValidator: ELTextFieldValidator {

private enum Constants {
static let matchRule = "SELF MATCHES %@"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import Foundation

/// Описывает валидацию ввода
public struct ELTextFieldValidation {
public struct ELTextFieldValidation: Sendable {
/// Предоставляет правило валидации
public let validator: ELTextFieldValidator
/// Предоставляет правило срабатывания проверки валидности текста
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import Foundation

/// Правило срабатывания валидации поля ввода
public enum ELTextFieldValidationRule {
public enum ELTextFieldValidationRule: Sendable {
/// Каждый раз при изменении текста
case onChange
/// При завершении редактирования
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import Foundation

/// Валидатор для проверки корректности введенного текста
public protocol ELTextFieldValidator {
public protocol ELTextFieldValidator: Sendable {

/// Проверяет валидность текста
///
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import Foundation
import UIKit

/// Используется для хранения данных о TextInput
public struct ELTextInputViewModel {
public struct ELTextInputViewModel: Sendable {
public var text: String?
public var placeholder: String?
public var leftView: UIView?
Expand All @@ -16,10 +16,10 @@ public struct ELTextInputViewModel {
/// Маппер для преобразования текста плейсхолдера
///
/// Используется в случае, когда плейсхолдер имеет кастомный шрифт
public var attributedPlaceholderMapper: ((String?) -> NSAttributedString?)?
public var attributedPlaceholderMapper: (@Sendable (String?) -> NSAttributedString?)?

/// Маппер для преобразования введенного текста
///
/// Используется в случае, когда текст имеет кастомный шрифт
public var attributedTextMapper: ((String?) -> NSAttributedString?)?
public var attributedTextMapper: (@Sendable (String?) -> NSAttributedString?)?
}
1 change: 1 addition & 0 deletions Code/Containers/ELContainerDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import Foundation

/// Методы делегата для обработки дополнительных событий с полем ввода
@MainActor
public protocol ELContainerDelegate: AnyObject {

func startEditing(in behavior: ELTextFieldBehavior)
Expand Down
1 change: 1 addition & 0 deletions Code/Inputs/ELTextInput.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import Foundation
import UIKit

@MainActor
public protocol ELTextInput: UIView {
var attributedTextMapper: ((String?) -> NSAttributedString?)? { get set }
var enteredText: String? { get set }
Expand Down
2 changes: 2 additions & 0 deletions Code/Inputs/ELTextInputDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import UIKit
/// Методы делегата TextInput
///
/// Является оберткой над UITextFieldDelegate и UITextViewDelegate
@MainActor
public protocol ELTextInputDelegate: AnyObject {
func textInputShouldClear(_ textInput: ELTextInput) -> Bool
func textInputShouldBeginEditing(_ textInput: ELTextInput) -> Bool
Expand All @@ -27,6 +28,7 @@ public protocol ELTextInputDelegate: AnyObject {
) -> Bool
}

@MainActor
public protocol ELTouchesDelegate: AnyObject {
func pointInside(in textInput: ELTextInput, isInside: Bool)
func touchesBegan(in textInput: ELTextInput, touches: Set<UITouch>, with event: UIEvent?)
Expand Down
Loading