From 537db952b32e08ec5de321407a5946a3cf35c5be Mon Sep 17 00:00:00 2001 From: robot-divkit Date: Mon, 28 Aug 2023 18:46:02 +0300 Subject: [PATCH] Release 27.4.0 --- .mapping.json | 14 ++- .../NetworkingPublic/ImageHolderFactory.swift | 6 +- Core/NetworkingPublic/RemoteImageHolder.swift | 35 +++++++- DivKit/Debug/ErrorListView.swift | 32 +++---- DivKit/DivBlockModelingContext.swift | 6 +- DivKit/DivBlockProvider.swift | 7 +- DivKit/DivFlagsInfo.swift | 8 +- DivKit/DivKitComponents.swift | 16 +++- DivKit/DivKitInfo.swift | 2 +- DivKit/DivKitLogger.swift | 2 +- DivKit/Expressions/ExpressionResolver.swift | 4 +- .../Functions/ValueFunctions.swift | 14 +-- .../DivBase/DivBaseExtensions.swift | 53 +---------- DivKit/Extensions/DivInputExtensions.swift | 4 +- DivKit/Extensions/DivPointExtensions.swift | 10 +++ DivKit/Extensions/DivTooltipExtensions.swift | 89 +++++++++++++++++++ DivKit/generated_sources/DivTooltip.swift | 9 +- .../CustomImagePreviewExtensionHandler.swift | 1 - .../Shimmer/DefaultShimmerViewFactory.swift | 4 +- .../ShimmerImagePreviewExtensions.swift | 2 +- DivKitExtensions/Shimmer/ShimmerStyle.swift | 4 +- .../SizeProviderBlock+UIViewRenderable.swift | 6 +- .../SizeProvider/SizeProviderBlock.swift | 2 +- .../SizeProviderExtensionHandler.swift | 16 ++-- .../Blocks/BlockTooltip+Layout.swift | 4 + LayoutKit/LayoutKit/Blocks/BlockTooltip.swift | 13 ++- .../LayoutKit/Tooltips/TooltipFactory.swift | 12 +++ .../LayoutKit/Tooltips/TooltipManager.swift | 6 +- ...TextFieldBlock+UIViewRenderableBlock.swift | 4 +- Package.swift | 2 +- Specs/BasePublic/27.4.0/BasePublic.podspec | 23 +++++ .../27.4.0/BaseTinyPublic.podspec | 20 +++++ .../BaseUIPublic/27.4.0/BaseUIPublic.podspec | 22 +++++ .../27.4.0/CommonCorePublic.podspec | 22 +++++ Specs/DivKit/27.4.0/DivKit.podspec | 25 ++++++ .../27.4.0/DivKitExtensions.podspec | 22 +++++ Specs/LayoutKit/27.4.0/LayoutKit.podspec | 23 +++++ .../27.4.0/LayoutKitInterface.podspec | 24 +++++ .../27.4.0/NetworkingPublic.podspec | 22 +++++ .../27.4.0/Serialization.podspec | 23 +++++ 40 files changed, 489 insertions(+), 124 deletions(-) create mode 100644 DivKit/Extensions/DivPointExtensions.swift create mode 100644 DivKit/Extensions/DivTooltipExtensions.swift create mode 100644 Specs/BasePublic/27.4.0/BasePublic.podspec create mode 100644 Specs/BaseTinyPublic/27.4.0/BaseTinyPublic.podspec create mode 100644 Specs/BaseUIPublic/27.4.0/BaseUIPublic.podspec create mode 100644 Specs/CommonCorePublic/27.4.0/CommonCorePublic.podspec create mode 100644 Specs/DivKit/27.4.0/DivKit.podspec create mode 100644 Specs/DivKitExtensions/27.4.0/DivKitExtensions.podspec create mode 100644 Specs/LayoutKit/27.4.0/LayoutKit.podspec create mode 100644 Specs/LayoutKitInterface/27.4.0/LayoutKitInterface.podspec create mode 100644 Specs/NetworkingPublic/27.4.0/NetworkingPublic.podspec create mode 100644 Specs/Serialization/27.4.0/Serialization.podspec diff --git a/.mapping.json b/.mapping.json index 8ca0c946..f3772633 100644 --- a/.mapping.json +++ b/.mapping.json @@ -325,6 +325,7 @@ "DivKit/Extensions/DivInputExtensions.swift":"divkit/public-ios/DivKit/Extensions/DivInputExtensions.swift", "DivKit/Extensions/DivPagerExtensions.swift":"divkit/public-ios/DivKit/Extensions/DivPagerExtensions.swift", "DivKit/Extensions/DivPivotExtensions.swift":"divkit/public-ios/DivKit/Extensions/DivPivotExtensions.swift", + "DivKit/Extensions/DivPointExtensions.swift":"divkit/public-ios/DivKit/Extensions/DivPointExtensions.swift", "DivKit/Extensions/DivSelectExtensions.swift":"divkit/public-ios/DivKit/Extensions/DivSelectExtensions.swift", "DivKit/Extensions/DivSeparatorExtensions.swift":"divkit/public-ios/DivKit/Extensions/DivSeparatorExtensions.swift", "DivKit/Extensions/DivSizeExtensions.swift":"divkit/public-ios/DivKit/Extensions/DivSizeExtensions.swift", @@ -333,6 +334,7 @@ "DivKit/Extensions/DivStateExtensions.swift":"divkit/public-ios/DivKit/Extensions/DivStateExtensions.swift", "DivKit/Extensions/DivTabsExtensions.swift":"divkit/public-ios/DivKit/Extensions/DivTabsExtensions.swift", "DivKit/Extensions/DivTextExtensions.swift":"divkit/public-ios/DivKit/Extensions/DivTextExtensions.swift", + "DivKit/Extensions/DivTooltipExtensions.swift":"divkit/public-ios/DivKit/Extensions/DivTooltipExtensions.swift", "DivKit/Extensions/DivTransformExtensions.swift":"divkit/public-ios/DivKit/Extensions/DivTransformExtensions.swift", "DivKit/Extensions/DivVideoExtensions.swift":"divkit/public-ios/DivKit/Extensions/DivVideoExtensions.swift", "DivKit/Extensions/DivVisibilityActionExtensions.swift":"divkit/public-ios/DivKit/Extensions/DivVisibilityActionExtensions.swift", @@ -914,6 +916,7 @@ "Specs/BasePublic/27.1.0/BasePublic.podspec":"divkit/public-ios/Specs/BasePublic/27.1.0/BasePublic.podspec", "Specs/BasePublic/27.2.0/BasePublic.podspec":"divkit/public-ios/Specs/BasePublic/27.2.0/BasePublic.podspec", "Specs/BasePublic/27.3.0/BasePublic.podspec":"divkit/public-ios/Specs/BasePublic/27.3.0/BasePublic.podspec", + "Specs/BasePublic/27.4.0/BasePublic.podspec":"divkit/public-ios/Specs/BasePublic/27.4.0/BasePublic.podspec", "Specs/BaseTinyPublic/24.3.0/BaseTinyPublic.podspec":"divkit/public-ios/Specs/BaseTinyPublic/24.3.0/BaseTinyPublic.podspec", "Specs/BaseTinyPublic/25.0.0/BaseTinyPublic.podspec":"divkit/public-ios/Specs/BaseTinyPublic/25.0.0/BaseTinyPublic.podspec", "Specs/BaseTinyPublic/25.1.0/BaseTinyPublic.podspec":"divkit/public-ios/Specs/BaseTinyPublic/25.1.0/BaseTinyPublic.podspec", @@ -930,6 +933,7 @@ "Specs/BaseTinyPublic/27.1.0/BaseTinyPublic.podspec":"divkit/public-ios/Specs/BaseTinyPublic/27.1.0/BaseTinyPublic.podspec", "Specs/BaseTinyPublic/27.2.0/BaseTinyPublic.podspec":"divkit/public-ios/Specs/BaseTinyPublic/27.2.0/BaseTinyPublic.podspec", "Specs/BaseTinyPublic/27.3.0/BaseTinyPublic.podspec":"divkit/public-ios/Specs/BaseTinyPublic/27.3.0/BaseTinyPublic.podspec", + "Specs/BaseTinyPublic/27.4.0/BaseTinyPublic.podspec":"divkit/public-ios/Specs/BaseTinyPublic/27.4.0/BaseTinyPublic.podspec", "Specs/BaseUIPublic/24.3.0/BaseUIPublic.podspec":"divkit/public-ios/Specs/BaseUIPublic/24.3.0/BaseUIPublic.podspec", "Specs/BaseUIPublic/25.0.0/BaseUIPublic.podspec":"divkit/public-ios/Specs/BaseUIPublic/25.0.0/BaseUIPublic.podspec", "Specs/BaseUIPublic/25.1.0/BaseUIPublic.podspec":"divkit/public-ios/Specs/BaseUIPublic/25.1.0/BaseUIPublic.podspec", @@ -946,6 +950,7 @@ "Specs/BaseUIPublic/27.1.0/BaseUIPublic.podspec":"divkit/public-ios/Specs/BaseUIPublic/27.1.0/BaseUIPublic.podspec", "Specs/BaseUIPublic/27.2.0/BaseUIPublic.podspec":"divkit/public-ios/Specs/BaseUIPublic/27.2.0/BaseUIPublic.podspec", "Specs/BaseUIPublic/27.3.0/BaseUIPublic.podspec":"divkit/public-ios/Specs/BaseUIPublic/27.3.0/BaseUIPublic.podspec", + "Specs/BaseUIPublic/27.4.0/BaseUIPublic.podspec":"divkit/public-ios/Specs/BaseUIPublic/27.4.0/BaseUIPublic.podspec", "Specs/CommonCorePublic/24.3.0/CommonCorePublic.podspec":"divkit/public-ios/Specs/CommonCorePublic/24.3.0/CommonCorePublic.podspec", "Specs/CommonCorePublic/25.0.0/CommonCorePublic.podspec":"divkit/public-ios/Specs/CommonCorePublic/25.0.0/CommonCorePublic.podspec", "Specs/CommonCorePublic/25.1.0/CommonCorePublic.podspec":"divkit/public-ios/Specs/CommonCorePublic/25.1.0/CommonCorePublic.podspec", @@ -962,6 +967,7 @@ "Specs/CommonCorePublic/27.1.0/CommonCorePublic.podspec":"divkit/public-ios/Specs/CommonCorePublic/27.1.0/CommonCorePublic.podspec", "Specs/CommonCorePublic/27.2.0/CommonCorePublic.podspec":"divkit/public-ios/Specs/CommonCorePublic/27.2.0/CommonCorePublic.podspec", "Specs/CommonCorePublic/27.3.0/CommonCorePublic.podspec":"divkit/public-ios/Specs/CommonCorePublic/27.3.0/CommonCorePublic.podspec", + "Specs/CommonCorePublic/27.4.0/CommonCorePublic.podspec":"divkit/public-ios/Specs/CommonCorePublic/27.4.0/CommonCorePublic.podspec", "Specs/DivKit/24.3.0/DivKit.podspec":"divkit/public-ios/Specs/DivKit/24.3.0/DivKit.podspec", "Specs/DivKit/25.0.0/DivKit.podspec":"divkit/public-ios/Specs/DivKit/25.0.0/DivKit.podspec", "Specs/DivKit/25.1.0/DivKit.podspec":"divkit/public-ios/Specs/DivKit/25.1.0/DivKit.podspec", @@ -978,6 +984,7 @@ "Specs/DivKit/27.1.0/DivKit.podspec":"divkit/public-ios/Specs/DivKit/27.1.0/DivKit.podspec", "Specs/DivKit/27.2.0/DivKit.podspec":"divkit/public-ios/Specs/DivKit/27.2.0/DivKit.podspec", "Specs/DivKit/27.3.0/DivKit.podspec":"divkit/public-ios/Specs/DivKit/27.3.0/DivKit.podspec", + "Specs/DivKit/27.4.0/DivKit.podspec":"divkit/public-ios/Specs/DivKit/27.4.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", @@ -994,6 +1001,7 @@ "Specs/DivKitExtensions/27.1.0/DivKitExtensions.podspec":"divkit/public-ios/Specs/DivKitExtensions/27.1.0/DivKitExtensions.podspec", "Specs/DivKitExtensions/27.2.0/DivKitExtensions.podspec":"divkit/public-ios/Specs/DivKitExtensions/27.2.0/DivKitExtensions.podspec", "Specs/DivKitExtensions/27.3.0/DivKitExtensions.podspec":"divkit/public-ios/Specs/DivKitExtensions/27.3.0/DivKitExtensions.podspec", + "Specs/DivKitExtensions/27.4.0/DivKitExtensions.podspec":"divkit/public-ios/Specs/DivKitExtensions/27.4.0/DivKitExtensions.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", @@ -1010,6 +1018,7 @@ "Specs/LayoutKit/27.1.0/LayoutKit.podspec":"divkit/public-ios/Specs/LayoutKit/27.1.0/LayoutKit.podspec", "Specs/LayoutKit/27.2.0/LayoutKit.podspec":"divkit/public-ios/Specs/LayoutKit/27.2.0/LayoutKit.podspec", "Specs/LayoutKit/27.3.0/LayoutKit.podspec":"divkit/public-ios/Specs/LayoutKit/27.3.0/LayoutKit.podspec", + "Specs/LayoutKit/27.4.0/LayoutKit.podspec":"divkit/public-ios/Specs/LayoutKit/27.4.0/LayoutKit.podspec", "Specs/LayoutKitInterface/24.3.0/LayoutKitInterface.podspec":"divkit/public-ios/Specs/LayoutKitInterface/24.3.0/LayoutKitInterface.podspec", "Specs/LayoutKitInterface/25.0.0/LayoutKitInterface.podspec":"divkit/public-ios/Specs/LayoutKitInterface/25.0.0/LayoutKitInterface.podspec", "Specs/LayoutKitInterface/25.1.0/LayoutKitInterface.podspec":"divkit/public-ios/Specs/LayoutKitInterface/25.1.0/LayoutKitInterface.podspec", @@ -1026,6 +1035,7 @@ "Specs/LayoutKitInterface/27.1.0/LayoutKitInterface.podspec":"divkit/public-ios/Specs/LayoutKitInterface/27.1.0/LayoutKitInterface.podspec", "Specs/LayoutKitInterface/27.2.0/LayoutKitInterface.podspec":"divkit/public-ios/Specs/LayoutKitInterface/27.2.0/LayoutKitInterface.podspec", "Specs/LayoutKitInterface/27.3.0/LayoutKitInterface.podspec":"divkit/public-ios/Specs/LayoutKitInterface/27.3.0/LayoutKitInterface.podspec", + "Specs/LayoutKitInterface/27.4.0/LayoutKitInterface.podspec":"divkit/public-ios/Specs/LayoutKitInterface/27.4.0/LayoutKitInterface.podspec", "Specs/NetworkingPublic/24.3.0/NetworkingPublic.podspec":"divkit/public-ios/Specs/NetworkingPublic/24.3.0/NetworkingPublic.podspec", "Specs/NetworkingPublic/25.0.0/NetworkingPublic.podspec":"divkit/public-ios/Specs/NetworkingPublic/25.0.0/NetworkingPublic.podspec", "Specs/NetworkingPublic/25.1.0/NetworkingPublic.podspec":"divkit/public-ios/Specs/NetworkingPublic/25.1.0/NetworkingPublic.podspec", @@ -1042,6 +1052,7 @@ "Specs/NetworkingPublic/27.1.0/NetworkingPublic.podspec":"divkit/public-ios/Specs/NetworkingPublic/27.1.0/NetworkingPublic.podspec", "Specs/NetworkingPublic/27.2.0/NetworkingPublic.podspec":"divkit/public-ios/Specs/NetworkingPublic/27.2.0/NetworkingPublic.podspec", "Specs/NetworkingPublic/27.3.0/NetworkingPublic.podspec":"divkit/public-ios/Specs/NetworkingPublic/27.3.0/NetworkingPublic.podspec", + "Specs/NetworkingPublic/27.4.0/NetworkingPublic.podspec":"divkit/public-ios/Specs/NetworkingPublic/27.4.0/NetworkingPublic.podspec", "Specs/Serialization/24.3.0/Serialization.podspec":"divkit/public-ios/Specs/Serialization/24.3.0/Serialization.podspec", "Specs/Serialization/25.0.0/Serialization.podspec":"divkit/public-ios/Specs/Serialization/25.0.0/Serialization.podspec", "Specs/Serialization/25.1.0/Serialization.podspec":"divkit/public-ios/Specs/Serialization/25.1.0/Serialization.podspec", @@ -1057,5 +1068,6 @@ "Specs/Serialization/27.0.0/Serialization.podspec":"divkit/public-ios/Specs/Serialization/27.0.0/Serialization.podspec", "Specs/Serialization/27.1.0/Serialization.podspec":"divkit/public-ios/Specs/Serialization/27.1.0/Serialization.podspec", "Specs/Serialization/27.2.0/Serialization.podspec":"divkit/public-ios/Specs/Serialization/27.2.0/Serialization.podspec", - "Specs/Serialization/27.3.0/Serialization.podspec":"divkit/public-ios/Specs/Serialization/27.3.0/Serialization.podspec" + "Specs/Serialization/27.3.0/Serialization.podspec":"divkit/public-ios/Specs/Serialization/27.3.0/Serialization.podspec", + "Specs/Serialization/27.4.0/Serialization.podspec":"divkit/public-ios/Specs/Serialization/27.4.0/Serialization.podspec" } \ No newline at end of file diff --git a/Core/NetworkingPublic/ImageHolderFactory.swift b/Core/NetworkingPublic/ImageHolderFactory.swift index 43742e98..aa020d00 100644 --- a/Core/NetworkingPublic/ImageHolderFactory.swift +++ b/Core/NetworkingPublic/ImageHolderFactory.swift @@ -22,7 +22,8 @@ public struct ImageHolderFactory { public init( requester: URLResourceRequesting, localImageProvider: LocalImageProviding? = nil, - imageProcessingQueue: OperationQueueType + imageProcessingQueue: OperationQueueType, + imageLoadingOptimizationEnabled: Bool = false ) { _make = { url, placeholder in guard let url = url else { @@ -35,7 +36,8 @@ public struct ImageHolderFactory { url: url, placeholder: placeholder, requester: requester, - imageProcessingQueue: imageProcessingQueue + imageProcessingQueue: imageProcessingQueue, + imageLoadingOptimizationEnabled: imageLoadingOptimizationEnabled ) } } diff --git a/Core/NetworkingPublic/RemoteImageHolder.swift b/Core/NetworkingPublic/RemoteImageHolder.swift index 1dec0bfc..5c348124 100644 --- a/Core/NetworkingPublic/RemoteImageHolder.swift +++ b/Core/NetworkingPublic/RemoteImageHolder.swift @@ -30,7 +30,8 @@ public final class RemoteImageHolder: ImageHolder { url: URL, placeholder: ImagePlaceholder? = nil, requester: URLResourceRequesting, - imageProcessingQueue: OperationQueueType + imageProcessingQueue: OperationQueueType, + imageLoadingOptimizationEnabled: Bool = false ) { weak var weakSelf: RemoteImageHolder? let shouldCallCompletionWithNil = placeholder == nil @@ -55,7 +56,12 @@ public final class RemoteImageHolder: ImageHolder { case .gif: image = Image.animatedImage(with: value.data as CFData) case .jpeg, .png, .tiff, .unknown: - image = Image(data: value.data, scale: PlatformDescription.screenScale()) + if imageLoadingOptimizationEnabled, + let decodedImage = makeDecodedImage(data: value.data) { + image = decodedImage + } else { + image = Image(data: value.data, scale: PlatformDescription.screenScale()) + } } #else image = Image(data: value.data, scale: PlatformDescription.screenScale()) @@ -121,6 +127,30 @@ public final class RemoteImageHolder: ImageHolder { } } +#if os(iOS) +import ImageIO + +private func makeDecodedImage(data: Data) -> Image? { + let imageSourceOptions = [kCGImageSourceShouldCache: false] as CFDictionary + guard let imageSource = CGImageSourceCreateWithData(data as CFData, imageSourceOptions) else { + return nil + } + + let imageOptions = [kCGImageSourceShouldCacheImmediately: true] as CFDictionary + let index: Int + if #available(iOS 12.0, *) { + index = CGImageSourceGetPrimaryImageIndex(imageSource) + } else { + index = 0 + } + guard let image = CGImageSourceCreateImageAtIndex(imageSource, index, imageOptions) else { + return nil + } + + return Image(cgImage: image) +} +#endif + extension RemoteImageHolder: CustomDebugStringConvertible { public var debugDescription: String { "URL = \(dbgStr(url)), placeholder = \(dbgStr(placeholder?.debugDescription))" @@ -132,4 +162,3 @@ extension RemoteImageHolder { (self.placeholder === placeholder && url == remoteImageURL) ? self : nil } } - diff --git a/DivKit/Debug/ErrorListView.swift b/DivKit/Debug/ErrorListView.swift index 33fe0f3e..a57a94e1 100644 --- a/DivKit/Debug/ErrorListView.swift +++ b/DivKit/Debug/ErrorListView.swift @@ -9,8 +9,8 @@ final class ErrorListView: UIView { private let errorString: String init(errors: [String]) { - errorString = errors.joined(separator: "\n") - let block = makeErrorBlock(errorsString: errorString, errorsCount: errors.count) + errorString = errors.joined(separator: "\n\n") + let block = makeErrorBlock(errors: errors) self.errorView = block.makeBlockView() let blockFrame = CGRect(origin: .zero, size: block.intrinsicSize) super.init(frame: blockFrame) @@ -46,14 +46,14 @@ extension ErrorListView: UIActionEventPerforming { } } -private func makeErrorBlock(errorsString: String, errorsCount: Int) -> Block { +private func makeErrorBlock(errors: [String]) -> Block { try! ContainerBlock( layoutDirection: .vertical, widthTrait: .intrinsic, heightTrait: .intrinsic, children: [ - .init(content: makeHeaderBlock(errorsCount: errorsCount)), - .init(content: makeErrorListBlock(errorString: errorsString)), + .init(content: makeHeaderBlock(errorsCount: errors.count)), + .init(content: makeErrorListBlock(errors: errors)), ] ).addingHorizontalGaps(15) .addingVerticalGaps(top: 0, bottom: 15) @@ -124,18 +124,20 @@ private func makeHeaderBlock(errorsCount: Int) -> Block { ) } -private func makeErrorListBlock(errorString: String) -> Block { - let textBlock = TextBlock( - widthTrait: .intrinsic(constrained: true, minSize: 0, maxSize: 350), - heightTrait: .intrinsic, - text: errorString.with(typo: errorsTypo), - verticalAlignment: .leading, - minNumberOfHiddenLines: 0 - ) +private func makeErrorListBlock(errors: [String]) -> Block { + let errorBlocks = errors.map { + TextBlock( + widthTrait: .intrinsic(constrained: true, minSize: 0, maxSize: 350), + heightTrait: .intrinsic, + text: $0.with(typo: errorsTypo), + verticalAlignment: .leading, + minNumberOfHiddenLines: 0 + ) + } return try! GalleryBlock( - gaps: [.zero, .zero], - children: [textBlock], + gaps: [0] + Array.init(repeating: 10, count: errorBlocks.count), + children: errorBlocks, path: rootPath, direction: .vertical, crossAlignment: .leading, diff --git a/DivKit/DivBlockModelingContext.swift b/DivKit/DivBlockModelingContext.swift index 7f55233e..6a11f952 100644 --- a/DivKit/DivBlockModelingContext.swift +++ b/DivKit/DivBlockModelingContext.swift @@ -2,6 +2,7 @@ import CoreGraphics import BasePublic import BaseUIPublic +import CommonCorePublic import LayoutKit import NetworkingPublic import Serialization @@ -38,6 +39,7 @@ public struct DivBlockModelingContext { public let errorsStorage: DivErrorsStorage internal let variableTracker: DivVariableTracker? private let persistentValuesStorage: DivPersistentValuesStorage + public let tooltipViewFactory: DivTooltipViewFactory? var overridenWidth: DivOverridenSize? var overridenHeight: DivOverridenSize? @@ -80,7 +82,8 @@ public struct DivBlockModelingContext { errorsStorage: DivErrorsStorage = DivErrorsStorage(errors: []), layoutDirection: UserInterfaceLayoutDirection = .leftToRight, variableTracker: DivVariableTracker? = nil, - persistentValuesStorage: DivPersistentValuesStorage = DivPersistentValuesStorage() + persistentValuesStorage: DivPersistentValuesStorage = DivPersistentValuesStorage(), + tooltipViewFactory: DivTooltipViewFactory? = nil ) { self.cardId = cardId self.cardLogId = cardLogId @@ -105,6 +108,7 @@ public struct DivBlockModelingContext { self.layoutDirection = layoutDirection self.variableTracker = variableTracker self.persistentValuesStorage = persistentValuesStorage + self.tooltipViewFactory = tooltipViewFactory var extensionsHandlersDictionary = [String: DivExtensionHandler]() extensionHandlers.forEach { diff --git a/DivKit/DivBlockProvider.swift b/DivKit/DivBlockProvider.swift index 61473d3a..77b7e2bb 100644 --- a/DivKit/DivBlockProvider.swift +++ b/DivKit/DivBlockProvider.swift @@ -123,13 +123,14 @@ public final class DivBlockProvider { debugParams: debugParams, parentScrollView: parentScrollView ) + dataErrors.forEach { context.errorsStorage.add($0) } do { block = try measurements.renderTime.updateMeasure { try divData.makeBlock( context: context ) } - let errors: [DivError] = dataErrors + context.errorsStorage.errors + let errors = context.errorsStorage.errors debugParams.processMeasurements((cardId: cardId, measurements: measurements)) debugParams.processErrors((cardId: cardId, errors: errors)) } catch { @@ -195,9 +196,9 @@ public final class DivBlockProvider { ) -> Block { guard debugParams.isDebugInfoEnabled else { return noDataBlock } - var errors: [DivError] = dataErrors + var errors: [DivError] = [] errors.append(error as DivError) - errors.append(contentsOf: context?.errorsStorage.errors ?? []) + errors.append(contentsOf: context?.errorsStorage.errors ?? dataErrors) DivKitLogger.error("\(message). Error: \(error).") debugParams.processErrors((cardId: cardId, errors: errors)) return makeErrorsBlock(errors.map(errorMessage(_:))) diff --git a/DivKit/DivFlagsInfo.swift b/DivKit/DivFlagsInfo.swift index 68b36f3f..93d20e64 100644 --- a/DivKit/DivFlagsInfo.swift +++ b/DivKit/DivFlagsInfo.swift @@ -6,9 +6,13 @@ /// included in the framework. /// You can access the default `DivFlagsInfo` instance using the static property `default`. public struct DivFlagsInfo { + /// Enable experimental image loading optimization + public let imageLoadingOptimizationEnabled: Bool /// Creates an instance of `DivFlagsInfo`. - public init() {} + public init(imageLoadingOptimizationEnabled: Bool) { + self.imageLoadingOptimizationEnabled = imageLoadingOptimizationEnabled + } /// The default instance of `DivFlagsInfo`. - public static let `default` = DivFlagsInfo() + public static let `default` = DivFlagsInfo(imageLoadingOptimizationEnabled: false) } diff --git a/DivKit/DivKitComponents.swift b/DivKit/DivKitComponents.swift index c6da3598..5b21b109 100644 --- a/DivKit/DivKitComponents.swift +++ b/DivKit/DivKitComponents.swift @@ -129,7 +129,10 @@ public final class DivKitComponents { let requestPerformer = requestPerformer ?? URLRequestPerformer(urlTransform: nil) self.imageHolderFactory = imageHolderFactory - ?? makeImageHolderFactory(requestPerformer: requestPerformer) + ?? makeImageHolderFactory( + requestPerformer: requestPerformer, + imageLoadingOptimizationEnabled: flagsInfo.imageLoadingOptimizationEnabled + ) self.patchProvider = patchProvider ?? DivPatchDownloader(requestPerformer: requestPerformer) @@ -278,7 +281,8 @@ public final class DivKitComponents { parentScrollView: parentScrollView, layoutDirection: layoutDirection, variableTracker: variableTracker, - persistentValuesStorage: persistentValuesStorage + persistentValuesStorage: persistentValuesStorage, + tooltipViewFactory: makeTooltipViewFactory(divKitComponents: self, cardId: cardId) ) } @@ -315,7 +319,10 @@ public final class DivKitComponents { } } -func makeImageHolderFactory(requestPerformer: URLRequestPerforming) -> ImageHolderFactory { +func makeImageHolderFactory( + requestPerformer: URLRequestPerforming, + imageLoadingOptimizationEnabled: Bool = false +) -> ImageHolderFactory { ImageHolderFactory( requester: NetworkURLResourceRequester( performer: requestPerformer @@ -323,7 +330,8 @@ func makeImageHolderFactory(requestPerformer: URLRequestPerforming) -> ImageHold imageProcessingQueue: OperationQueue( name: "tech.divkit.image-processing", qos: .userInitiated - ) + ), + imageLoadingOptimizationEnabled: imageLoadingOptimizationEnabled ) } diff --git a/DivKit/DivKitInfo.swift b/DivKit/DivKitInfo.swift index 9f844590..d963db2e 100644 --- a/DivKit/DivKitInfo.swift +++ b/DivKit/DivKitInfo.swift @@ -1,3 +1,3 @@ public enum DivKitInfo { - public static let version = "27.3.0" + public static let version = "27.4.0" } diff --git a/DivKit/DivKitLogger.swift b/DivKit/DivKitLogger.swift index 7b866c22..31d1812a 100644 --- a/DivKit/DivKitLogger.swift +++ b/DivKit/DivKitLogger.swift @@ -1,6 +1,6 @@ import Foundation -private var externalLogger: (DivErrorLevel, String) -> Void = { _,_ in } +private var externalLogger: (DivErrorLevel, String) -> Void = { _, _ in } public enum DivKitLogger { public static var isEnabled: Bool = false diff --git a/DivKit/Expressions/ExpressionResolver.swift b/DivKit/Expressions/ExpressionResolver.swift index 93368cb0..25680fe6 100644 --- a/DivKit/Expressions/ExpressionResolver.swift +++ b/DivKit/Expressions/ExpressionResolver.swift @@ -253,7 +253,8 @@ public final class ExpressionResolver { private lazy var supportedFunctions: [ AnyCalcExpression.Symbol: AnyCalcExpression.SymbolEvaluator ] = lock.withLock { - _supportedFunctions + ValueFunctions.allCases.map { $0.getDeclaration(resolver: self) }.flat() + ValueFunctions.allCases.map { $0.getDeclaration(resolver: self) } + .reduce(into: _supportedFunctions) { $0[$1.0] = $1.1 } } } @@ -277,4 +278,3 @@ extension Array where Element == [AnyCalcExpression.Symbol: AnyCalcExpression.Sy reduce([:], +) } } - diff --git a/DivKit/Expressions/Functions/ValueFunctions.swift b/DivKit/Expressions/Functions/ValueFunctions.swift index 2f4ab2b4..220338e5 100644 --- a/DivKit/Expressions/Functions/ValueFunctions.swift +++ b/DivKit/Expressions/Functions/ValueFunctions.swift @@ -20,14 +20,14 @@ enum ValueFunctions: String, CaseIterable { case getStoredBooleanValue func getDeclaration(resolver: ExpressionResolver) - -> [AnyCalcExpression.Symbol: AnyCalcExpression.SymbolEvaluator] { - [ + -> (AnyCalcExpression.Symbol, AnyCalcExpression.SymbolEvaluator) { + let function = getFunction(resolver: resolver) + return ( .function( rawValue, - arity: getFunction(resolver: resolver).arity - ): getFunction(resolver: resolver) - .symbolEvaluator, - ] + arity: function.arity + ), function.symbolEvaluator + ) } func getFunction(resolver: ExpressionResolver) -> Function { @@ -153,7 +153,7 @@ extension ExpressionResolver { } } - fileprivate func getStoredValueFunctionWithTransform( + fileprivate func getStoredValueFunctionWithTransform( transform: @escaping (U) throws -> T ) -> GetOrDefaultWithTransform { { name, fallbackValue in diff --git a/DivKit/Extensions/DivBase/DivBaseExtensions.swift b/DivKit/Extensions/DivBase/DivBaseExtensions.swift index b9424d02..2870d8ef 100644 --- a/DivKit/Extensions/DivBase/DivBaseExtensions.swift +++ b/DivKit/Extensions/DivBase/DivBaseExtensions.swift @@ -84,7 +84,7 @@ extension DivBase { } ), scheduler: context.scheduler, - tooltips: try makeTooltips(context: context) + tooltips: try tooltips.makeTooltips(context: context) ) .addingTransform( transform: transform.resolveRotation(expressionResolver) @@ -178,15 +178,6 @@ extension DivBase { return nil } - private func makeTooltips(context: DivBlockModelingContext) throws -> [BlockTooltip] { - try tooltips?.iterativeFlatMap { div, index in - let tooltipContext = modified(context) { - $0.parentPath = $0.parentPath + "tooltip" + index - } - return try div.makeTooltip(context: tooltipContext) - } ?? [] - } - private func applyTransitioningAnimations( to block: Block, context: DivBlockModelingContext, @@ -368,45 +359,3 @@ extension DivBorder { ) } } - -extension DivTooltip { - fileprivate func makeTooltip(context: DivBlockModelingContext) throws - -> BlockTooltip? { - let expressionResolver = context.expressionResolver - guard let position = resolvePosition(expressionResolver)?.cast() else { - return nil - } - let block = try div.value.makeBlock(context: context) - return BlockTooltip( - id: id, - block: block, - duration: Duration(milliseconds: resolveDuration(expressionResolver)), - offset: offset?.cast(with: expressionResolver) ?? .zero, - position: position - ) - } -} - -extension DivTooltip.Position { - fileprivate func cast() -> BlockTooltip.Position { - switch self { - case .left: return .left - case .topLeft: return .topLeft - case .top: return .top - case .topRight: return .topRight - case .right: return .right - case .bottomRight: return .bottomRight - case .bottom: return .bottom - case .bottomLeft: return .bottomLeft - } - } -} - -extension DivPoint { - fileprivate func cast(with expressionResolver: ExpressionResolver) -> CGPoint { - CGPoint( - x: x.resolveUnit(expressionResolver).makeScaledValue(x.resolveValue(expressionResolver) ?? 0), - y: y.resolveUnit(expressionResolver).makeScaledValue(y.resolveValue(expressionResolver) ?? 0) - ) - } -} diff --git a/DivKit/Extensions/DivInputExtensions.swift b/DivKit/Extensions/DivInputExtensions.swift index 7eaecfec..f4b476ba 100644 --- a/DivKit/Extensions/DivInputExtensions.swift +++ b/DivKit/Extensions/DivInputExtensions.swift @@ -37,8 +37,8 @@ extension DivInput: DivBlockModeling { if let lineHeightInt = resolveLineHeight(expressionResolver) { let lineHeight = CGFloat(lineHeightInt) typo = typo.with(height: lineHeight) - if lineHeight > font.lineHeight { - typo = typo.with(baseline: (lineHeight - font.lineHeight) / 2) + if lineHeight > font.defaultLineHeight() { + typo = typo.with(baseline: (lineHeight - font.defaultLineHeight()) / 2) } } diff --git a/DivKit/Extensions/DivPointExtensions.swift b/DivKit/Extensions/DivPointExtensions.swift new file mode 100644 index 00000000..7621572b --- /dev/null +++ b/DivKit/Extensions/DivPointExtensions.swift @@ -0,0 +1,10 @@ +import Foundation + +extension DivPoint { + internal func cast(with expressionResolver: ExpressionResolver) -> CGPoint { + CGPoint( + x: x.resolveUnit(expressionResolver).makeScaledValue(x.resolveValue(expressionResolver) ?? 0), + y: y.resolveUnit(expressionResolver).makeScaledValue(y.resolveValue(expressionResolver) ?? 0) + ) + } +} diff --git a/DivKit/Extensions/DivTooltipExtensions.swift b/DivKit/Extensions/DivTooltipExtensions.swift new file mode 100644 index 00000000..04734308 --- /dev/null +++ b/DivKit/Extensions/DivTooltipExtensions.swift @@ -0,0 +1,89 @@ +import BasePublic +import CommonCorePublic +import Foundation +import LayoutKit + +#if os(iOS) +public typealias DivTooltipViewFactory = (Div) -> VisibleBoundsTrackingView +#else +public typealias DivTooltipViewFactory = (Div) -> ViewType +#endif + +extension DivTooltip { + fileprivate func makeTooltip(context: DivBlockModelingContext) throws + -> BlockTooltip? { + let expressionResolver = context.expressionResolver + guard let position = resolvePosition(expressionResolver)?.cast() else { + return nil + } + + let block = try div.value.makeBlock(context: context) + + let tooltipViewFactory: TooltipViewFactory = + Variable { [tooltipViewFactory = context.tooltipViewFactory, div = self.div] in + guard let tooltipViewFactory = tooltipViewFactory else { return nil } + return tooltipViewFactory(div) + } + + return BlockTooltip( + id: id, + block: block, + duration: Duration(milliseconds: resolveDuration(expressionResolver)), + offset: offset?.cast(with: expressionResolver) ?? .zero, + position: position, + tooltipViewFactory: tooltipViewFactory + ) + } +} + +extension DivTooltip.Position { + fileprivate func cast() -> BlockTooltip.Position { + switch self { + case .left: return .left + case .topLeft: return .topLeft + case .top: return .top + case .topRight: return .topRight + case .right: return .right + case .bottomRight: return .bottomRight + case .bottom: return .bottom + case .bottomLeft: return .bottomLeft + case .center: return .center + } + } +} + +extension Optional where Wrapped == [DivTooltip] { + func makeTooltips( + context: DivBlockModelingContext + ) throws -> [BlockTooltip] { + try self?.iterativeFlatMap { div, index in + let tooltipContext = modified(context) { + $0.parentPath = $0.parentPath + "tooltip" + index + } + return try div.makeTooltip(context: tooltipContext) + } ?? [] + } +} + +public func makeTooltipViewFactory( + divKitComponents: DivKitComponents, + cardId: DivCardID +) -> DivTooltipViewFactory? { + #if os(iOS) + return { (div: Div) in + let view = DivView(divKitComponents: divKitComponents) + let divData = DivData( + logId: cardId.rawValue, + states: [.init(div: div, stateId: 0)], + timers: nil, + transitionAnimationSelector: nil, + variableTriggers: nil, + variables: nil + ) + view.setSource(.init(kind: .divData(divData), cardId: cardId)) + return view + } + #else + return nil + #endif +} diff --git a/DivKit/generated_sources/DivTooltip.swift b/DivKit/generated_sources/DivTooltip.swift index 9d0ce259..a0deac97 100644 --- a/DivKit/generated_sources/DivTooltip.swift +++ b/DivKit/generated_sources/DivTooltip.swift @@ -7,14 +7,15 @@ import Serialization public final class DivTooltip { @frozen public enum Position: String, CaseIterable { - case left = "left" + case left case topLeft = "top-left" - case top = "top" + case top case topRight = "top-right" - case right = "right" + case right case bottomRight = "bottom-right" - case bottom = "bottom" + case bottom case bottomLeft = "bottom-left" + case center } public let animationIn: DivAnimation? diff --git a/DivKitExtensions/ExtensionHandlers/CustomImagePreviewExtensionHandler.swift b/DivKitExtensions/ExtensionHandlers/CustomImagePreviewExtensionHandler.swift index 4f4e41e5..0ac4a4c5 100644 --- a/DivKitExtensions/ExtensionHandlers/CustomImagePreviewExtensionHandler.swift +++ b/DivKitExtensions/ExtensionHandlers/CustomImagePreviewExtensionHandler.swift @@ -34,4 +34,3 @@ public final class CustomImagePreviewExtensionHandler: DivExtensionHandler { } private let defaultImageURL = URL(string: "empty://") - diff --git a/DivKitExtensions/Shimmer/DefaultShimmerViewFactory.swift b/DivKitExtensions/Shimmer/DefaultShimmerViewFactory.swift index e290122d..8afdf5c9 100644 --- a/DivKitExtensions/Shimmer/DefaultShimmerViewFactory.swift +++ b/DivKitExtensions/Shimmer/DefaultShimmerViewFactory.swift @@ -2,11 +2,11 @@ import UIKit public class DefaultShimmerViewFactory { private let effectBeginTime: CFTimeInterval - + public init(effectBeginTime: CFTimeInterval = CACurrentMediaTime()) { self.effectBeginTime = effectBeginTime } - + public func makeView(style: ShimmerStyle) -> UIView { return ShimmerView(style: style, effectBeginTime: effectBeginTime) } diff --git a/DivKitExtensions/Shimmer/ShimmerImagePreviewExtensions.swift b/DivKitExtensions/Shimmer/ShimmerImagePreviewExtensions.swift index 2de19ee1..cb4f4ad1 100644 --- a/DivKitExtensions/Shimmer/ShimmerImagePreviewExtensions.swift +++ b/DivKitExtensions/Shimmer/ShimmerImagePreviewExtensions.swift @@ -24,7 +24,7 @@ public final class ShimmerImagePreviewExtension: DivExtensionHandler { else { return block } - + let expressionResolver = context.expressionResolver let imageURL = div.resolveImageUrl(expressionResolver) let view = viewFactory(div.getShimmerStyle(expressionResolver: expressionResolver) ?? .default) diff --git a/DivKitExtensions/Shimmer/ShimmerStyle.swift b/DivKitExtensions/Shimmer/ShimmerStyle.swift index c659332d..530ff88d 100644 --- a/DivKitExtensions/Shimmer/ShimmerStyle.swift +++ b/DivKitExtensions/Shimmer/ShimmerStyle.swift @@ -9,7 +9,7 @@ public struct ShimmerStyle { public let colorsAndLocations: [(Color, CGFloat)] public let angle: CGFloat public let duration: CGFloat - + public init(colorsAndLocations: [(Color, CGFloat)], angle: CGFloat, duration: CGFloat) { self.colorsAndLocations = colorsAndLocations self.angle = angle @@ -90,7 +90,7 @@ extension Dictionary where Key == String { return expression.flatMap(fromExpression) } } - + fileprivate func getOptionalArrayElementsAsExpression( _ key: Key, fromExpression: (String) -> T? diff --git a/DivKitExtensions/SizeProvider/SizeProviderBlock+UIViewRenderable.swift b/DivKitExtensions/SizeProvider/SizeProviderBlock+UIViewRenderable.swift index 1bc72c12..ad6daa49 100644 --- a/DivKitExtensions/SizeProvider/SizeProviderBlock+UIViewRenderable.swift +++ b/DivKitExtensions/SizeProvider/SizeProviderBlock+UIViewRenderable.swift @@ -34,12 +34,12 @@ private final class SizeProviderBlockView: BlockView { init() { super.init(frame: .zero) } - + @available(*, unavailable) required init?(coder _: NSCoder) { fatalError("init(coder:) has not been implemented") } - + var effectiveBackgroundColor: UIColor? { childView.backgroundColor } func configure( @@ -58,7 +58,7 @@ private final class SizeProviderBlockView: BlockView { ) setNeedsLayout() } - + override func layoutSubviews() { super.layoutSubviews() childView.frame = bounds diff --git a/DivKitExtensions/SizeProvider/SizeProviderBlock.swift b/DivKitExtensions/SizeProvider/SizeProviderBlock.swift index 7254217b..5405b34e 100644 --- a/DivKitExtensions/SizeProvider/SizeProviderBlock.swift +++ b/DivKitExtensions/SizeProvider/SizeProviderBlock.swift @@ -7,7 +7,7 @@ final class SizeProviderBlock: WrapperBlock, LayoutCachingDefaultImpl { public let child: Block let widthUpdater: ValueUpdater? let heightUpdater: ValueUpdater? - + public init( child: Block, widthUpdater: ValueUpdater?, diff --git a/DivKitExtensions/SizeProvider/SizeProviderExtensionHandler.swift b/DivKitExtensions/SizeProvider/SizeProviderExtensionHandler.swift index 2b30ff6e..0b9f98df 100644 --- a/DivKitExtensions/SizeProvider/SizeProviderExtensionHandler.swift +++ b/DivKitExtensions/SizeProvider/SizeProviderExtensionHandler.swift @@ -5,17 +5,17 @@ import Serialization public final class SizeProviderExtensionHandler: DivExtensionHandler { public let id = "size_provider" - + private let variablesStorage: DivVariablesStorage private let autodisposePool = AutodisposePool() // Stores variables that has been updated during the layout cycle to prevent relayout. // onCardUpdated() must be called when the card is updated and new layout cycle begins. private var updatedVariables: Set = [] - + public init(variablesStorage: DivVariablesStorage) { self.variablesStorage = variablesStorage - + variablesStorage.changeEvents.addObserver { [weak self] event in let variableNames: Set switch event.kind { @@ -31,7 +31,7 @@ public final class SizeProviderExtensionHandler: DivExtensionHandler { } }.dispose(in: autodisposePool) } - + public func applyAfterBaseProperties( to block: Block, div: DivBase, @@ -51,7 +51,7 @@ public final class SizeProviderExtensionHandler: DivExtensionHandler { heightUpdater: makeValueUpdater(context: context, variableName: heightVariableName) ) } - + public func onCardUpdated(reasons: [DivActionURLHandler.UpdateReason]) { let hasNotVariableReason = reasons.isEmpty || reasons.contains { switch $0 { @@ -65,7 +65,7 @@ public final class SizeProviderExtensionHandler: DivExtensionHandler { updatedVariables = [] } } - + private func update( cardId: DivCardID, variableName: DivVariableName, @@ -75,12 +75,12 @@ public final class SizeProviderExtensionHandler: DivExtensionHandler { if (value == previousValue) { return } - + if updatedVariables.contains(variableName) { DivKitLogger.warning("[SizeProviderExtensionHandler] Variable '\(variableName)' was already updated during the layout cycle.") return } - + updatedVariables.insert(variableName) variablesStorage.update( diff --git a/LayoutKit/LayoutKit/Blocks/BlockTooltip+Layout.swift b/LayoutKit/LayoutKit/Blocks/BlockTooltip+Layout.swift index 22756799..d46a5132 100644 --- a/LayoutKit/LayoutKit/Blocks/BlockTooltip+Layout.swift +++ b/LayoutKit/LayoutKit/Blocks/BlockTooltip+Layout.swift @@ -23,6 +23,7 @@ extension CGRect { case .bottomRight: return coordinate(ofCorner: .bottomRight) case .bottom: return CGPoint(x: midX, y: maxY) case .bottomLeft: return coordinate(ofCorner: .bottomLeft) + case .center: return CGPoint(x: midX, y: midY) } } } @@ -38,6 +39,7 @@ extension BlockTooltip.Position { case .bottomRight: return .topLeft case .bottom: return .top case .bottomLeft: return .topRight + case .center: return .center } } } @@ -66,6 +68,8 @@ extension CGRect { origin = coordinate.movingX(by: -0.5 * size.width).movingY(by: -size.height) case .bottomLeft: origin = coordinate.movingY(by: -size.height) + case .center: + origin = coordinate.movingX(by: -0.5 * size.width).movingY(by: -size.height / 2) } self.init(origin: origin, size: size) } diff --git a/LayoutKit/LayoutKit/Blocks/BlockTooltip.swift b/LayoutKit/LayoutKit/Blocks/BlockTooltip.swift index 136750f3..60c02c6c 100644 --- a/LayoutKit/LayoutKit/Blocks/BlockTooltip.swift +++ b/LayoutKit/LayoutKit/Blocks/BlockTooltip.swift @@ -1,6 +1,11 @@ +import CommonCorePublic import CoreGraphics -import CommonCorePublic +#if os(iOS) +public typealias TooltipViewFactory = Variable +#else +public typealias TooltipViewFactory = Variable +#endif public struct BlockTooltip: Equatable { public enum Position: String, CaseIterable { @@ -12,6 +17,7 @@ public struct BlockTooltip: Equatable { case bottomRight case bottom case bottomLeft + case center } public let id: String @@ -19,19 +25,22 @@ public struct BlockTooltip: Equatable { public let duration: Duration public let offset: CGPoint public let position: Position + public let tooltipViewFactory: TooltipViewFactory? public init( id: String, block: Block, duration: Duration, offset: CGPoint, - position: BlockTooltip.Position + position: BlockTooltip.Position, + tooltipViewFactory: TooltipViewFactory? = nil ) { self.id = id self.block = block self.duration = duration self.offset = offset self.position = position + self.tooltipViewFactory = tooltipViewFactory } public static func ==(lhs: BlockTooltip, rhs: BlockTooltip) -> Bool { diff --git a/LayoutKit/LayoutKit/Tooltips/TooltipFactory.swift b/LayoutKit/LayoutKit/Tooltips/TooltipFactory.swift index 17ebc910..f8a523bf 100644 --- a/LayoutKit/LayoutKit/Tooltips/TooltipFactory.swift +++ b/LayoutKit/LayoutKit/Tooltips/TooltipFactory.swift @@ -66,6 +66,11 @@ extension BlockTooltip.Position { cornerTailSize, drawingHandler: { drawCornerTail(style: .topRight, color: color, context: $0) } ) + case .center: + imageHolder = Image.imageOfSize( + cornerTailSize, + drawingHandler: { _ in } + ) } return ImageBlock(imageHolder: imageHolder!) } @@ -130,6 +135,13 @@ extension BlockTooltip.Position { makeTail(color: theme.backgroundColor), ] ) + case .center: + return try! ContainerBlock( + layoutDirection: .vertical, + horizontalChildrenAlignment: .center, + gaps: [0, -1, 0], + children: [makeTail(color: theme.backgroundColor), child] + ) } } } diff --git a/LayoutKit/LayoutKit/Tooltips/TooltipManager.swift b/LayoutKit/LayoutKit/Tooltips/TooltipManager.swift index e8b8a360..3c41b816 100644 --- a/LayoutKit/LayoutKit/Tooltips/TooltipManager.swift +++ b/LayoutKit/LayoutKit/Tooltips/TooltipManager.swift @@ -129,7 +129,11 @@ extension TooltipAnchorView { id: tooltip.id, duration: tooltip.duration, view: { - let tooltipView = tooltip.block.makeBlockView() + var tooltipView: VisibleBoundsTrackingView = tooltip.block.makeBlockView() + if let tooltipViewFactory = tooltip.tooltipViewFactory, + let view = tooltipViewFactory.value { + tooltipView = view + } let frame = tooltip.calculateFrame(targeting: bounds) tooltipView.frame = convert(frame, to: nil) return tooltipView diff --git a/LayoutKit/LayoutKit/UI/Blocks/TextFieldBlock+UIViewRenderableBlock.swift b/LayoutKit/LayoutKit/UI/Blocks/TextFieldBlock+UIViewRenderableBlock.swift index 6e71d804..37559c42 100644 --- a/LayoutKit/LayoutKit/UI/Blocks/TextFieldBlock+UIViewRenderableBlock.swift +++ b/LayoutKit/LayoutKit/UI/Blocks/TextFieldBlock+UIViewRenderableBlock.swift @@ -134,9 +134,9 @@ private final class TextFieldBlockView: BlockView, VisibleBoundsTrackingLeaf { _ = self?.textField.resignFirstResponder() } } - guard textField.window != nil else { + guard textField.window != nil else { self.postponedUpdateOfInteraction = setFirstResponder - break + break } setFirstResponder() case .disabled: diff --git a/Package.swift b/Package.swift index 8f89178a..cd4e4c4b 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:5.5 +// swift-tools-version:5.7 import PackageDescription diff --git a/Specs/BasePublic/27.4.0/BasePublic.podspec b/Specs/BasePublic/27.4.0/BasePublic.podspec new file mode 100644 index 00000000..f5613c8a --- /dev/null +++ b/Specs/BasePublic/27.4.0/BasePublic.podspec @@ -0,0 +1,23 @@ +Pod::Spec.new do |s| + s.name = 'BasePublic' + s.version = '27.4.0' + s.summary = 'Part of DivKit framework' + s.description = 'Part of DivKit framework' + s.homepage = 'https://divkit.tech' + + s.license = { :type => 'MIT', :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 'BaseTinyPublic', s.version.to_s + s.dependency 'BaseUIPublic', s.version.to_s + + s.source_files = [ + 'Core/BasePublic/**/*' + ] +end diff --git a/Specs/BaseTinyPublic/27.4.0/BaseTinyPublic.podspec b/Specs/BaseTinyPublic/27.4.0/BaseTinyPublic.podspec new file mode 100644 index 00000000..c65ab9bc --- /dev/null +++ b/Specs/BaseTinyPublic/27.4.0/BaseTinyPublic.podspec @@ -0,0 +1,20 @@ +Pod::Spec.new do |s| + s.name = 'BaseTinyPublic' + s.version = '27.4.0' + s.summary = 'Part of DivKit framework' + s.description = 'Part of DivKit framework' + s.homepage = 'https://divkit.tech' + + s.license = { :type => 'MIT', :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.source_files = [ + 'Core/BaseTinyPublic/**/*' + ] +end diff --git a/Specs/BaseUIPublic/27.4.0/BaseUIPublic.podspec b/Specs/BaseUIPublic/27.4.0/BaseUIPublic.podspec new file mode 100644 index 00000000..b6a34fe1 --- /dev/null +++ b/Specs/BaseUIPublic/27.4.0/BaseUIPublic.podspec @@ -0,0 +1,22 @@ +Pod::Spec.new do |s| + s.name = 'BaseUIPublic' + s.version = '27.4.0' + s.summary = 'Part of DivKit framework' + s.description = 'Part of DivKit framework' + s.homepage = 'https://divkit.tech' + + s.license = { :type => 'MIT', :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 'BaseTinyPublic', s.version.to_s + + s.source_files = [ + 'Core/BaseUIPublic/**/*' + ] +end diff --git a/Specs/CommonCorePublic/27.4.0/CommonCorePublic.podspec b/Specs/CommonCorePublic/27.4.0/CommonCorePublic.podspec new file mode 100644 index 00000000..cfb6de1a --- /dev/null +++ b/Specs/CommonCorePublic/27.4.0/CommonCorePublic.podspec @@ -0,0 +1,22 @@ +Pod::Spec.new do |s| + s.name = 'CommonCorePublic' + s.version = '27.4.0' + s.summary = 'Part of DivKit framework' + s.description = 'Part of DivKit framework' + s.homepage = 'https://divkit.tech' + + s.license = { :type => 'MIT', :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 'BasePublic', s.version.to_s + + s.source_files = [ + 'Core/CommonCorePublic/**/*' + ] +end diff --git a/Specs/DivKit/27.4.0/DivKit.podspec b/Specs/DivKit/27.4.0/DivKit.podspec new file mode 100644 index 00000000..14495d1c --- /dev/null +++ b/Specs/DivKit/27.4.0/DivKit.podspec @@ -0,0 +1,25 @@ +Pod::Spec.new do |s| + s.name = 'DivKit' + s.version = '27.4.0' + s.summary = 'DivKit framework' + s.description = 'DivKit is a backend-driven UI framework' + s.homepage = 'https://divkit.tech' + + s.license = { :type => 'MIT', :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 'CommonCorePublic', s.version.to_s + s.dependency 'LayoutKit', s.version.to_s + s.dependency 'NetworkingPublic', s.version.to_s + s.dependency 'Serialization', s.version.to_s + + s.source_files = [ + 'DivKit/**/*' + ] +end diff --git a/Specs/DivKitExtensions/27.4.0/DivKitExtensions.podspec b/Specs/DivKitExtensions/27.4.0/DivKitExtensions.podspec new file mode 100644 index 00000000..86294dda --- /dev/null +++ b/Specs/DivKitExtensions/27.4.0/DivKitExtensions.podspec @@ -0,0 +1,22 @@ +Pod::Spec.new do |s| + s.name = 'DivKitExtensions' + s.version = '27.4.0' + s.summary = 'DivKit framework extensions' + s.description = 'Part of DivKit framework' + s.homepage = 'https://divkit.tech' + + s.license = { :type => 'MIT', :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/LayoutKit/27.4.0/LayoutKit.podspec b/Specs/LayoutKit/27.4.0/LayoutKit.podspec new file mode 100644 index 00000000..0b93372f --- /dev/null +++ b/Specs/LayoutKit/27.4.0/LayoutKit.podspec @@ -0,0 +1,23 @@ +Pod::Spec.new do |s| + s.name = 'LayoutKit' + s.version = '27.4.0' + s.summary = 'Part of DivKit framework' + s.description = 'Part of DivKit framework' + s.homepage = 'https://divkit.tech' + + s.license = { :type => 'MIT', :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 'CommonCorePublic', s.version.to_s + s.dependency 'LayoutKitInterface', s.version.to_s + + s.source_files = [ + 'LayoutKit/LayoutKit/**/*' + ] +end diff --git a/Specs/LayoutKitInterface/27.4.0/LayoutKitInterface.podspec b/Specs/LayoutKitInterface/27.4.0/LayoutKitInterface.podspec new file mode 100644 index 00000000..11e712fc --- /dev/null +++ b/Specs/LayoutKitInterface/27.4.0/LayoutKitInterface.podspec @@ -0,0 +1,24 @@ +Pod::Spec.new do |s| + s.name = 'LayoutKitInterface' + s.version = '27.4.0' + s.summary = 'Part of DivKit framework' + s.description = 'Part of DivKit framework' + s.homepage = 'https://divkit.tech' + + s.license = { :type => 'MIT', :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 'BasePublic', s.version.to_s + s.dependency 'BaseTinyPublic', s.version.to_s + s.dependency 'BaseUIPublic', s.version.to_s + + s.source_files = [ + 'LayoutKit/Interface/**/*' + ] +end diff --git a/Specs/NetworkingPublic/27.4.0/NetworkingPublic.podspec b/Specs/NetworkingPublic/27.4.0/NetworkingPublic.podspec new file mode 100644 index 00000000..a1800f66 --- /dev/null +++ b/Specs/NetworkingPublic/27.4.0/NetworkingPublic.podspec @@ -0,0 +1,22 @@ +Pod::Spec.new do |s| + s.name = 'NetworkingPublic' + s.version = '27.4.0' + s.summary = 'Part of DivKit framework' + s.description = 'Part of DivKit framework' + s.homepage = 'https://divkit.tech' + + s.license = { :type => 'MIT', :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 'BasePublic', s.version.to_s + + s.source_files = [ + 'Core/NetworkingPublic/**/*' + ] +end diff --git a/Specs/Serialization/27.4.0/Serialization.podspec b/Specs/Serialization/27.4.0/Serialization.podspec new file mode 100644 index 00000000..eeac8caf --- /dev/null +++ b/Specs/Serialization/27.4.0/Serialization.podspec @@ -0,0 +1,23 @@ +Pod::Spec.new do |s| + s.name = 'Serialization' + s.version = '27.4.0' + s.summary = 'Serialization' + s.summary = 'Part of DivKit framework' + s.description = 'Part of DivKit framework' + s.homepage = 'https://divkit.tech' + + s.license = { :type => 'MIT', :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 'CommonCorePublic', s.version.to_s + + s.source_files = [ + 'Serialization/**/*' + ] +end