diff --git a/.mapping.json b/.mapping.json index a9d0e9d6d..1d1bd713c 100644 --- a/.mapping.json +++ b/.mapping.json @@ -21162,6 +21162,7 @@ "client/ios/LayoutKit/LayoutKit/Blocks/PageControlBlock.swift":"divkit/public/client/ios/LayoutKit/LayoutKit/Blocks/PageControlBlock.swift", "client/ios/LayoutKit/LayoutKit/Blocks/PagerBlock.swift":"divkit/public/client/ios/LayoutKit/LayoutKit/Blocks/PagerBlock.swift", "client/ios/LayoutKit/LayoutKit/Blocks/PinchToZoomBlock.swift":"divkit/public/client/ios/LayoutKit/LayoutKit/Blocks/PinchToZoomBlock.swift", + "client/ios/LayoutKit/LayoutKit/Blocks/RemoteURLContaining.swift":"divkit/public/client/ios/LayoutKit/LayoutKit/Blocks/RemoteURLContaining.swift", "client/ios/LayoutKit/LayoutKit/Blocks/ResizableBlockMeasure.swift":"divkit/public/client/ios/LayoutKit/LayoutKit/Blocks/ResizableBlockMeasure.swift", "client/ios/LayoutKit/LayoutKit/Blocks/RoundedRect.swift":"divkit/public/client/ios/LayoutKit/LayoutKit/Blocks/RoundedRect.swift", "client/ios/LayoutKit/LayoutKit/Blocks/SeparatorBlock.swift":"divkit/public/client/ios/LayoutKit/LayoutKit/Blocks/SeparatorBlock.swift", diff --git a/client/ios/DivKitExtensions/Animations/Lottie/LottieAnimationBlock.swift b/client/ios/DivKitExtensions/Animations/Lottie/LottieAnimationBlock.swift index 319e0c762..0e53227d7 100644 --- a/client/ios/DivKitExtensions/Animations/Lottie/LottieAnimationBlock.swift +++ b/client/ios/DivKitExtensions/Animations/Lottie/LottieAnimationBlock.swift @@ -31,6 +31,10 @@ final class LottieAnimationBlock: SizeForwardingBlock { func getImageHolders() -> [ImageHolder] { [] } + func getRemoteURLs() -> [URL] { + (animationHolder as? RemoteAnimationHolder).map { [$0.url] } ?? [] + } + func equals(_ other: Block) -> Bool { guard let other = other as? LottieAnimationBlock else { return false diff --git a/client/ios/DivKitExtensions/Animations/Rive/RiveAnimationBlock.swift b/client/ios/DivKitExtensions/Animations/Rive/RiveAnimationBlock.swift index 4003db375..bfb4cbd3f 100644 --- a/client/ios/DivKitExtensions/Animations/Rive/RiveAnimationBlock.swift +++ b/client/ios/DivKitExtensions/Animations/Rive/RiveAnimationBlock.swift @@ -58,6 +58,10 @@ public final class RiveAnimationBlock: BlockWithTraits { } public func getImageHolders() -> [ImageHolder] { [] } + + public func getRemoteURLs() -> [URL] { + (animationHolder as? RemoteAnimationHolder).map { [$0.url] } ?? [] + } } extension RiveAnimationBlock: LayoutCachingDefaultImpl {} diff --git a/client/ios/LayoutKit/LayoutKit/Blocks/Anchor/AnchorBlock.swift b/client/ios/LayoutKit/LayoutKit/Blocks/Anchor/AnchorBlock.swift index 04f0febff..e6a768135 100644 --- a/client/ios/LayoutKit/LayoutKit/Blocks/Anchor/AnchorBlock.swift +++ b/client/ios/LayoutKit/LayoutKit/Blocks/Anchor/AnchorBlock.swift @@ -1,4 +1,5 @@ import CoreGraphics +import Foundation import VGSL public final class AnchorBlock: BlockWithLayout, BlockWithTraits { @@ -152,6 +153,10 @@ public final class AnchorBlock: BlockWithLayout, BlockWithTraits { contents.flatMap { $0.getImageHolders() } } + public func getRemoteURLs() -> [URL] { + contents.flatMap { $0.getRemoteURLs() } + } + public func updated(withStates states: BlocksState) throws -> Self { try Self( direction: direction, diff --git a/client/ios/LayoutKit/LayoutKit/Blocks/BackgroundBlock.swift b/client/ios/LayoutKit/LayoutKit/Blocks/BackgroundBlock.swift index de27486e4..cea76bef1 100644 --- a/client/ios/LayoutKit/LayoutKit/Blocks/BackgroundBlock.swift +++ b/client/ios/LayoutKit/LayoutKit/Blocks/BackgroundBlock.swift @@ -56,6 +56,10 @@ extension BackgroundBlock { public func getImageHolders() -> [ImageHolder] { child.getImageHolders() + background.getImageHolders() } + + public func getRemoteURLs() -> [URL] { + child.getRemoteURLs() + background.getRemoteURLs() + } } extension Block { diff --git a/client/ios/LayoutKit/LayoutKit/Blocks/Block.swift b/client/ios/LayoutKit/LayoutKit/Blocks/Block.swift index 8c70f49f9..5b7bcf412 100644 --- a/client/ios/LayoutKit/LayoutKit/Blocks/Block.swift +++ b/client/ios/LayoutKit/LayoutKit/Blocks/Block.swift @@ -12,6 +12,7 @@ public protocol Block: AnyObject, CustomDebugStringConvertible, BlockRenderingImpl, ImageContaining, + RemoteURLContaining, LayoutCaching, ElementStateUpdating, ElementFocusUpdating, diff --git a/client/ios/LayoutKit/LayoutKit/Blocks/Container/ContainerBlock.swift b/client/ios/LayoutKit/LayoutKit/Blocks/Container/ContainerBlock.swift index c3bc74b5b..f692b65ce 100644 --- a/client/ios/LayoutKit/LayoutKit/Blocks/Container/ContainerBlock.swift +++ b/client/ios/LayoutKit/LayoutKit/Blocks/Container/ContainerBlock.swift @@ -545,6 +545,12 @@ extension ContainerBlock: ImageContaining { } } +extension ContainerBlock: RemoteURLContaining { + public func getRemoteURLs() -> [URL] { + children.flatMap { $0.content.getRemoteURLs() } + } +} + extension ContainerBlock: ElementStateUpdating { public func updated(withStates states: BlocksState) throws -> ContainerBlock { let newChildren = try children.map { diff --git a/client/ios/LayoutKit/LayoutKit/Blocks/GalleryBlock.swift b/client/ios/LayoutKit/LayoutKit/Blocks/GalleryBlock.swift index d5aed8c0e..7949250a7 100644 --- a/client/ios/LayoutKit/LayoutKit/Blocks/GalleryBlock.swift +++ b/client/ios/LayoutKit/LayoutKit/Blocks/GalleryBlock.swift @@ -155,6 +155,12 @@ extension GalleryBlock: ImageContaining { } } +extension GalleryBlock: RemoteURLContaining { + public func getRemoteURLs() -> [URL] { + model.items.flatMap { $0.content.getRemoteURLs() } + } +} + extension GalleryBlock: ElementStateUpdating { public func updated(withStates states: BlocksState) throws -> GalleryBlock { let newBlocks = try model.items.map { try $0.content.updated(withStates: states) } diff --git a/client/ios/LayoutKit/LayoutKit/Blocks/Grid/GridBlock.swift b/client/ios/LayoutKit/LayoutKit/Blocks/Grid/GridBlock.swift index a4acb6ce7..3c3ab034b 100644 --- a/client/ios/LayoutKit/LayoutKit/Blocks/Grid/GridBlock.swift +++ b/client/ios/LayoutKit/LayoutKit/Blocks/Grid/GridBlock.swift @@ -1,4 +1,5 @@ import CoreGraphics +import Foundation import VGSL public final class GridBlock: BlockWithTraits, BlockWithLayout { @@ -142,6 +143,10 @@ public final class GridBlock: BlockWithTraits, BlockWithLayout { items.flatMap { $0.contents.getImageHolders() } } + public func getRemoteURLs() -> [URL] { + items.flatMap { $0.contents.getRemoteURLs() } + } + public func intrinsicContentHeight(forWidth width: CGFloat) -> CGFloat { if case let .fixed(value) = heightTrait { return value diff --git a/client/ios/LayoutKit/LayoutKit/Blocks/LaidOutBlock.swift b/client/ios/LayoutKit/LayoutKit/Blocks/LaidOutBlock.swift index c492bd33a..952a6170d 100644 --- a/client/ios/LayoutKit/LayoutKit/Blocks/LaidOutBlock.swift +++ b/client/ios/LayoutKit/LayoutKit/Blocks/LaidOutBlock.swift @@ -1,4 +1,5 @@ import CoreGraphics +import Foundation import VGSL final class LaidOutBlock: Block { @@ -65,6 +66,12 @@ extension LaidOutBlock: ImageContaining { } } +extension LaidOutBlock: RemoteURLContaining { + func getRemoteURLs() -> [URL] { + block.getRemoteURLs() + } +} + extension LaidOutBlock { func updated(withStates states: BlocksState) throws -> LaidOutBlock { let newBlock = try block.updated(withStates: states) diff --git a/client/ios/LayoutKit/LayoutKit/Blocks/LayeredBlock.swift b/client/ios/LayoutKit/LayoutKit/Blocks/LayeredBlock.swift index 13e0589cc..adac495c3 100644 --- a/client/ios/LayoutKit/LayoutKit/Blocks/LayeredBlock.swift +++ b/client/ios/LayoutKit/LayoutKit/Blocks/LayeredBlock.swift @@ -1,4 +1,5 @@ import CoreGraphics +import Foundation import VGSL public final class LayeredBlock: BlockWithTraits, BlockWithLayout { @@ -103,6 +104,12 @@ extension LayeredBlock: ImageContaining { } } +extension LayeredBlock: RemoteURLContaining { + public func getRemoteURLs() -> [URL] { + children.flatMap { $0.content.getRemoteURLs() } + } +} + extension LayeredBlock: ElementStateUpdating { public func updated(withStates states: BlocksState) throws -> LayeredBlock { let newChildren = try children.map { diff --git a/client/ios/LayoutKit/LayoutKit/Blocks/MaskedBlock.swift b/client/ios/LayoutKit/LayoutKit/Blocks/MaskedBlock.swift index b0cee560f..c8f040ad6 100644 --- a/client/ios/LayoutKit/LayoutKit/Blocks/MaskedBlock.swift +++ b/client/ios/LayoutKit/LayoutKit/Blocks/MaskedBlock.swift @@ -48,6 +48,12 @@ extension MaskedBlock: ImageContaining { } } +extension MaskedBlock: RemoteURLContaining { + public func getRemoteURLs() -> [URL] { + maskBlock.getRemoteURLs() + maskedBlock.getRemoteURLs() + } +} + extension MaskedBlock: ElementFocusUpdating { public func updated(path: UIElementPath, isFocused: Bool) throws -> MaskedBlock { let newMaskBlock = try maskBlock.updated(path: path, isFocused: isFocused) diff --git a/client/ios/LayoutKit/LayoutKit/Blocks/PagerBlock.swift b/client/ios/LayoutKit/LayoutKit/Blocks/PagerBlock.swift index c8c72d0da..2a7f2ebdc 100644 --- a/client/ios/LayoutKit/LayoutKit/Blocks/PagerBlock.swift +++ b/client/ios/LayoutKit/LayoutKit/Blocks/PagerBlock.swift @@ -106,6 +106,12 @@ extension PagerBlock: ImageContaining { } } +extension PagerBlock: RemoteURLContaining { + public func getRemoteURLs() -> [URL] { + gallery.items.flatMap { $0.content.getRemoteURLs() } + } +} + extension PagerBlock: ElementStateUpdating { public func updated(withStates states: BlocksState) throws -> PagerBlock { let newBlocks = try gallery.items.map { try $0.content.updated(withStates: states) } diff --git a/client/ios/LayoutKit/LayoutKit/Blocks/RemoteURLContaining.swift b/client/ios/LayoutKit/LayoutKit/Blocks/RemoteURLContaining.swift new file mode 100644 index 000000000..9f67eae89 --- /dev/null +++ b/client/ios/LayoutKit/LayoutKit/Blocks/RemoteURLContaining.swift @@ -0,0 +1,9 @@ +import Foundation + +public protocol RemoteURLContaining { + func getRemoteURLs() -> [URL] +} + +extension RemoteURLContaining { + public func getRemoteURLs() -> [URL] { [] } +} diff --git a/client/ios/LayoutKit/LayoutKit/Blocks/SwitchableContainerBlock.swift b/client/ios/LayoutKit/LayoutKit/Blocks/SwitchableContainerBlock.swift index e7b7cdf01..4a38bacda 100644 --- a/client/ios/LayoutKit/LayoutKit/Blocks/SwitchableContainerBlock.swift +++ b/client/ios/LayoutKit/LayoutKit/Blocks/SwitchableContainerBlock.swift @@ -214,6 +214,12 @@ extension SwitchableContainerBlock: ImageContaining { } } +extension SwitchableContainerBlock: RemoteURLContaining { + public func getRemoteURLs() -> [URL] { + items.0.content.getRemoteURLs() + items.1.content.getRemoteURLs() + } +} + extension SwitchableContainerBlock: ElementStateUpdating { public func updated(withStates states: BlocksState) throws -> SwitchableContainerBlock { let newItems = try map(items) { diff --git a/client/ios/LayoutKit/LayoutKit/Blocks/TabsBlock.swift b/client/ios/LayoutKit/LayoutKit/Blocks/TabsBlock.swift index 679ab6914..ad18a099e 100644 --- a/client/ios/LayoutKit/LayoutKit/Blocks/TabsBlock.swift +++ b/client/ios/LayoutKit/LayoutKit/Blocks/TabsBlock.swift @@ -104,6 +104,12 @@ extension TabsBlock: ImageContaining { } } +extension TabsBlock: RemoteURLContaining { + public func getRemoteURLs() -> [URL] { + model.contentsModel.pages.flatMap { $0.block.getRemoteURLs() } + } +} + extension TabsBlock: ElementStateUpdating { public func updated(withStates states: BlocksState) throws -> TabsBlock { let newPages = try model.contentsModel.pages diff --git a/client/ios/LayoutKit/LayoutKit/Blocks/Video/VideoBlock.swift b/client/ios/LayoutKit/LayoutKit/Blocks/Video/VideoBlock.swift index e66a0b14b..2ecc1b011 100644 --- a/client/ios/LayoutKit/LayoutKit/Blocks/Video/VideoBlock.swift +++ b/client/ios/LayoutKit/LayoutKit/Blocks/Video/VideoBlock.swift @@ -48,6 +48,10 @@ public final class VideoBlock: BlockWithTraits { public func getImageHolders() -> [ImageHolder] { [] } + public func getRemoteURLs() -> [URL] { + model.videoData.videos.map(\.url) + } + public func equals(_ other: Block) -> Bool { guard let other = other as? VideoBlock else { return false diff --git a/client/ios/LayoutKit/LayoutKit/Blocks/VideoBlockLegacy.swift b/client/ios/LayoutKit/LayoutKit/Blocks/VideoBlockLegacy.swift index 0f88a02ea..09b8e71b0 100644 --- a/client/ios/LayoutKit/LayoutKit/Blocks/VideoBlockLegacy.swift +++ b/client/ios/LayoutKit/LayoutKit/Blocks/VideoBlockLegacy.swift @@ -53,6 +53,10 @@ public final class VideoBlockLegacy: BlockWithTraits { preview.asArray() } + public func getRemoteURLs() -> [URL] { + [videoAssetHolder.url] + } + public func equals(_ other: Block) -> Bool { guard let other = other as? VideoBlockLegacy else { return false diff --git a/client/ios/LayoutKit/LayoutKit/Blocks/WrapperBlock.swift b/client/ios/LayoutKit/LayoutKit/Blocks/WrapperBlock.swift index 94b14e948..5fefc8724 100644 --- a/client/ios/LayoutKit/LayoutKit/Blocks/WrapperBlock.swift +++ b/client/ios/LayoutKit/LayoutKit/Blocks/WrapperBlock.swift @@ -1,4 +1,5 @@ import CoreGraphics +import Foundation import VGSL public protocol WrapperBlock: SizeForwardingBlock { @@ -23,6 +24,10 @@ extension WrapperBlock { child.getImageHolders() } + public func getRemoteURLs() -> [URL] { + child.getRemoteURLs() + } + public func updated(withStates states: BlocksState) throws -> Self { let newChild = try child.updated(withStates: states) return makeCopyIfChanged(wrapping: newChild) diff --git a/client/ios/LayoutKit/LayoutKit/UI/Blocks/DecoratingBlock+UIViewRenderableBlock.swift b/client/ios/LayoutKit/LayoutKit/UI/Blocks/DecoratingBlock+UIViewRenderableBlock.swift index 448260077..911fed78a 100644 --- a/client/ios/LayoutKit/LayoutKit/UI/Blocks/DecoratingBlock+UIViewRenderableBlock.swift +++ b/client/ios/LayoutKit/LayoutKit/UI/Blocks/DecoratingBlock+UIViewRenderableBlock.swift @@ -377,19 +377,22 @@ private final class DecoratingView: UIControl, BlockViewProtocol, VisibleBoundsT } let oldModel = self.model - if self.model?.tooltips.isEmpty ?? true, !model.tooltips.isEmpty { - renderingDelegate?.tooltipAnchorViewAdded(anchorView: self) - } else if self.model?.tooltips.isEmpty == false, model.tooltips.isEmpty { - renderingDelegate?.tooltipAnchorViewRemoved(anchorView: self) - } - let shouldUpdateChildView = model.child !== self.model?.child || self.observer !== observer || self.renderingDelegate !== renderingDelegate + + if oldModel?.tooltips.isEmpty == false, model.tooltips.isEmpty { + renderingDelegate?.tooltipAnchorViewRemoved(anchorView: self) + } + self.model = model self.observer = observer self.renderingDelegate = renderingDelegate + if oldModel?.tooltips.isEmpty ?? true, !model.tooltips.isEmpty { + renderingDelegate?.tooltipAnchorViewAdded(anchorView: self) + } + if oldModel?.blurEffect != model.blurEffect { blurView = model.blurEffect.map { UIVisualEffectView(effect: UIBlurEffect(style: $0.cast())) } } diff --git a/client/ios/LayoutKit/LayoutKit/ViewModels/Background.swift b/client/ios/LayoutKit/LayoutKit/ViewModels/Background.swift index 07cd1c49d..6179f6205 100644 --- a/client/ios/LayoutKit/LayoutKit/ViewModels/Background.swift +++ b/client/ios/LayoutKit/LayoutKit/ViewModels/Background.swift @@ -1,3 +1,4 @@ +import Foundation import VGSL public enum Background: Equatable { @@ -124,6 +125,26 @@ extension Background: ImageContaining { } } +extension Background: RemoteURLContaining { + public func getRemoteURLs() -> [URL] { + switch self { + case let .composite(first, second, _): + first.getRemoteURLs() + second.getRemoteURLs() + case let .withInsets(background, _): + background.getRemoteURLs() + case let .block(block): + block.getRemoteURLs() + case .solidColor, + .tiledImage, + .image, + .ninePatchImage, + .gradient, + .transparentAction: + [] + } + } +} + extension [Background] { public func composite() -> Element? { if isEmpty { return nil } diff --git a/client/ios/LayoutKit/LayoutKit/ViewModels/TabbedPages/TabPageViewModel.swift b/client/ios/LayoutKit/LayoutKit/ViewModels/TabbedPages/TabPageViewModel.swift index a06dd8366..e7ed76ae8 100644 --- a/client/ios/LayoutKit/LayoutKit/ViewModels/TabbedPages/TabPageViewModel.swift +++ b/client/ios/LayoutKit/LayoutKit/ViewModels/TabbedPages/TabPageViewModel.swift @@ -1,3 +1,4 @@ +import Foundation import VGSL public class TabPageViewModel { @@ -49,6 +50,12 @@ extension TabPageViewModel: ImageContaining { } } +extension TabPageViewModel: RemoteURLContaining { + public func getRemoteURLs() -> [URL] { + block.getRemoteURLs() + } +} + extension TabPageViewModel: CustomDebugStringConvertible { public var debugDescription: String { """