From 57b3e7fa3260b7d8516f968f7feeeb6b185a630f Mon Sep 17 00:00:00 2001 From: robot-divkit Date: Mon, 15 Jan 2024 15:47:34 +0300 Subject: [PATCH] Release 29.2.0 --- .mapping.json | 6 ++ .../CopyToClipboardActionHandler.swift | 10 ++- DivKit/Actions/DivActionHandler.swift | 6 +- DivKit/Actions/DivActionLogger.swift | 4 +- DivKit/Debug/Block+DebugInfo.swift | 2 +- DivKit/DivBlockModelingContext.swift | 13 --- DivKit/DivError.swift | 2 +- DivKit/DivImageHolderFactory.swift | 2 +- DivKit/DivKitComponents.swift | 4 - DivKit/DivKitInfo.swift | 2 +- DivKit/DivStatePath.swift | 4 +- .../CalcExpression/AnyCalcExpression.swift | 2 +- .../CalcExpression/CalcExpression.swift | 8 +- .../CalcExpression/CalcExpressionError.swift | 18 ++-- DivKit/Expressions/Expression.swift | 9 -- DivKit/Expressions/ExpressionError.swift | 2 +- DivKit/Expressions/ExpressionLink.swift | 7 +- DivKit/Expressions/ExpressionResolver.swift | 35 +++----- .../Functions/ArrayFunctions.swift | 2 +- .../Functions/IntervalFunctions.swift | 2 +- .../Functions/StringFunctions.swift | 2 +- DivKit/Expressions/FunctionsProvider.swift | 4 +- .../Serialization/DictionaryExtensions.swift | 26 ++---- .../Serialization/Expression+Helpers.swift | 34 ++------ .../Expression+ValidSerializationValue.swift | 11 --- .../Serialization/FieldExtensions.swift | 42 ++-------- DivKit/Extensions/ArrayExtensions.swift | 2 +- .../DivAccessibilityExtensions.swift | 69 +++++++--------- .../Extensions/DivAction/DivActionBase.swift | 11 ++- .../DivAction/DivActionExtensions.swift | 13 +-- .../DivAction/DivActionsHolder.swift | 2 +- .../DivBase/DivBaseExtensions.swift | 44 +++++----- .../DivContainer+Accessibility.swift | 72 ++++++++++++++++ .../DivContainer/DivContainerExtensions.swift | 24 ++---- .../DivContainerItemsExtensions.swift | 82 +++++++------------ .../DivData/DivDataPatchExtensions.swift | 6 +- .../DivDisappearActionExtensions.swift | 5 +- .../Extensions/DivEdgeInsetsExtensions.swift | 6 +- DivKit/Extensions/DivExtensions.swift | 42 +--------- .../DivGallery/DivGallerySizeModifier.swift | 2 +- DivKit/Extensions/DivGridExtensions.swift | 2 +- .../DivImage/DivImageProtocol.swift | 2 +- .../Extensions/DivIndicatorExtensions.swift | 6 +- DivKit/Extensions/DivSliderExtensions.swift | 4 +- DivKit/Extensions/DivStateExtensions.swift | 2 +- DivKit/Extensions/DivTabsExtensions.swift | 6 +- DivKit/Extensions/DivTextExtensions.swift | 44 ++++------ DivKit/Extensions/DivTooltipExtensions.swift | 4 +- DivKit/Extensions/DivVideoExtensions.swift | 2 +- .../DivVisibilityActionExtensions.swift | 5 +- DivKit/RunLoopCardUpdateAggregator.swift | 22 +++-- DivKit/States/DivStateManager.swift | 2 +- .../Templates/SerializationExtensions.swift | 34 +++----- DivKit/Timers/DivTimerController.swift | 2 +- DivKit/Timers/TimeIntervalMeasuring.swift | 4 +- DivKit/Variables/DivTriggersStorage.swift | 2 +- DivKit/Variables/DivVariableStorage.swift | 6 +- DivKit/Variables/DivVariableTracker.swift | 20 +++-- DivKit/Variables/DivVariableValue.swift | 2 +- DivKit/Variables/DivVariablesStorage.swift | 6 +- DivKit/Views/DivBlockProvider.swift | 6 +- DivKit/Views/DivView.swift | 4 +- DivKit/generated_sources/DivText.swift | 8 +- .../generated_sources/DivTextTemplate.swift | 6 +- ...ationBlockView+UIViewRenderableBlock.swift | 2 +- .../Animations/AnimationBlockView.swift | 4 +- .../ImageExtensionHandler.swift | 2 +- .../PinchToZoomExtensionHandler.swift | 2 +- .../TextExtensionHandler.swift | 2 +- DivKitExtensions/Shimmer/ShimmerStyle.swift | 6 +- DivKitExtensions/Shimmer/ShimmerView.swift | 2 +- .../SizeProviderExtensionHandler.swift | 4 +- LayoutKit/Interface/UIElementPath.swift | 2 +- LayoutKit/Interface/UserInterfaceAction.swift | 2 +- .../Base/AttributedStringExtensions.swift | 2 +- .../LayoutKit/Base/MaskedInputViewModel.swift | 4 +- .../LayoutKit/Base/Masks/MaskValidator.swift | 2 +- LayoutKit/LayoutKit/Base/TimeMeasure.swift | 2 +- .../Anchor/AnchorBlock+UIViewRenderable.swift | 2 +- .../LayoutKit/Blocks/Block+Debugging.swift | 16 ++-- LayoutKit/LayoutKit/Blocks/Block.swift | 4 +- LayoutKit/LayoutKit/Blocks/BlockError.swift | 4 +- .../Container/AxialAlignmentManager.swift | 2 +- .../Blocks/Container/ContainerBlock.swift | 33 ++++---- .../Container/ContainerBlockLayout.swift | 40 ++++----- .../Blocks/Container/WrapLayoutGroups.swift | 22 ++--- .../Decorations/Block+Decorations.swift | 9 +- LayoutKit/LayoutKit/Blocks/GalleryBlock.swift | 4 +- .../LayoutKit/Blocks/Grid/GridBlock.swift | 2 +- .../LayoutKit/Blocks/Grid/GridLayout.swift | 18 ++-- .../Array+ImageRenderableBlock.swift | 2 +- .../LayoutKit/Blocks/IntrincisHeights.swift | 2 +- LayoutKit/LayoutKit/Blocks/LayeredBlock.swift | 8 +- LayoutKit/LayoutKit/Blocks/PagerBlock.swift | 4 +- .../LayoutKit/Blocks/Shadow/ShadedBlock.swift | 2 +- .../LayoutKit/Blocks/Slider/SliderView.swift | 12 +-- LayoutKit/LayoutKit/Blocks/TabsBlock.swift | 2 +- LayoutKit/LayoutKit/Blocks/TextBlock.swift | 6 +- .../Blocks/TextFieldBlock+Debugging.swift | 2 +- .../LayoutKit/Blocks/TextFieldBlock.swift | 2 +- .../LayoutKit/Blocks/TextInputBlock.swift | 2 +- .../Blocks/TransitioningAnimation.swift | 2 +- LayoutKit/LayoutKit/GenericViewBlock.swift | 4 +- .../UI/Actions/UIActionEventPerforming.swift | 4 +- .../UI/Actions/UIActionExtensions.swift | 2 +- .../Base/GenericCollectionReusableView.swift | 4 +- .../UI/Base/GenericCollectionViewCell.swift | 4 +- .../UI/Base/GenericCollectionViewLayout.swift | 2 +- ...ableImageBlock+UIViewRenderableBlock.swift | 2 +- .../UI/Blocks/Array+UIViewRenderable.swift | 2 +- ...ackgroundBlock+UIViewRenderableBlock.swift | 2 +- ...ecoratingBlock+UIViewRenderableBlock.swift | 10 +-- ...AnimationBlock+UIViewRenderableBlock.swift | 12 +-- .../LayoutKit/UI/Blocks/ElementState.swift | 2 +- .../GridBlock+UIViewRenderableBlock.swift | 2 +- .../ShadedBlock+UIViewRenderableBlock.swift | 2 +- .../StateBlock+UIViewRenderableBlock.swift | 4 +- ...SwipeContainerBlock+UIViewRenderable.swift | 2 +- .../TextBlock+UIViewRenderableBlock.swift | 32 ++++---- ...TextFieldBlock+UIViewRenderableBlock.swift | 2 +- ...TextInputBlock+UIViewRenderableBlock.swift | 10 +-- .../UI/Blocks/TooltipContainerView.swift | 2 +- ...sitioningBlock+UIViewRenderableBlock.swift | 4 +- .../UIView+TransitioningAnimation.swift | 2 +- .../UI/Blocks/UIViewRenderable.swift | 4 +- .../VideoBlock+UIViewRenderableBlock.swift | 2 +- .../UI/Views/Background+UIViewRendering.swift | 2 +- .../UI/Views/ContextMenuDelegate.swift | 4 +- .../LayoutKit/UI/Views/GalleryView.swift | 8 +- .../Views/TabbedPages/TabContentsView.swift | 8 +- .../UI/Views/TabbedPages/TabListView.swift | 4 +- .../TabbedPages/TabListViewDelegate.swift | 8 +- .../TabbedPages/TabSelectionWireframe.swift | 8 +- .../Views/TabbedPages/TabbedPagesView.swift | 2 +- .../LayoutKit/UI/Views/ViewWithShadow.swift | 4 +- .../LayoutKit/ViewModels/Background.swift | 2 +- .../ViewModels/GalleryViewLayout.swift | 14 ++-- .../ViewModels/GalleryViewModel.swift | 2 +- .../ViewModels/PagerViewLayout.swift | 12 +-- .../TabbedPages/TabContentsViewLayout.swift | 2 +- .../TabbedPages/TabContentsViewModel.swift | 4 +- .../TabInterimItemExtensions.swift | 2 +- .../TabbedPages/TabListViewModel.swift | 2 +- .../TabbedPages/TabViewLayout.swift | 4 +- Serialization/DeserializationError.swift | 6 +- Serialization/Dictionary+Serialization.swift | 6 +- Specs/DivKit/29.2.0/DivKit.podspec | 25 ++++++ .../29.2.0/DivKitExtensions.podspec | 22 +++++ .../29.2.0/DivKit_LayoutKit.podspec | 24 ++++++ .../29.2.0/DivKit_LayoutKitInterface.podspec | 25 ++++++ .../29.2.0/DivKit_Serialization.podspec | 23 ++++++ 151 files changed, 715 insertions(+), 706 deletions(-) create mode 100644 DivKit/Extensions/DivContainer/DivContainer+Accessibility.swift create mode 100644 Specs/DivKit/29.2.0/DivKit.podspec create mode 100644 Specs/DivKitExtensions/29.2.0/DivKitExtensions.podspec create mode 100644 Specs/DivKit_LayoutKit/29.2.0/DivKit_LayoutKit.podspec create mode 100644 Specs/DivKit_LayoutKitInterface/29.2.0/DivKit_LayoutKitInterface.podspec create mode 100644 Specs/DivKit_Serialization/29.2.0/DivKit_Serialization.podspec diff --git a/.mapping.json b/.mapping.json index 6641ee82..19a4b803 100644 --- a/.mapping.json +++ b/.mapping.json @@ -76,6 +76,7 @@ "DivKit/Extensions/DivBase/DivBaseExtensions.swift":"divkit/public-ios/DivKit/Extensions/DivBase/DivBaseExtensions.swift", "DivKit/Extensions/DivChangeTransitionExtensions.swift":"divkit/public-ios/DivKit/Extensions/DivChangeTransitionExtensions.swift", "DivKit/Extensions/DivContainer/DivCollectionItemsBuilderExtensions.swift":"divkit/public-ios/DivKit/Extensions/DivContainer/DivCollectionItemsBuilderExtensions.swift", + "DivKit/Extensions/DivContainer/DivContainer+Accessibility.swift":"divkit/public-ios/DivKit/Extensions/DivContainer/DivContainer+Accessibility.swift", "DivKit/Extensions/DivContainer/DivContainerExtensions.swift":"divkit/public-ios/DivKit/Extensions/DivContainer/DivContainerExtensions.swift", "DivKit/Extensions/DivContainer/DivContainerItemsExtensions.swift":"divkit/public-ios/DivKit/Extensions/DivContainer/DivContainerItemsExtensions.swift", "DivKit/Extensions/DivContainer/DivContainerSizeModifier.swift":"divkit/public-ios/DivKit/Extensions/DivContainer/DivContainerSizeModifier.swift", @@ -842,6 +843,7 @@ "Specs/DivKit/29.0.0/DivKit.podspec":"divkit/public-ios/Specs/DivKit/29.0.0/DivKit.podspec", "Specs/DivKit/29.0.1/DivKit.podspec":"divkit/public-ios/Specs/DivKit/29.0.1/DivKit.podspec", "Specs/DivKit/29.1.0/DivKit.podspec":"divkit/public-ios/Specs/DivKit/29.1.0/DivKit.podspec", + "Specs/DivKit/29.2.0/DivKit.podspec":"divkit/public-ios/Specs/DivKit/29.2.0/DivKit.podspec", "Specs/DivKitExtensions/24.3.0/DivKitExtensions.podspec":"divkit/public-ios/Specs/DivKitExtensions/24.3.0/DivKitExtensions.podspec", "Specs/DivKitExtensions/25.0.0/DivKitExtensions.podspec":"divkit/public-ios/Specs/DivKitExtensions/25.0.0/DivKitExtensions.podspec", "Specs/DivKitExtensions/25.1.0/DivKitExtensions.podspec":"divkit/public-ios/Specs/DivKitExtensions/25.1.0/DivKitExtensions.podspec", @@ -877,6 +879,7 @@ "Specs/DivKitExtensions/29.0.0/DivKitExtensions.podspec":"divkit/public-ios/Specs/DivKitExtensions/29.0.0/DivKitExtensions.podspec", "Specs/DivKitExtensions/29.0.1/DivKitExtensions.podspec":"divkit/public-ios/Specs/DivKitExtensions/29.0.1/DivKitExtensions.podspec", "Specs/DivKitExtensions/29.1.0/DivKitExtensions.podspec":"divkit/public-ios/Specs/DivKitExtensions/29.1.0/DivKitExtensions.podspec", + "Specs/DivKitExtensions/29.2.0/DivKitExtensions.podspec":"divkit/public-ios/Specs/DivKitExtensions/29.2.0/DivKitExtensions.podspec", "Specs/DivKit_LayoutKit/28.0.1/DivKit_LayoutKit.podspec":"divkit/public-ios/Specs/DivKit_LayoutKit/28.0.1/DivKit_LayoutKit.podspec", "Specs/DivKit_LayoutKit/28.1.0/DivKit_LayoutKit.podspec":"divkit/public-ios/Specs/DivKit_LayoutKit/28.1.0/DivKit_LayoutKit.podspec", "Specs/DivKit_LayoutKit/28.10.0/DivKit_LayoutKit.podspec":"divkit/public-ios/Specs/DivKit_LayoutKit/28.10.0/DivKit_LayoutKit.podspec", @@ -894,6 +897,7 @@ "Specs/DivKit_LayoutKit/29.0.0/DivKit_LayoutKit.podspec":"divkit/public-ios/Specs/DivKit_LayoutKit/29.0.0/DivKit_LayoutKit.podspec", "Specs/DivKit_LayoutKit/29.0.1/DivKit_LayoutKit.podspec":"divkit/public-ios/Specs/DivKit_LayoutKit/29.0.1/DivKit_LayoutKit.podspec", "Specs/DivKit_LayoutKit/29.1.0/DivKit_LayoutKit.podspec":"divkit/public-ios/Specs/DivKit_LayoutKit/29.1.0/DivKit_LayoutKit.podspec", + "Specs/DivKit_LayoutKit/29.2.0/DivKit_LayoutKit.podspec":"divkit/public-ios/Specs/DivKit_LayoutKit/29.2.0/DivKit_LayoutKit.podspec", "Specs/DivKit_LayoutKitInterface/28.0.1/DivKit_LayoutKitInterface.podspec":"divkit/public-ios/Specs/DivKit_LayoutKitInterface/28.0.1/DivKit_LayoutKitInterface.podspec", "Specs/DivKit_LayoutKitInterface/28.1.0/DivKit_LayoutKitInterface.podspec":"divkit/public-ios/Specs/DivKit_LayoutKitInterface/28.1.0/DivKit_LayoutKitInterface.podspec", "Specs/DivKit_LayoutKitInterface/28.10.0/DivKit_LayoutKitInterface.podspec":"divkit/public-ios/Specs/DivKit_LayoutKitInterface/28.10.0/DivKit_LayoutKitInterface.podspec", @@ -911,6 +915,7 @@ "Specs/DivKit_LayoutKitInterface/29.0.0/DivKit_LayoutKitInterface.podspec":"divkit/public-ios/Specs/DivKit_LayoutKitInterface/29.0.0/DivKit_LayoutKitInterface.podspec", "Specs/DivKit_LayoutKitInterface/29.0.1/DivKit_LayoutKitInterface.podspec":"divkit/public-ios/Specs/DivKit_LayoutKitInterface/29.0.1/DivKit_LayoutKitInterface.podspec", "Specs/DivKit_LayoutKitInterface/29.1.0/DivKit_LayoutKitInterface.podspec":"divkit/public-ios/Specs/DivKit_LayoutKitInterface/29.1.0/DivKit_LayoutKitInterface.podspec", + "Specs/DivKit_LayoutKitInterface/29.2.0/DivKit_LayoutKitInterface.podspec":"divkit/public-ios/Specs/DivKit_LayoutKitInterface/29.2.0/DivKit_LayoutKitInterface.podspec", "Specs/DivKit_Serialization/28.0.1/DivKit_Serialization.podspec":"divkit/public-ios/Specs/DivKit_Serialization/28.0.1/DivKit_Serialization.podspec", "Specs/DivKit_Serialization/28.1.0/DivKit_Serialization.podspec":"divkit/public-ios/Specs/DivKit_Serialization/28.1.0/DivKit_Serialization.podspec", "Specs/DivKit_Serialization/28.10.0/DivKit_Serialization.podspec":"divkit/public-ios/Specs/DivKit_Serialization/28.10.0/DivKit_Serialization.podspec", @@ -928,6 +933,7 @@ "Specs/DivKit_Serialization/29.0.0/DivKit_Serialization.podspec":"divkit/public-ios/Specs/DivKit_Serialization/29.0.0/DivKit_Serialization.podspec", "Specs/DivKit_Serialization/29.0.1/DivKit_Serialization.podspec":"divkit/public-ios/Specs/DivKit_Serialization/29.0.1/DivKit_Serialization.podspec", "Specs/DivKit_Serialization/29.1.0/DivKit_Serialization.podspec":"divkit/public-ios/Specs/DivKit_Serialization/29.1.0/DivKit_Serialization.podspec", + "Specs/DivKit_Serialization/29.2.0/DivKit_Serialization.podspec":"divkit/public-ios/Specs/DivKit_Serialization/29.2.0/DivKit_Serialization.podspec", "Specs/LayoutKit/24.3.0/LayoutKit.podspec":"divkit/public-ios/Specs/LayoutKit/24.3.0/LayoutKit.podspec", "Specs/LayoutKit/25.0.0/LayoutKit.podspec":"divkit/public-ios/Specs/LayoutKit/25.0.0/LayoutKit.podspec", "Specs/LayoutKit/25.1.0/LayoutKit.podspec":"divkit/public-ios/Specs/LayoutKit/25.1.0/LayoutKit.podspec", diff --git a/DivKit/Actions/CopyToClipboardActionHandler.swift b/DivKit/Actions/CopyToClipboardActionHandler.swift index 67834dd0..b7e91ea1 100644 --- a/DivKit/Actions/CopyToClipboardActionHandler.swift +++ b/DivKit/Actions/CopyToClipboardActionHandler.swift @@ -5,17 +5,19 @@ import UIKit #endif final class CopyToClipboardActionHandler { - func handle(_ action: DivActionCopyToClipboard) { + func handle( + _ action: DivActionCopyToClipboard, + context: DivActionHandlingContext + ) { #if os(iOS) let pasteboard = UIPasteboard.general - switch action.content { case let .contentText(text): - if let text = text.value.rawValue { + if let text = text.resolveValue(context.expressionResolver) { pasteboard.string = text } case let .contentUrl(url): - if let url = url.value.rawValue { + if let url = url.resolveValue(context.expressionResolver) { pasteboard.url = url } } diff --git a/DivKit/Actions/DivActionHandler.swift b/DivKit/Actions/DivActionHandler.swift index 215f74a4..b089fa7d 100644 --- a/DivKit/Actions/DivActionHandler.swift +++ b/DivKit/Actions/DivActionHandler.swift @@ -95,7 +95,7 @@ public final class DivActionHandler { default: action = parseAction(type: DivActionTemplate.self, json: params.action) } - guard let action = action else { + guard let action else { return } @@ -129,7 +129,7 @@ public final class DivActionHandler { case let .divActionArrayRemoveValue(action): arrayRemoveValueActionHandler.handle(action, context: context) case let .divActionCopyToClipboard(action): - copyToClipboardActionHandler.handle(action) + copyToClipboardActionHandler.handle(action, context: context) case .none: isHandled = false default: @@ -170,7 +170,7 @@ public final class DivActionHandler { url, cardId: context.cardId, completion: { [weak self] result in - guard let self = self else { + guard let self else { return } let callbackActions: [DivAction] diff --git a/DivKit/Actions/DivActionLogger.swift b/DivKit/Actions/DivActionLogger.swift index 7f039547..9335f1a5 100644 --- a/DivKit/Actions/DivActionLogger.swift +++ b/DivKit/Actions/DivActionLogger.swift @@ -23,11 +23,11 @@ public struct DefaultDivActionLogger: DivActionLogger { public func log(url: URL, referer: URL?, payload: [String: Any]?) { var request = URLRequest(url: url) - if let referer = referer { + if let referer { request.setValue(referer.absoluteString, forHTTPHeaderField: "referer") } - if let payload = payload { + if let payload { let json: JSONObject = .object(payload.typedJSON()) guard let body = try? json.toJSONString().data(using: .utf8) else { assertionFailure("Can't serialize JSON payload") diff --git a/DivKit/Debug/Block+DebugInfo.swift b/DivKit/Debug/Block+DebugInfo.swift index 22c8079e..dfd2a09e 100644 --- a/DivKit/Debug/Block+DebugInfo.swift +++ b/DivKit/Debug/Block+DebugInfo.swift @@ -55,7 +55,7 @@ extension Block { child: indicator, showDebugInfo: { #if os(iOS) - debugParams.showDebugInfo(ErrorListView(errors: errors.map { $0.prettyMessage })) + debugParams.showDebugInfo(ErrorListView(errors: errors.map(\.prettyMessage))) #else return #endif diff --git a/DivKit/DivBlockModelingContext.swift b/DivKit/DivBlockModelingContext.swift index 6e935887..a5e1c5a4 100644 --- a/DivKit/DivBlockModelingContext.swift +++ b/DivKit/DivBlockModelingContext.swift @@ -30,7 +30,6 @@ public struct DivBlockModelingContext { let debugParams: DebugParams let scheduler: Scheduling let playerFactory: PlayerFactory? - private(set) var childrenA11yDescription: String? private(set) weak var parentScrollView: ScrollView? public private(set) var errorsStorage: DivErrorsStorage private let persistentValuesStorage: DivPersistentValuesStorage @@ -64,7 +63,6 @@ public struct DivBlockModelingContext { playerFactory: PlayerFactory? = nil, debugParams: DebugParams = DebugParams(), scheduler: Scheduling? = nil, - childrenA11yDescription: String? = nil, parentScrollView: ScrollView? = nil, errorsStorage: DivErrorsStorage? = nil, layoutDirection: UserInterfaceLayoutDirection = .leftToRight, @@ -113,7 +111,6 @@ public struct DivBlockModelingContext { playerFactory: playerFactory, debugParams: debugParams, scheduler: scheduler, - childrenA11yDescription: childrenA11yDescription, parentScrollView: parentScrollView, errorsStorage: errorsStorage, layoutDirection: layoutDirection, @@ -143,7 +140,6 @@ public struct DivBlockModelingContext { playerFactory: PlayerFactory?, debugParams: DebugParams, scheduler: Scheduling?, - childrenA11yDescription: String?, parentScrollView: ScrollView?, errorsStorage: DivErrorsStorage?, layoutDirection: UserInterfaceLayoutDirection, @@ -168,7 +164,6 @@ public struct DivBlockModelingContext { self.playerFactory = playerFactory self.debugParams = debugParams self.scheduler = scheduler ?? TimerScheduler() - self.childrenA11yDescription = childrenA11yDescription self.parentScrollView = parentScrollView self.errorsStorage = errorsStorage ?? DivErrorsStorage(errors: []) self.layoutDirection = layoutDirection @@ -314,14 +309,6 @@ extension DivBlockModelingContext { return context } - - func modifying( - childrenA11yDescription: String? - ) -> Self { - modified(self) { - $0.childrenA11yDescription = childrenA11yDescription - } - } } private func makeExpressionResolver( diff --git a/DivKit/DivError.swift b/DivKit/DivError.swift index c36babfd..79cb9684 100644 --- a/DivKit/DivError.swift +++ b/DivKit/DivError.swift @@ -40,7 +40,7 @@ extension DivError { "[\(path)]: \(message)" + ( causes.isEmpty ? "" - : " caused by \(rootCauses.map { $0.description }.joined(separator: "; "))" + : " caused by \(rootCauses.map(\.description).joined(separator: "; "))" ) } } diff --git a/DivKit/DivImageHolderFactory.swift b/DivKit/DivImageHolderFactory.swift index 9936e86f..8e80d20a 100644 --- a/DivKit/DivImageHolderFactory.swift +++ b/DivKit/DivImageHolderFactory.swift @@ -45,7 +45,7 @@ final class DefaultImageHolderFactory: DivImageHolderFactory { } func make(_ url: URL?, _ placeholder: ImagePlaceholder?) -> ImageHolder { - guard let url = url else { + guard let url else { return placeholder?.toImageHolder() ?? NilImageHolder() } return RemoteImageHolder( diff --git a/DivKit/DivKitComponents.swift b/DivKit/DivKitComponents.swift index 28ff3ef3..ccb00a29 100644 --- a/DivKit/DivKitComponents.swift +++ b/DivKit/DivKitComponents.swift @@ -321,10 +321,6 @@ public final class DivKitComponents { timerStorage.set(cardId: cardId, timers: divData.timers ?? []) } - public func flushUpdateActions() { - updateAggregator.flushUpdateActions() - } - private func onVariablesChanged(event: DivVariablesStorage.ChangeEvent) { switch event.kind { case let .global(variables): diff --git a/DivKit/DivKitInfo.swift b/DivKit/DivKitInfo.swift index c76a02c8..2dfc778b 100644 --- a/DivKit/DivKitInfo.swift +++ b/DivKit/DivKitInfo.swift @@ -1,3 +1,3 @@ public enum DivKitInfo { - public static let version = "29.1.0" + public static let version = "29.2.0" } diff --git a/DivKit/DivStatePath.swift b/DivKit/DivStatePath.swift index 3a030335..918df46e 100644 --- a/DivKit/DivStatePath.swift +++ b/DivKit/DivStatePath.swift @@ -55,9 +55,9 @@ extension Tagged where Tag == DivDataStateIDTag, RawValue == Int { } } -extension Optional where Wrapped == DivStatePath { +extension DivStatePath? { public static func +(parent: Self, child: String) -> DivStatePath { - if let parent = parent { + if let parent { return parent + DivStateID(rawValue: child) } else { return DivStatePath(rawValue: UIElementPath(child)) diff --git a/DivKit/Expressions/CalcExpression/AnyCalcExpression.swift b/DivKit/Expressions/CalcExpression/AnyCalcExpression.swift index d9274d68..e87358d8 100644 --- a/DivKit/Expressions/CalcExpression/AnyCalcExpression.swift +++ b/DivKit/Expressions/CalcExpression/AnyCalcExpression.swift @@ -706,7 +706,7 @@ extension AnyCalcExpression { default: return args[0] } - } + }, ] } diff --git a/DivKit/Expressions/CalcExpression/CalcExpression.swift b/DivKit/Expressions/CalcExpression/CalcExpression.swift index b35a0d41..3351994b 100644 --- a/DivKit/Expressions/CalcExpression/CalcExpression.swift +++ b/DivKit/Expressions/CalcExpression/CalcExpression.swift @@ -273,7 +273,7 @@ extension CalcExpression { ":": -8, // ternary ].mapValues { ($0, false) } precedences["?"] = (-7, true) // ternary - for op in [ "<", "<=", ">=", ">", "==", "!=" ] { // comparison + for op in ["<", "<=", ">=", ">", "==", "!="] { // comparison precedences[op] = (-4, true) } return precedences @@ -411,7 +411,7 @@ struct ParsedCalcExpression: CustomStringConvertible { guard case .variable = $0 else { return false } return true } - .map { $0.name } + .map(\.name) } } @@ -442,7 +442,7 @@ private enum Subexpression: CustomStringConvertible { case let .literal(literal): return literal case let .symbol(symbol, args, fn): - guard let fn = fn else { + guard let fn else { return .error(CalcExpression.Error.undefinedSymbol(symbol)) } do { @@ -457,7 +457,7 @@ private enum Subexpression: CustomStringConvertible { var description: String { func arguments(_ args: [Subexpression]) -> String { - args.map { $0.description } + args.map(\.description) .joined(separator: ", ") } switch self { diff --git a/DivKit/Expressions/CalcExpression/CalcExpressionError.swift b/DivKit/Expressions/CalcExpression/CalcExpressionError.swift index fbeb4cd2..0e1ccc35 100644 --- a/DivKit/Expressions/CalcExpression/CalcExpressionError.swift +++ b/DivKit/Expressions/CalcExpression/CalcExpressionError.swift @@ -4,28 +4,28 @@ extension CalcExpression { enum Error: Swift.Error, CustomStringConvertible, Equatable { /// An application-specific error case message(String) - + /// An application-specific error without information about failed expression case shortMessage(String) - + /// The parser encountered a sequence of characters it didn't recognize case unexpectedToken(String) - + /// The parser expected to find a delimiter (e.g. closing paren) but didn't case missingDelimiter(String) - + /// The specified constant, operator or function was not recognized case undefinedSymbol(Symbol) - + /// A function was called with the wrong number of arguments (arity) case arityMismatch(Symbol) - + case escaping - + var description: String { switch self { case let .message(message), - let .shortMessage(message): + let .shortMessage(message): return message case let .unexpectedToken(string): return "Unexpected token: \(string)" @@ -57,7 +57,7 @@ extension CalcExpression { return "Incorrect string escape" } } - + func makeOutputMessage(for expression: String) -> String { switch self { case let .shortMessage(message): diff --git a/DivKit/Expressions/Expression.swift b/DivKit/Expressions/Expression.swift index 65835a47..bdc5858a 100644 --- a/DivKit/Expressions/Expression.swift +++ b/DivKit/Expressions/Expression.swift @@ -4,15 +4,6 @@ import Foundation public enum Expression { case value(T) case link(ExpressionLink) - - public var rawValue: T? { - switch self { - case let .value(value): - return value - case .link: - return nil - } - } } extension Expression: Equatable where T: Equatable { diff --git a/DivKit/Expressions/ExpressionError.swift b/DivKit/Expressions/ExpressionError.swift index 283eefe0..db67d418 100644 --- a/DivKit/Expressions/ExpressionError.swift +++ b/DivKit/Expressions/ExpressionError.swift @@ -15,7 +15,7 @@ public struct ExpressionError: Error { extension ExpressionError: CustomStringConvertible { public var description: String { - if let expression = expression { + if let expression { return "\(message). Expression: \(expression)" } return message diff --git a/DivKit/Expressions/ExpressionLink.swift b/DivKit/Expressions/ExpressionLink.swift index a206bcfb..10124b5c 100644 --- a/DivKit/Expressions/ExpressionLink.swift +++ b/DivKit/Expressions/ExpressionLink.swift @@ -1,6 +1,7 @@ import Foundation import CommonCorePublic +import Serialization public struct ExpressionLink { enum Item { @@ -12,13 +13,12 @@ public struct ExpressionLink { let items: [Item] let variablesNames: [String] let rawValue: String - let validator: ExpressionValueValidator? - let errorTracker: ExpressionErrorTracker? + let validator: AnyValueValidator? @usableFromInline init?( rawValue: String, - validator: ExpressionValueValidator? = nil, + validator: AnyValueValidator? = nil, errorTracker: ExpressionErrorTracker? = nil, resolveNested: Bool = true ) throws { @@ -76,7 +76,6 @@ public struct ExpressionLink { self.variablesNames = variablesNames self.rawValue = rawValue self.validator = validator - self.errorTracker = errorTracker } } diff --git a/DivKit/Expressions/ExpressionResolver.swift b/DivKit/Expressions/ExpressionResolver.swift index e9ee09bd..52d54f05 100644 --- a/DivKit/Expressions/ExpressionResolver.swift +++ b/DivKit/Expressions/ExpressionResolver.swift @@ -2,8 +2,6 @@ import Foundation import CommonCorePublic -public typealias ExpressionValueValidator = (T) -> Bool - public typealias ExpressionErrorTracker = (ExpressionError) -> Void public final class ExpressionResolver { @@ -173,11 +171,7 @@ public final class ExpressionResolver { return nil } do { - return try validatedValue( - value: evaluate(parsedExpression), - validator: link.validator, - rawValue: link.rawValue - ) + return try validatedValue(value: evaluate(parsedExpression), link: link) } catch let error as CalcExpression.Error { let expression = parsedExpression.description errorTracker( @@ -192,7 +186,7 @@ public final class ExpressionResolver { private func evaluateString( link: ExpressionLink, - initializer: (String) -> T? + initializer: (String) -> T? = { $0 } ) -> T? { var stringValue = "" for item in link.items { @@ -213,19 +207,13 @@ public final class ExpressionResolver { case let .string(value): stringValue += value case let .nestedCalcExpression(link): - if let expression = evaluateString( - link: link, - initializer: { $0 } - ) { + if let expression = evaluateString(link: link) { let link = try? ExpressionLink( rawValue: "@{\(expression)}", - errorTracker: link.errorTracker, + errorTracker: errorTracker, resolveNested: false ) - if let link = link, let value = evaluateString( - link: link, - initializer: { $0 } - ) { + if let link, let value = evaluateString(link: link) { stringValue += value } } @@ -240,7 +228,7 @@ public final class ExpressionResolver { ) return nil } - return validatedValue(value: result, validator: link.validator, rawValue: link.rawValue) + return validatedValue(value: result, link: link) } private func evaluate(_ parsedExpression: ParsedCalcExpression) throws -> T { @@ -253,14 +241,15 @@ public final class ExpressionResolver { private func validatedValue( value: T?, - validator: ExpressionValueValidator?, - rawValue: String + link: ExpressionLink ) -> T? { - if let validator = validator, let value = value { - if validator(value) { + if let validator = link.validator, let value { + if validator.isValid(value) { return value } else { - errorTracker(ExpressionError("Failed to validate value: \(value)", expression: rawValue)) + errorTracker( + ExpressionError("Failed to validate value: \(value)", expression: link.rawValue) + ) return nil } } diff --git a/DivKit/Expressions/Functions/ArrayFunctions.swift b/DivKit/Expressions/Functions/ArrayFunctions.swift index 4c54f0f3..93483fd5 100644 --- a/DivKit/Expressions/Functions/ArrayFunctions.swift +++ b/DivKit/Expressions/Functions/ArrayFunctions.swift @@ -491,7 +491,7 @@ enum ArrayFunctions: String, CaseIterable { index: Int, expression: String ) throws -> AnyHashable { - guard index >= 0 && index < array.count + guard index >= 0, index < array.count else { throw Error.indexOutOfBounds(expression, index, array.count).message } return array[index] } diff --git a/DivKit/Expressions/Functions/IntervalFunctions.swift b/DivKit/Expressions/Functions/IntervalFunctions.swift index 1b312fcd..97e84009 100644 --- a/DivKit/Expressions/Functions/IntervalFunctions.swift +++ b/DivKit/Expressions/Functions/IntervalFunctions.swift @@ -108,7 +108,7 @@ enum IntervalFunctions: String, CaseIterable { throw AnyCalcExpression.Error.incorrectMilliseconds("\(funcName)(\(milliseconds))") } var val = milliseconds / divider - if let whole = whole { + if let whole { val = val % whole } return val diff --git a/DivKit/Expressions/Functions/StringFunctions.swift b/DivKit/Expressions/Functions/StringFunctions.swift index 9a11e570..055d8d44 100644 --- a/DivKit/Expressions/Functions/StringFunctions.swift +++ b/DivKit/Expressions/Functions/StringFunctions.swift @@ -210,7 +210,7 @@ private func calcPad(value: String, len: Int, pad: String) -> String { while part.count + value.count < len { part += pad } - if part.count > 0 && part.count + value.count > len { + if part.count > 0, part.count + value.count > len { part = String(part.prefix(len - value.count)) } return part diff --git a/DivKit/Expressions/FunctionsProvider.swift b/DivKit/Expressions/FunctionsProvider.swift index 4864e70b..769c99a0 100644 --- a/DivKit/Expressions/FunctionsProvider.swift +++ b/DivKit/Expressions/FunctionsProvider.swift @@ -27,7 +27,7 @@ final class FunctionsProvider { GetStoredValueFunctions.allCases.forEach { functions.put( $0.rawValue, - $0.getFunction { self.persistentValuesStorage.get(name: $0) } + $0.getFunction(persistentValuesStorage.get) ) } return functions @@ -47,7 +47,7 @@ private let staticFunctions: [AnyCalcExpression.Symbol: Function] = { return functions }() -extension Dictionary where Key == AnyCalcExpression.Symbol, Value == Function { +extension [AnyCalcExpression.Symbol: Function] { fileprivate mutating func put(_ name: String, _ function: Function) { self[.function(name, arity: function.arity)] = function } diff --git a/DivKit/Expressions/Serialization/DictionaryExtensions.swift b/DivKit/Expressions/Serialization/DictionaryExtensions.swift index 11a5a889..a36ce5e0 100644 --- a/DivKit/Expressions/Serialization/DictionaryExtensions.swift +++ b/DivKit/Expressions/Serialization/DictionaryExtensions.swift @@ -3,19 +3,7 @@ import Foundation import BasePublic import Serialization -extension Dictionary where Key == String, Value == Any { - func getOptionalExpressionField( - _ key: String - ) throws -> Field>? { - Field.makeOptional( - valueGetter: (try? getOptionalField( - key, - transform: { expressionTransform($0, transform: { safeCFCast($0 as CFTypeRef) }) } - )).flatMap { $0 }, - linkGetter: link(for: key) - ) - } - +extension [String: Any] { func getOptionalExpressionField( _ key: String ) throws -> Field>? { @@ -30,13 +18,11 @@ extension Dictionary where Key == String, Value == Any { func getOptionalExpressionField( _ key: String, - transform: (U) -> T?, - validator: AnyValueValidator>? = nil + transform: (U) -> T? ) throws -> Field>? { try getOptionalField( key, - transform: { expressionTransform($0, transform: transform) }, - validator: validator + transform: { expressionTransform($0, transform: transform) } ) } @@ -48,15 +34,13 @@ extension Dictionary where Key == String, Value == Any { func getOptionalExpressionArray( _ key: String, - transform: (U) -> T?, - validator: AnyArrayValueValidator>? = nil + transform: (U) -> T? ) throws -> Field<[Expression]>? { try getOptionalArray( key, transform: { (value: U) in expressionTransform(value, transform: transform) - }, - validator: validator + } ) } } diff --git a/DivKit/Expressions/Serialization/Expression+Helpers.swift b/DivKit/Expressions/Serialization/Expression+Helpers.swift index 39d12d77..1d58f47a 100644 --- a/DivKit/Expressions/Serialization/Expression+Helpers.swift +++ b/DivKit/Expressions/Serialization/Expression+Helpers.swift @@ -7,7 +7,7 @@ import Serialization func expressionTransform( _ value: Any?, transform: (U) -> T?, - validator: ExpressionValueValidator? = nil + validator: AnyValueValidator? = nil ) -> Expression? { do { if let rawValue = value as? String, @@ -23,7 +23,7 @@ func expressionTransform( return nil } - guard let value = value else { + guard let value else { return nil } @@ -32,7 +32,7 @@ func expressionTransform( return nil } - if let transformedValue = transform(value), validator?(transformedValue) != false { + if let transformedValue = transform(value), validator?.isValid(transformedValue) != false { return .value(transformedValue) } @@ -47,33 +47,19 @@ func deserialize( deserialize(value, transform: { $0 }, validator: validator) } -@inlinable -func deserialize( - _ value: Any, - validator: AnyValueValidator? = nil -) -> DeserializationResult> { - deserialize( - value, - transform: { (rawValue: String) in safeCFCast(rawValue as CFTypeRef) }, - validator: validator, - customTypeName: "Expression" - ) -} - @inlinable func deserialize( _ value: Any, transform: (T) -> U?, - validator: AnyValueValidator? = nil, - customTypeName: String? = nil + validator: AnyValueValidator? = nil ) -> DeserializationResult> { guard let result: Expression = expressionTransform( value, transform: transform, - validator: validator?.isValid + validator: validator ) else { return .failure(NonEmptyArray(.typeMismatch( - expected: customTypeName ?? "Expression<\(U.self)>", + expected: "Expression<\(U.self)>", representation: value ))) } @@ -90,11 +76,7 @@ func deserialize( deserialize( value, transform: { (rawElement: T) -> DeserializationResult> in - deserialize( - rawElement, - transform: transform, - validator: nil - ) + deserialize(rawElement, transform: transform) }, validator: validator ) @@ -108,7 +90,7 @@ func deserialize( guard let result: Expression = expressionTransform( value, transform: T.init(rawValue:), - validator: validator?.isValid + validator: validator ) else { return .failure(NonEmptyArray(.typeMismatch( expected: "Expression<\(T.self)>", diff --git a/DivKit/Expressions/Serialization/Expression+ValidSerializationValue.swift b/DivKit/Expressions/Serialization/Expression+ValidSerializationValue.swift index 8bb60c23..1ffb7266 100644 --- a/DivKit/Expressions/Serialization/Expression+ValidSerializationValue.swift +++ b/DivKit/Expressions/Serialization/Expression+ValidSerializationValue.swift @@ -58,17 +58,6 @@ extension Expression where T == String { } } -extension Expression where T == CFString { - func toValidSerializationValue() -> String { - switch self { - case let .value(value): - return String(value) - case let .link(link): - return link.rawValue - } - } -} - extension Expression where T == URL { func toValidSerializationValue() -> String { switch self { diff --git a/DivKit/Expressions/Serialization/FieldExtensions.swift b/DivKit/Expressions/Serialization/FieldExtensions.swift index 04232248..a628ce1b 100644 --- a/DivKit/Expressions/Serialization/FieldExtensions.swift +++ b/DivKit/Expressions/Serialization/FieldExtensions.swift @@ -25,12 +25,9 @@ extension Field { valueForLink: { safeValueForLink( { try context.templateData.getField( $0, - transform: { expressionTransform( - $0, - transform: E.init(rawValue:), - validator: validator?.isValid - ) }, - validator: nil + transform: { + expressionTransform($0, transform: E.init(rawValue:), validator: validator) + } ) }, link: $0 ) } @@ -47,12 +44,9 @@ extension Field { valueForLink: { safeValueForLink( { try context.templateData.getField( $0, - transform: { expressionTransform( - $0, - transform: transform, - validator: validator?.isValid - ) }, - validator: nil + transform: { + expressionTransform($0, transform: transform, validator: validator) + } ) }, link: $0 ) } @@ -75,7 +69,7 @@ extension Field { return context.templateData.getArray( link, transform: { (value: U) in - expressionTransform(value, transform: transform, validator: nil) + expressionTransform(value, transform: transform) }, validator: validator ) @@ -142,25 +136,3 @@ extension Field { } } } - -extension Field where T == Expression { - func resolveValue( - context: TemplatesContext, - validator: AnyValueValidator? = nil - ) -> DeserializationResult { - resolveExpression( - valueForLink: { safeValueForLink( - { try context.templateData.getField( - $0, - transform: { expressionTransform( - $0, - transform: { (rawValue: String) in safeCFCast(rawValue as CFTypeRef) }, - validator: validator?.isValid - ) }, - validator: nil - ) }, - link: $0 - ) } - ) - } -} diff --git a/DivKit/Extensions/ArrayExtensions.swift b/DivKit/Extensions/ArrayExtensions.swift index a0797fe0..7773e5e9 100644 --- a/DivKit/Extensions/ArrayExtensions.swift +++ b/DivKit/Extensions/ArrayExtensions.swift @@ -1,7 +1,7 @@ import CommonCorePublic import LayoutKit -extension Array where Element == Div { +extension [Div] { func makeBlocks( context: DivBlockModelingContext, sizeModifier: DivSizeModifier? = nil, diff --git a/DivKit/Extensions/DivAccessibilityExtensions.swift b/DivKit/Extensions/DivAccessibilityExtensions.swift index 6f4c1ba1..c5fcdc25 100644 --- a/DivKit/Extensions/DivAccessibilityExtensions.swift +++ b/DivKit/Extensions/DivAccessibilityExtensions.swift @@ -3,44 +3,42 @@ import CommonCorePublic extension DivAccessibility { func resolve( - _ context: DivBlockModelingContext, - id: String? + _ expressionResolver: ExpressionResolver, + id: String?, + customDescriptionProvider: (() -> String?)? ) -> AccessibilityElement { - let expressionResolver = context.expressionResolver - let mode = resolveMode(expressionResolver) + if resolveMode(expressionResolver) == .exclude { + return AccessibilityElement( + traits: .none, + strings: AccessibilityElement.Strings(label: nil), + hideElementWithChildren: true + ) + } + + var label: String? = nil + if let customDescriptionProvider { + label = customDescriptionProvider() + } else if let description = resolveDescription(expressionResolver) { + label = description + } + if label == nil, type != nil { + label = "" + } + return AccessibilityElement( - traits: type?.cast() ?? .none, + traits: traits, strings: AccessibilityElement.Strings( - label: resolveDescription(context, mode: mode), + label: label, hint: resolveHint(expressionResolver), value: resolveStateDescription(expressionResolver), identifier: id ), - startsMediaSession: resolveMuteAfterAction(expressionResolver), - hideElementWithChildren: mode.isExclude + startsMediaSession: resolveMuteAfterAction(expressionResolver) ) } - private func resolveDescription( - _ context: DivBlockModelingContext, - mode: Mode - ) -> String? { - if let description = resolveDescription(context.expressionResolver) { - return description - } - if mode == .merge { - return context.childrenA11yDescription - } - if type != nil { - return "" - } - return nil - } -} - -extension DivAccessibility.Kind { - func cast() -> AccessibilityElement.Traits { - switch self { + private var traits: AccessibilityElement.Traits { + switch type { case .button: return .button case .header: @@ -53,22 +51,11 @@ extension DivAccessibility.Kind { return .searchField case .tabBar: return .tabBar - case .none: - return .none case .list, .select: DivKitLogger.warning("Unsupported accessibility type") return .none - } - } -} - -extension DivAccessibility.Mode { - var isExclude: Bool { - switch self { - case .exclude: - return true - case .default, .merge: - return false + case .none?, nil: + return .none } } } diff --git a/DivKit/Extensions/DivAction/DivActionBase.swift b/DivKit/Extensions/DivAction/DivActionBase.swift index d6f2b272..2bf5adec 100644 --- a/DivKit/Extensions/DivAction/DivActionBase.swift +++ b/DivKit/Extensions/DivAction/DivActionBase.swift @@ -25,10 +25,17 @@ extension DivActionBase { ) -> UserInterfaceAction.Payload { // url parameter is used for backward compatibility, it should be removed // when all custom div-action handlers will be replaced - let url = url?.rawValue.map { $0.adding(cardId: cardId.rawValue) } + let url: URL? + switch self.url { + case let .value(value): + url = value.adding(cardId: cardId.rawValue) + case .link, .none: + url = nil + } + return .divAction( params: UserInterfaceAction.DivActionParams( - action: JSONObject.object(toDictionary().typedJSON()), + action: .object(toDictionary().typedJSON()), cardId: cardId.rawValue, source: source, url: url diff --git a/DivKit/Extensions/DivAction/DivActionExtensions.swift b/DivKit/Extensions/DivAction/DivActionExtensions.swift index d78a1fe7..615e0b91 100644 --- a/DivKit/Extensions/DivAction/DivActionExtensions.swift +++ b/DivKit/Extensions/DivAction/DivActionExtensions.swift @@ -4,7 +4,10 @@ import LayoutKit extension DivAction: DivActionBase {} extension DivAction { - func uiAction(context: DivBlockModelingContext) -> UserInterfaceAction { + func uiAction(context: DivBlockModelingContext) -> UserInterfaceAction? { + guard resolveIsEnabled(context.expressionResolver) else { + return nil + } let payload: UserInterfaceAction.Payload if let menuPayload = makeMenuPayload(context: context) { payload = menuPayload @@ -24,12 +27,12 @@ extension DivAction { } private func makeMenuPayload(context: DivBlockModelingContext) -> UserInterfaceAction.Payload? { - guard let menuItems = menuItems else { return nil } + guard let menuItems else { return nil } let expressionResolver = context.expressionResolver let items: [Menu.Item] = menuItems.compactMap { item in if let actions = item.actions { - let uiActions = actions.map { $0.uiAction(context: context) } + let uiActions = actions.compactMap { $0.uiAction(context: context) } if !uiActions.isEmpty { return Menu.Item( actions: uiActions, @@ -52,8 +55,8 @@ extension DivAction { } } -extension Array where Element == DivAction { +extension [DivAction] { func uiActions(context: DivBlockModelingContext) -> [UserInterfaceAction] { - map { $0.uiAction(context: context) } + compactMap { $0.uiAction(context: context) } } } diff --git a/DivKit/Extensions/DivAction/DivActionsHolder.swift b/DivKit/Extensions/DivAction/DivActionsHolder.swift index 818441fe..a97e26ba 100644 --- a/DivKit/Extensions/DivAction/DivActionsHolder.swift +++ b/DivKit/Extensions/DivAction/DivActionsHolder.swift @@ -54,7 +54,7 @@ extension Block { context: DivBlockModelingContext, actionsHolder: DivActionsHolder? ) -> Block { - guard let actionsHolder = actionsHolder else { + guard let actionsHolder else { return self } diff --git a/DivKit/Extensions/DivBase/DivBaseExtensions.swift b/DivKit/Extensions/DivBase/DivBaseExtensions.swift index ecb75450..583be64a 100644 --- a/DivKit/Extensions/DivBase/DivBaseExtensions.swift +++ b/DivKit/Extensions/DivBase/DivBaseExtensions.swift @@ -11,7 +11,7 @@ extension DivBase { context: DivBlockModelingContext, actionsHolder: DivActionsHolder?, options: BasePropertiesOptions = [], - customA11yElement: AccessibilityElement? = nil, + customA11yDescriptionProvider: (() -> String?)? = nil, clipToBounds: Bool = true ) throws -> Block { let expressionResolver = context.expressionResolver @@ -69,6 +69,15 @@ extension DivBase { boundary = nil } + let shadow = border?.resolveShadow(expressionResolver) + + let accessibilityElement = (accessibility ?? DivAccessibility()) + .resolve( + expressionResolver, + id: id, + customDescriptionProvider: customA11yDescriptionProvider + ) + block = try applyBackground( getBackground(focusState), to: block, @@ -77,7 +86,7 @@ extension DivBase { .addingDecorations( boundary: boundary, border: border?.resolveBorder(expressionResolver), - shadow: border?.resolveShadow(expressionResolver), + shadow: shadow, visibilityActions: hasVisibilityActions ? visibilityActions : nil, lastVisibleBounds: hasVisibilityActions ? Property( getter: { context.lastVisibleBoundsCache.lastVisibleBounds(for: context.parentPath) }, @@ -89,32 +98,26 @@ extension DivBase { } ) : nil, scheduler: hasVisibilityActions ? context.scheduler : nil, - tooltips: tooltips.makeTooltips(context: context) + tooltips: tooltips.makeTooltips(context: context), + accessibilityElement: accessibilityElement ) - + + let rotation = transform?.resolveRotation(expressionResolver) + if let transform { block = block.addingTransform( - transform: transform.resolveRotation(expressionResolver) + transform: rotation .flatMap { CGAffineTransform(rotationAngle: CGFloat($0) * .pi / 180) } ?? .identity, anchorPoint: transform.resolveAnchorPoint(expressionResolver) ) } - - let accessibilityElement: AccessibilityElement - if let customA11yElement { - accessibilityElement = customA11yElement - } else { - accessibilityElement = (accessibility ?? DivAccessibility()).resolve(context, id: id) - } block = applyTransitioningAnimations(to: block, context: context, statePath: statePath) .addActions(context: context, actionsHolder: actionsHolder) .addingEdgeInsets(externalInsets, clipsToBounds: false) .addingDecorations( - boundary: transform?.resolveRotation(expressionResolver).flatMap { _ in .noClip } ?? - border?.resolveShadow(expressionResolver).flatMap { _ in .noClip }, - alpha: CGFloat(resolveAlpha(expressionResolver)), - accessibilityElement: accessibilityElement + boundary: rotation != nil || shadow != nil ? .noClip : nil, + alpha: CGFloat(resolveAlpha(expressionResolver)) ) return applyExtensionHandlersAfterBaseProperties( @@ -156,13 +159,14 @@ extension DivBase { context: DivBlockModelingContext ) -> [VisibilityAction] { (visibilityActions ?? visibilityAction.asArray()) - .map { $0.makeVisibilityAction(context: context) } + .compactMap { $0.makeVisibilityAction(context: context) } } private func makeDisappearActions( context: DivBlockModelingContext ) -> [VisibilityAction] { - disappearActions?.map { $0.makeDisappearAction(context: context) } ?? [] + disappearActions? + .compactMap { $0.makeDisappearAction(context: context) } ?? [] } private func applyTransitioningAnimations( @@ -221,7 +225,7 @@ extension DivBase { to block: Block, context: DivBlockModelingContext ) -> Block { - guard let backgrounds = backgrounds else { + guard let backgrounds else { return block } @@ -309,7 +313,7 @@ extension LayoutTrait { extension DivBorder { fileprivate func resolveBorder(_ expressionResolver: ExpressionResolver) -> BlockBorder? { - guard let stroke = stroke else { + guard let stroke else { return nil } return BlockBorder( diff --git a/DivKit/Extensions/DivContainer/DivContainer+Accessibility.swift b/DivKit/Extensions/DivContainer/DivContainer+Accessibility.swift new file mode 100644 index 00000000..927f8167 --- /dev/null +++ b/DivKit/Extensions/DivContainer/DivContainer+Accessibility.swift @@ -0,0 +1,72 @@ +import Foundation + +extension DivContainer { + func resolveAccessibilityDescription(_ context: DivBlockModelingContext) -> String? { + guard let accessibility else { + return nil + } + + let expressionResolver = context.expressionResolver + switch accessibility.resolveMode(expressionResolver) { + case .default: + return accessibility.resolveDescription(expressionResolver) + case .merge: + if let description = accessibility.resolveDescription(expressionResolver) { + return description + } + return nonNilItems.resolveMergedDescription(context) + case .exclude: + return nil + } + } +} + +extension [Div] { + fileprivate func resolveMergedDescription(_ context: DivBlockModelingContext) -> String? { + var result = "" + func traverse(div: Div) { + if let descritpion = div.resolveDescription(context), !descritpion.isEmpty { + result = result.isEmpty ? descritpion : result + " " + descritpion + } + div.children.forEach(traverse) + } + forEach(traverse) + return result.isEmpty ? nil : result + } +} + +extension Div { + fileprivate func resolveDescription(_ context: DivBlockModelingContext) -> String? { + let expressionResolver = context.expressionResolver + let accessibility = value.accessibility + guard accessibility?.resolveMode(expressionResolver) != .exclude else { + return nil + } + switch self { + case .divContainer, + .divCustom, + .divGallery, + .divGifImage, + .divGrid, + .divImage, + .divIndicator, + .divInput, + .divPager, + .divSelect, + .divSeparator, + .divSlider, + .divState, + .divTabs, + .divVideo: + return accessibility?.resolveDescription(expressionResolver) + case let .divText(divText): + let extensionDescription = context + .getExtensionHandlers(for: divText) + .compactMap { $0.accessibilityElement?.strings.label } + .reduce(nil) { $0?.appending(" " + $1) ?? $1 } + return extensionDescription ?? + accessibility?.resolveDescription(expressionResolver) ?? + divText.resolveText(expressionResolver) + } + } +} diff --git a/DivKit/Extensions/DivContainer/DivContainerExtensions.swift b/DivKit/Extensions/DivContainer/DivContainerExtensions.swift index cdb7e236..4b61cad7 100644 --- a/DivKit/Extensions/DivContainer/DivContainerExtensions.swift +++ b/DivKit/Extensions/DivContainer/DivContainerExtensions.swift @@ -7,10 +7,11 @@ extension DivContainer: DivBlockModeling { public func makeBlock(context: DivBlockModelingContext) throws -> Block { try applyBaseProperties( to: { try makeBaseBlock(context: context) }, - context: context.modifying( - childrenA11yDescription: resolveChildrenA11yDescription(context) - ), + context: context, actionsHolder: self, + customA11yDescriptionProvider: { [unowned self] in + resolveAccessibilityDescription(context) + }, clipToBounds: resolveClipToBounds(context.expressionResolver) ) } @@ -38,7 +39,7 @@ extension DivContainer: DivBlockModeling { } let aspectRatio = aspect.resolveAspectRatio(expressionResolver) - if let aspectRatio = aspectRatio { + if let aspectRatio { if block.calculateWidthFirst { return block.aspectRatio(aspectRatio) } @@ -47,17 +48,6 @@ extension DivContainer: DivBlockModeling { return block } - private func resolveChildrenA11yDescription(_ context: DivBlockModelingContext) -> String? { - var result = "" - func traverse(div: Div) { - result = [result, div.resolveA11yDescription(context)].compactMap { $0 } - .joined(separator: " ") - div.children.forEach(traverse(div:)) - } - nonNilItems.forEach(traverse) - return result.isEmpty ? nil : result - } - private func makeOverlapBlock(context: DivBlockModelingContext) throws -> LayeredBlock { let expressionResolver = context.expressionResolver let defaultAlignment = BlockAlignment2D( @@ -161,7 +151,7 @@ extension DivContainer: DivBlockModeling { private func resolveSeparator( _ context: DivBlockModelingContext ) throws -> ContainerBlock.Separator? { - guard let separator = separator else { + guard let separator else { return nil } let separatorBlock = separator.style.makeBlock( @@ -185,7 +175,7 @@ extension DivContainer: DivBlockModeling { private func resolveLineSeparator( _ context: DivBlockModelingContext ) -> ContainerBlock.Separator? { - guard let lineSeparator = lineSeparator else { + guard let lineSeparator else { return nil } let lineSeparatorBlock = lineSeparator.style.makeBlock( diff --git a/DivKit/Extensions/DivContainer/DivContainerItemsExtensions.swift b/DivKit/Extensions/DivContainer/DivContainerItemsExtensions.swift index 13f8de92..f221a369 100644 --- a/DivKit/Extensions/DivContainer/DivContainerItemsExtensions.swift +++ b/DivKit/Extensions/DivContainer/DivContainerItemsExtensions.swift @@ -1,68 +1,44 @@ import CommonCorePublic import LayoutKit -enum DivContainerDataSource { - case divs([Div]) - case itemBuilder(DivCollectionItemBuilder) -} - extension DivContainer { - private var dataSource: DivContainerDataSource? { - if let itemBuilder { - return .itemBuilder(itemBuilder) - } - if let items { - return .divs(items) - } - return nil - } - func makeChildren( context: DivBlockModelingContext, mappedBy modificator: (Div, Block, DivBlockModelingContext) throws -> T ) throws -> [T] { - guard let dataSource else { - throw DivBlockModelingError( - "DivContainer has no items and itemBuilder property", - path: context.parentPath - ) + if let itemBuilder { + return try itemBuilder.makeBlocks(context: context, mappedBy: modificator) } - - switch dataSource { - case let .divs(items): - let expressionResolver = context.expressionResolver - let orientation = resolveOrientation(expressionResolver) - let filtredItems = items.filter { - guard resolveLayoutMode(expressionResolver) == .wrap else { return true } - if orientation == .vertical, $0.isHorizontallyMatchParent { - context.addWarning( - message: "Vertical DivContainer with wrap layout mode contains item with match_parent width" - ) - return false - } - if orientation == .horizontal, $0.isVerticallyMatchParent { - context.addWarning( - message: "Horizontal DivContainer with wrap layout mode contains item with match_parent height" - ) - return false - } + + let expressionResolver = context.expressionResolver + let orientation = resolveOrientation(expressionResolver) + let filtredItems = nonNilItems.filter { + guard resolveLayoutMode(expressionResolver) == .wrap else { return true } + if orientation == .vertical, $0.isHorizontallyMatchParent { + context.addWarning( + message: "Vertical DivContainer with wrap layout mode contains item with match_parent width" + ) + return false + } + if orientation == .horizontal, $0.isVerticallyMatchParent { + context.addWarning( + message: "Horizontal DivContainer with wrap layout mode contains item with match_parent height" + ) + return false + } + return true + } - return try filtredItems.makeBlocks( - context: context, - sizeModifier: DivContainerSizeModifier( - context: context, - container: self, - orientation: orientation - ), - mappedBy: modificator - ) - case let .itemBuilder(itemBuilder): - return try itemBuilder.makeBlocks( + return try filtredItems.makeBlocks( + context: context, + sizeModifier: DivContainerSizeModifier( context: context, - mappedBy: modificator - ) - } + container: self, + orientation: orientation + ), + mappedBy: modificator + ) } } diff --git a/DivKit/Extensions/DivData/DivDataPatchExtensions.swift b/DivKit/Extensions/DivData/DivDataPatchExtensions.swift index 81617478..4a9b6a80 100644 --- a/DivKit/Extensions/DivData/DivDataPatchExtensions.swift +++ b/DivKit/Extensions/DivData/DivDataPatchExtensions.swift @@ -18,7 +18,7 @@ extension DivData { extension Div { fileprivate func applySingleItemPatch(_ patch: DivPatch) -> Div { - if let id = id, let change = patch.getChange(id: id) { + if let id, let change = patch.getChange(id: id) { guard let items = change.items, items.count == 1 else { DivKitLogger.error("Patch contains multiple items, but single item is expected: \(id)") return self @@ -29,7 +29,7 @@ extension Div { } fileprivate func applyOptionalItemPatch(_ patch: DivPatch) -> Div? { - if let id = id, let change = patch.getChange(id: id) { + if let id, let change = patch.getChange(id: id) { guard let items = change.items else { return nil } @@ -43,7 +43,7 @@ extension Div { } fileprivate func applyMultipleItemsPatch(_ patch: DivPatch) -> [Div] { - if let id = id, let change = patch.getChange(id: id) { + if let id, let change = patch.getChange(id: id) { return change.items ?? [] } return [applyPatchToChildren(patch)] diff --git a/DivKit/Extensions/DivDisappearActionExtensions.swift b/DivKit/Extensions/DivDisappearActionExtensions.swift index f5a87f9e..c3eba74b 100644 --- a/DivKit/Extensions/DivDisappearActionExtensions.swift +++ b/DivKit/Extensions/DivDisappearActionExtensions.swift @@ -4,8 +4,11 @@ import CommonCorePublic import LayoutKit extension DivDisappearAction { - func makeDisappearAction(context: DivBlockModelingContext) -> VisibilityAction { + func makeDisappearAction(context: DivBlockModelingContext) -> VisibilityAction? { let expressionResolver = context.expressionResolver + guard resolveIsEnabled(expressionResolver) else { + return nil + } let logLimitValue = resolveLogLimit(expressionResolver) let path = context.parentPath + logId return VisibilityAction( diff --git a/DivKit/Extensions/DivEdgeInsetsExtensions.swift b/DivKit/Extensions/DivEdgeInsetsExtensions.swift index 405351c1..c556fa74 100644 --- a/DivKit/Extensions/DivEdgeInsetsExtensions.swift +++ b/DivKit/Extensions/DivEdgeInsetsExtensions.swift @@ -4,15 +4,15 @@ import BaseUIPublic import CommonCorePublic import LayoutKit -extension Optional { +extension DivEdgeInsets? { func resolve(_ context: DivBlockModelingContext) -> EdgeInsets { self?.resolve(context) ?? EdgeInsets.zero } - + func resolveHorizontalInsets(_ expressionResolver: ExpressionResolver) -> SideInsets { self?.resolveHorizontalInsets(expressionResolver) ?? SideInsets.zero } - + func resolveVerticalInsets(_ expressionResolver: ExpressionResolver) -> SideInsets { self?.resolveVerticalInsets(expressionResolver) ?? SideInsets.zero } diff --git a/DivKit/Extensions/DivExtensions.swift b/DivKit/Extensions/DivExtensions.swift index 9c2e9e91..020b1e9b 100644 --- a/DivKit/Extensions/DivExtensions.swift +++ b/DivKit/Extensions/DivExtensions.swift @@ -24,42 +24,6 @@ extension Div { } } -extension Div { - func resolveA11yDescription(_ context: DivBlockModelingContext) -> String? { - let expressionResolver = context.expressionResolver - let accessibility = value.accessibility - guard accessibility?.resolveMode(expressionResolver) != .exclude else { - return nil - } - switch self { - case .divContainer, - .divCustom, - .divGallery, - .divGifImage, - .divGrid, - .divImage, - .divIndicator, - .divInput, - .divPager, - .divTabs, - .divSelect, - .divSeparator, - .divSlider, - .divVideo, - .divState: - return accessibility?.resolveDescription(expressionResolver) - case let .divText(divText): - let handlerDescription = context - .getExtensionHandlers(for: divText) - .compactMap { $0.accessibilityElement?.strings.label } - .reduce(nil) { $0?.appending(" " + $1) ?? $1 } - return handlerDescription ?? - divText.accessibility?.resolveDescription(expressionResolver) ?? - divText.resolveText(expressionResolver) as String? - } - } -} - extension Div { var isHorizontallyMatchParent: Bool { switch value.width { @@ -80,13 +44,13 @@ extension Div { } } -extension Sequence where Element == Div { +extension Sequence
{ var hasHorizontallyMatchParent: Bool { contains { $0.isHorizontallyMatchParent } } var allHorizontallyMatchParent: Bool { - allSatisfy { $0.isHorizontallyMatchParent } + allSatisfy(\.isHorizontallyMatchParent) } var hasVerticallyMatchParent: Bool { @@ -94,6 +58,6 @@ extension Sequence where Element == Div { } var allVerticallyMatchParent: Bool { - allSatisfy { $0.isVerticallyMatchParent } + allSatisfy(\.isVerticallyMatchParent) } } diff --git a/DivKit/Extensions/DivGallery/DivGallerySizeModifier.swift b/DivKit/Extensions/DivGallery/DivGallerySizeModifier.swift index 4ef64fe5..2a2d97f2 100644 --- a/DivKit/Extensions/DivGallery/DivGallerySizeModifier.swift +++ b/DivKit/Extensions/DivGallery/DivGallerySizeModifier.swift @@ -16,7 +16,7 @@ struct DivGallerySizeModifier: DivSizeModifier { direction: GalleryViewModel.Direction ) { let items = gallery.nonNilItems - + if direction == .vertical, gallery.getTransformedWidth(context).isIntrinsic, items.allHorizontallyMatchParent { diff --git a/DivKit/Extensions/DivGridExtensions.swift b/DivKit/Extensions/DivGridExtensions.swift index 7ef9fbf3..50885ead 100644 --- a/DivKit/Extensions/DivGridExtensions.swift +++ b/DivKit/Extensions/DivGridExtensions.swift @@ -9,7 +9,7 @@ extension DivGrid: DivBlockModeling { actionsHolder: self ) } - + var nonNilItems: [Div] { items ?? [] } diff --git a/DivKit/Extensions/DivImage/DivImageProtocol.swift b/DivKit/Extensions/DivImage/DivImageProtocol.swift index 97d9bf2e..2e1648e3 100644 --- a/DivKit/Extensions/DivImage/DivImageProtocol.swift +++ b/DivKit/Extensions/DivImage/DivImageProtocol.swift @@ -12,7 +12,7 @@ protocol DivImageProtocol: DivBase, DivImageContentMode { extension DivImageProtocol { func resolveHeight(_ context: DivBlockModelingContext) -> ImageBlockHeight { - if let aspect = aspect { + if let aspect { return .ratio(aspect.resolveRatio(context.expressionResolver) ?? 0) } return .trait(resolveContentHeightTrait(context)) diff --git a/DivKit/Extensions/DivIndicatorExtensions.swift b/DivKit/Extensions/DivIndicatorExtensions.swift index 2e6bc663..a8e7cbe6 100644 --- a/DivKit/Extensions/DivIndicatorExtensions.swift +++ b/DivKit/Extensions/DivIndicatorExtensions.swift @@ -36,7 +36,7 @@ extension DivIndicator: DivBlockModeling { let hightightedScaleX: CGFloat let hightightedScaleY: CGFloat - if let activeRect = activeRect, let inactiveRect = inactiveRect { + if let activeRect, let inactiveRect { hightightedScaleX = activeRect.size.width / inactiveRect.size.width hightightedScaleY = activeRect.size.height / inactiveRect.size.height } else { @@ -47,7 +47,7 @@ extension DivIndicator: DivBlockModeling { let disappearingScaleX: CGFloat let disappearingScaleY: CGFloat - if let inactiveRect = inactiveRect, let inactiveMinimumRect = inactiveMinimumRect { + if let inactiveRect, let inactiveMinimumRect { disappearingScaleX = inactiveMinimumRect.size.width / inactiveRect.size.width disappearingScaleY = inactiveMinimumRect.size.height / inactiveRect.size.height } else { @@ -106,7 +106,7 @@ extension DivIndicator: DivBlockModeling { with shape: DivRoundedRectangleShape?, resolver: ExpressionResolver ) -> PageIndicatorConfiguration.RoundedRectangleIndicator? { - guard let shape = shape else { + guard let shape else { return nil } return PageIndicatorConfiguration.RoundedRectangleIndicator( diff --git a/DivKit/Extensions/DivSliderExtensions.swift b/DivKit/Extensions/DivSliderExtensions.swift index 9ce04878..61c11b40 100644 --- a/DivKit/Extensions/DivSliderExtensions.swift +++ b/DivKit/Extensions/DivSliderExtensions.swift @@ -44,7 +44,7 @@ extension DivSlider: DivBlockModeling { offsetY: thumbTextStyle?.offset?.y.resolveValue(expressionResolver) ?? 0 ) let secondThumb: SliderModel.ThumbModel? - if let thumbSecondaryValueVariable = thumbSecondaryValueVariable { + if let thumbSecondaryValueVariable { let secondThumbValue = context.makeBinding( variableName: thumbSecondaryValueVariable, defaultValue: 0 @@ -212,7 +212,7 @@ private func makeRoundedRectangle( resolver: ExpressionResolver ) -> MarksConfiguration .RoundedRectangle? { - guard let mark = mark, + guard let mark, let divShapeDrawable = mark.value as? DivShapeDrawable, let shape = divShapeDrawable.shape.value as? DivRoundedRectangleShape else { return nil diff --git a/DivKit/Extensions/DivStateExtensions.swift b/DivKit/Extensions/DivStateExtensions.swift index 8875b855..457e1e72 100644 --- a/DivKit/Extensions/DivStateExtensions.swift +++ b/DivKit/Extensions/DivStateExtensions.swift @@ -49,7 +49,7 @@ extension DivState: DivBlockModeling { var animationIn: [TransitioningAnimation]? var animationOut: [TransitioningAnimation]? let activeStateId = activeState.stateId - if let stateManagerItem = stateManagerItem, + if let stateManagerItem, let previousState = getPreviousState(stateManagerItem: stateManagerItem), previousState.stateId != activeStateId, let previousDiv = previousState.div { diff --git a/DivKit/Extensions/DivTabsExtensions.swift b/DivKit/Extensions/DivTabsExtensions.swift index c6eca581..00184f7c 100644 --- a/DivKit/Extensions/DivTabsExtensions.swift +++ b/DivKit/Extensions/DivTabsExtensions.swift @@ -43,7 +43,7 @@ extension DivTabs: DivBlockModeling { let titleStyle = tabTitleStyle ?? DivTabs.TabTitleStyle() let listModel = TabListViewModel( - tabTitles: tabs.map { $0.title }, + tabTitles: tabs.map(\.title), titleStyle: titleStyle.resolve(context), layoutDirection: context.layoutDirection, listPaddings: titlePaddings.resolve(context) @@ -51,7 +51,7 @@ extension DivTabs: DivBlockModeling { let expressionResolver = context.expressionResolver let contentsModel = try TabContentsViewModel( - pages: tabs.map { $0.page }, + pages: tabs.map(\.page), pagesHeight: resolveDynamicHeight(expressionResolver) ? .bySelectedPage : .byHighestPage, @@ -179,7 +179,7 @@ extension DivTabs.TabTitleStyle { extension Typo { fileprivate func with(height: Int?) -> Typo { - if let height = height { + if let height { return with(height: CGFloat(height)) } else { return self diff --git a/DivKit/Extensions/DivTextExtensions.swift b/DivKit/Extensions/DivTextExtensions.swift index c77b537a..83cf2d69 100644 --- a/DivKit/Extensions/DivTextExtensions.swift +++ b/DivKit/Extensions/DivTextExtensions.swift @@ -9,15 +9,24 @@ import NetworkingPublic extension DivText: DivBlockModeling { public func makeBlock(context: DivBlockModelingContext) throws -> Block { - try applyBaseProperties( - to: { try makeBaseBlock(context: context) }, + let expressionResolver = context.expressionResolver + let lazyText = Lazy(getter: { [unowned self] in + resolveText(expressionResolver) ?? "" + }) + return try applyBaseProperties( + to: { try makeBaseBlock(context: context, text: lazyText) }, context: context, actionsHolder: self, - customA11yElement: resolveAccessibilityElement(context.expressionResolver) + customA11yDescriptionProvider: { [unowned self] in + accessibility?.resolveDescription(expressionResolver) ?? lazyText.value + } ) } - private func makeBaseBlock(context: DivBlockModelingContext) throws -> Block { + private func makeBaseBlock( + context: DivBlockModelingContext, + text: Lazy + ) throws -> Block { let expressionResolver = context.expressionResolver let font = context.fontProvider.font( @@ -60,7 +69,7 @@ extension DivText: DivBlockModeling { } let attributedString = makeAttributedString( - text: resolveText(expressionResolver) ?? ("" as CFString), + text: text.value as CFString, typo: typo, ranges: ranges, actions: nil, @@ -135,7 +144,7 @@ extension DivText: DivBlockModeling { images: [Image]?, text: NSAttributedString? ) -> [TextBlock.InlineImage] { - guard let text = text else { + guard let text else { return [] } return (images ?? []) @@ -206,7 +215,7 @@ extension DivText: DivBlockModeling { } private func resolveGradient(_ expressionResolver: ExpressionResolver) -> Gradient? { - guard let textGradient = textGradient else { + guard let textGradient else { return nil } switch textGradient { @@ -224,25 +233,6 @@ extension DivText: DivBlockModeling { ).map { .radial($0) } } } - - private func resolveAccessibilityElement( - _ expressionResolver: ExpressionResolver - ) -> AccessibilityElement? { - let accessibility = accessibility ?? DivAccessibility() - guard accessibility.resolveDescription(expressionResolver) == nil else { - return nil - } - return AccessibilityElement( - traits: accessibility.type?.cast() ?? .none, - strings: AccessibilityElement.Strings( - label: resolveText(expressionResolver) as String?, - hint: accessibility.resolveHint(expressionResolver), - value: accessibility.resolveStateDescription(expressionResolver), - identifier: id - ), - hideElementWithChildren: accessibility.resolveMode(expressionResolver).isExclude - ) - } } extension CFMutableAttributedString { @@ -250,7 +240,7 @@ extension CFMutableAttributedString { _ actions: [UserInterfaceAction]?, at range: CFRange ) { - if let actions = actions { + if let actions { ActionsAttribute(actions: actions).apply(to: self, at: range) } } diff --git a/DivKit/Extensions/DivTooltipExtensions.swift b/DivKit/Extensions/DivTooltipExtensions.swift index 0b81699e..0da9a120 100644 --- a/DivKit/Extensions/DivTooltipExtensions.swift +++ b/DivKit/Extensions/DivTooltipExtensions.swift @@ -22,7 +22,7 @@ extension DivTooltip { let tooltipViewFactory: TooltipViewFactory = Variable { [tooltipViewFactory = context.tooltipViewFactory, div = self.div] in - guard let tooltipViewFactory = tooltipViewFactory else { return nil } + guard let tooltipViewFactory else { return nil } return tooltipViewFactory(div) } @@ -53,7 +53,7 @@ extension DivTooltip.Position { } } -extension Optional where Wrapped == [DivTooltip] { +extension [DivTooltip]? { func makeTooltips( context: DivBlockModelingContext ) throws -> [BlockTooltip] { diff --git a/DivKit/Extensions/DivVideoExtensions.swift b/DivKit/Extensions/DivVideoExtensions.swift index 2c88233d..368e42ee 100644 --- a/DivKit/Extensions/DivVideoExtensions.swift +++ b/DivKit/Extensions/DivVideoExtensions.swift @@ -70,7 +70,7 @@ extension DivVideo: DivBlockModeling { playerFactory: playerFactory ) - if let aspectRatio = aspectRatio { + if let aspectRatio { return AspectBlock(content: videoBlock, aspectRatio: aspectRatio) } diff --git a/DivKit/Extensions/DivVisibilityActionExtensions.swift b/DivKit/Extensions/DivVisibilityActionExtensions.swift index 37af9d2a..3db10761 100644 --- a/DivKit/Extensions/DivVisibilityActionExtensions.swift +++ b/DivKit/Extensions/DivVisibilityActionExtensions.swift @@ -4,8 +4,11 @@ import CommonCorePublic import LayoutKit extension DivVisibilityAction { - func makeVisibilityAction(context: DivBlockModelingContext) -> VisibilityAction { + func makeVisibilityAction(context: DivBlockModelingContext) -> VisibilityAction? { let expressionResolver = context.expressionResolver + guard resolveIsEnabled(expressionResolver) else { + return nil + } let logLimitValue = resolveLogLimit(expressionResolver) let path = context.parentPath + logId return VisibilityAction( diff --git a/DivKit/RunLoopCardUpdateAggregator.swift b/DivKit/RunLoopCardUpdateAggregator.swift index 20c224ee..63b68189 100644 --- a/DivKit/RunLoopCardUpdateAggregator.swift +++ b/DivKit/RunLoopCardUpdateAggregator.swift @@ -4,6 +4,7 @@ import Foundation final class RunLoopCardUpdateAggregator { private var enabled: Bool = true + private var scheduled: Bool = false private var batch: [DivActionURLHandler.UpdateReason] = [] private let updateCardAction: DivKitComponents.UpdateCardAction private let mainThreadAsyncRunner: MainThreadAsyncRunner @@ -26,25 +27,22 @@ final class RunLoopCardUpdateAggregator { func aggregate(_ reason: DivActionURLHandler.UpdateReason) { Thread.assertIsMain() guard enabled else { return } - let notScheduled = batch.isEmpty batch.append(reason) - if notScheduled { + if !scheduled { + scheduled = true mainThreadAsyncRunner { [weak self] in - self?.flushUpdateActions() + guard let self else { return } + if let reasons = NonEmptyArray(self.batch.merge()) { + self.batch = [] + self.scheduled = false + self.updateCardAction(reasons) + } } } } - - func flushUpdateActions() { - guard let reasons = NonEmptyArray(self.batch.merge()) else { - return - } - batch = [] - updateCardAction(reasons) - } } -extension Array where Element == DivActionURLHandler.UpdateReason { +extension [DivActionURLHandler.UpdateReason] { fileprivate func merge() -> [DivActionURLHandler.UpdateReason] { var variables: DivActionURLHandler.UpdateReason.AffectedCards = .specific([]) diff --git a/DivKit/States/DivStateManager.swift b/DivKit/States/DivStateManager.swift index a8319c34..f086654b 100644 --- a/DivKit/States/DivStateManager.swift +++ b/DivKit/States/DivStateManager.swift @@ -194,7 +194,7 @@ extension DivBase { } } -extension Array where Element == String { +extension [String] { fileprivate mutating func appendIdWithStateChangeTransition(div: Div) { if let id = div.id, div.value.shouldApplyTransition(.stateChange) { append(id) diff --git a/DivKit/Templates/SerializationExtensions.swift b/DivKit/Templates/SerializationExtensions.swift index 724b5e0b..af807941 100644 --- a/DivKit/Templates/SerializationExtensions.swift +++ b/DivKit/Templates/SerializationExtensions.swift @@ -20,7 +20,7 @@ extension Field { } /// Deserialization for Field? -extension Dictionary where Key == String, Value == Any { +extension [String: Any] { @inlinable func link(for key: String) -> TemplatedPropertyLink? { self["$" + key] as? TemplatedPropertyLink @@ -29,12 +29,10 @@ extension Dictionary where Key == String, Value == Any { @inlinable func getOptionalField( _ key: String, - transform: (U) -> T?, - validator: AnyValueValidator? = nil + transform: (U) -> T? ) throws -> Field? { Field.makeOptional( - valueGetter: (try? self.getOptionalField(key, transform: transform, validator: validator)) - .flatMap { $0 }, + valueGetter: (try? self.getOptionalField(key, transform: transform)).flatMap { $0 }, linkGetter: link(for: key) ) } @@ -58,19 +56,17 @@ extension Dictionary where Key == String, Value == Any { @inlinable func getOptionalField( _ key: String, - templateToType: [TemplateName: String], - validator: AnyValueValidator? = nil + templateToType: [TemplateName: String] ) throws -> Field? { try getOptionalField( key, - transform: { (dict: Self) in try? T(dictionary: dict, templateToType: templateToType) }, - validator: validator + transform: { (dict: Self) in try? T(dictionary: dict, templateToType: templateToType) } ) } } /// Deserializaton for Field<[T]> and [T] -extension Dictionary where Key == String, Value == Any { +extension [String: Any] { @inlinable func getOptionalArray( _ key: String, @@ -113,28 +109,24 @@ extension Dictionary where Key == String, Value == Any { @inlinable func getOptionalArray( _ key: String, - templateToType: [TemplateName: String], - validator: AnyArrayValueValidator? = nil + templateToType: [TemplateName: String] ) throws -> Field<[T]>? { try getOptionalArray( key, - transform: { (dict: Self) in try? T(dictionary: dict, templateToType: templateToType) }, - validator: validator + transform: { (dict: Self) in try? T(dictionary: dict, templateToType: templateToType) } ) } } -extension Dictionary where Key == String, Value == Any { +extension [String: Any] { @inlinable func getField( _ key: String, - templateToType: [TemplateName: String], - validator: AnyValueValidator? = nil + templateToType: [TemplateName: String] ) throws -> T { try getField( key, - transform: { (dict: Self) in try T(dictionary: dict, templateToType: templateToType) }, - validator: validator + transform: { (dict: Self) in try T(dictionary: dict, templateToType: templateToType) } ) } } @@ -163,7 +155,6 @@ func deserialize( _ value: Any, templates: [TemplateName: Any], templateToType: [TemplateName: String], - validator: AnyValueValidator? = nil, type: T.Type ) -> DeserializationResult { deserialize( @@ -172,8 +163,7 @@ func deserialize( templates: templates, templateToType: templateToType, type: type - ), - validator: validator + ) ) } diff --git a/DivKit/Timers/DivTimerController.swift b/DivKit/Timers/DivTimerController.swift index 2dcbdea1..2d6c3d8f 100644 --- a/DivKit/Timers/DivTimerController.swift +++ b/DivKit/Timers/DivTimerController.swift @@ -249,7 +249,7 @@ extension DivTimer { DivKitLogger.failure("Timer '\(self.id)' parameters is not valid: tick_interval not set") return false } - if self.tickActions == nil && self.valueVariable == nil { + if self.tickActions == nil, self.valueVariable == nil { DivKitLogger .failure("Timer '\(self.id)' parameters is not valid: set tickActions or valueVariable") return false diff --git a/DivKit/Timers/TimeIntervalMeasuring.swift b/DivKit/Timers/TimeIntervalMeasuring.swift index 642df183..eac84d2a 100644 --- a/DivKit/Timers/TimeIntervalMeasuring.swift +++ b/DivKit/Timers/TimeIntervalMeasuring.swift @@ -20,7 +20,7 @@ final class TimeIntervalMeasuring: TimeMeasuring { public func pause() { paused = true - if let startDate = startDate { + if let startDate { passedTimeInterval += Date().timeIntervalSince(startDate) } } @@ -34,7 +34,7 @@ final class TimeIntervalMeasuring: TimeMeasuring { if paused { return passedTimeInterval } - if let startDate = startDate { + if let startDate { return passedTimeInterval + Date().timeIntervalSince(startDate) } return 0 diff --git a/DivKit/Variables/DivTriggersStorage.swift b/DivKit/Variables/DivTriggersStorage.swift index eaf6f256..41790e07 100644 --- a/DivKit/Variables/DivTriggersStorage.swift +++ b/DivKit/Variables/DivTriggersStorage.swift @@ -146,7 +146,7 @@ extension DivTrigger { } // oldVariables is nil for initial trigger resolving - guard let oldVariables = oldVariables else { + guard let oldVariables else { return true } diff --git a/DivKit/Variables/DivVariableStorage.swift b/DivKit/Variables/DivVariableStorage.swift index 4559aee8..45ea6c16 100644 --- a/DivKit/Variables/DivVariableStorage.swift +++ b/DivKit/Variables/DivVariableStorage.swift @@ -35,7 +35,7 @@ public final class DivVariableStorage { public init(outerStorage: DivVariableStorage? = nil) { self.outerStorage = outerStorage - if let outerStorage = outerStorage { + if let outerStorage { weak var weakSelf: DivVariableStorage? let outerStorageEvents: Signal = outerStorage.changeEvents.compactMap { guard let self = weakSelf else { @@ -59,7 +59,7 @@ public final class DivVariableStorage { let variable = lock.read { values[name] } - if let variable = variable { + if let variable { return variable.typedValue() } return outerStorage?.getValue(name) @@ -157,7 +157,7 @@ public final class DivVariableStorage { return } - if let outerStorage = outerStorage { + if let outerStorage { outerStorage.update(name: name, valueFactory: valueFactory) } else { DivKitLogger.error("Variable is not declared: \(name)") diff --git a/DivKit/Variables/DivVariableTracker.swift b/DivKit/Variables/DivVariableTracker.swift index 76d0f8c1..de0bc009 100644 --- a/DivKit/Variables/DivVariableTracker.swift +++ b/DivKit/Variables/DivVariableTracker.swift @@ -1,23 +1,31 @@ import Foundation +import VGSL_Fundamentals_Tiny + public final class DivVariableTracker { - private var usedVariables: [DivCardID: Set] = [:] + private var usedVariables = Atomic<[DivCardID: Set]>(initialValue: [:]) init() {} func onModelingStarted(cardId: DivCardID) { - usedVariables[cardId] = [] + usedVariables.accessWrite { value in + value[cardId] = [] + } } func onVariablesUsed(cardId: DivCardID, variables: Set) { - usedVariables[cardId] = (usedVariables[cardId] ?? []).union(variables) + usedVariables.accessWrite { value in + value[cardId] = (value[cardId] ?? []).union(variables) + } } func getAffectedCards(variables: Set) -> Set { var cardIds = Set() - usedVariables.forEach { cardId, usedVariables in - if !usedVariables.isDisjoint(with: variables) { - cardIds.insert(cardId) + usedVariables.accessRead { value in + value.forEach { cardId, usedVariables in + if !usedVariables.isDisjoint(with: variables) { + cardIds.insert(cardId) + } } } return cardIds diff --git a/DivKit/Variables/DivVariableValue.swift b/DivKit/Variables/DivVariableValue.swift index b56003c3..f24279a7 100644 --- a/DivKit/Variables/DivVariableValue.swift +++ b/DivKit/Variables/DivVariableValue.swift @@ -35,7 +35,7 @@ public enum DivVariableValue: Hashable { } } - init?(_ value: T) { + init?(_ value: some Any) { switch value { case let value as String: self = .string(value) diff --git a/DivKit/Variables/DivVariablesStorage.swift b/DivKit/Variables/DivVariablesStorage.swift index f2f8ec55..cbdd45e5 100644 --- a/DivKit/Variables/DivVariablesStorage.swift +++ b/DivKit/Variables/DivVariablesStorage.swift @@ -77,7 +77,7 @@ public final class DivVariablesStorage { let variable = lock.read { cardVariables[cardId]?[name] } - if let variable = variable { + if let variable { return variable.typedValue() } return globalStorage.getValue(name) @@ -275,7 +275,7 @@ private func makeDivVariableValue( return newValue } -extension Collection where Element == DivVariable { +extension Collection { public func extractDivVariableValues() -> DivVariables { var variables = DivVariables() forEach { variable in @@ -341,7 +341,7 @@ extension Dictionary where Key == String { } } -extension Dictionary where Key == String, Value == Color { +extension [String: Color] { public func mapToDivVariables() -> DivVariables { mapToDivVariables(valueTransform: DivVariableValue.color) } diff --git a/DivKit/Views/DivBlockProvider.swift b/DivKit/Views/DivBlockProvider.swift index 5a8281b9..672bc664 100644 --- a/DivKit/Views/DivBlockProvider.swift +++ b/DivKit/Views/DivBlockProvider.swift @@ -95,9 +95,9 @@ final class DivBlockProvider { } private func update(reasons: [DivActionURLHandler.UpdateReason]) { - guard var divData = divData else { + guard var divData else { guard debugParams.isDebugInfoEnabled else { return } - block = makeErrorsBlock(dataErrors.map { $0.prettyMessage }) + block = makeErrorsBlock(dataErrors.map(\.prettyMessage)) return } @@ -204,7 +204,7 @@ final class DivBlockProvider { } if debugParams.isDebugInfoEnabled { - return makeErrorsBlock(errors.map { $0.prettyMessage }) + return makeErrorsBlock(errors.map(\.prettyMessage)) } else { return noDataBlock } diff --git a/DivKit/Views/DivView.swift b/DivKit/Views/DivView.swift index 57f3cbe0..7bb9b2cb 100644 --- a/DivKit/Views/DivView.swift +++ b/DivKit/Views/DivView.swift @@ -133,7 +133,7 @@ public final class DivView: VisibleBoundsTrackingView { /// /// - Returns: The calculated intrinsic content size. public override var intrinsicContentSize: CGSize { - guard let cardSize = cardSize else { + guard let cardSize else { return CGSize(width: DivView.noIntrinsicMetric, height: DivView.noIntrinsicMetric) } let width: CGFloat @@ -159,7 +159,7 @@ public final class DivView: VisibleBoundsTrackingView { } private func update(block: Block) { - if let blockView = blockView, block.canConfigureBlockView(blockView) { + if let blockView, block.canConfigureBlockView(blockView) { block.configureBlockView( blockView, observer: self, diff --git a/DivKit/generated_sources/DivText.swift b/DivKit/generated_sources/DivText.swift index 8742dccf..ae936de7 100644 --- a/DivKit/generated_sources/DivText.swift +++ b/DivKit/generated_sources/DivText.swift @@ -227,7 +227,7 @@ public final class DivText: DivBase { public let selectable: Expression // default value: false public let selectedActions: [DivAction]? public let strike: Expression // default value: none - public let text: Expression + public let text: Expression public let textAlignmentHorizontal: Expression // default value: start public let textAlignmentVertical: Expression // default value: top public let textColor: Expression // default value: #FF000000 @@ -313,8 +313,8 @@ public final class DivText: DivBase { resolver.resolveEnum(strike) ?? DivLineStyle.none } - public func resolveText(_ resolver: ExpressionResolver) -> CFString? { - resolver.resolveString(text, initializer: { $0 as CFString}) + public func resolveText(_ resolver: ExpressionResolver) -> String? { + resolver.resolveString(text, initializer: { $0 }) } public func resolveTextAlignmentHorizontal(_ resolver: ExpressionResolver) -> DivAlignmentHorizontal { @@ -398,7 +398,7 @@ public final class DivText: DivBase { selectable: Expression? = nil, selectedActions: [DivAction]? = nil, strike: Expression? = nil, - text: Expression, + text: Expression, textAlignmentHorizontal: Expression? = nil, textAlignmentVertical: Expression? = nil, textColor: Expression? = nil, diff --git a/DivKit/generated_sources/DivTextTemplate.swift b/DivKit/generated_sources/DivTextTemplate.swift index 1d2087cd..679af191 100644 --- a/DivKit/generated_sources/DivTextTemplate.swift +++ b/DivKit/generated_sources/DivTextTemplate.swift @@ -665,7 +665,7 @@ public final class DivTextTemplate: TemplateValue { public let selectable: Field>? // default value: false public let selectedActions: Field<[DivActionTemplate]>? public let strike: Field>? // default value: none - public let text: Field>? + public let text: Field>? public let textAlignmentHorizontal: Field>? // default value: start public let textAlignmentVertical: Field>? // default value: top public let textColor: Field>? // default value: #FF000000 @@ -784,7 +784,7 @@ public final class DivTextTemplate: TemplateValue { selectable: Field>? = nil, selectedActions: Field<[DivActionTemplate]>? = nil, strike: Field>? = nil, - text: Field>? = nil, + text: Field>? = nil, textAlignmentHorizontal: Field>? = nil, textAlignmentVertical: Field>? = nil, textColor: Field>? = nil, @@ -1073,7 +1073,7 @@ public final class DivTextTemplate: TemplateValue { var selectableValue: DeserializationResult> = parent?.selectable?.value() ?? .noValue var selectedActionsValue: DeserializationResult<[DivAction]> = .noValue var strikeValue: DeserializationResult> = parent?.strike?.value() ?? .noValue - var textValue: DeserializationResult> = parent?.text?.value() ?? .noValue + var textValue: DeserializationResult> = parent?.text?.value() ?? .noValue var textAlignmentHorizontalValue: DeserializationResult> = parent?.textAlignmentHorizontal?.value() ?? .noValue var textAlignmentVerticalValue: DeserializationResult> = parent?.textAlignmentVertical?.value() ?? .noValue var textColorValue: DeserializationResult> = parent?.textColor?.value() ?? .noValue diff --git a/DivKitExtensions/Animations/AnimationBlockView+UIViewRenderableBlock.swift b/DivKitExtensions/Animations/AnimationBlockView+UIViewRenderableBlock.swift index 3fbd548d..fda5a46f 100644 --- a/DivKitExtensions/Animations/AnimationBlockView+UIViewRenderableBlock.swift +++ b/DivKitExtensions/Animations/AnimationBlockView+UIViewRenderableBlock.swift @@ -20,7 +20,7 @@ extension LottieAnimationBlock { renderingDelegate _: RenderingDelegate? ) { let lottieView = view as! AnimationBlockView - if lottieView.animationHolder !== animationHolder { + if lottieView.animationHolder != animationHolder { lottieView.animatableView = animatableView.value lottieView.animationHolder = animationHolder } diff --git a/DivKitExtensions/Animations/AnimationBlockView.swift b/DivKitExtensions/Animations/AnimationBlockView.swift index 8a915e12..b88c5952 100644 --- a/DivKitExtensions/Animations/AnimationBlockView.swift +++ b/DivKitExtensions/Animations/AnimationBlockView.swift @@ -21,9 +21,9 @@ final class AnimationBlockView: BlockView { let newValue = animationHolder animationRequest = animationHolder? .requestAnimationWithCompletion { [weak self] animationSource in - guard let self = self, + guard let self, newValue === self.animationHolder, - let animationSource = animationSource else { + let animationSource else { return } diff --git a/DivKitExtensions/ExtensionHandlers/ImageExtensionHandler.swift b/DivKitExtensions/ExtensionHandlers/ImageExtensionHandler.swift index 59516e19..ef002039 100644 --- a/DivKitExtensions/ExtensionHandlers/ImageExtensionHandler.swift +++ b/DivKitExtensions/ExtensionHandlers/ImageExtensionHandler.swift @@ -21,7 +21,7 @@ public final class ImageExtensionHandler: DivExtensionHandler { ) -> Block { guard let block = block as? ImageBlock, - let image = image + let image else { return block } diff --git a/DivKitExtensions/ExtensionHandlers/PinchToZoomExtensionHandler.swift b/DivKitExtensions/ExtensionHandlers/PinchToZoomExtensionHandler.swift index 330e4121..b963f319 100644 --- a/DivKitExtensions/ExtensionHandlers/PinchToZoomExtensionHandler.swift +++ b/DivKitExtensions/ExtensionHandlers/PinchToZoomExtensionHandler.swift @@ -17,7 +17,7 @@ public final class PinchToZoomExtensionHandler: DivExtensionHandler { div _: DivBase, context: DivBlockModelingContext ) -> Block { - guard let overlayView = overlayView else { + guard let overlayView else { context.addError(message: "PinchToZoomExtensionHandler.overlayView is nil") return EmptyBlock() } diff --git a/DivKitExtensions/ExtensionHandlers/TextExtensionHandler.swift b/DivKitExtensions/ExtensionHandlers/TextExtensionHandler.swift index 8ae7ed8f..0bc56784 100644 --- a/DivKitExtensions/ExtensionHandlers/TextExtensionHandler.swift +++ b/DivKitExtensions/ExtensionHandlers/TextExtensionHandler.swift @@ -26,7 +26,7 @@ public final class TextExtensionHandler: DivExtensionHandler { ) -> Block { guard let textBlock = block as? TextBlock, - let text = text, + let text, let newTextBlock = TextBlock(copyingAttributesFrom: textBlock, text: text) else { return block diff --git a/DivKitExtensions/Shimmer/ShimmerStyle.swift b/DivKitExtensions/Shimmer/ShimmerStyle.swift index 5e1e48ee..afda6217 100644 --- a/DivKitExtensions/Shimmer/ShimmerStyle.swift +++ b/DivKitExtensions/Shimmer/ShimmerStyle.swift @@ -23,17 +23,17 @@ extension ShimmerStyle { "angle", expressionResolver: expressionResolver ) ?? defaultAngle - + self.duration = try dictionary.getOptionalFloat( "duration", expressionResolver: expressionResolver ) ?? defaultDuration - + let colors: [Color] = try dictionary.getOptionalArray( "colors", transform: { expressionResolver.resolveColor($0) } ) ?? defaultColors - + let locations: [CGFloat] = try dictionary.getOptionalFloatArray( "locations", expressionResolver: expressionResolver diff --git a/DivKitExtensions/Shimmer/ShimmerView.swift b/DivKitExtensions/Shimmer/ShimmerView.swift index 2b3d6ff8..6b824c1a 100644 --- a/DivKitExtensions/Shimmer/ShimmerView.swift +++ b/DivKitExtensions/Shimmer/ShimmerView.swift @@ -84,7 +84,7 @@ extension CAGradientLayer { fileprivate func apply(style: ShimmerStyle) { calculatePoints(for: style.angle) - colors = style.colorsAndLocations.map { $0.0.cgColor } + colors = style.colorsAndLocations.map(\.0.cgColor) locations = style.colorsAndLocations.map(\.1).map { NSNumber(value: $0.native) } } } diff --git a/DivKitExtensions/SizeProvider/SizeProviderExtensionHandler.swift b/DivKitExtensions/SizeProvider/SizeProviderExtensionHandler.swift index 5a7c7a4f..73f711d2 100644 --- a/DivKitExtensions/SizeProvider/SizeProviderExtensionHandler.swift +++ b/DivKitExtensions/SizeProvider/SizeProviderExtensionHandler.swift @@ -43,7 +43,7 @@ public final class SizeProviderExtensionHandler: DivExtensionHandler { .getOptionalField("width_variable_name") let heightVariableName: DivVariableName? = try? extensionParams .getOptionalField("height_variable_name") - if widthVariableName == nil && heightVariableName == nil { + if widthVariableName == nil, heightVariableName == nil { DivKitLogger.error("No valid params for SizeProviderExtensionHandler") return block } @@ -99,7 +99,7 @@ public final class SizeProviderExtensionHandler: DivExtensionHandler { context: DivBlockModelingContext, variableName: DivVariableName? ) -> ValueUpdater? { - guard let variableName = variableName else { + guard let variableName else { return nil } return { [weak self] in diff --git a/LayoutKit/Interface/UIElementPath.swift b/LayoutKit/Interface/UIElementPath.swift index dd238162..d899c576 100644 --- a/LayoutKit/Interface/UIElementPath.swift +++ b/LayoutKit/Interface/UIElementPath.swift @@ -75,7 +75,7 @@ extension UIElementPath { } } -extension Optional where Wrapped == UIElementPath { +extension UIElementPath? { public static func +(parent: Self, child: String) -> UIElementPath { parent.map { $0 + child } ?? UIElementPath(child) } diff --git a/LayoutKit/Interface/UserInterfaceAction.swift b/LayoutKit/Interface/UserInterfaceAction.swift index 624928c7..16c50b28 100644 --- a/LayoutKit/Interface/UserInterfaceAction.swift +++ b/LayoutKit/Interface/UserInterfaceAction.swift @@ -259,7 +259,7 @@ extension UserInterfaceAction.Payload: CustomDebugStringConvertible { } } -extension Optional where Wrapped == URL { +extension URL? { public func action( with path: UIElementPath, accessibilityElement: AccessibilityElement? = nil diff --git a/LayoutKit/LayoutKit/Base/AttributedStringExtensions.swift b/LayoutKit/LayoutKit/Base/AttributedStringExtensions.swift index ff3f15e4..d792178e 100644 --- a/LayoutKit/LayoutKit/Base/AttributedStringExtensions.swift +++ b/LayoutKit/LayoutKit/Base/AttributedStringExtensions.swift @@ -1,6 +1,6 @@ import Foundation -extension Optional where Wrapped == NSAttributedString { +extension NSAttributedString? { func attribute(key: NSAttributedString.Key, defaultValue: T) -> T { guard case let .some(string) = self, !string.isEmpty else { return defaultValue diff --git a/LayoutKit/LayoutKit/Base/MaskedInputViewModel.swift b/LayoutKit/LayoutKit/Base/MaskedInputViewModel.swift index 9af2f22d..d4f9b6ab 100644 --- a/LayoutKit/LayoutKit/Base/MaskedInputViewModel.swift +++ b/LayoutKit/LayoutKit/Base/MaskedInputViewModel.swift @@ -43,12 +43,12 @@ public class MaskedInputViewModel { ) maskValidator.newValues.skipRepeats().addObserver { [weak self] maskValidator in - guard let self = self else { return } + guard let self else { return } self.rawText = maskValidator.formatted(rawText: self.rawText, rawCursorPosition: nil).rawText }.dispose(in: disposePool) signal.addObserver { [weak self] action in - guard let self = self else { return } + guard let self else { return } let newString: String let newCursorPosition: CursorData? switch action { diff --git a/LayoutKit/LayoutKit/Base/Masks/MaskValidator.swift b/LayoutKit/LayoutKit/Base/Masks/MaskValidator.swift index 6f1c1eb0..dbc91cec 100644 --- a/LayoutKit/LayoutKit/Base/Masks/MaskValidator.swift +++ b/LayoutKit/LayoutKit/Base/Masks/MaskValidator.swift @@ -25,7 +25,7 @@ public final class MaskValidator: Equatable { from: data.text.index(data.text.startIndex, offsetBy: pos), to: $0.index ) <= 0 } - if let removeIndex = removeIndex { + if let removeIndex { data.rawData.remove(at: removeIndex) } return ( diff --git a/LayoutKit/LayoutKit/Base/TimeMeasure.swift b/LayoutKit/LayoutKit/Base/TimeMeasure.swift index 6c3a380d..aa004d11 100644 --- a/LayoutKit/LayoutKit/Base/TimeMeasure.swift +++ b/LayoutKit/LayoutKit/Base/TimeMeasure.swift @@ -15,7 +15,7 @@ public final class TimeMeasure { } private func stop() { - if let startTime = startTime { + if let startTime { time = Time( value: Int(Date().timeIntervalSince(startTime) * 1000), status: status diff --git a/LayoutKit/LayoutKit/Blocks/Anchor/AnchorBlock+UIViewRenderable.swift b/LayoutKit/LayoutKit/Blocks/Anchor/AnchorBlock+UIViewRenderable.swift index cc81a32f..db0681df 100644 --- a/LayoutKit/LayoutKit/Blocks/Anchor/AnchorBlock+UIViewRenderable.swift +++ b/LayoutKit/LayoutKit/Blocks/Anchor/AnchorBlock+UIViewRenderable.swift @@ -68,7 +68,7 @@ private final class AnchorView: BlockView, VisibleBoundsTrackingContainer { self.observer = observer func reuse(_ block: Block?, view: BlockView?) -> BlockView? { - guard let block = block else { + guard let block else { view?.removeFromSuperview() return nil } diff --git a/LayoutKit/LayoutKit/Blocks/Block+Debugging.swift b/LayoutKit/LayoutKit/Blocks/Block+Debugging.swift index 651f5560..36adbffb 100644 --- a/LayoutKit/LayoutKit/Blocks/Block+Debugging.swift +++ b/LayoutKit/LayoutKit/Blocks/Block+Debugging.swift @@ -131,7 +131,7 @@ extension SwitchBlock: CustomDebugStringConvertible { Enabled: \(enabled) """ - if let action = action { + if let action { result += "\n URL: \(dbgStr(action.url))" result += "\n Path: \(dbgStr(action.path))" } @@ -201,7 +201,7 @@ extension AnimationChanges: CustomDebugStringConvertible { extension BlockAnimation: CustomDebugStringConvertible { public var debugDescription: String { - "{ Animation changes:\(changes), KeyTimes: \(keyTimes.map { $0.value }), Duration: \(duration.value) }" + "{ Animation changes:\(changes), KeyTimes: \(keyTimes.map(\.value)), Duration: \(duration.value) }" } } @@ -336,7 +336,7 @@ extension GridBlock: CustomDebugStringConvertible { Items map: \(formatTable(grid.itemsIndices).indented()) Items: - \(items.map { $0.debugDescription }.joined(separator: ",\n").indented()) + \(items.map(\.debugDescription).joined(separator: ",\n").indented()) } """ } @@ -351,7 +351,7 @@ extension DecoratingBlock: CustomDebugStringConvertible { decorations.append("Background color: \(backgroundColor)") } - if let actions = actions { + if let actions { var actionDescription = "Actions:\n" for action in actions { actionDescription += " UIAction:\n" @@ -362,7 +362,7 @@ extension DecoratingBlock: CustomDebugStringConvertible { decorations.append(actionDescription) } - if let actionAnimation = actionAnimation { + if let actionAnimation { var description = "Action animation:\n" for animation in actionAnimation.touchDown { description += " TouchDown animation:\n" @@ -390,7 +390,7 @@ extension DecoratingBlock: CustomDebugStringConvertible { decorations.append("Boundary: \(boundary)") } - if let border = border { + if let border { decorations.append("Border: \(border)") } @@ -500,10 +500,10 @@ extension EmptyBlock: CustomDebugStringConvertible { } } -private func formatTable(_ rawTable: [[T]]) -> String { +private func formatTable(_ rawTable: [[some Any]]) -> String { let table = rawTable.map { $0.map(String.init(describing:)) } guard !table.isEmpty else { return "Empty table" } - let columnCounts = table.map { $0.count } + let columnCounts = table.map(\.count) guard columnCounts.min() == columnCounts.max() else { return "Malformed table" } diff --git a/LayoutKit/LayoutKit/Blocks/Block.swift b/LayoutKit/LayoutKit/Blocks/Block.swift index 261f065a..8c260866 100644 --- a/LayoutKit/LayoutKit/Blocks/Block.swift +++ b/LayoutKit/LayoutKit/Blocks/Block.swift @@ -205,7 +205,7 @@ public func !==(lhs: [Block], rhs: [Block]) -> Bool { !(lhs === rhs) } -extension Sequence where Element == Block { +extension Sequence { public var hasVerticallyNonResizable: Bool { contains { !$0.isVerticallyResizable } } @@ -248,7 +248,7 @@ extension Sequence where Element == Block { var maxWidthOfHorizontallyNonResizableBlocks: CGFloat? { self .filter { !$0.isHorizontallyResizable } - .map { $0.widthOfHorizontallyNonResizableBlock } + .map(\.widthOfHorizontallyNonResizableBlock) .max() } diff --git a/LayoutKit/LayoutKit/Blocks/BlockError.swift b/LayoutKit/LayoutKit/Blocks/BlockError.swift index 70bcffeb..8149870f 100644 --- a/LayoutKit/LayoutKit/Blocks/BlockError.swift +++ b/LayoutKit/LayoutKit/Blocks/BlockError.swift @@ -10,8 +10,8 @@ public struct BlockError: Error { // Workaround for swift compiler bug, when protocol is not conforming parent protocol @inlinable -public func modifyError( - _ modificator: (BlockError) -> T, +public func modifyError( + _ modificator: (BlockError) -> some Error, _ block: () throws -> R ) throws -> R { do { diff --git a/LayoutKit/LayoutKit/Blocks/Container/AxialAlignmentManager.swift b/LayoutKit/LayoutKit/Blocks/Container/AxialAlignmentManager.swift index c37e2e4e..34c6eca4 100644 --- a/LayoutKit/LayoutKit/Blocks/Container/AxialAlignmentManager.swift +++ b/LayoutKit/LayoutKit/Blocks/Container/AxialAlignmentManager.swift @@ -63,7 +63,7 @@ final class AxialAlignmentManager { } } -extension Array where Element == CGRect { +extension [CGRect] { fileprivate func applyOffset( with axialAlignment: ContainerBlock.AxialAlignment, layoutDirection: ContainerBlock.LayoutDirection, diff --git a/LayoutKit/LayoutKit/Blocks/Container/ContainerBlock.swift b/LayoutKit/LayoutKit/Blocks/Container/ContainerBlock.swift index ddb4a028..174fe883 100644 --- a/LayoutKit/LayoutKit/Blocks/Container/ContainerBlock.swift +++ b/LayoutKit/LayoutKit/Blocks/Container/ContainerBlock.swift @@ -183,13 +183,13 @@ public final class ContainerBlock: BlockWithLayout { if layoutMode == .wrap { switch layoutDirection { case .horizontal: - guard (children.map { $0.content }.allVerticallyNonResizable) else { + guard children.map(\.content).allVerticallyNonResizable else { throw BlockError( "Container block error: horizontal wrap container has children with resizable height" ) } case .vertical: - guard (children.map { $0.content }.allHorizontallyNonResizable) else { + guard children.map(\.content).allHorizontallyNonResizable else { throw BlockError( "Container block error: vertical wrap container has children with resizable width" ) @@ -200,13 +200,13 @@ public final class ContainerBlock: BlockWithLayout { if case .intrinsic = widthTrait { switch layoutDirection { case .horizontal: - guard (children.map { $0.content }.allHorizontallyNonResizable) else { + guard children.map(\.content).allHorizontallyNonResizable else { throw BlockError( "Container block error: horizontal intrinsic-width container has children with resizable width" ) } case .vertical: - guard (children.map { $0.content }.hasHorizontallyNonResizable) else { + guard children.map(\.content).hasHorizontallyNonResizable else { throw BlockError( "Container block error: in vertical intrinsic-width container all children have resizable width" ) @@ -219,7 +219,7 @@ public final class ContainerBlock: BlockWithLayout { case .horizontal: break // this is currently a valid case, see `.max() ?? 0` on line 163 case .vertical: - guard (children.map { $0.content }.allVerticallyNonResizable) else { + guard children.map(\.content).allVerticallyNonResizable else { throw BlockError( "Container block error: vertical intrinsic-height container has children with resizable height" ) @@ -255,9 +255,9 @@ public final class ContainerBlock: BlockWithLayout { var result: CGFloat switch layoutDirection { case .horizontal: - result = (children.map { $0.content.intrinsicContentWidth } + gaps).reduce(0, +) + result = (children.map(\.content.intrinsicContentWidth) + gaps).reduce(0, +) case .vertical: - result = children.map { $0.content.intrinsicContentWidth }.max()! + result = children.map(\.content.intrinsicContentWidth).max()! } if case let .intrinsic(_, minSize, maxSize) = widthTrait { @@ -300,9 +300,9 @@ public final class ContainerBlock: BlockWithLayout { size: CGSize(width: width, height: .zero), needCompressConstrainedBlocks: false ) - result = layout.blockFrames.map { $0.maxY }.max() ?? 0 + result = layout.blockFrames.map(\.maxY).max() ?? 0 case .vertical: - let childrenHeights = children.map { $0.content }.intrinsicHeights(forWidth: width) + let childrenHeights = children.map(\.content).intrinsicHeights(forWidth: width) result = (childrenHeights + gaps).reduce(0, +) } @@ -332,13 +332,13 @@ public final class ContainerBlock: BlockWithLayout { switch layoutDirection { case .horizontal: - result = (children.map { $0.content.widthOfHorizontallyNonResizableBlock } + gaps) + result = (children.map(\.content.widthOfHorizontallyNonResizableBlock) + gaps) .reduce(0, +) case .vertical: // MOBYANDEXIOS-1092: Only non-resizable children can influence the width of a container // because the widths of resizable children depend on the width of container itself result = children.filter { !$0.content.isHorizontallyResizable } - .map { $0.content.widthOfHorizontallyNonResizableBlock }.max()! + .map(\.content.widthOfHorizontallyNonResizableBlock).max()! } cached.nonResizableSize = (width: result, height: nil) @@ -385,7 +385,7 @@ public final class ContainerBlock: BlockWithLayout { crossAlignment: crossAlignment, size: CGSize(width: .zero, height: height) ) - result = layout.blockFrames.map { $0.maxX }.max()! + result = layout.blockFrames.map(\.maxX).max()! cached.nonResizableSize = (width: result, height: height) return result } @@ -453,7 +453,7 @@ private func makeGapsWithSeparators( separator: ContainerBlock.Separator?, layoutMode: ContainerBlock.LayoutMode ) -> [CGFloat] { - guard layoutMode == .noWrap, let separator = separator else { + guard layoutMode == .noWrap, let separator else { return gaps } return Array.build { @@ -486,7 +486,7 @@ private func makeChildrenWithSeparators( separator: ContainerBlock.Separator?, layoutMode: ContainerBlock.LayoutMode ) -> [ContainerBlock.Child] { - guard layoutMode == .noWrap, let separator = separator else { + guard layoutMode == .noWrap, let separator else { return children } return Array.build { @@ -565,9 +565,8 @@ extension ContainerBlock.CrossAlignment { } } -extension Sequence where Element == ContainerBlock.Child { - fileprivate func applyingContents(_ contents: S) -> [ContainerBlock.Child] - where S.Element == Block { +extension Sequence { + fileprivate func applyingContents(_ contents: some Sequence) -> [ContainerBlock.Child] { zip(self, contents).map { child, newContent in modified(child) { $0.content = newContent } } diff --git a/LayoutKit/LayoutKit/Blocks/Container/ContainerBlockLayout.swift b/LayoutKit/LayoutKit/Blocks/Container/ContainerBlockLayout.swift index df753ff5..da31b71c 100644 --- a/LayoutKit/LayoutKit/Blocks/Container/ContainerBlockLayout.swift +++ b/LayoutKit/LayoutKit/Blocks/Container/ContainerBlockLayout.swift @@ -105,15 +105,15 @@ struct ContainerBlockLayout { children.reverse() } - let horizontallyResizableBlocks = children.map { $0.content } - .filter { $0.isHorizontallyResizable } + let horizontallyResizableBlocks = children.map(\.content) + .filter(\.isHorizontallyResizable) let widthOfHorizontallyNonResizableBlocks = - widthsOfHorizontallyNonResizableBlocksIn(children.map { $0.content }).reduce(0, +) + widthsOfHorizontallyNonResizableBlocksIn(children.map(\.content)).reduce(0, +) let widthAvailableForResizableBlocks = ( size.width - widthOfHorizontallyNonResizableBlocks - gapsSize ) let resizableBlockWeights = horizontallyResizableBlocks - .map { $0.weightOfHorizontallyResizableBlock.rawValue } + .map(\.weightOfHorizontallyResizableBlock.rawValue) let widthAvailablePerWeightUnit = max(0, widthAvailableForResizableBlocks) / resizableBlockWeights.reduce(0, +) @@ -123,8 +123,8 @@ struct ContainerBlockLayout { lengthAvailableForResizableBlocks: widthAvailableForResizableBlocks ) - let horizontallyConstrainedBlocks = children.map { $0.content } - .filter { $0.isHorizontallyConstrained } + let horizontallyConstrainedBlocks = children.map(\.content) + .filter(\.isHorizontallyConstrained) var constrainedBlockSizesIterator = decreaseConstrainedBlockSizes( blockSizes: horizontallyConstrainedBlocks .map { .init(size: $0.widthOfHorizontallyNonResizableBlock, minSize: $0.minWidth) }, @@ -155,7 +155,7 @@ struct ContainerBlockLayout { contentSize = x frames.addBaselineOffset(children: children, ascent: containerAscent) case .vertical: - let blocks = children.map { $0.content } + let blocks = children.map(\.content) let blockSizes = blocks.map { ( @@ -176,9 +176,9 @@ struct ContainerBlockLayout { let heightAvailableForResizableBlocks = size .height - heightOfVerticallyNonResizableBlocks - gapsSize - let verticallyResizableBlocks = blocks.filter { $0.isVerticallyResizable } + let verticallyResizableBlocks = blocks.filter(\.isVerticallyResizable) let verticallyResizableBlocksWeight = verticallyResizableBlocks - .map { $0.weightOfVerticallyResizableBlock.rawValue } + .map(\.weightOfVerticallyResizableBlock.rawValue) .reduce(0, +) var blockMeasure = ResizableBlockMeasure( resizableBlockCount: verticallyResizableBlocks.count, @@ -188,7 +188,7 @@ struct ContainerBlockLayout { ) var constrainedBlockSizesIterator = decreaseConstrainedBlockSizes( - blockSizes: blockSizes.filter { $0.0.isVerticallyConstrained }.map { + blockSizes: blockSizes.filter(\.0.isVerticallyConstrained).map { ConstrainedBlockSize(size: $0.1, minSize: $0.0.minHeight) }, lengthToDecrease: heightAvailableForResizableBlocks < 0 ? @@ -354,7 +354,7 @@ struct ContainerBlockLayout { public var leftInset: CGFloat { let leftMargin = layoutDirection == .horizontal ? gaps.first! : 0 return ContentFitting( - offsets: blockFrames.map { $0.minX }, + offsets: blockFrames.map(\.minX), margin: leftMargin ).insetValue } @@ -362,7 +362,7 @@ struct ContainerBlockLayout { public var topInset: CGFloat { let topMargin = layoutDirection == .vertical ? gaps.first! : 0 return ContentFitting( - offsets: blockFrames.map { $0.minY }, + offsets: blockFrames.map(\.minY), margin: topMargin ).insetValue } @@ -372,8 +372,8 @@ struct ContainerBlockLayout { public var contentSize: CGSize { CGSize( - width: blockFrames.map { $0.maxX }.max()!, - height: blockFrames.map { $0.maxY }.max()! + width: blockFrames.map(\.maxX).max()!, + height: blockFrames.map(\.maxY).max()! ) } @@ -383,10 +383,10 @@ struct ContainerBlockLayout { childSize: CGSize ) -> CGFloat? { let childAscent = child.contentAscent(forWidth: childSize.width) - guard let containerAscent = containerAscent else { + guard let containerAscent else { return childAscent } - guard let childAscent = childAscent else { + guard let childAscent else { return containerAscent } return max(containerAscent, childAscent) @@ -402,7 +402,7 @@ private func heightsOfVerticallyNonResizableBlocksIn( } func widthsOfHorizontallyNonResizableBlocksIn(_ blocks: [Block]) -> [CGFloat] { - blocks.filter { !$0.isHorizontallyResizable }.map { $0.widthOfHorizontallyNonResizableBlock } + blocks.filter { !$0.isHorizontallyResizable }.map(\.widthOfHorizontallyNonResizableBlock) } extension Block { @@ -415,12 +415,12 @@ extension Block { } } -extension Array where Element == CGRect { +extension [CGRect] { fileprivate mutating func addBaselineOffset( children: [ContainerBlock.Child], ascent: CGFloat? ) { - guard let ascent = ascent, ascent > 0 else { + guard let ascent, ascent > 0 else { return } var framesWithOffset = [CGRect]() @@ -442,7 +442,7 @@ extension ContainerBlock.Child { } fileprivate func baselineOffset(ascent: CGFloat?, width: CGFloat) -> CGFloat { - guard let ascent = ascent, ascent > 0, + guard let ascent, ascent > 0, let childAscent = contentAscent(forWidth: width) else { return 0 } diff --git a/LayoutKit/LayoutKit/Blocks/Container/WrapLayoutGroups.swift b/LayoutKit/LayoutKit/Blocks/Container/WrapLayoutGroups.swift index c75b0fc8..0534af43 100644 --- a/LayoutKit/LayoutKit/Blocks/Container/WrapLayoutGroups.swift +++ b/LayoutKit/LayoutKit/Blocks/Container/WrapLayoutGroups.swift @@ -49,7 +49,7 @@ struct WrapLayoutGroups { if child.isResizable(for: layoutDirection) { startNewLine() var childSize = child.content.size(forResizableBlockSize: size) - if let separator = separator { + if let separator { if separator.showAtStart { childSize[keyPath: keyPath] = childSize[keyPath: keyPath] - separatorSize[keyPath: keyPath] @@ -90,11 +90,11 @@ struct WrapLayoutGroups { groups.reverse() } - childrenWithSeparators = groups.flatMap { $0 }.map { $0.child } + childrenWithSeparators = groups.flatMap { $0 }.map(\.child) } private var separatorOffset: CGFloat { - guard let separator = separator else { + guard let separator else { return 0 } let separatorSize = separatorSize[keyPath: keyPath] @@ -163,56 +163,56 @@ struct WrapLayoutGroups { } private mutating func addStartLineSeparator() { - guard let lineSeparator = lineSeparator, lineSeparator.showAtStart else { + guard let lineSeparator, lineSeparator.showAtStart else { return } addLineSeparator() } private mutating func addBetweenLineSeparator() { - guard let lineSeparator = lineSeparator, lineSeparator.showBetween else { + guard let lineSeparator, lineSeparator.showBetween else { return } addLineSeparator() } private mutating func addEndLineSeparator() { - guard let lineSeparator = lineSeparator, lineSeparator.showAtEnd else { + guard let lineSeparator, lineSeparator.showAtEnd else { return } addLineSeparator() } private mutating func addLineSeparator() { - guard let lineSeparator = lineSeparator else { + guard let lineSeparator else { return } groups.append([(child: lineSeparator.style, childSize: lineSeparatorSize, lineOffset: 0)]) } private mutating func addStartSeparator() { - guard let separator = separator, separator.showAtStart else { + guard let separator, separator.showAtStart else { return } addSeparator() } private mutating func addEndSeparator() { - guard let separator = separator, separator.showAtEnd else { + guard let separator, separator.showAtEnd else { return } addSeparator() } private mutating func addBetweenSeparator() { - guard let separator = separator, separator.showBetween else { + guard let separator, separator.showBetween else { return } addSeparator() } private mutating func addSeparator() { - guard let separator = separator, !separatorAdded else { + guard let separator, !separatorAdded else { return } separatorAdded = true diff --git a/LayoutKit/LayoutKit/Blocks/Decorations/Block+Decorations.swift b/LayoutKit/LayoutKit/Blocks/Decorations/Block+Decorations.swift index 5fd4dc21..dd838fa0 100644 --- a/LayoutKit/LayoutKit/Blocks/Decorations/Block+Decorations.swift +++ b/LayoutKit/LayoutKit/Blocks/Decorations/Block+Decorations.swift @@ -222,14 +222,13 @@ extension Block { ) -> Block { guard insets != .zero || forceWrapping else { return self } - let newBoundary: BoundaryTrait? = clipsToBounds.map { $0 ? .clips : .noClip } if let block = self as? DecoratingBlock, block.canSafelyExtendPaddings { return block.modifying(paddings: block.paddings + insets) } return DecoratingBlock( child: self, - boundary: newBoundary ?? .clips, + boundary: clipsToBounds == false ? .noClip : .clips, paddings: insets ) } @@ -267,7 +266,9 @@ extension Block { extension DecoratingBlock { fileprivate var canSafelyExtendPaddings: Bool { backgroundColor.alpha.isApproximatelyEqualTo(0) + && accessibilityElement == nil && actions == nil + && doubleTapActions == nil && longTapActions == nil && analyticsURL == nil && boundary.allCornersAreApproximatelyEqualToZero() @@ -276,7 +277,7 @@ extension DecoratingBlock { #if INTERNAL_BUILD fileprivate func makeNewBoundary(fromModifying newBoundary: BoundaryTrait?) -> BoundaryTrait? { - guard let newBoundary = newBoundary else { + guard let newBoundary else { return nil } switch (boundary, newBoundary) { @@ -306,7 +307,7 @@ extension DecoratingBlock { #endif } -extension Optional where Wrapped == BoundaryTrait { +extension BoundaryTrait? { fileprivate var shouldApplyBoundary: Bool { switch self { case .noClip?, .none: diff --git a/LayoutKit/LayoutKit/Blocks/GalleryBlock.swift b/LayoutKit/LayoutKit/Blocks/GalleryBlock.swift index f1d1d4b3..d95c656f 100644 --- a/LayoutKit/LayoutKit/Blocks/GalleryBlock.swift +++ b/LayoutKit/LayoutKit/Blocks/GalleryBlock.swift @@ -24,7 +24,7 @@ public final class GalleryBlock: BlockWithTraits { self.heightTrait = heightTrait if case .intrinsic = widthTrait, case .vertical = model.direction { - guard model.items.map({ $0.content }).hasHorizontallyNonResizable else { + guard model.items.map(\.content).hasHorizontallyNonResizable else { throw BlockError( "Gallery block error: in intrinsic-width vertical gallery all children have resizable width" ) @@ -172,7 +172,7 @@ extension GalleryBlock: ElementStateUpdating { extension GalleryBlock: LayoutCachingDefaultImpl {} -extension Array where Element == GalleryViewModel.Item { +extension [GalleryViewModel.Item] { fileprivate mutating func apply(contents: [Block]) { for i in indices { self[i].content = contents[i] diff --git a/LayoutKit/LayoutKit/Blocks/Grid/GridBlock.swift b/LayoutKit/LayoutKit/Blocks/Grid/GridBlock.swift index cbda4178..bb67b8b3 100644 --- a/LayoutKit/LayoutKit/Blocks/Grid/GridBlock.swift +++ b/LayoutKit/LayoutKit/Blocks/Grid/GridBlock.swift @@ -107,7 +107,7 @@ public final class GridBlock: BlockWithTraits, BlockWithLayout { contentAlignment: contentAlignment, items: items, columnCount: columnCount, - grid: Grid(spans: items.map { $0.span }, columnCount: columnCount) + grid: Grid(spans: items.map(\.span), columnCount: columnCount) ) try validateLayoutTraits() } diff --git a/LayoutKit/LayoutKit/Blocks/Grid/GridLayout.swift b/LayoutKit/LayoutKit/Blocks/Grid/GridLayout.swift index 6ec43ce2..fe0cad15 100644 --- a/LayoutKit/LayoutKit/Blocks/Grid/GridLayout.swift +++ b/LayoutKit/LayoutKit/Blocks/Grid/GridLayout.swift @@ -149,8 +149,8 @@ private func makeEnumeratedItems( } } -private func calculateSizes( - for nonResizableItems: [T?], +private func calculateSizes( + for nonResizableItems: [(some NonResizableItem)?], grid: Grid, weights: [LayoutTrait.Weight?], direction: Direction, @@ -173,8 +173,8 @@ private func calculateSizes( ) } -private func calculateSizes( - for items: [T?], +private func calculateSizes( + for items: [(some NonResizableItem)?], in grid: Grid, weights: [LayoutTrait.Weight?], weightToSize: CGFloat, @@ -188,7 +188,7 @@ private func calculateSizes( weights .enumerated() .filter { $0.element != nil } - .map { $0.offset } + .map(\.offset) ) let spans = Set(items.compactMap { $0?.span }).sorted(by: <) @@ -306,8 +306,8 @@ private func calculateWeights( return result } -private func calculateWeightToSize( - for nonResizableItems: [T?], +private func calculateWeightToSize( + for nonResizableItems: [(some NonResizableItem)?], grid: Grid, weights: [LayoutTrait.Weight?], direction: Direction, @@ -343,8 +343,8 @@ private func calculateWeightToSize( return max(weightToBoundingSize, weightToIntrinsicSize) } -private func calculateWeightToIntrinsicSize( - for nonResizableItems: [T?], +private func calculateWeightToIntrinsicSize( + for nonResizableItems: [(some NonResizableItem)?], grid: Grid, weights: [LayoutTrait.Weight?], direction: Direction diff --git a/LayoutKit/LayoutKit/Blocks/ImageRenderableBlock/Array+ImageRenderableBlock.swift b/LayoutKit/LayoutKit/Blocks/ImageRenderableBlock/Array+ImageRenderableBlock.swift index 275a6f8f..e082911d 100644 --- a/LayoutKit/LayoutKit/Blocks/ImageRenderableBlock/Array+ImageRenderableBlock.swift +++ b/LayoutKit/LayoutKit/Blocks/ImageRenderableBlock/Array+ImageRenderableBlock.swift @@ -1,6 +1,6 @@ import CoreGraphics -extension Array where Element == ImageRenderableBlock { +extension [ImageRenderableBlock] { func draw( in context: CGContext, offset: CGPoint, diff --git a/LayoutKit/LayoutKit/Blocks/IntrincisHeights.swift b/LayoutKit/LayoutKit/Blocks/IntrincisHeights.swift index 54c4010a..ec281c77 100644 --- a/LayoutKit/LayoutKit/Blocks/IntrincisHeights.swift +++ b/LayoutKit/LayoutKit/Blocks/IntrincisHeights.swift @@ -1,6 +1,6 @@ import CoreGraphics -extension Array where Element == Block { +extension [Block] { func intrinsicHeights(forWidth width: CGFloat) -> [CGFloat] { map { let blockWidth: CGFloat diff --git a/LayoutKit/LayoutKit/Blocks/LayeredBlock.swift b/LayoutKit/LayoutKit/Blocks/LayeredBlock.swift index 241b83a6..a565e092 100644 --- a/LayoutKit/LayoutKit/Blocks/LayeredBlock.swift +++ b/LayoutKit/LayoutKit/Blocks/LayeredBlock.swift @@ -55,10 +55,10 @@ public final class LayeredBlock: BlockWithTraits, BlockWithLayout { case let .fixed(width): return width case let .intrinsic(_, minSize, maxSize): - let width = children.map { $0.content.intrinsicContentWidth }.max()! + let width = children.map(\.content.intrinsicContentWidth).max()! return clamp(width, min: minSize, max: maxSize) case .weighted: - return children.map { $0.content.intrinsicContentWidth }.max()! + return children.map(\.content.intrinsicContentWidth).max()! } } @@ -67,10 +67,10 @@ public final class LayeredBlock: BlockWithTraits, BlockWithLayout { case let .fixed(height): return height case let .intrinsic(_, minSize, maxSize): - let height = children.map { $0.content }.intrinsicHeights(forWidth: width).max()! + let height = children.map(\.content).intrinsicHeights(forWidth: width).max()! return clamp(height, min: minSize, max: maxSize) case .weighted: - return children.map { $0.content }.intrinsicHeights(forWidth: width).max()! + return children.map(\.content).intrinsicHeights(forWidth: width).max()! } } diff --git a/LayoutKit/LayoutKit/Blocks/PagerBlock.swift b/LayoutKit/LayoutKit/Blocks/PagerBlock.swift index ac1a5bb6..8484ae6f 100644 --- a/LayoutKit/LayoutKit/Blocks/PagerBlock.swift +++ b/LayoutKit/LayoutKit/Blocks/PagerBlock.swift @@ -37,7 +37,7 @@ public final class PagerBlock: BlockWithTraits { self.heightTrait = heightTrait if case .intrinsic = widthTrait, case .vertical = gallery.direction { - guard gallery.items.map({ $0.content }).hasHorizontallyNonResizable else { + guard gallery.items.map(\.content).hasHorizontallyNonResizable else { throw BlockError( "Pager block error: in intrinsic-width vertical pager all children have resizable width" ) @@ -135,7 +135,7 @@ extension PagerBlock: ElementStateUpdating { extension PagerBlock: LayoutCachingDefaultImpl {} -extension Array where Element == GalleryViewModel.Item { +extension [GalleryViewModel.Item] { fileprivate mutating func apply(contents: [Block]) { for i in indices { self[i].content = contents[i] diff --git a/LayoutKit/LayoutKit/Blocks/Shadow/ShadedBlock.swift b/LayoutKit/LayoutKit/Blocks/Shadow/ShadedBlock.swift index 91945102..b72aadb9 100644 --- a/LayoutKit/LayoutKit/Blocks/Shadow/ShadedBlock.swift +++ b/LayoutKit/LayoutKit/Blocks/Shadow/ShadedBlock.swift @@ -42,7 +42,7 @@ extension ShadedBlock: Equatable { extension Block { public func shaded(with shadow: BlockShadow?) -> Block { - guard let shadow = shadow else { return self } + guard let shadow else { return self } return ShadedBlock(block: self, shadow: shadow) } diff --git a/LayoutKit/LayoutKit/Blocks/Slider/SliderView.swift b/LayoutKit/LayoutKit/Blocks/Slider/SliderView.swift index 526d6fcb..2bbecb44 100644 --- a/LayoutKit/LayoutKit/Blocks/Slider/SliderView.swift +++ b/LayoutKit/LayoutKit/Blocks/Slider/SliderView.swift @@ -29,7 +29,7 @@ final class SliderView: BlockView, VisibleBoundsTrackingLeaf { self.sliderModel = sliderModel inactiveRangeTracks = inactiveRangeTracks.reused( - with: sliderModel.ranges.map { $0.inactiveTrack }, + with: sliderModel.ranges.map(\.inactiveTrack), attachTo: inactiveTrackView, observer: observer, overscrollDelegate: overscrollDelegate, @@ -37,7 +37,7 @@ final class SliderView: BlockView, VisibleBoundsTrackingLeaf { ) activeRangeTracks = activeRangeTracks.reused( - with: sliderModel.ranges.map { $0.activeTrack }, + with: sliderModel.ranges.map(\.activeTrack), attachTo: activeTrackView, observer: observer, overscrollDelegate: overscrollDelegate, @@ -185,8 +185,8 @@ final class SliderView: BlockView, VisibleBoundsTrackingLeaf { switch recognizer.state { case .began: thumbAnimator?.stopAnimation(true) - if let firstThumb = firstThumb, - let secondThumb = secondThumb { + if let firstThumb, + let secondThumb { if abs(firstThumb.frame.origin.x - location.x) < abs(secondThumb.frame.origin.x - location.x) { activeThumb = .first @@ -397,8 +397,8 @@ final class SliderView: BlockView, VisibleBoundsTrackingLeaf { progress: CGFloat, thumbModel: SliderModel.ThumbModel? ) { - guard let thumbView = thumbView, - let thumbModel = thumbModel else { + guard let thumbView, + let thumbModel else { return } diff --git a/LayoutKit/LayoutKit/Blocks/TabsBlock.swift b/LayoutKit/LayoutKit/Blocks/TabsBlock.swift index 58bcf406..3e0b6e35 100644 --- a/LayoutKit/LayoutKit/Blocks/TabsBlock.swift +++ b/LayoutKit/LayoutKit/Blocks/TabsBlock.swift @@ -74,7 +74,7 @@ public final class TabsBlock: BlockWithTraits { } private func checkConstraints() throws { - let blocks = model.contentsModel.pages.map { $0.block } + let blocks = model.contentsModel.pages.map(\.block) if case .intrinsic = widthTrait, !blocks.hasHorizontallyNonResizable { throw BlockError("Tabs block error: in intrinsic-width tab all children have resizable width") diff --git a/LayoutKit/LayoutKit/Blocks/TextBlock.swift b/LayoutKit/LayoutKit/Blocks/TextBlock.swift index 98f08cb5..2c811930 100644 --- a/LayoutKit/LayoutKit/Blocks/TextBlock.swift +++ b/LayoutKit/LayoutKit/Blocks/TextBlock.swift @@ -65,7 +65,7 @@ public final class TextBlock: BlockWithTraits { self.accessibilityElement = accessibilityElement self.canSelect = canSelect self.truncationImages = truncationImages - if let truncationToken = truncationToken { + if let truncationToken { (self.truncationToken, self.truncationAttachments) = setImagePlaceholders( for: truncationImages, to: truncationToken ) @@ -160,7 +160,7 @@ public final class TextBlock: BlockWithTraits { } public func getImageHolders() -> [ImageHolder] { - images.map { $0.holder } + images.map(\.holder) } public static func ==(lhs: TextBlock, rhs: TextBlock) -> Bool { @@ -281,7 +281,7 @@ private let defaultFont = Font.systemFont(ofSize: Font.systemFontSize) extension TextBlock.InlineImage { fileprivate var tintColorImage: Image? { let holderImage = holder.image - guard let tintColor = tintColor else { return holderImage } + guard let tintColor else { return holderImage } return holderImage?.redrawn(withTintColor: tintColor) } } diff --git a/LayoutKit/LayoutKit/Blocks/TextFieldBlock+Debugging.swift b/LayoutKit/LayoutKit/Blocks/TextFieldBlock+Debugging.swift index 11a9dfb0..70d86431 100644 --- a/LayoutKit/LayoutKit/Blocks/TextFieldBlock+Debugging.swift +++ b/LayoutKit/LayoutKit/Blocks/TextFieldBlock+Debugging.swift @@ -54,7 +54,7 @@ extension TextFieldBlock: CustomDebugStringConvertible { result += "\n RightControl: \(control)" } - if let toolbar = toolbar { + if let toolbar { result += "\n Toolbar: \(toolbar)" } result += "\n}" diff --git a/LayoutKit/LayoutKit/Blocks/TextFieldBlock.swift b/LayoutKit/LayoutKit/Blocks/TextFieldBlock.swift index 38f71a86..6f10de5d 100644 --- a/LayoutKit/LayoutKit/Blocks/TextFieldBlock.swift +++ b/LayoutKit/LayoutKit/Blocks/TextFieldBlock.swift @@ -328,7 +328,7 @@ extension TextFieldBlock.Placeholders.Separate.AnimatableAttributes { } extension TextFieldBlock.ToolbarType { - public static func == ( + public static func ==( lhs: TextFieldBlock.ToolbarType, rhs: TextFieldBlock.ToolbarType ) -> Bool { diff --git a/LayoutKit/LayoutKit/Blocks/TextInputBlock.swift b/LayoutKit/LayoutKit/Blocks/TextInputBlock.swift index 0b976e4f..7de57545 100644 --- a/LayoutKit/LayoutKit/Blocks/TextInputBlock.swift +++ b/LayoutKit/LayoutKit/Blocks/TextInputBlock.swift @@ -134,7 +134,7 @@ public final class TextInputBlock: BlockWithTraits { case let .fixed(value): return value case let .intrinsic(_, minSize, maxSize): - guard let maxVisibleLines = maxVisibleLines else { + guard let maxVisibleLines else { let textHeight = ceil(textForMeasuring.sizeForWidth(width).height) return clamp(textHeight, min: minSize, max: maxSize) } diff --git a/LayoutKit/LayoutKit/Blocks/TransitioningAnimation.swift b/LayoutKit/LayoutKit/Blocks/TransitioningAnimation.swift index d1a10e63..c8e8e30b 100644 --- a/LayoutKit/LayoutKit/Blocks/TransitioningAnimation.swift +++ b/LayoutKit/LayoutKit/Blocks/TransitioningAnimation.swift @@ -47,7 +47,7 @@ public struct TransitioningAnimation: Equatable { } } -extension Array where Element == TransitioningAnimation { +extension [TransitioningAnimation] { func withDelay(_ delay: Double) -> [TransitioningAnimation] { if delay == 0 { return self diff --git a/LayoutKit/LayoutKit/GenericViewBlock.swift b/LayoutKit/LayoutKit/GenericViewBlock.swift index 7ad7a6b5..f9b71742 100644 --- a/LayoutKit/LayoutKit/GenericViewBlock.swift +++ b/LayoutKit/LayoutKit/GenericViewBlock.swift @@ -138,7 +138,7 @@ extension GenericViewBlock.Trait { } } -extension Optional where Wrapped == CGFloat { +extension CGFloat? { fileprivate var trait: GenericViewBlock.Trait { map(GenericViewBlock.Trait.fixed) ?? GenericViewBlock.Trait.resizable } @@ -154,7 +154,7 @@ extension GenericViewBlock.Trait { } } -extension Optional where Wrapped == GenericViewBlock.Content { +extension GenericViewBlock.Content? { static func !==(lhs: GenericViewBlock.Content?, rhs: GenericViewBlock.Content?) -> Bool { switch (lhs, rhs) { case let (lValue?, rValue?): return !(lValue === rValue) diff --git a/LayoutKit/LayoutKit/UI/Actions/UIActionEventPerforming.swift b/LayoutKit/LayoutKit/UI/Actions/UIActionEventPerforming.swift index 810d9462..81046fc7 100644 --- a/LayoutKit/LayoutKit/UI/Actions/UIActionEventPerforming.swift +++ b/LayoutKit/LayoutKit/UI/Actions/UIActionEventPerforming.swift @@ -27,7 +27,7 @@ public final class UIActionEvent: AppActionEventProtocol { } } -extension Array: AppActionEventProtocol where Element == UIActionEvent { +extension [UIActionEvent]: AppActionEventProtocol { public func makeHandler(responder: UIResponder) -> Handler? { (responder as? UIActionEventPerforming)?.perform(uiActionEvents:from:) } @@ -39,7 +39,7 @@ extension UIActionEvent { } } -extension Array where Element == UIActionEvent { +extension [UIActionEvent] { public func handlingURLPayload( handleEvent: @escaping (UIActionEvent, _ isLast: Bool) -> Void ) -> [UIActionEvent] { diff --git a/LayoutKit/LayoutKit/UI/Actions/UIActionExtensions.swift b/LayoutKit/LayoutKit/UI/Actions/UIActionExtensions.swift index c049ddc9..2b0a9754 100644 --- a/LayoutKit/LayoutKit/UI/Actions/UIActionExtensions.swift +++ b/LayoutKit/LayoutKit/UI/Actions/UIActionExtensions.swift @@ -26,7 +26,7 @@ extension UserInterfaceAction { } } -extension Array where Element == UserInterfaceAction { +extension [UserInterfaceAction] { public func perform(sendingFrom sender: UserInterfaceAction.ResponderType) { #if os(iOS) forEach { diff --git a/LayoutKit/LayoutKit/UI/Base/GenericCollectionReusableView.swift b/LayoutKit/LayoutKit/UI/Base/GenericCollectionReusableView.swift index 8dec3d28..803358cc 100644 --- a/LayoutKit/LayoutKit/UI/Base/GenericCollectionReusableView.swift +++ b/LayoutKit/LayoutKit/UI/Base/GenericCollectionReusableView.swift @@ -9,7 +9,7 @@ public final class GenericCollectionReusableView: UICollectionReusableView { private var view: BlockView? { didSet { oldValue?.removeFromSuperview() - if let view = view { + if let view { addSubview(view) setNeedsLayout() } @@ -19,7 +19,7 @@ public final class GenericCollectionReusableView: UICollectionReusableView { public func configure(model: UIViewRenderable, observer: ElementStateObserver? = nil) { self.model = model - if let view = view, model.canConfigureBlockView(view) { + if let view, model.canConfigureBlockView(view) { model.configureBlockView( view, observer: observer, diff --git a/LayoutKit/LayoutKit/UI/Base/GenericCollectionViewCell.swift b/LayoutKit/LayoutKit/UI/Base/GenericCollectionViewCell.swift index 8e578ff2..3cbd9d92 100644 --- a/LayoutKit/LayoutKit/UI/Base/GenericCollectionViewCell.swift +++ b/LayoutKit/LayoutKit/UI/Base/GenericCollectionViewCell.swift @@ -12,7 +12,7 @@ open class GenericCollectionViewCell: UICollectionViewCell, VisibleBoundsTrackin public private(set) var view: BlockView? { didSet { oldValue?.removeFromSuperview() - if let view = view { + if let view { contentView.addSubview(view) setNeedsLayout() } @@ -28,7 +28,7 @@ open class GenericCollectionViewCell: UICollectionViewCell, VisibleBoundsTrackin ) { self.model = model - if let view = view, model.canConfigureBlockView(view) { + if let view, model.canConfigureBlockView(view) { model.configureBlockView( view, observer: observer, diff --git a/LayoutKit/LayoutKit/UI/Base/GenericCollectionViewLayout.swift b/LayoutKit/LayoutKit/UI/Base/GenericCollectionViewLayout.swift index f28dddc0..f7147ba9 100644 --- a/LayoutKit/LayoutKit/UI/Base/GenericCollectionViewLayout.swift +++ b/LayoutKit/LayoutKit/UI/Base/GenericCollectionViewLayout.swift @@ -16,7 +16,7 @@ public final class GenericCollectionViewLayout: UICollectionViewLayout { public override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? { - guard let layout = layout else { + guard let layout else { return nil } return UICollectionViewLayoutAttributes( diff --git a/LayoutKit/LayoutKit/UI/Blocks/AnimatableImageBlock+UIViewRenderableBlock.swift b/LayoutKit/LayoutKit/UI/Blocks/AnimatableImageBlock+UIViewRenderableBlock.swift index 6aa282b8..105bbf32 100644 --- a/LayoutKit/LayoutKit/UI/Blocks/AnimatableImageBlock+UIViewRenderableBlock.swift +++ b/LayoutKit/LayoutKit/UI/Blocks/AnimatableImageBlock+UIViewRenderableBlock.swift @@ -43,7 +43,7 @@ private class AnimatableImageContainer: UIStackView, BlockViewProtocol, VisibleB let newValue = imageHolder imageRequest = imageHolder?.requestImageWithCompletion { [weak self] image in - guard let self = self, + guard let self, newValue === self.imageHolder else { return } diff --git a/LayoutKit/LayoutKit/UI/Blocks/Array+UIViewRenderable.swift b/LayoutKit/LayoutKit/UI/Blocks/Array+UIViewRenderable.swift index 944447cf..70f91ea6 100644 --- a/LayoutKit/LayoutKit/UI/Blocks/Array+UIViewRenderable.swift +++ b/LayoutKit/LayoutKit/UI/Blocks/Array+UIViewRenderable.swift @@ -2,7 +2,7 @@ import UIKit import CommonCorePublic -extension Array where Element == BlockView { +extension [BlockView] { func reused( with blocks: [UIViewRenderable], attachTo parent: UIView, diff --git a/LayoutKit/LayoutKit/UI/Blocks/BackgroundBlock+UIViewRenderableBlock.swift b/LayoutKit/LayoutKit/UI/Blocks/BackgroundBlock+UIViewRenderableBlock.swift index cf58b670..172dec35 100644 --- a/LayoutKit/LayoutKit/UI/Blocks/BackgroundBlock+UIViewRenderableBlock.swift +++ b/LayoutKit/LayoutKit/UI/Blocks/BackgroundBlock+UIViewRenderableBlock.swift @@ -130,7 +130,7 @@ extension UIViewRenderable { overscrollDelegate: ScrollDelegate?, renderingDelegate: RenderingDelegate? ) -> BlockView { - if let view = view, canConfigureBlockView(view) { + if let view, canConfigureBlockView(view) { configureBlockView( view, observer: observer, diff --git a/LayoutKit/LayoutKit/UI/Blocks/DecoratingBlock+UIViewRenderableBlock.swift b/LayoutKit/LayoutKit/UI/Blocks/DecoratingBlock+UIViewRenderableBlock.swift index 558395b5..0acc920d 100644 --- a/LayoutKit/LayoutKit/UI/Blocks/DecoratingBlock+UIViewRenderableBlock.swift +++ b/LayoutKit/LayoutKit/UI/Blocks/DecoratingBlock+UIViewRenderableBlock.swift @@ -53,7 +53,7 @@ extension DecoratingBlock { } } -extension Optional where Wrapped == NonEmpty<[UserInterfaceAction]> { +extension NonEmpty<[UserInterfaceAction]>? { fileprivate var hasPayload: Bool { switch self { case let .some(actions): @@ -64,7 +64,7 @@ extension Optional where Wrapped == NonEmpty<[UserInterfaceAction]> { } } -extension Optional where Wrapped == LongTapActions { +extension LongTapActions? { fileprivate var hasPayload: Bool { self?.hasPayload ?? false } @@ -170,7 +170,7 @@ private final class DecoratingView: UIControl, BlockViewProtocol, VisibleBoundsT private var borderLayer: CALayer? { didSet { oldValue?.removeFromSuperlayer() - if let borderLayer = borderLayer { + if let borderLayer { borderLayer.zPosition = 1000 layer.addSublayer(borderLayer) } @@ -180,9 +180,9 @@ private final class DecoratingView: UIControl, BlockViewProtocol, VisibleBoundsT private var blurView: UIVisualEffectView? { didSet { oldValue?.removeFromSuperview() - if let blurView = blurView { + if let blurView { blurView.isUserInteractionEnabled = false - if let childView = childView { + if let childView { insertSubview(blurView, belowSubview: childView) } else { addSubview(blurView) diff --git a/LayoutKit/LayoutKit/UI/Blocks/DetachableAnimationBlock+UIViewRenderableBlock.swift b/LayoutKit/LayoutKit/UI/Blocks/DetachableAnimationBlock+UIViewRenderableBlock.swift index 78a4406e..3f95f232 100644 --- a/LayoutKit/LayoutKit/UI/Blocks/DetachableAnimationBlock+UIViewRenderableBlock.swift +++ b/LayoutKit/LayoutKit/UI/Blocks/DetachableAnimationBlock+UIViewRenderableBlock.swift @@ -34,7 +34,7 @@ extension DetachableAnimationBlock { final class DetachableAnimationBlockView: BlockView { private var childView: BlockView? { didSet { - if let childView = childView { + if let childView { addSubview(childView) animatedView = nil } else { @@ -104,8 +104,8 @@ final class DetachableAnimationBlockView: BlockView { in container: UIView, startFrame: CGRect ) { - guard let childView = childView, - let animationChange = animationChange else { + guard let childView, + let animationChange else { return } let finishFrame = convertFrame(to: container) @@ -148,7 +148,7 @@ final class DetachableAnimationBlockView: BlockView { } public func removeWithAnimation(in container: UIView) { - guard let childView = childView else { + guard let childView else { return } @@ -161,8 +161,8 @@ final class DetachableAnimationBlockView: BlockView { } public func addWithAnimation(in container: UIView) { - guard let childView = childView, - let animationIn = animationIn else { + guard let childView, + let animationIn else { return } diff --git a/LayoutKit/LayoutKit/UI/Blocks/ElementState.swift b/LayoutKit/LayoutKit/UI/Blocks/ElementState.swift index 481d49ed..f6033b69 100644 --- a/LayoutKit/LayoutKit/UI/Blocks/ElementState.swift +++ b/LayoutKit/LayoutKit/UI/Blocks/ElementState.swift @@ -10,7 +10,7 @@ public protocol ElementStateObserver: AnyObject { func elementStateChanged(_ state: ElementState, forPath path: UIElementPath) } -extension Dictionary where Key == UIElementPath, Value == ElementState { +extension [UIElementPath: ElementState] { @inlinable public func getState(at path: Key) -> T? { guard let value = self[path] else { diff --git a/LayoutKit/LayoutKit/UI/Blocks/GridBlock+UIViewRenderableBlock.swift b/LayoutKit/LayoutKit/UI/Blocks/GridBlock+UIViewRenderableBlock.swift index 8e2490ef..57470b05 100644 --- a/LayoutKit/LayoutKit/UI/Blocks/GridBlock+UIViewRenderableBlock.swift +++ b/LayoutKit/LayoutKit/UI/Blocks/GridBlock+UIViewRenderableBlock.swift @@ -69,7 +69,7 @@ private final class GridView: BlockView, VisibleBoundsTrackingContainer { // including view hierarchy layout. preventLayout = true blockViews = blockViews.reused( - with: model.items.map { $0.contents }, + with: model.items.map(\.contents), attachTo: self, observer: observer, overscrollDelegate: overscrollDelegate, diff --git a/LayoutKit/LayoutKit/UI/Blocks/ShadedBlock+UIViewRenderableBlock.swift b/LayoutKit/LayoutKit/UI/Blocks/ShadedBlock+UIViewRenderableBlock.swift index 7e1b103e..03adad8b 100644 --- a/LayoutKit/LayoutKit/UI/Blocks/ShadedBlock+UIViewRenderableBlock.swift +++ b/LayoutKit/LayoutKit/UI/Blocks/ShadedBlock+UIViewRenderableBlock.swift @@ -63,7 +63,7 @@ private final class ShadedBlockView: ViewWithShadow, BlockViewProtocol, guard self.model != model || self.observer !== observer else { return } self.model = model self.observer = observer - if let blockView = blockView, model.block.canConfigureBlockView(blockView) { + if let blockView, model.block.canConfigureBlockView(blockView) { model.block.configureBlockView( blockView, observer: observer, diff --git a/LayoutKit/LayoutKit/UI/Blocks/StateBlock+UIViewRenderableBlock.swift b/LayoutKit/LayoutKit/UI/Blocks/StateBlock+UIViewRenderableBlock.swift index 7a75206c..b3d04e87 100644 --- a/LayoutKit/LayoutKit/UI/Blocks/StateBlock+UIViewRenderableBlock.swift +++ b/LayoutKit/LayoutKit/UI/Blocks/StateBlock+UIViewRenderableBlock.swift @@ -83,8 +83,8 @@ private final class SubviewStorage: RenderingDelegate { func getViewsToAdd() -> [DetachableAnimationBlockView] { views - .filter { $0.view.hasAnimationIn } - .map { $0.view } + .filter(\.view.hasAnimationIn) + .map(\.view) } func getViewsToTransition( diff --git a/LayoutKit/LayoutKit/UI/Blocks/SwipeContainerBlock+UIViewRenderable.swift b/LayoutKit/LayoutKit/UI/Blocks/SwipeContainerBlock+UIViewRenderable.swift index f25a2858..830632f3 100644 --- a/LayoutKit/LayoutKit/UI/Blocks/SwipeContainerBlock+UIViewRenderable.swift +++ b/LayoutKit/LayoutKit/UI/Blocks/SwipeContainerBlock+UIViewRenderable.swift @@ -85,7 +85,7 @@ private final class SwipeContainerBlockView: BlockView, VisibleBoundsTrackingCon ) swipeContainerView.state = model.state swipeContainerView.swipeOutAction = { [weak self] state in - guard let self = self, model.state == .normal else { return } + guard let self, model.state == .normal else { return } UIView.animate( withDuration: closeDuration, animations: { diff --git a/LayoutKit/LayoutKit/UI/Blocks/TextBlock+UIViewRenderableBlock.swift b/LayoutKit/LayoutKit/UI/Blocks/TextBlock+UIViewRenderableBlock.swift index 0028f69b..198c4887 100644 --- a/LayoutKit/LayoutKit/UI/Blocks/TextBlock+UIViewRenderableBlock.swift +++ b/LayoutKit/LayoutKit/UI/Blocks/TextBlock+UIViewRenderableBlock.swift @@ -42,7 +42,7 @@ private final class TextBlockContainer: BlockView, VisibleBoundsTrackingLeaf { guard textGradient == nil || textGradient != oldValue else { return } - if let textGradient = textGradient { + if let textGradient { gradientView = textGradient.uiView currentView = gradientView } else { @@ -58,7 +58,7 @@ private final class TextBlockContainer: BlockView, VisibleBoundsTrackingLeaf { return } oldValue?.removeFromSuperview() - if let currentView = currentView { + if let currentView { addSubview(currentView) } setNeedsLayout() @@ -220,7 +220,7 @@ private final class TextBlockView: UIView { required init?(coder _: NSCoder) { fatalError("init(coder:) has not been implemented") } override func draw(_ rect: CGRect) { - guard let model = model else { return } + guard let model else { return } let textLayout: AttributedStringLayout = model.text.drawAndGetLayout( inContext: UIGraphicsGetCurrentContext()!, verticalPosition: model.verticalPosition, @@ -241,7 +241,7 @@ private final class TextBlockView: UIView { } override func point(inside point: CGPoint, with _: UIEvent?) -> Bool { - guard let textLayout = textLayout else { + guard let textLayout else { return false } return model.canSelect && bounds.contains(point) @@ -253,7 +253,7 @@ private final class TextBlockView: UIView { } @objc private func handleTap(_ gesture: UITapGestureRecognizer) { - guard gesture.state == .ended, let textLayout = textLayout else { + guard gesture.state == .ended, let textLayout else { return } let tapLocation = gesture.location(in: gesture.view) @@ -292,7 +292,7 @@ private final class TextBlockView: UIView { .applying(CGAffineTransform(translationX: 0, y: bounds.height).scaledBy(x: 1, y: -1)) ) UIMenuController.shared.hideMenu(animated: true) - if let elementIndex = elementIndex { + if let elementIndex { let prefix = model.text.string.prefix(elementIndex) let suffix = model.text.string.suffix(from: prefix.endIndex) let trailing = elementIndex + suffix.distance( @@ -306,7 +306,7 @@ private final class TextBlockView: UIView { } func handleSelectionTapEnded(_: UIGestureRecognizer) { - guard let selectionRect = selectionRect else { + guard let selectionRect else { return } UIMenuController.shared.presentMenu(from: self, in: selectionRect) @@ -327,8 +327,8 @@ private final class TextBlockView: UIView { ) switch gesture.state { case .began: - guard let selectedRange = selectedRange, - let elementIndex = elementIndex else { + guard let selectedRange, + let elementIndex else { return } let lineIndex = textLayout?.lines.lastIndex(where: { @@ -352,7 +352,7 @@ private final class TextBlockView: UIView { abs($0 - selectedRange.lowerBound), abs($0 - selectedRange.upperBound) ) < 5 } - guard let nearestIndex = nearestIndex else { + guard let nearestIndex else { return } activePointer = @@ -362,8 +362,8 @@ private final class TextBlockView: UIView { ) ? .leading : .trailing case .changed: - guard let activePointer = activePointer, let elementIndex = elementIndex, - let selectedRange = selectedRange else { + guard let activePointer, let elementIndex, + let selectedRange else { return } switch activePointer { @@ -374,7 +374,7 @@ private final class TextBlockView: UIView { } case .ended, .cancelled, .failed: activePointer = nil - guard let selectionRect = selectionRect else { + guard let selectionRect else { return } UIMenuController.shared.presentMenu(from: self, in: selectionRect) @@ -411,7 +411,7 @@ private final class TextBlockView: UIView { let maxSymbolIndex = textLayout?.lines .compactMap { !$0.isTruncated ? $0.range.upperBound : -1 }.max() - if let selectedRange = selectedRange { + if let selectedRange { UIPasteboard.general.string = model.text.string[Range(uncheckedBounds: ( selectedRange.lowerBound, min(selectedRange.upperBound, maxSymbolIndex ?? .max) @@ -447,7 +447,7 @@ extension TextBlockView: UIGestureRecognizerDelegate { extension Image { fileprivate func withTintColor(_ color: Color?) -> Image { - guard let color = color else { return self } + guard let color else { return self } return self.redrawn(withTintColor: color) } } @@ -486,7 +486,7 @@ private enum ActivePointer { extension AttributedStringLayout { fileprivate func getTapElementIndex(from point: CGPoint) -> Int? { let lineLayout = lines.last(where: { point.y <= $0.verticalOffset }) - guard let lineLayout = lineLayout, + guard let lineLayout, point.x > lineLayout.horizontalOffset else { return nil } diff --git a/LayoutKit/LayoutKit/UI/Blocks/TextFieldBlock+UIViewRenderableBlock.swift b/LayoutKit/LayoutKit/UI/Blocks/TextFieldBlock+UIViewRenderableBlock.swift index d0b35ae7..930cd56b 100644 --- a/LayoutKit/LayoutKit/UI/Blocks/TextFieldBlock+UIViewRenderableBlock.swift +++ b/LayoutKit/LayoutKit/UI/Blocks/TextFieldBlock+UIViewRenderableBlock.swift @@ -479,7 +479,7 @@ extension TextFieldBlockView: UITextFieldDelegate { extension UITextField { fileprivate func setTextPreservingPosition(_ newText: NSAttributedString?) { - guard let newText = newText else { + guard let newText else { attributedText = nil return } diff --git a/LayoutKit/LayoutKit/UI/Blocks/TextInputBlock+UIViewRenderableBlock.swift b/LayoutKit/LayoutKit/UI/Blocks/TextInputBlock+UIViewRenderableBlock.swift index 97493506..64545bb0 100644 --- a/LayoutKit/LayoutKit/UI/Blocks/TextInputBlock+UIViewRenderableBlock.swift +++ b/LayoutKit/LayoutKit/UI/Blocks/TextInputBlock+UIViewRenderableBlock.swift @@ -213,7 +213,7 @@ private final class TextInputBlockView: BlockView, VisibleBoundsTrackingLeaf { mask: MaskValidator? ) { self.typo = typo.with(alignment: textAlignment) - if let mask = mask, let rawTextValue = rawTextValue { + if let mask, let rawTextValue { self.textValue = textValue setupMaskedViewModelIfNeeded(mask: mask, rawTextValue: rawTextValue) } else { @@ -304,13 +304,13 @@ private final class TextInputBlockView: BlockView, VisibleBoundsTrackingLeaf { } }.dispose(in: disposePool) maskedViewModel?.$rawText.currentAndNewValues.addObserver { [weak self] input in - guard let self = self else { return } + guard let self else { return } self.rawTextValue.value = input }.dispose(in: disposePool) maskedViewModel?.$text.currentAndNewValues .addObserver { [weak self] input in - guard let self = self else { return } + guard let self else { return } DispatchQueue.main.async { self.setTextData(input) self.textValue.value = input @@ -445,13 +445,13 @@ extension TextInputBlockView { private func onFocus() { onFocusActions.perform(sendingFrom: self) - guard let path = path else { return } + guard let path else { return } observer?.elementStateChanged(FocusViewState(isFocused: true), forPath: path) } private func onBlur() { onBlurActions.perform(sendingFrom: self) - guard let path = path else { return } + guard let path else { return } observer?.elementStateChanged(FocusViewState(isFocused: false), forPath: path) } diff --git a/LayoutKit/LayoutKit/UI/Blocks/TooltipContainerView.swift b/LayoutKit/LayoutKit/UI/Blocks/TooltipContainerView.swift index 311b1f39..25c034b4 100644 --- a/LayoutKit/LayoutKit/UI/Blocks/TooltipContainerView.swift +++ b/LayoutKit/LayoutKit/UI/Blocks/TooltipContainerView.swift @@ -47,7 +47,7 @@ public final class TooltipContainerView: UIView, UIActionEventPerforming { public override func layoutSubviews() { super.layoutSubviews() - if let lastNonZeroBounds = lastNonZeroBounds, + if let lastNonZeroBounds, lastNonZeroBounds != bounds { close() } diff --git a/LayoutKit/LayoutKit/UI/Blocks/TransitioningBlock+UIViewRenderableBlock.swift b/LayoutKit/LayoutKit/UI/Blocks/TransitioningBlock+UIViewRenderableBlock.swift index 4263cb73..61d640c5 100644 --- a/LayoutKit/LayoutKit/UI/Blocks/TransitioningBlock+UIViewRenderableBlock.swift +++ b/LayoutKit/LayoutKit/UI/Blocks/TransitioningBlock+UIViewRenderableBlock.swift @@ -105,7 +105,7 @@ private final class TransitioningBlockView: BlockView, VisibleBoundsTrackingCont weak overscrollDelegate, weak renderingDelegate ] in - guard let self = self else { return } + guard let self else { return } self.toView = model.block.to.reuse( self.toView, observer: observer, @@ -143,7 +143,7 @@ private final class TransitioningBlockView: BlockView, VisibleBoundsTrackingCont animations: [TransitioningAnimation], completion: Action? = nil ) { - guard let view = view else { + guard let view else { completion?() return } diff --git a/LayoutKit/LayoutKit/UI/Blocks/UIView+TransitioningAnimation.swift b/LayoutKit/LayoutKit/UI/Blocks/UIView+TransitioningAnimation.swift index 385c5cd2..cfb72e55 100644 --- a/LayoutKit/LayoutKit/UI/Blocks/UIView+TransitioningAnimation.swift +++ b/LayoutKit/LayoutKit/UI/Blocks/UIView+TransitioningAnimation.swift @@ -10,7 +10,7 @@ extension UIView { animated: Bool, completion: Action? = nil ) { - guard let animations = animations, !animations.isEmpty else { + guard let animations, !animations.isEmpty else { completion?() return } diff --git a/LayoutKit/LayoutKit/UI/Blocks/UIViewRenderable.swift b/LayoutKit/LayoutKit/UI/Blocks/UIViewRenderable.swift index 5f2da2c1..7fd7ac9f 100644 --- a/LayoutKit/LayoutKit/UI/Blocks/UIViewRenderable.swift +++ b/LayoutKit/LayoutKit/UI/Blocks/UIViewRenderable.swift @@ -80,7 +80,7 @@ extension UIViewRenderable { superview: UIView?, subviewPosition: SubviewPosition = .trailing ) -> BlockView { - if let view = view, canConfigureBlockView(view) { + if let view, canConfigureBlockView(view) { configureBlockView( view, observer: observer, @@ -116,7 +116,7 @@ extension UIViewRenderable { } } -extension Optional where Wrapped == UIViewRenderable { +extension UIViewRenderable? { public func reuse( _ view: BlockView?, observer: ElementStateObserver? = nil, diff --git a/LayoutKit/LayoutKit/UI/Blocks/VideoBlock+UIViewRenderableBlock.swift b/LayoutKit/LayoutKit/UI/Blocks/VideoBlock+UIViewRenderableBlock.swift index 7614d09c..30b0017a 100644 --- a/LayoutKit/LayoutKit/UI/Blocks/VideoBlock+UIViewRenderableBlock.swift +++ b/LayoutKit/LayoutKit/UI/Blocks/VideoBlock+UIViewRenderableBlock.swift @@ -53,7 +53,7 @@ private final class VideoBlockView: BlockView, VisibleBoundsTrackingContainer { playerSignal = player?.signal.addObserver { [weak self] event in onMainThread { - guard let self = self else { return } + guard let self else { return } switch event { case let .currentTimeUpdate(time): diff --git a/LayoutKit/LayoutKit/UI/Views/Background+UIViewRendering.swift b/LayoutKit/LayoutKit/UI/Views/Background+UIViewRendering.swift index 0e6fe0db..6c864409 100644 --- a/LayoutKit/LayoutKit/UI/Views/Background+UIViewRendering.swift +++ b/LayoutKit/LayoutKit/UI/Views/Background+UIViewRendering.swift @@ -33,7 +33,7 @@ private final class BackgroundView: BlockView, VisibleBoundsTrackingLeaf { didSet { guard oldValue !== innerView else { return } oldValue?.removeFromSuperview() - if let innerView = innerView { + if let innerView { addSubview(innerView) } } diff --git a/LayoutKit/LayoutKit/UI/Views/ContextMenuDelegate.swift b/LayoutKit/LayoutKit/UI/Views/ContextMenuDelegate.swift index fb34a705..855e6900 100644 --- a/LayoutKit/LayoutKit/UI/Views/ContextMenuDelegate.swift +++ b/LayoutKit/LayoutKit/UI/Views/ContextMenuDelegate.swift @@ -19,7 +19,7 @@ final class ContextMenuDelegate: NSObject, UIContextMenuInteractionDelegate { configurationForMenuAtLocation _: CGPoint ) -> UIContextMenuConfiguration? { UIContextMenuConfiguration(identifier: nil, previewProvider: makeVC) { [weak self] _ in - guard let self = self, let sender = self.view else { + guard let self, let sender = self.view else { return nil } return self.contextMenu.makeUIMenu(sender: sender) @@ -38,7 +38,7 @@ final class ContextMenuDelegate: NSObject, UIContextMenuInteractionDelegate { _: UIContextMenuInteraction, previewForHighlightingMenuWithConfiguration _: UIContextMenuConfiguration ) -> UITargetedPreview? { - guard let view = view else { + guard let view else { return nil } diff --git a/LayoutKit/LayoutKit/UI/Views/GalleryView.swift b/LayoutKit/LayoutKit/UI/Views/GalleryView.swift index bd77cec9..12097d54 100644 --- a/LayoutKit/LayoutKit/UI/Views/GalleryView.swift +++ b/LayoutKit/LayoutKit/UI/Views/GalleryView.swift @@ -105,7 +105,7 @@ public final class GalleryView: BlockView { updateLayoutIfNeeded(to: model) if oldModel != model { - let blocks = model.items.map { $0.content } + let blocks = model.items.map(\.content) dataSource.blocks = blocks if oldModel?.layoutDirection != model.layoutDirection { collectionView.semanticContentAttribute = model @@ -153,7 +153,7 @@ public final class GalleryView: BlockView { self.state = state - if notifyingObservers, let model = model { + if notifyingObservers, let model { observer?.elementStateChanged(state, forPath: model.path) } } @@ -179,7 +179,7 @@ public final class GalleryView: BlockView { ) contentPager.setInitialOffset(layout.pageOrigins.first ?? .zero) } - if let contentPager = contentPager { + if let contentPager { configure(contentPager) } else { let contentPager = ScrollableContentPager() @@ -236,7 +236,7 @@ public final class GalleryView: BlockView { collectionView.frame = bounds mask!.frame = bounds.insetBy(dx: 0, dy: shadowInsetValue) - if let model = model { + if let model { updateLayoutIfNeeded(to: model) } if case let .pending(state) = deferredStateSetting { diff --git a/LayoutKit/LayoutKit/UI/Views/TabbedPages/TabContentsView.swift b/LayoutKit/LayoutKit/UI/Views/TabbedPages/TabContentsView.swift index e7c58378..289ee731 100644 --- a/LayoutKit/LayoutKit/UI/Views/TabbedPages/TabContentsView.swift +++ b/LayoutKit/LayoutKit/UI/Views/TabbedPages/TabContentsView.swift @@ -14,7 +14,7 @@ class TabContentsView: BlockView { private var footerView: UIView? { didSet { oldValue?.removeFromSuperview() - if let footerView = footerView { + if let footerView { addSubview(footerView) } } @@ -23,7 +23,7 @@ class TabContentsView: BlockView { private var backgroundView: BlockView? { didSet { oldValue?.removeFromSuperview() - if let backgroundView = backgroundView { + if let backgroundView { insertSubview(backgroundView, at: 0) } } @@ -96,7 +96,7 @@ class TabContentsView: BlockView { if oldModel == nil || oldModel.pages !== model.pages || oldObserver !== observer { dataSource.models = [model.pages.map { $0.block as! CollectionCellModel }] - if let backgroundView = backgroundView, + if let backgroundView, let background = model.background, background.canConfigureBlockView(backgroundView) { background.configureBlockView( @@ -192,7 +192,7 @@ class TabContentsView: BlockView { collectionView.contentOffset = selectedPageContentOffset let newLayout = TabContentsViewLayout( - pages: model.pages.map { $0.block }, + pages: model.pages.map(\.block), footer: model.footer, size: collectionView.bounds.size, pagesInsets: model.contentInsets.horizontalInsets diff --git a/LayoutKit/LayoutKit/UI/Views/TabbedPages/TabListView.swift b/LayoutKit/LayoutKit/UI/Views/TabbedPages/TabListView.swift index 3563dcab..5c039102 100644 --- a/LayoutKit/LayoutKit/UI/Views/TabbedPages/TabListView.swift +++ b/LayoutKit/LayoutKit/UI/Views/TabbedPages/TabListView.swift @@ -86,7 +86,7 @@ final class TabListView: UIView { collectionView.frame = bounds delegate.size = bounds.size - if let animationInfo = animationInfo { + if let animationInfo { let fromLayout = delegate.collectionView( collectionView, layoutForItemSelection: animationInfo.fromSelection, @@ -140,7 +140,7 @@ final class TabListView: UIView { collectionView.layoutIfNeeded() let pillSize = CGSize( - width: model.items.map { $0.totalSize.width }.interim(at: selection), + width: model.items.map(\.totalSize.width).interim(at: selection), height: model.items.first!.totalSize.height ) let halfPill = pillSize.height / 2 diff --git a/LayoutKit/LayoutKit/UI/Views/TabbedPages/TabListViewDelegate.swift b/LayoutKit/LayoutKit/UI/Views/TabbedPages/TabListViewDelegate.swift index 4f72af98..9583864e 100644 --- a/LayoutKit/LayoutKit/UI/Views/TabbedPages/TabListViewDelegate.swift +++ b/LayoutKit/LayoutKit/UI/Views/TabbedPages/TabListViewDelegate.swift @@ -96,11 +96,11 @@ final class TabListViewDelegate: NSObject, UICollectionViewDelegateFlowLayout { } if layoutDirection == .rightToLeft { - let pillSizeWidth = itemSizes.map { $0.width }.interim(at: itemSelection) + let pillSizeWidth = itemSizes.map(\.width).interim(at: itemSelection) pillOriginX = size.width - pillSizeWidth - pillOriginX } - if let offset = offset { + if let offset { return Layout( contentOffset: CGPoint(x: offset, y: 0), pillOriginX: pillOriginX - (offset - contentOffsetX) @@ -183,7 +183,7 @@ final class TabListViewDelegate: NSObject, UICollectionViewDelegateFlowLayout { } private func sendScrollEvent(_ scrollView: UIScrollView) { - guard let scrollInfo = scrollInfo else { + guard let scrollInfo else { return } @@ -243,7 +243,7 @@ extension UICollectionView { indexPaths.map { ($0, layoutAttributesForItem(at: $0)?.frame) }.compactMap { indexPath, frame in - if let frame = frame { + if let frame { return (indexPath, frame) } else { return nil diff --git a/LayoutKit/LayoutKit/UI/Views/TabbedPages/TabSelectionWireframe.swift b/LayoutKit/LayoutKit/UI/Views/TabbedPages/TabSelectionWireframe.swift index a6bcf4d6..ade3d8fe 100644 --- a/LayoutKit/LayoutKit/UI/Views/TabbedPages/TabSelectionWireframe.swift +++ b/LayoutKit/LayoutKit/UI/Views/TabbedPages/TabSelectionWireframe.swift @@ -23,7 +23,7 @@ final class TabSelectionWireframe { extension TabSelectionWireframe: TabContentsViewDelegate { func tabContentsViewDidChangeRelativeContentOffsetTo(_ offset: CGFloat) { - guard let tabListView = tabListView else { return } + guard let tabListView else { return } let newModel = tabListSelectionDataSource.modelForItemSelection(offset) tabListView.model = newModel } @@ -35,13 +35,13 @@ extension TabSelectionWireframe: TabContentsViewDelegate { extension TabSelectionWireframe: TabListViewDelegateTabSelection { func tabListViewDidSelectItemAt(_ index: Int, withUrl url: URL?, path: UIElementPath) { - guard let contentsView = tabContentsView, let tabListView = tabListView else { + guard let contentsView = tabContentsView, let tabListView else { return } let selection = CGFloat(index) let action: UserInterfaceAction if contentsView.selectedPageIndex.isApproximatelyEqualTo(selection) { - if let url = url { + if let url { action = UserInterfaceAction(url: url, path: path) } else { action = UserInterfaceAction(url: tabChangedUrl, path: path) @@ -55,7 +55,7 @@ extension TabSelectionWireframe: TabListViewDelegateTabSelection { } func tabListViewDidScrollTo(_ offset: CGFloat) { - guard let tabListView = tabListView else { + guard let tabListView else { return } tabListView.model = tabListView.model.map { modified($0) { $0.offset = offset } } diff --git a/LayoutKit/LayoutKit/UI/Views/TabbedPages/TabbedPagesView.swift b/LayoutKit/LayoutKit/UI/Views/TabbedPages/TabbedPagesView.swift index 394493bc..2d3c3656 100644 --- a/LayoutKit/LayoutKit/UI/Views/TabbedPages/TabbedPagesView.swift +++ b/LayoutKit/LayoutKit/UI/Views/TabbedPages/TabbedPagesView.swift @@ -103,7 +103,7 @@ public final class TabbedPagesView: BlockView, VisibleBoundsTrackingContainer { let view: UIView - if let separatorView = separatorView { + if let separatorView { view = separatorView } else { view = UIView() diff --git a/LayoutKit/LayoutKit/UI/Views/ViewWithShadow.swift b/LayoutKit/LayoutKit/UI/Views/ViewWithShadow.swift index cac88ab4..c474c579 100644 --- a/LayoutKit/LayoutKit/UI/Views/ViewWithShadow.swift +++ b/LayoutKit/LayoutKit/UI/Views/ViewWithShadow.swift @@ -18,7 +18,7 @@ open class ViewWithShadow: UIView { return } - if let shadow = shadow { + if let shadow { layer.shadowRadius = shadow.blurRadius layer.shadowOffset = CGSize(width: shadow.offset.x, height: shadow.offset.y) layer.shadowOpacity = shadow.opacity @@ -50,7 +50,7 @@ open class ViewWithShadow: UIView { return } - if let shadow = shadow { + if let shadow { layer.shadowPath = .roundedRect( size: bounds.size, cornerRadii: shadow.cornerRadii diff --git a/LayoutKit/LayoutKit/ViewModels/Background.swift b/LayoutKit/LayoutKit/ViewModels/Background.swift index 1ce64823..7d87f0e3 100644 --- a/LayoutKit/LayoutKit/ViewModels/Background.swift +++ b/LayoutKit/LayoutKit/ViewModels/Background.swift @@ -125,7 +125,7 @@ extension Background: ImageContaining { } } -extension Array where Element == Background { +extension [Background] { public func composite() -> Element? { if isEmpty { return nil } return dropFirst().reduce(first!, +) diff --git a/LayoutKit/LayoutKit/ViewModels/GalleryViewLayout.swift b/LayoutKit/LayoutKit/ViewModels/GalleryViewLayout.swift index 942e57c3..37ead44e 100644 --- a/LayoutKit/LayoutKit/ViewModels/GalleryViewLayout.swift +++ b/LayoutKit/LayoutKit/ViewModels/GalleryViewLayout.swift @@ -33,7 +33,7 @@ public struct GalleryViewLayout: GalleryViewLayouting, Equatable { public let contentSize: CGSize public var pageOrigins: [CGFloat] { - blockPages.map { $0.origin } + blockPages.map(\.origin) } public init(model: GalleryViewModel, boundsSize: CGSize? = nil) { @@ -138,12 +138,12 @@ extension GalleryViewModel { let rightGap = lastGap(forSize: size) let bottomGap = crossInsets(forSize: size).trailing let width = lastFrame.maxX + rightGap - let maxHeight = frames.map { $0.maxY }.max()! + bottomGap + let maxHeight = frames.map(\.maxY).max()! + bottomGap return CGSize(width: width, height: maxHeight) case .vertical: let rightGap = crossInsets(forSize: size).trailing let bottomGap = lastGap(forSize: size) - let maxWidth = frames.map { $0.maxX }.max()! + rightGap + let maxWidth = frames.map(\.maxX).max()! + rightGap let height = lastFrame.maxY + bottomGap return CGSize(width: maxWidth, height: height) } @@ -161,7 +161,7 @@ extension GalleryViewModel { } private func horizontallyOrientedFrames(fitting size: CGSize?) -> [CGRect] { - let blocks = items.map { $0.content } + let blocks = items.map(\.content) let widths = blocks.map { $0.isHorizontallyResizable ? size?.width ?? 0 @@ -170,7 +170,7 @@ extension GalleryViewModel { let crossInsets = self.crossInsets(forSize: size) let crossSpacing = metrics.crossSpacing let maxItemHeight: CGFloat - if let size = size { + if let size { maxItemHeight = (size.height - crossInsets.sum - crossSpacing * CGFloat(columnCount - 1)) / CGFloat(columnCount) } else if let maxNonResizableHeight = blocks @@ -209,11 +209,11 @@ extension GalleryViewModel { let crossInsets = self.crossInsets(forSize: size) let crossSpacing = metrics.crossSpacing let maxItemWidth: CGFloat - if let size = size { + if let size { maxItemWidth = (size.width - crossInsets.sum - crossSpacing * CGFloat(columnCount - 1)) / CGFloat(columnCount) } else { - let blocks = items.map { $0.content } + let blocks = items.map(\.content) if let maxNonResizebleWidth = blocks.maxWidthOfHorizontallyNonResizableBlocks { maxItemWidth = maxNonResizebleWidth } else { diff --git a/LayoutKit/LayoutKit/ViewModels/GalleryViewModel.swift b/LayoutKit/LayoutKit/ViewModels/GalleryViewModel.swift index 51da29d4..3f2d89a9 100644 --- a/LayoutKit/LayoutKit/ViewModels/GalleryViewModel.swift +++ b/LayoutKit/LayoutKit/ViewModels/GalleryViewModel.swift @@ -167,7 +167,7 @@ private func validateContent( of items: [GalleryViewModel.Item], with direction: GalleryViewModel.Direction ) { - let blocks = items.map { $0.content } + let blocks = items.map(\.content) switch direction { case .horizontal: precondition( diff --git a/LayoutKit/LayoutKit/ViewModels/PagerViewLayout.swift b/LayoutKit/LayoutKit/ViewModels/PagerViewLayout.swift index 60d68aeb..4abf498d 100644 --- a/LayoutKit/LayoutKit/ViewModels/PagerViewLayout.swift +++ b/LayoutKit/LayoutKit/ViewModels/PagerViewLayout.swift @@ -24,7 +24,7 @@ public struct PagerViewLayout: GalleryViewLayouting, Equatable { public let contentSize: CGSize public var pageOrigins: [CGFloat] { - blockPages.map { $0.origin } + blockPages.map(\.origin) } public init( @@ -148,12 +148,12 @@ extension GalleryViewModel { let rightGap = lastGap(forSize: size) let bottomGap = crossInsets(forSize: size).trailing let width = lastFrame.maxX + rightGap - let maxHeight = neigbourFrames.map { $0.maxY }.max()! + let maxHeight = neigbourFrames.map(\.maxY).max()! return CGSize(width: width, height: maxHeight + bottomGap) case .vertical: let rightGap = crossInsets(forSize: size).trailing let bottomGap = lastGap(forSize: size) - let maxWidth = neigbourFrames.map { $0.maxX }.max()! + let maxWidth = neigbourFrames.map(\.maxX).max()! let height = lastFrame.maxY + bottomGap return CGSize(width: maxWidth + rightGap, height: height) } @@ -181,7 +181,7 @@ extension GalleryViewModel { fitting size: CGSize?, layoutMode: PagerBlock.LayoutMode ) -> [CGRect] { - let blocks = items.map { $0.content } + let blocks = items.map(\.content) let widths = (0.. [CGRect] { let crossInsets = self.crossInsets(forSize: size) - let blocks = items.map { $0.content } + let blocks = items.map(\.content) let maxWidth = size.map { $0.width - crossInsets.sum } ?? blocks .filter { !$0.isHorizontallyResizable } - .map { $0.widthOfHorizontallyNonResizableBlock }.max()! + .map(\.widthOfHorizontallyNonResizableBlock).max()! let minX = crossInsets.leading let gaps = self.gaps(forSize: size) diff --git a/LayoutKit/LayoutKit/ViewModels/TabbedPages/TabContentsViewLayout.swift b/LayoutKit/LayoutKit/ViewModels/TabbedPages/TabContentsViewLayout.swift index 3666d551..878dd434 100644 --- a/LayoutKit/LayoutKit/ViewModels/TabbedPages/TabContentsViewLayout.swift +++ b/LayoutKit/LayoutKit/ViewModels/TabbedPages/TabContentsViewLayout.swift @@ -63,7 +63,7 @@ struct TabContentsViewLayout: Equatable { } } -extension Array where Element == Block { +extension [Block] { fileprivate func intrinsicContentHeight( forWidth width: CGFloat, selectedPageIndex index: CGFloat diff --git a/LayoutKit/LayoutKit/ViewModels/TabbedPages/TabContentsViewModel.swift b/LayoutKit/LayoutKit/ViewModels/TabbedPages/TabContentsViewModel.swift index 6b3aa700..ccbb836d 100644 --- a/LayoutKit/LayoutKit/ViewModels/TabbedPages/TabContentsViewModel.swift +++ b/LayoutKit/LayoutKit/ViewModels/TabbedPages/TabContentsViewModel.swift @@ -44,7 +44,7 @@ public struct TabContentsViewModel: Equatable { throw BlockError("Tab error: no children provided") } - if let footer = footer, footer.isVerticallyResizable { + if let footer, footer.isVerticallyResizable { throw BlockError("Tab error: vertically resizable footer is unsupported") } } @@ -62,7 +62,7 @@ public struct TabContentsViewModel: Equatable { extension TabContentsViewModel: CustomDebugStringConvertible { public var debugDescription: String { - let pagesDescription = pages.map { $0.debugDescription } + let pagesDescription = pages.map(\.debugDescription) return """ { path: \(dbgStr(path)), pages: \(pagesDescription), diff --git a/LayoutKit/LayoutKit/ViewModels/TabbedPages/TabInterimItemExtensions.swift b/LayoutKit/LayoutKit/ViewModels/TabbedPages/TabInterimItemExtensions.swift index d926bb66..3ddd20b5 100644 --- a/LayoutKit/LayoutKit/ViewModels/TabbedPages/TabInterimItemExtensions.swift +++ b/LayoutKit/LayoutKit/ViewModels/TabbedPages/TabInterimItemExtensions.swift @@ -2,7 +2,7 @@ import CoreGraphics import CommonCorePublic -extension Array where Element == CGFloat { +extension [CGFloat] { func interim(at index: CGFloat) -> CGFloat { let leftIndex = floorIndex(index) let leftItem = self[leftIndex] diff --git a/LayoutKit/LayoutKit/ViewModels/TabbedPages/TabListViewModel.swift b/LayoutKit/LayoutKit/ViewModels/TabbedPages/TabListViewModel.swift index 52d2603f..7f63d2b2 100644 --- a/LayoutKit/LayoutKit/ViewModels/TabbedPages/TabListViewModel.swift +++ b/LayoutKit/LayoutKit/ViewModels/TabbedPages/TabListViewModel.swift @@ -71,7 +71,7 @@ public final class TabListViewModel: Equatable { extension TabListViewModel: CustomDebugStringConvertible { public var debugDescription: String { - let titlesDescriptions = tabTitles.map { $0.debugDescription } + let titlesDescriptions = tabTitles.map(\.debugDescription) return """ { titles: \(titlesDescriptions), titleStyle: \(titleStyle), diff --git a/LayoutKit/LayoutKit/ViewModels/TabbedPages/TabViewLayout.swift b/LayoutKit/LayoutKit/ViewModels/TabbedPages/TabViewLayout.swift index 930e47a8..7ea8bc7b 100644 --- a/LayoutKit/LayoutKit/ViewModels/TabbedPages/TabViewLayout.swift +++ b/LayoutKit/LayoutKit/ViewModels/TabbedPages/TabViewLayout.swift @@ -88,7 +88,7 @@ public struct TabViewLayout: Equatable { extension TabContentsViewModel { fileprivate var intrinsicWidth: CGFloat { TabContentsViewLayout.intrinsicWidth( - for: pages.map { $0.block }, + for: pages.map(\.block), footer: footer, pagesInsets: contentInsets.horizontalInsets ) @@ -100,7 +100,7 @@ extension TabContentsViewModel { ) -> CGFloat { TabContentsViewLayout.intrinsicHeight( forWidth: width, - pages: pages.map { $0.block }, + pages: pages.map(\.block), pagesHeightMode: pagesHeight, selectedPageIndex: selectedPageIndex, footer: footer, diff --git a/Serialization/DeserializationError.swift b/Serialization/DeserializationError.swift index 5cf177cf..9f43f0bc 100644 --- a/Serialization/DeserializationError.swift +++ b/Serialization/DeserializationError.swift @@ -93,9 +93,7 @@ public indirect enum DeserializationError: Error, CustomStringConvertible { public var rootCauses: [DeserializationError] { switch self { case let .composite(_, causes): - return causes.flatMap { - $0.rootCauses - } + return causes.flatMap(\.rootCauses) case let .nestedObjectError(field, error): return error.rootCauses.map { .nestedObjectError(field: field, error: $0) } default: @@ -133,7 +131,7 @@ public indirect enum DeserializationError: Error, CustomStringConvertible { } } -fileprivate func dbgStrLimited(_ val: T?, limit: UInt = 100) -> String { +fileprivate func dbgStrLimited(_ val: (some Any)?, limit: UInt = 100) -> String { val.map { "\($0)".crop(limit) } ?? "nil" } diff --git a/Serialization/Dictionary+Serialization.swift b/Serialization/Dictionary+Serialization.swift index 732c07dc..4a095e2c 100644 --- a/Serialization/Dictionary+Serialization.swift +++ b/Serialization/Dictionary+Serialization.swift @@ -21,10 +21,10 @@ extension DeserializationResult { } @usableFromInline -func invalidFieldErrorForKey( - _ key: [T], +func invalidFieldErrorForKey( + _ key: [some Any], element: Int? = nil, - representation: U? + representation: (some Any)? ) -> DeserializationError { let keyStrings: [String] = key.map { "\($0)" } return .invalidFieldRepresentation( diff --git a/Specs/DivKit/29.2.0/DivKit.podspec b/Specs/DivKit/29.2.0/DivKit.podspec new file mode 100644 index 00000000..3448e614 --- /dev/null +++ b/Specs/DivKit/29.2.0/DivKit.podspec @@ -0,0 +1,25 @@ +Pod::Spec.new do |s| + s.name = 'DivKit' + s.version = '29.2.0' + s.summary = 'DivKit framework' + s.description = 'DivKit is a backend-driven UI framework' + s.homepage = 'https://divkit.tech' + + s.license = { :type => 'Apache License, Version 2.0', :file => 'LICENSE' } + s.author = { 'divkit' => 'divkit@yandex-team.ru' } + s.source = { :git => 'https://github.com/divkit/divkit-ios.git', :tag => s.version.to_s } + + s.swift_version = '5.7' + s.requires_arc = true + s.prefix_header_file = false + s.platforms = { :ios => '11.0' } + + s.dependency 'DivKit_LayoutKit', s.version.to_s + s.dependency 'DivKit_Serialization', s.version.to_s + s.dependency 'VGSLCommonCore', '~> 2.4' + s.dependency 'VGSLNetworking', '~> 2.4' + + s.source_files = [ + 'DivKit/**/*' + ] +end diff --git a/Specs/DivKitExtensions/29.2.0/DivKitExtensions.podspec b/Specs/DivKitExtensions/29.2.0/DivKitExtensions.podspec new file mode 100644 index 00000000..3e319d01 --- /dev/null +++ b/Specs/DivKitExtensions/29.2.0/DivKitExtensions.podspec @@ -0,0 +1,22 @@ +Pod::Spec.new do |s| + s.name = 'DivKitExtensions' + s.version = '29.2.0' + s.summary = 'DivKit framework extensions' + s.description = 'Part of DivKit framework' + s.homepage = 'https://divkit.tech' + + s.license = { :type => 'Apache License, Version 2.0', :file => 'LICENSE' } + s.author = { 'divkit' => 'divkit@yandex-team.ru' } + s.source = { :git => 'https://github.com/divkit/divkit-ios.git', :tag => s.version.to_s } + + s.swift_version = '5.7' + s.requires_arc = true + s.prefix_header_file = false + s.platforms = { :ios => '11.0' } + + s.dependency 'DivKit', s.version.to_s + + s.source_files = [ + 'DivKitExtensions/**/*' + ] +end diff --git a/Specs/DivKit_LayoutKit/29.2.0/DivKit_LayoutKit.podspec b/Specs/DivKit_LayoutKit/29.2.0/DivKit_LayoutKit.podspec new file mode 100644 index 00000000..0cb7693b --- /dev/null +++ b/Specs/DivKit_LayoutKit/29.2.0/DivKit_LayoutKit.podspec @@ -0,0 +1,24 @@ +Pod::Spec.new do |s| + s.name = 'DivKit_LayoutKit' + s.module_name = 'LayoutKit' + s.version = '29.2.0' + s.summary = 'Part of DivKit framework' + s.description = 'Part of DivKit framework' + s.homepage = 'https://divkit.tech' + + s.license = { :type => 'Apache License, Version 2.0', :file => 'LICENSE' } + s.author = { 'divkit' => 'divkit@yandex-team.ru' } + s.source = { :git => 'https://github.com/divkit/divkit-ios.git', :tag => s.version.to_s } + + s.swift_version = '5.7' + s.requires_arc = true + s.prefix_header_file = false + s.platforms = { :ios => '11.0' } + + s.dependency 'DivKit_LayoutKitInterface', s.version.to_s + s.dependency 'VGSLCommonCore', '~> 2.4' + + s.source_files = [ + 'LayoutKit/LayoutKit/**/*' + ] +end diff --git a/Specs/DivKit_LayoutKitInterface/29.2.0/DivKit_LayoutKitInterface.podspec b/Specs/DivKit_LayoutKitInterface/29.2.0/DivKit_LayoutKitInterface.podspec new file mode 100644 index 00000000..ac1fdb6d --- /dev/null +++ b/Specs/DivKit_LayoutKitInterface/29.2.0/DivKit_LayoutKitInterface.podspec @@ -0,0 +1,25 @@ +Pod::Spec.new do |s| + s.name = 'DivKit_LayoutKitInterface' + s.module_name = 'LayoutKitInterface' + s.version = '29.2.0' + s.summary = 'Part of DivKit framework' + s.description = 'Part of DivKit framework' + s.homepage = 'https://divkit.tech' + + s.license = { :type => 'Apache License, Version 2.0', :file => 'LICENSE' } + s.author = { 'divkit' => 'divkit@yandex-team.ru' } + s.source = { :git => 'https://github.com/divkit/divkit-ios.git', :tag => s.version.to_s } + + s.swift_version = '5.7' + s.requires_arc = true + s.prefix_header_file = false + s.platforms = { :ios => '11.0' } + + s.dependency 'VGSLBase', '~> 2.4' + s.dependency 'VGSLBaseTiny', '~> 2.4' + s.dependency 'VGSLBaseUI', '~> 2.4' + + s.source_files = [ + 'LayoutKit/Interface/**/*' + ] +end diff --git a/Specs/DivKit_Serialization/29.2.0/DivKit_Serialization.podspec b/Specs/DivKit_Serialization/29.2.0/DivKit_Serialization.podspec new file mode 100644 index 00000000..8a81d7bb --- /dev/null +++ b/Specs/DivKit_Serialization/29.2.0/DivKit_Serialization.podspec @@ -0,0 +1,23 @@ +Pod::Spec.new do |s| + s.name = 'DivKit_Serialization' + s.module_name = 'Serialization' + s.version = '29.2.0' + s.summary = 'Part of DivKit framework' + s.description = 'Part of DivKit framework' + s.homepage = 'https://divkit.tech' + + s.license = { :type => 'Apache License, Version 2.0', :file => 'LICENSE' } + s.author = { 'divkit' => 'divkit@yandex-team.ru' } + s.source = { :git => 'https://github.com/divkit/divkit-ios.git', :tag => s.version.to_s } + + s.swift_version = '5.7' + s.requires_arc = true + s.prefix_header_file = false + s.platforms = { :ios => '11.0' } + + s.dependency 'VGSLCommonCore', '~> 2.4' + + s.source_files = [ + 'Serialization/**/*' + ] +end