From 88da2ab50885cf8779bc57deb189e44599d65c76 Mon Sep 17 00:00:00 2001 From: Ivan Smolin Date: Mon, 18 Jul 2022 18:22:42 +0300 Subject: [PATCH] feat: UITextView now support configuration with BaseTextAttributes ReconfigurableView & ChangeableViewModel for non-destructing state update WrappedViewHolder protocol with table/collection view cell implementations --- CHANGELOG.md | 7 ++ LeadKit.podspec | 2 +- README.md | 24 ++++-- TIAppleMapUtils/TIAppleMapUtils.podspec | 2 +- TIAuth/TIAuth.podspec | 2 +- TIFoundationUtils/TIFoundationUtils.podspec | 2 +- TIGoogleMapUtils/TIGoogleMapUtils.podspec | 2 +- TIKeychainUtils/TIKeychainUtils.podspec | 2 +- TIMapUtils/TIMapUtils.podspec | 2 +- TIMoyaNetworking/TIMoyaNetworking.podspec | 2 +- .../DefaultTokenInterceptor.swift | 4 +- .../EndpointResponseTokenInterceptor.swift | 4 +- ...ltSecuritySchemesRequestPreprocessor.swift | 2 +- TINetworking/TINetworking.podspec | 2 +- TINetworkingCache/TINetworkingCache.podspec | 2 +- TIPagination/TIPagination.podspec | 2 +- TISwiftUICore/TISwiftUICore.podspec | 2 +- TISwiftUtils/TISwiftUtils.podspec | 2 +- TITableKitUtils/TITableKitUtils.podspec | 2 +- TITransitions/TITransitions.podspec | 2 +- .../ContainerCollectionViewCell.swift | 78 +++++++++++++++++++ .../Wrappers/ContainerTableViewCell.swift | 56 +++++++++++++ .../Sources/Wrappers/EdgeConstraints.swift | 54 +++++++++++++ .../ReusableCollectionContainerView.swift | 78 +++++++++++++++++++ .../WrappedViewHolder+ConfigurableView.swift | 35 +++++++++ .../Sources/Wrappers/WrappedViewHolder.swift | 55 +++++++++++++ TIUIElements/TIUIElements.podspec | 2 +- .../ActivityIndicator/ActivityIndicator.swift | 0 .../ActivityIndicatorHolder.swift | 0 .../Animatable.swift | 0 .../ChangeableViewModel.swift | 25 ++++++ .../ConfigurableView/ConfigurableView.swift | 0 .../ConfigurableView/ReconfigurableView.swift | 25 ++++++ .../InitializableViewProtocol.swift | 0 .../InitializeableViewController.swift | 0 .../Presenter/DefaultUIViewPresenter.swift | 45 +++++++++++ .../Presenter/ReusableUIViewPresenter.swift | 25 ++++++ .../Sources/Presenter/UIViewPresenters.swift | 27 +++++++ .../BaseTextAttributes.swift | 42 +++++++--- .../BaseTextAttributesConfigurable.swift | 16 +++- .../TextAttributes/ViewText/ViewText.swift | 4 + TIUIKitCore/TIUIKitCore.podspec | 2 +- TIYandexMapUtils/TIYandexMapUtils.podspec | 2 +- 43 files changed, 598 insertions(+), 44 deletions(-) create mode 100644 TIUIElements/Sources/Wrappers/ContainerCollectionViewCell.swift create mode 100644 TIUIElements/Sources/Wrappers/ContainerTableViewCell.swift create mode 100644 TIUIElements/Sources/Wrappers/EdgeConstraints.swift create mode 100644 TIUIElements/Sources/Wrappers/ReusableCollectionContainerView.swift create mode 100644 TIUIElements/Sources/Wrappers/WrappedViewHolder+ConfigurableView.swift create mode 100644 TIUIElements/Sources/Wrappers/WrappedViewHolder.swift rename TIUIKitCore/Sources/{Protocols => }/ActivityIndicator/ActivityIndicator.swift (100%) rename TIUIKitCore/Sources/{Protocols => }/ActivityIndicator/ActivityIndicatorHolder.swift (100%) rename TIUIKitCore/Sources/{Protocols/Animatable => ActivityIndicator}/Animatable.swift (100%) create mode 100644 TIUIKitCore/Sources/ConfigurableView/ChangeableViewModel.swift rename TIUIKitCore/Sources/{Protocols => }/ConfigurableView/ConfigurableView.swift (100%) create mode 100644 TIUIKitCore/Sources/ConfigurableView/ReconfigurableView.swift rename TIUIKitCore/Sources/{Protocols/InitializableViewProtocol => InitializableView}/InitializableViewProtocol.swift (100%) rename TIUIKitCore/Sources/{Protocols/InitializeableViewController => InitializableView}/InitializeableViewController.swift (100%) create mode 100644 TIUIKitCore/Sources/Presenter/DefaultUIViewPresenter.swift create mode 100644 TIUIKitCore/Sources/Presenter/ReusableUIViewPresenter.swift create mode 100644 TIUIKitCore/Sources/Presenter/UIViewPresenters.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index 86e1929f..c8b83a52 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +### 1.23.0 + +- **Update**: `UITextView` now support configuration with `BaseTextAttributes` +- **Add**: `ReconfigurableView` & `ChangeableViewModel` for non-destructing state update +- **Add**: `WrappedViewHolder` protocol with table/collection view cell implementations +- **Add**: `UIViewPresenter` and `ReusableUIViewPresenter ` protocols with default implementation for proper handling view/cells reuse + ### 1.22.0 - **Update**: Asynchronous request preprocessing diff --git a/LeadKit.podspec b/LeadKit.podspec index 4d42224b..4887cb1f 100644 --- a/LeadKit.podspec +++ b/LeadKit.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "LeadKit" - s.version = "1.22.0" + s.version = "1.23.0" s.summary = "iOS framework with a bunch of tools for rapid development" s.homepage = "https://github.com/TouchInstinct/LeadKit" s.license = "Apache License, Version 2.0" diff --git a/README.md b/README.md index 1f3fdd91..e8ca5c99 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,27 @@ # LeadKit + LeadKit is the iOS framework with a bunch of tools for rapid app development. -## Additional - -This repository contains the following additional frameworks: +This repository contains the following frameworks: +- [TISwiftUtils](TISwiftUtils) - a bunch of useful helpers for Swift development. +- [TIFoundationUtils](TIFoundationUtils) - set of helpers for Foundation framework classes. - [TIUIKitCore](TIUIKitCore) - core ui elements and protocols from LeadKit. -- [TITransitions](TITransitions) - set of custom transitions to present controller. +- [TISwiftUICore](TISwiftUICore) Core UI elements: protocols, views and helpers. - [TIUIElements](TIUIElements) - bunch of of useful protocols and views. - [OTPSwiftView](OTPSwiftView) - a fully customizable OTP view. -- [TISwiftUtils](TISwiftUtils) - a bunch of useful helpers for development. -- [TITableKitUtils](TITableKitUtils) - Set of helpers for TableKit classes. -- [TIFoundationUtils](TIFoundationUtils) - Set of helpers for Foundation framework classes. -- [TIKeychainUtils](TIKeychainUtils) - Set of helpers for Keychain classes. +- [TITableKitUtils](TITableKitUtils) - set of helpers for TableKit classes. +- [TIKeychainUtils](TIKeychainUtils) - set of helpers for Keychain classes. - [TIPagination](TIPagination) - realisation of paginating items from a data source. - [TINetworking](TINetworking) - Swagger-frendly networking layer helpers. - [TIMoyaNetworking](TIMoyaNetworking) - Moya + Swagger network service. +- [TIAppleMapUtils](TIAppleMapUtils) - set of helpers for map objects clustering and interacting using Apple MapKit. +- [TIGoogleMapUtils](TIGoogleMapUtils) - set of helpers for map objects clustering and interacting using Google Maps SDK. +- [TIYandexMapUtils](TIYandexMapUtils) - set of helpers for map objects clustering and interacting using Yandex Maps SDK. +- [TIAuth](TIAuth) - login, registration, confirmation and other related actions Useful docs: + - [Semantic Commit Messages](docs/semantic-commit-messages.md) - commit message codestyle. - [Snippets](docs/snippets.md) - useful commands and scripts for development. @@ -51,3 +55,7 @@ pod 'TISwiftUtils', 'x.y.z' pod 'TIFoundationUtils', 'x.y.z' # ... ``` + +## Legacy + +Code located in root `Sources` folder and `LeadKit.podspec` should be treated as legacy and shouldn't be used in newly created projects. Please use TI* modules via SPM or CocoaPods. \ No newline at end of file diff --git a/TIAppleMapUtils/TIAppleMapUtils.podspec b/TIAppleMapUtils/TIAppleMapUtils.podspec index 59ba157b..82814370 100644 --- a/TIAppleMapUtils/TIAppleMapUtils.podspec +++ b/TIAppleMapUtils/TIAppleMapUtils.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'TIAppleMapUtils' - s.version = '1.22.0' + s.version = '1.23.0' s.summary = 'Set of helpers for map objects clustering and interacting using Apple MapKit.' s.homepage = 'https://github.com/TouchInstinct/LeadKit/tree/' + s.version.to_s + '/' + s.name s.license = { :type => 'MIT', :file => 'LICENSE' } diff --git a/TIAuth/TIAuth.podspec b/TIAuth/TIAuth.podspec index 3266d6e5..c96a5dc6 100644 --- a/TIAuth/TIAuth.podspec +++ b/TIAuth/TIAuth.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'TIAuth' - s.version = '1.22.0' + s.version = '1.23.0' s.summary = 'Login, registration, confirmation and other related actions' s.homepage = 'https://github.com/TouchInstinct/LeadKit/tree/' + s.version.to_s + '/' + s.name s.license = { :type => 'MIT', :file => 'LICENSE' } diff --git a/TIFoundationUtils/TIFoundationUtils.podspec b/TIFoundationUtils/TIFoundationUtils.podspec index 07b02a63..e9337522 100644 --- a/TIFoundationUtils/TIFoundationUtils.podspec +++ b/TIFoundationUtils/TIFoundationUtils.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'TIFoundationUtils' - s.version = '1.22.0' + s.version = '1.23.0' s.summary = 'Set of helpers for Foundation framework classes.' s.homepage = 'https://github.com/TouchInstinct/LeadKit/tree/' + s.version.to_s + '/' + s.name s.license = { :type => 'MIT', :file => 'LICENSE' } diff --git a/TIGoogleMapUtils/TIGoogleMapUtils.podspec b/TIGoogleMapUtils/TIGoogleMapUtils.podspec index ea5456a5..51afd867 100644 --- a/TIGoogleMapUtils/TIGoogleMapUtils.podspec +++ b/TIGoogleMapUtils/TIGoogleMapUtils.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'TIGoogleMapUtils' - s.version = '1.22.0' + s.version = '1.23.0' s.summary = 'Set of helpers for map objects clustering and interacting using Google Maps SDK.' s.homepage = 'https://github.com/TouchInstinct/LeadKit/tree/' + s.version.to_s + '/' + s.name s.license = { :type => 'MIT', :file => 'LICENSE' } diff --git a/TIKeychainUtils/TIKeychainUtils.podspec b/TIKeychainUtils/TIKeychainUtils.podspec index d099e240..8a5bf760 100644 --- a/TIKeychainUtils/TIKeychainUtils.podspec +++ b/TIKeychainUtils/TIKeychainUtils.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'TIKeychainUtils' - s.version = '1.22.0' + s.version = '1.23.0' s.summary = 'Set of helpers for Keychain classes.' s.homepage = 'https://github.com/TouchInstinct/LeadKit/tree/' + s.version.to_s + '/' + s.name s.license = { :type => 'MIT', :file => 'LICENSE' } diff --git a/TIMapUtils/TIMapUtils.podspec b/TIMapUtils/TIMapUtils.podspec index ef157380..1fcf1bfd 100644 --- a/TIMapUtils/TIMapUtils.podspec +++ b/TIMapUtils/TIMapUtils.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'TIMapUtils' - s.version = '1.22.0' + s.version = '1.23.0' s.summary = 'Set of helpers for map objects clustering and interacting.' s.homepage = 'https://github.com/TouchInstinct/LeadKit/tree/' + s.version.to_s + '/' + s.name s.license = { :type => 'MIT', :file => 'LICENSE' } diff --git a/TIMoyaNetworking/TIMoyaNetworking.podspec b/TIMoyaNetworking/TIMoyaNetworking.podspec index d4061461..f97087fd 100644 --- a/TIMoyaNetworking/TIMoyaNetworking.podspec +++ b/TIMoyaNetworking/TIMoyaNetworking.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'TIMoyaNetworking' - s.version = '1.22.0' + s.version = '1.23.0' s.summary = 'Moya + Swagger network service.' s.homepage = 'https://github.com/TouchInstinct/LeadKit/tree/' + s.version.to_s + '/' + s.name s.license = { :type => 'MIT', :file => 'LICENSE' } diff --git a/TINetworking/Sources/Interceptors/DefaultTokenInterceptor.swift b/TINetworking/Sources/Interceptors/DefaultTokenInterceptor.swift index 3cc8f0bc..a1b0e528 100644 --- a/TINetworking/Sources/Interceptors/DefaultTokenInterceptor.swift +++ b/TINetworking/Sources/Interceptors/DefaultTokenInterceptor.swift @@ -38,11 +38,11 @@ open class DefaultTokenInterceptor: RequestInterceptor { public var defaultRetryStrategy: RetryResult = .doNotRetry public var requestModificationClosure: RequestModificationClosure? - public init(isTokenInvalidClosure: @escaping ShouldRefreshTokenClosure, + public init(shouldRefreshTokenClosure: @escaping ShouldRefreshTokenClosure, refreshTokenClosure: @escaping RefreshTokenClosure, requestModificationClosure: RequestModificationClosure? = nil) { - self.shouldRefreshToken = isTokenInvalidClosure + self.shouldRefreshToken = shouldRefreshTokenClosure self.refreshTokenClosure = refreshTokenClosure self.requestModificationClosure = requestModificationClosure } diff --git a/TINetworking/Sources/Interceptors/EndpointResponseTokenInterceptor.swift b/TINetworking/Sources/Interceptors/EndpointResponseTokenInterceptor.swift index 41434978..31c0b1af 100644 --- a/TINetworking/Sources/Interceptors/EndpointResponseTokenInterceptor.swift +++ b/TINetworking/Sources/Interceptors/EndpointResponseTokenInterceptor.swift @@ -29,14 +29,14 @@ open class EndpointResponseTokenInterceptor: DefaultTokenInterceptor 'MIT', :file => 'LICENSE' } diff --git a/TINetworkingCache/TINetworkingCache.podspec b/TINetworkingCache/TINetworkingCache.podspec index fa086f5a..2750e15a 100644 --- a/TINetworkingCache/TINetworkingCache.podspec +++ b/TINetworkingCache/TINetworkingCache.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'TINetworkingCache' - s.version = '1.22.0' + s.version = '1.23.0' s.summary = 'Caching results of EndpointRequests.' s.homepage = 'https://github.com/TouchInstinct/LeadKit/tree/' + s.version.to_s + '/' + s.name s.license = { :type => 'MIT', :file => 'LICENSE' } diff --git a/TIPagination/TIPagination.podspec b/TIPagination/TIPagination.podspec index be2e9143..39f0d82b 100644 --- a/TIPagination/TIPagination.podspec +++ b/TIPagination/TIPagination.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'TIPagination' - s.version = '1.22.0' + s.version = '1.23.0' s.summary = 'Generic pagination component.' s.homepage = 'https://github.com/TouchInstinct/LeadKit/tree/' + s.version.to_s + '/' + s.name s.license = { :type => 'MIT', :file => 'LICENSE' } diff --git a/TISwiftUICore/TISwiftUICore.podspec b/TISwiftUICore/TISwiftUICore.podspec index 7c8dde9f..b4275ad7 100644 --- a/TISwiftUICore/TISwiftUICore.podspec +++ b/TISwiftUICore/TISwiftUICore.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'TISwiftUICore' - s.version = '1.22.0' + s.version = '1.23.0' s.summary = 'Core UI elements: protocols, views and helpers..' s.homepage = 'https://github.com/TouchInstinct/LeadKit/tree/' + s.version.to_s + '/' + s.name s.license = { :type => 'MIT', :file => 'LICENSE' } diff --git a/TISwiftUtils/TISwiftUtils.podspec b/TISwiftUtils/TISwiftUtils.podspec index f22e5a1e..8bf7e61f 100644 --- a/TISwiftUtils/TISwiftUtils.podspec +++ b/TISwiftUtils/TISwiftUtils.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'TISwiftUtils' - s.version = '1.22.0' + s.version = '1.23.0' s.summary = 'Bunch of useful helpers for Swift development.' s.homepage = 'https://github.com/TouchInstinct/LeadKit/tree/' + s.version.to_s + '/' + s.name s.license = { :type => 'MIT', :file => 'LICENSE' } diff --git a/TITableKitUtils/TITableKitUtils.podspec b/TITableKitUtils/TITableKitUtils.podspec index d808aba8..ec633a93 100644 --- a/TITableKitUtils/TITableKitUtils.podspec +++ b/TITableKitUtils/TITableKitUtils.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'TITableKitUtils' - s.version = '1.22.0' + s.version = '1.23.0' s.summary = 'Set of helpers for TableKit classes.' s.homepage = 'https://github.com/TouchInstinct/LeadKit/tree/' + s.version.to_s + '/' + s.name s.license = { :type => 'MIT', :file => 'LICENSE' } diff --git a/TITransitions/TITransitions.podspec b/TITransitions/TITransitions.podspec index e1dcf910..8da93086 100644 --- a/TITransitions/TITransitions.podspec +++ b/TITransitions/TITransitions.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'TITransitions' - s.version = '1.22.0' + s.version = '1.23.0' s.summary = 'Set of custom transitions to present controller. ' s.homepage = 'https://github.com/TouchInstinct/LeadKit/tree/' + s.version.to_s + '/' + s.name s.license = { :type => 'MIT', :file => 'LICENSE' } diff --git a/TIUIElements/Sources/Wrappers/ContainerCollectionViewCell.swift b/TIUIElements/Sources/Wrappers/ContainerCollectionViewCell.swift new file mode 100644 index 00000000..c9a4dcef --- /dev/null +++ b/TIUIElements/Sources/Wrappers/ContainerCollectionViewCell.swift @@ -0,0 +1,78 @@ +// +// Copyright (c) 2022 Touch Instinct +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the Software), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +import UIKit +import TIUIKitCore + +open class ContainerCollectionViewCell: UICollectionViewCell, InitializableViewProtocol, WrappedViewHolder { + // MARK: - WrappedViewHolder + + public private(set) lazy var wrappedView = createView() + + public var contentInsets: UIEdgeInsets = .zero { + didSet { + contentEdgeConstraints?.update(from: contentInsets) + } + } + + private var contentEdgeConstraints: EdgeConstraints? + + // MARK: - Initialization + + override init(frame: CGRect) { + super.init(frame: frame) + + initializeView() + } + + required public init?(coder: NSCoder) { + super.init(coder: coder) + + initializeView() + } + + // MARK: - InitializableView + + open func addViews() { + addSubview(wrappedView) + } + + open func bindViews() { + // override in subclass + } + + open func configureLayout() { + contentEdgeConstraints = configureWrappedViewLayout() + } + + open func configureAppearance() { + // override in subclass + } + + open func localize() { + // override in subclass + } + + open func createView() -> View { + return View() + } +} diff --git a/TIUIElements/Sources/Wrappers/ContainerTableViewCell.swift b/TIUIElements/Sources/Wrappers/ContainerTableViewCell.swift new file mode 100644 index 00000000..f22aed9e --- /dev/null +++ b/TIUIElements/Sources/Wrappers/ContainerTableViewCell.swift @@ -0,0 +1,56 @@ +// +// Copyright (c) 2022 Touch Instinct +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the Software), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +import UIKit +import TIUIKitCore + +open class ContainerTableViewCell: BaseInitializableCell, WrappedViewHolder { + // MARK: - WrappedViewHolder + + public private(set) lazy var wrappedView = createView() + + public var contentInsets: UIEdgeInsets = .zero { + didSet { + contentEdgeConstraints?.update(from: contentInsets) + } + } + + private var contentEdgeConstraints: EdgeConstraints? + + // MARK: - InitializableView + + override open func addViews() { + super.addViews() + + addSubview(wrappedView) + } + + override open func configureLayout() { + super.configureLayout() + + contentEdgeConstraints = configureWrappedViewLayout() + } + + open func createView() -> View { + return View() + } +} diff --git a/TIUIElements/Sources/Wrappers/EdgeConstraints.swift b/TIUIElements/Sources/Wrappers/EdgeConstraints.swift new file mode 100644 index 00000000..0274afd8 --- /dev/null +++ b/TIUIElements/Sources/Wrappers/EdgeConstraints.swift @@ -0,0 +1,54 @@ +// +// Copyright (c) 2022 Touch Instinct +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the Software), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +import UIKit + +public struct EdgeConstraints { + public let leadingConstraint: NSLayoutConstraint + public let trailingConstraint: NSLayoutConstraint + public let topConstraint: NSLayoutConstraint + public let bottomConstraint: NSLayoutConstraint + + public var allConstraints: [NSLayoutConstraint] { + [ + leadingConstraint, + trailingConstraint, + topConstraint, + bottomConstraint + ] + } + + public func activate() { + NSLayoutConstraint.activate(allConstraints) + } + + public func deactivate() { + NSLayoutConstraint.deactivate(allConstraints) + } + + public func update(from insets: UIEdgeInsets) { + leadingConstraint.constant = insets.left + trailingConstraint.constant = -insets.right + topConstraint.constant = insets.top + bottomConstraint.constant = -insets.bottom + } +} diff --git a/TIUIElements/Sources/Wrappers/ReusableCollectionContainerView.swift b/TIUIElements/Sources/Wrappers/ReusableCollectionContainerView.swift new file mode 100644 index 00000000..c73cf449 --- /dev/null +++ b/TIUIElements/Sources/Wrappers/ReusableCollectionContainerView.swift @@ -0,0 +1,78 @@ +// +// Copyright (c) 2022 Touch Instinct +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the Software), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +import UIKit +import TIUIKitCore + +open class ReusableCollectionContainerView: UICollectionReusableView, InitializableViewProtocol, WrappedViewHolder { + // MARK: - WrappedViewHolder + + public private(set) lazy var wrappedView = createView() + + public var contentInsets: UIEdgeInsets = .zero { + didSet { + contentEdgeConstraints?.update(from: contentInsets) + } + } + + private var contentEdgeConstraints: EdgeConstraints? + + // MARK: - Initialization + + override init(frame: CGRect) { + super.init(frame: frame) + + initializeView() + } + + required public init?(coder: NSCoder) { + super.init(coder: coder) + + initializeView() + } + + // MARK: - InitializableView + + open func addViews() { + addSubview(wrappedView) + } + + open func bindViews() { + // override in subclass + } + + open func configureLayout() { + contentEdgeConstraints = configureWrappedViewLayout() + } + + open func configureAppearance() { + // override in subclass + } + + open func localize() { + // override in subclass + } + + open func createView() -> View { + return View() + } +} diff --git a/TIUIElements/Sources/Wrappers/WrappedViewHolder+ConfigurableView.swift b/TIUIElements/Sources/Wrappers/WrappedViewHolder+ConfigurableView.swift new file mode 100644 index 00000000..b6c6f863 --- /dev/null +++ b/TIUIElements/Sources/Wrappers/WrappedViewHolder+ConfigurableView.swift @@ -0,0 +1,35 @@ +// +// Copyright (c) 2022 Touch Instinct +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the Software), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +import TIUIKitCore + +public extension WrappedViewHolder where View: ConfigurableView { + func configure(with viewModel: View.ViewModelType) { + wrappedView.configure(with: viewModel) + } +} + +public extension WrappedViewHolder where View: ReconfigurableView { + func apply(change: View.ViewModelType.Change) { + wrappedView.apply(change: change) + } +} diff --git a/TIUIElements/Sources/Wrappers/WrappedViewHolder.swift b/TIUIElements/Sources/Wrappers/WrappedViewHolder.swift new file mode 100644 index 00000000..720a2cc0 --- /dev/null +++ b/TIUIElements/Sources/Wrappers/WrappedViewHolder.swift @@ -0,0 +1,55 @@ +// +// Copyright (c) 2022 Touch Instinct +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the Software), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +import UIKit + +public protocol WrappedViewHolder { + associatedtype View: UIView + + var wrappedView: View { get } + var contentView: UIView { get } + var contentInsets: UIEdgeInsets { get set } +} + +public extension WrappedViewHolder { + func wrappedViewConstraints() -> EdgeConstraints { + .init(leadingConstraint: wrappedView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor), + trailingConstraint: wrappedView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor), + topConstraint: wrappedView.topAnchor.constraint(equalTo: contentView.topAnchor), + bottomConstraint: wrappedView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor)) + } + + func configureWrappedViewLayout() -> EdgeConstraints { + wrappedView.translatesAutoresizingMaskIntoConstraints = false + + let contentEdgeConstraints = wrappedViewConstraints() + contentEdgeConstraints.activate() + + return contentEdgeConstraints + } +} + +public extension WrappedViewHolder where Self: UIView { + var contentView: UIView { + self + } +} diff --git a/TIUIElements/TIUIElements.podspec b/TIUIElements/TIUIElements.podspec index 93d0709f..41ad1437 100644 --- a/TIUIElements/TIUIElements.podspec +++ b/TIUIElements/TIUIElements.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'TIUIElements' - s.version = '1.22.0' + s.version = '1.23.0' s.summary = 'Bunch of useful protocols and views.' s.homepage = 'https://github.com/TouchInstinct/LeadKit/tree/' + s.version.to_s + '/' + s.name s.license = { :type => 'MIT', :file => 'LICENSE' } diff --git a/TIUIKitCore/Sources/Protocols/ActivityIndicator/ActivityIndicator.swift b/TIUIKitCore/Sources/ActivityIndicator/ActivityIndicator.swift similarity index 100% rename from TIUIKitCore/Sources/Protocols/ActivityIndicator/ActivityIndicator.swift rename to TIUIKitCore/Sources/ActivityIndicator/ActivityIndicator.swift diff --git a/TIUIKitCore/Sources/Protocols/ActivityIndicator/ActivityIndicatorHolder.swift b/TIUIKitCore/Sources/ActivityIndicator/ActivityIndicatorHolder.swift similarity index 100% rename from TIUIKitCore/Sources/Protocols/ActivityIndicator/ActivityIndicatorHolder.swift rename to TIUIKitCore/Sources/ActivityIndicator/ActivityIndicatorHolder.swift diff --git a/TIUIKitCore/Sources/Protocols/Animatable/Animatable.swift b/TIUIKitCore/Sources/ActivityIndicator/Animatable.swift similarity index 100% rename from TIUIKitCore/Sources/Protocols/Animatable/Animatable.swift rename to TIUIKitCore/Sources/ActivityIndicator/Animatable.swift diff --git a/TIUIKitCore/Sources/ConfigurableView/ChangeableViewModel.swift b/TIUIKitCore/Sources/ConfigurableView/ChangeableViewModel.swift new file mode 100644 index 00000000..221853b9 --- /dev/null +++ b/TIUIKitCore/Sources/ConfigurableView/ChangeableViewModel.swift @@ -0,0 +1,25 @@ +// +// Copyright (c) 2022 Touch Instinct +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the Software), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +public protocol ChangeableViewModel { + associatedtype Change +} diff --git a/TIUIKitCore/Sources/Protocols/ConfigurableView/ConfigurableView.swift b/TIUIKitCore/Sources/ConfigurableView/ConfigurableView.swift similarity index 100% rename from TIUIKitCore/Sources/Protocols/ConfigurableView/ConfigurableView.swift rename to TIUIKitCore/Sources/ConfigurableView/ConfigurableView.swift diff --git a/TIUIKitCore/Sources/ConfigurableView/ReconfigurableView.swift b/TIUIKitCore/Sources/ConfigurableView/ReconfigurableView.swift new file mode 100644 index 00000000..e7dde664 --- /dev/null +++ b/TIUIKitCore/Sources/ConfigurableView/ReconfigurableView.swift @@ -0,0 +1,25 @@ +// +// Copyright (c) 2022 Touch Instinct +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the Software), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +public protocol ReconfigurableView: ConfigurableView where ViewModelType: ChangeableViewModel { + func apply(change: ViewModelType.Change) +} diff --git a/TIUIKitCore/Sources/Protocols/InitializableViewProtocol/InitializableViewProtocol.swift b/TIUIKitCore/Sources/InitializableView/InitializableViewProtocol.swift similarity index 100% rename from TIUIKitCore/Sources/Protocols/InitializableViewProtocol/InitializableViewProtocol.swift rename to TIUIKitCore/Sources/InitializableView/InitializableViewProtocol.swift diff --git a/TIUIKitCore/Sources/Protocols/InitializeableViewController/InitializeableViewController.swift b/TIUIKitCore/Sources/InitializableView/InitializeableViewController.swift similarity index 100% rename from TIUIKitCore/Sources/Protocols/InitializeableViewController/InitializeableViewController.swift rename to TIUIKitCore/Sources/InitializableView/InitializeableViewController.swift diff --git a/TIUIKitCore/Sources/Presenter/DefaultUIViewPresenter.swift b/TIUIKitCore/Sources/Presenter/DefaultUIViewPresenter.swift new file mode 100644 index 00000000..e05d46d3 --- /dev/null +++ b/TIUIKitCore/Sources/Presenter/DefaultUIViewPresenter.swift @@ -0,0 +1,45 @@ +// +// Copyright (c) 2022 Touch Instinct +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the Software), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +open class DefaultUIViewPresenter: ReusableUIViewPresenter{ + public private(set) weak var view: View? + + public init() {} + + // MARK: - UIViewPresenter + + open func didCompleteConfiguration(of view: View) { + self.view = view + } + + // MARK: - ReusableUIViewPresenter + + open func willReuse(view: View) { + if didConfigure(view: view) { + self.view = nil + } + } + + open func didConfigure(view: View) -> Bool { + self.view === view + } +} diff --git a/TIUIKitCore/Sources/Presenter/ReusableUIViewPresenter.swift b/TIUIKitCore/Sources/Presenter/ReusableUIViewPresenter.swift new file mode 100644 index 00000000..37048990 --- /dev/null +++ b/TIUIKitCore/Sources/Presenter/ReusableUIViewPresenter.swift @@ -0,0 +1,25 @@ +// +// Copyright (c) 2022 Touch Instinct +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the Software), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +public protocol ReusableUIViewPresenter: UIViewPresenter { + func willReuse(view: View) +} diff --git a/TIUIKitCore/Sources/Presenter/UIViewPresenters.swift b/TIUIKitCore/Sources/Presenter/UIViewPresenters.swift new file mode 100644 index 00000000..5f911d44 --- /dev/null +++ b/TIUIKitCore/Sources/Presenter/UIViewPresenters.swift @@ -0,0 +1,27 @@ +// +// Copyright (c) 2022 Touch Instinct +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the Software), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +public protocol UIViewPresenter { + associatedtype View: AnyObject // should be stored weakly + + func didCompleteConfiguration(of view: View) +} diff --git a/TIUIKitCore/Sources/TextAttributes/BaseTextAttributes/BaseTextAttributes.swift b/TIUIKitCore/Sources/TextAttributes/BaseTextAttributes/BaseTextAttributes.swift index 9a97abd0..bc1c53ec 100644 --- a/TIUIKitCore/Sources/TextAttributes/BaseTextAttributes/BaseTextAttributes.swift +++ b/TIUIKitCore/Sources/TextAttributes/BaseTextAttributes/BaseTextAttributes.swift @@ -20,8 +20,7 @@ // THE SOFTWARE. // -import UIKit.UIFont -import UIKit.UIColor +import UIKit /// Base set of attributes to configure appearance of text. open class BaseTextAttributes { @@ -32,6 +31,18 @@ open class BaseTextAttributes { public let lineHeightMultiple: CGFloat public let numberOfLines: Int + open var attributedStringAttributes: [NSAttributedString.Key : Any] { + let paragraphStyle = NSMutableParagraphStyle() + paragraphStyle.alignment = alignment + paragraphStyle.lineHeightMultiple = lineHeightMultiple + + return [ + .font: font, + .foregroundColor: color, + .paragraphStyle: paragraphStyle + ] + } + public init(font: UIFont, color: UIColor, alignment: NSTextAlignment, @@ -61,6 +72,10 @@ open class BaseTextAttributes { configure(textContainer: textField) } + open func configure(textView: UITextView) { + configure(textContainer: textView) + } + open func configure(button: UIButton, for state: UIControl.State) { if let buttonLabel = button.titleLabel { configure(label: buttonLabel) @@ -110,6 +125,14 @@ open class BaseTextAttributes { attributedTextConfiguration: { textField.attributedText = $0 }) } + open func configure(textView: UITextView, with string: String?) { + configure(textContainer: textView, + with: string, + appearanceConfiguration: configure(textView:), + textConfiguration: { textView.text = $0 }, + attributedTextConfiguration: { textView.attributedText = $0 }) + } + open func configure(button: UIButton, with string: String?, for state: UIControl.State) { configure(textContainer: button, with: string, @@ -122,17 +145,12 @@ open class BaseTextAttributes { } open func attributedString(for string: String) -> NSAttributedString { - let paragraphStyle = NSMutableParagraphStyle() - paragraphStyle.alignment = alignment - paragraphStyle.lineHeightMultiple = lineHeightMultiple + NSAttributedString(string: string, attributes: attributedStringAttributes) + } - let attributes: [NSAttributedString.Key: Any] = [ - .font: font, - .foregroundColor: color, - .paragraphStyle: paragraphStyle - ] - - return NSAttributedString(string: string, attributes: attributes) + open func apply(in attributedString: NSMutableAttributedString, at range: NSRange? = nil) { + attributedString.addAttributes(attributedStringAttributes, + range: range ?? NSRange(location: 0, length: attributedString.length)) } } diff --git a/TIUIKitCore/Sources/TextAttributes/BaseTextAttributes/BaseTextAttributesConfigurable.swift b/TIUIKitCore/Sources/TextAttributes/BaseTextAttributes/BaseTextAttributesConfigurable.swift index 7cdd18b8..4b771dad 100644 --- a/TIUIKitCore/Sources/TextAttributes/BaseTextAttributes/BaseTextAttributesConfigurable.swift +++ b/TIUIKitCore/Sources/TextAttributes/BaseTextAttributes/BaseTextAttributesConfigurable.swift @@ -22,7 +22,7 @@ import UIKit -protocol BaseTextAttributesConfigurable { +public protocol BaseTextAttributesConfigurable { func set(font: UIFont) func set(color: UIColor) func set(alignment: NSTextAlignment) @@ -55,3 +55,17 @@ extension UITextField: BaseTextAttributesConfigurable { textAlignment = alignment } } + +extension UITextView: BaseTextAttributesConfigurable { + public func set(font: UIFont) { + self.font = font + } + + public func set(color: UIColor) { + textColor = color + } + + public func set(alignment: NSTextAlignment) { + textAlignment = alignment + } +} diff --git a/TIUIKitCore/Sources/TextAttributes/ViewText/ViewText.swift b/TIUIKitCore/Sources/TextAttributes/ViewText/ViewText.swift index 2900fee8..8c28c41b 100644 --- a/TIUIKitCore/Sources/TextAttributes/ViewText/ViewText.swift +++ b/TIUIKitCore/Sources/TextAttributes/ViewText/ViewText.swift @@ -68,6 +68,10 @@ public struct ViewText { attributes.configure(textField: textField, with: text) } + public func configure(textView: UITextView) { + attributes.configure(textView: textView, with: text) + } + public func configure(button: UIButton, for state: UIControl.State) { attributes.configure(button: button, with: text, for: state) } diff --git a/TIUIKitCore/TIUIKitCore.podspec b/TIUIKitCore/TIUIKitCore.podspec index 32675f8d..e88542df 100644 --- a/TIUIKitCore/TIUIKitCore.podspec +++ b/TIUIKitCore/TIUIKitCore.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'TIUIKitCore' - s.version = '1.22.0' + s.version = '1.23.0' s.summary = 'Core UI elements: protocols, views and helpers.' s.homepage = 'https://github.com/TouchInstinct/LeadKit/tree/' + s.version.to_s + '/' + s.name s.license = { :type => 'MIT', :file => 'LICENSE' } diff --git a/TIYandexMapUtils/TIYandexMapUtils.podspec b/TIYandexMapUtils/TIYandexMapUtils.podspec index 851f7167..5d3b0c9c 100644 --- a/TIYandexMapUtils/TIYandexMapUtils.podspec +++ b/TIYandexMapUtils/TIYandexMapUtils.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'TIYandexMapUtils' - s.version = '1.22.0' + s.version = '1.23.0' s.summary = 'Set of helpers for map objects clustering and interacting using Yandex Maps SDK.' s.homepage = 'https://github.com/TouchInstinct/LeadKit/tree/' + s.version.to_s + '/' + s.name s.license = { :type => 'MIT', :file => 'LICENSE' }