Files
divkit/client/ios/DivKit/Extensions/DivData/DivDataPatchExtensions.swift
T
2022-11-11 18:05:05 +03:00

347 lines
10 KiB
Swift

import CommonCore
extension DivData {
public func applyPatch(_ patch: DivPatch) -> DivData {
let states = states.map {
State(div: $0.div.applySingleItemPatch(patch), stateId: $0.stateId)
}
return DivData(
logId: logId,
states: states,
timers: timers,
transitionAnimationSelector: transitionAnimationSelector,
variableTriggers: variableTriggers,
variables: variables
)
}
}
extension Div {
fileprivate func applySingleItemPatch(_ patch: DivPatch) -> Div {
if let id = 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
}
return items[0]
}
return applyPatchToChildren(patch)
}
fileprivate func applyOptionalItemPatch(_ patch: DivPatch) -> Div? {
if let id = id, let change = patch.getChange(id: id) {
guard let items = change.items else {
return nil
}
if items.count == 1 {
return items[0]
}
DivKitLogger.error("Patch contains multiple items, but single item is expected: \(id)")
return self
}
return applyPatchToChildren(patch)
}
fileprivate func applyMultipleItemsPatch(_ patch: DivPatch) -> [Div] {
if let id = id, let change = patch.getChange(id: id) {
return change.items ?? []
}
return [applyPatchToChildren(patch)]
}
private func applyPatchToChildren(_ patch: DivPatch) -> Div {
switch self {
case .divCustom,
.divGifImage,
.divImage,
.divIndicator,
.divSeparator,
.divSlider,
.divText,
.divInput:
// no children
return self
case let .divContainer(value):
return .divContainer(value.applyPatch(patch))
case let .divGallery(value):
return .divGallery(value.applyPatch(patch))
case let .divGrid(value):
return .divGrid(value.applyPatch(patch))
case let .divPager(value):
return .divPager(value.applyPatch(patch))
case let .divState(value):
return .divState(value.applyPatch(patch))
case let .divTabs(value):
return .divTabs(value.applyPatch(patch))
}
}
}
extension DivContainer {
fileprivate func applyPatch(_ patch: DivPatch) -> DivContainer {
let patchedItems = items.flatMap { $0.applyMultipleItemsPatch(patch) }
return DivContainer(
accessibility: accessibility,
action: action,
actionAnimation: actionAnimation,
actions: actions,
alignmentHorizontal: alignmentHorizontal,
alignmentVertical: alignmentVertical,
alpha: alpha,
background: background,
border: border,
columnSpan: columnSpan,
contentAlignmentHorizontal: contentAlignmentHorizontal,
contentAlignmentVertical: contentAlignmentVertical,
doubletapActions: doubletapActions,
extensions: extensions,
focus: focus,
height: height,
id: id,
items: patchedItems,
layoutMode: layoutMode,
lineSeparator: lineSeparator,
longtapActions: longtapActions,
margins: margins,
orientation: orientation,
paddings: paddings,
rowSpan: rowSpan,
selectedActions: selectedActions,
separator: separator,
tooltips: tooltips,
transform: transform,
transitionChange: transitionChange,
transitionIn: transitionIn,
transitionOut: transitionOut,
transitionTriggers: transitionTriggers,
visibility: visibility,
visibilityAction: visibilityAction,
visibilityActions: visibilityActions,
width: width
)
}
}
extension DivGallery {
fileprivate func applyPatch(_ patch: DivPatch) -> DivGallery {
let patchedItems = items.flatMap { $0.applyMultipleItemsPatch(patch) }
return DivGallery(
accessibility: accessibility,
alignmentHorizontal: alignmentHorizontal,
alignmentVertical: alignmentVertical,
alpha: alpha,
background: background,
border: border,
columnCount: columnCount,
columnSpan: columnSpan,
crossContentAlignment: crossContentAlignment,
crossSpacing: crossSpacing,
defaultItem: defaultItem,
extensions: extensions,
focus: focus,
height: height,
id: id,
itemSpacing: itemSpacing,
items: patchedItems,
margins: margins,
orientation: orientation,
paddings: paddings,
restrictParentScroll: restrictParentScroll,
rowSpan: rowSpan,
scrollMode: scrollMode,
selectedActions: selectedActions,
tooltips: tooltips,
transform: transform,
transitionChange: transitionChange,
transitionIn: transitionIn,
transitionOut: transitionOut,
transitionTriggers: transitionTriggers,
visibility: visibility,
visibilityAction: visibilityAction,
visibilityActions: visibilityActions,
width: width
)
}
}
extension DivGrid {
fileprivate func applyPatch(_ patch: DivPatch) -> DivGrid {
let patchedItems = items.flatMap { $0.applyMultipleItemsPatch(patch) }
return DivGrid(
accessibility: accessibility,
action: action,
actionAnimation: actionAnimation,
actions: actions,
alignmentHorizontal: alignmentHorizontal,
alignmentVertical: alignmentVertical,
alpha: alpha,
background: background,
border: border,
columnCount: columnCount,
columnSpan: columnSpan,
contentAlignmentHorizontal: contentAlignmentHorizontal,
contentAlignmentVertical: contentAlignmentVertical,
doubletapActions: doubletapActions,
extensions: extensions,
focus: focus,
height: height,
id: id,
items: patchedItems,
longtapActions: longtapActions,
margins: margins,
paddings: paddings,
rowSpan: rowSpan,
selectedActions: selectedActions,
tooltips: tooltips,
transform: transform,
transitionChange: transitionChange,
transitionIn: transitionIn,
transitionOut: transitionOut,
transitionTriggers: transitionTriggers,
visibility: visibility,
visibilityAction: visibilityAction,
visibilityActions: visibilityActions,
width: width
)
}
}
extension DivPager {
fileprivate func applyPatch(_ patch: DivPatch) -> DivPager {
let patchedItems = items.flatMap { $0.applyMultipleItemsPatch(patch) }
return DivPager(
accessibility: accessibility,
alignmentHorizontal: alignmentHorizontal,
alignmentVertical: alignmentVertical,
alpha: alpha,
background: background,
border: border,
columnSpan: columnSpan,
defaultItem: defaultItem,
extensions: extensions,
focus: focus,
height: height,
id: id,
itemSpacing: itemSpacing,
items: patchedItems,
layoutMode: layoutMode,
margins: margins,
orientation: orientation,
paddings: paddings,
restrictParentScroll: restrictParentScroll,
rowSpan: rowSpan,
selectedActions: selectedActions,
tooltips: tooltips,
transform: transform,
transitionChange: transitionChange,
transitionIn: transitionIn,
transitionOut: transitionOut,
transitionTriggers: transitionTriggers,
visibility: visibility,
visibilityAction: visibilityAction,
visibilityActions: visibilityActions,
width: width
)
}
}
extension DivState {
fileprivate func applyPatch(_ patch: DivPatch) -> DivState {
let patchedStates = states.map {
DivState.State(
animationIn: $0.animationIn,
animationOut: $0.animationOut,
div: $0.div?.applyOptionalItemPatch(patch),
stateId: $0.stateId,
swipeOutActions: $0.swipeOutActions
)
}
return DivState(
accessibility: accessibility,
alignmentHorizontal: alignmentHorizontal,
alignmentVertical: alignmentVertical,
alpha: alpha,
background: background,
border: border,
columnSpan: columnSpan,
defaultStateId: defaultStateId,
divId: divId,
extensions: extensions,
focus: focus,
height: height,
id: id,
margins: margins,
paddings: paddings,
rowSpan: rowSpan,
selectedActions: selectedActions,
states: patchedStates,
tooltips: tooltips,
transform: transform,
transitionAnimationSelector: transitionAnimationSelector,
transitionChange: transitionChange,
transitionIn: transitionIn,
transitionOut: transitionOut,
transitionTriggers: transitionTriggers,
visibility: visibility,
visibilityAction: visibilityAction,
visibilityActions: visibilityActions,
width: width
)
}
}
extension DivTabs {
fileprivate func applyPatch(_ patch: DivPatch) -> DivTabs {
let patchedItems = items.map {
DivTabs.Item(
div: $0.div.applySingleItemPatch(patch),
title: $0.title,
titleClickAction: $0.titleClickAction
)
}
return DivTabs(
accessibility: accessibility,
alignmentHorizontal: alignmentHorizontal,
alignmentVertical: alignmentVertical,
alpha: alpha,
background: background,
border: border,
columnSpan: columnSpan,
dynamicHeight: dynamicHeight,
extensions: extensions,
focus: focus,
hasSeparator: hasSeparator,
height: height,
id: id,
items: patchedItems,
margins: margins,
paddings: paddings,
restrictParentScroll: restrictParentScroll,
rowSpan: rowSpan,
selectedActions: selectedActions,
selectedTab: selectedTab,
separatorColor: separatorColor,
separatorPaddings: separatorPaddings,
switchTabsByContentSwipeEnabled: switchTabsByContentSwipeEnabled,
tabTitleStyle: tabTitleStyle,
titlePaddings: titlePaddings,
tooltips: tooltips,
transform: transform,
transitionChange: transitionChange,
transitionIn: transitionIn,
transitionOut: transitionOut,
transitionTriggers: transitionTriggers,
visibility: visibility,
visibilityAction: visibilityAction,
visibilityActions: visibilityActions,
width: width
)
}
}
extension DivPatch {
fileprivate func getChange(id: String) -> Change? {
changes.first { $0.id == id }
}
}