mirror of
https://github.com/divkit/divkit.git
synced 2026-06-06 20:07:59 +00:00
remove mutating properties from context.
This commit is contained in:
@@ -13,8 +13,8 @@ import AppKit
|
||||
|
||||
public struct DivBlockModelingContext {
|
||||
public let cardId: DivCardID
|
||||
var cardLogId: String?
|
||||
var parentDivStatePath: DivStatePath?
|
||||
private(set) var cardLogId: String?
|
||||
private(set) var parentDivStatePath: DivStatePath?
|
||||
let stateManager: DivStateManager
|
||||
public let blockStateStorage: DivBlockStateStorage
|
||||
let visibilityCounter: DivVisibilityCounting
|
||||
@@ -30,9 +30,9 @@ public struct DivBlockModelingContext {
|
||||
let debugParams: DebugParams
|
||||
let scheduler: Scheduling
|
||||
let playerFactory: PlayerFactory?
|
||||
var childrenA11yDescription: String?
|
||||
private(set) var childrenA11yDescription: String?
|
||||
private(set) weak var parentScrollView: ScrollView?
|
||||
public internal(set) var errorsStorage: DivErrorsStorage
|
||||
public private(set) var errorsStorage: DivErrorsStorage
|
||||
private let persistentValuesStorage: DivPersistentValuesStorage
|
||||
let tooltipViewFactory: DivTooltipViewFactory?
|
||||
public let variablesStorage: DivVariablesStorage
|
||||
@@ -40,20 +40,8 @@ public struct DivBlockModelingContext {
|
||||
private let variableValueProvider: (String) -> Any?
|
||||
private let functionsProvider: FunctionsProvider
|
||||
private let variableTracker: ExpressionResolver.VariableTracker
|
||||
|
||||
public internal(set) var parentPath: UIElementPath {
|
||||
didSet {
|
||||
expressionResolver = makeExpressionResolver(
|
||||
variableValueProvider: variableValueProvider,
|
||||
functionsProvider: functionsProvider,
|
||||
parentPath: parentPath,
|
||||
errorsStorage: errorsStorage,
|
||||
variableTracker: variableTracker
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
var sizeModifier: DivSizeModifier?
|
||||
public private(set) var parentPath: UIElementPath
|
||||
private(set) var sizeModifier: DivSizeModifier?
|
||||
|
||||
public init(
|
||||
cardId: DivCardID,
|
||||
@@ -82,6 +70,85 @@ public struct DivBlockModelingContext {
|
||||
variableTracker: DivVariableTracker? = nil,
|
||||
persistentValuesStorage: DivPersistentValuesStorage? = nil,
|
||||
tooltipViewFactory: DivTooltipViewFactory? = nil
|
||||
) {
|
||||
let variableTracker: ExpressionResolver.VariableTracker = { variables in
|
||||
variableTracker?.onVariablesUsed(cardId: cardId, variables: variables)
|
||||
}
|
||||
var extensionsHandlersDictionary = [String: DivExtensionHandler]()
|
||||
extensionHandlers.forEach {
|
||||
let id = $0.id
|
||||
if extensionsHandlersDictionary[id] != nil {
|
||||
DivKitLogger.failure("Duplicate DivExtensionHandler for: \(id)")
|
||||
return
|
||||
}
|
||||
extensionsHandlersDictionary[id] = $0
|
||||
}
|
||||
var stateInterceptorsDictionary = [String: DivStateInterceptor]()
|
||||
stateInterceptors.forEach {
|
||||
let id = $0.id
|
||||
if stateInterceptorsDictionary[id] != nil {
|
||||
DivKitLogger.failure("Duplicate DivStateInterceptor for: \(id)")
|
||||
return
|
||||
}
|
||||
stateInterceptorsDictionary[id] = $0
|
||||
}
|
||||
self.init(
|
||||
cardId: cardId,
|
||||
cardLogId: cardLogId,
|
||||
parentPath: parentPath,
|
||||
parentDivStatePath: parentDivStatePath,
|
||||
stateManager: stateManager,
|
||||
blockStateStorage: blockStateStorage,
|
||||
visibilityCounter: visibilityCounter,
|
||||
lastVisibleBoundsCache: lastVisibleBoundsCache,
|
||||
imageHolderFactory: imageHolderFactory,
|
||||
highPriorityImageHolderFactory: highPriorityImageHolderFactory,
|
||||
divCustomBlockFactory: divCustomBlockFactory,
|
||||
fontProvider: fontProvider,
|
||||
flagsInfo: flagsInfo,
|
||||
extensionHandlers: extensionsHandlersDictionary,
|
||||
stateInterceptors: stateInterceptorsDictionary,
|
||||
variablesStorage: variablesStorage,
|
||||
playerFactory: playerFactory,
|
||||
debugParams: debugParams,
|
||||
scheduler: scheduler,
|
||||
childrenA11yDescription: childrenA11yDescription,
|
||||
parentScrollView: parentScrollView,
|
||||
errorsStorage: errorsStorage,
|
||||
layoutDirection: layoutDirection,
|
||||
variableTracker: variableTracker,
|
||||
persistentValuesStorage: persistentValuesStorage,
|
||||
tooltipViewFactory: tooltipViewFactory
|
||||
)
|
||||
}
|
||||
|
||||
init(
|
||||
cardId: DivCardID,
|
||||
cardLogId: String?,
|
||||
parentPath: UIElementPath?,
|
||||
parentDivStatePath: DivStatePath?,
|
||||
stateManager: DivStateManager,
|
||||
blockStateStorage: DivBlockStateStorage,
|
||||
visibilityCounter: DivVisibilityCounting?,
|
||||
lastVisibleBoundsCache: DivLastVisibleBoundsCache?,
|
||||
imageHolderFactory: DivImageHolderFactory,
|
||||
highPriorityImageHolderFactory: DivImageHolderFactory?,
|
||||
divCustomBlockFactory: DivCustomBlockFactory?,
|
||||
fontProvider: DivFontProvider?,
|
||||
flagsInfo: DivFlagsInfo,
|
||||
extensionHandlers: [String: DivExtensionHandler],
|
||||
stateInterceptors: [String: DivStateInterceptor],
|
||||
variablesStorage: DivVariablesStorage,
|
||||
playerFactory: PlayerFactory?,
|
||||
debugParams: DebugParams,
|
||||
scheduler: Scheduling?,
|
||||
childrenA11yDescription: String?,
|
||||
parentScrollView: ScrollView?,
|
||||
errorsStorage: DivErrorsStorage?,
|
||||
layoutDirection: UserInterfaceLayoutDirection,
|
||||
variableTracker: @escaping ExpressionResolver.VariableTracker,
|
||||
persistentValuesStorage: DivPersistentValuesStorage?,
|
||||
tooltipViewFactory: DivTooltipViewFactory?
|
||||
) {
|
||||
self.cardId = cardId
|
||||
self.cardLogId = cardLogId
|
||||
@@ -104,36 +171,13 @@ public struct DivBlockModelingContext {
|
||||
self.parentScrollView = parentScrollView
|
||||
self.errorsStorage = errorsStorage ?? DivErrorsStorage(errors: [])
|
||||
self.layoutDirection = layoutDirection
|
||||
let variableTracker: ExpressionResolver.VariableTracker = { variables in
|
||||
variableTracker?.onVariablesUsed(cardId: cardId, variables: variables)
|
||||
}
|
||||
self.variableTracker = variableTracker
|
||||
let persistentValuesStorage = persistentValuesStorage ?? DivPersistentValuesStorage()
|
||||
self.persistentValuesStorage = persistentValuesStorage
|
||||
self.tooltipViewFactory = tooltipViewFactory
|
||||
self.variablesStorage = variablesStorage
|
||||
|
||||
var extensionsHandlersDictionary = [String: DivExtensionHandler]()
|
||||
extensionHandlers.forEach {
|
||||
let id = $0.id
|
||||
if extensionsHandlersDictionary[id] != nil {
|
||||
DivKitLogger.failure("Duplicate DivExtensionHandler for: \(id)")
|
||||
return
|
||||
}
|
||||
extensionsHandlersDictionary[id] = $0
|
||||
}
|
||||
self.extensionHandlers = extensionsHandlersDictionary
|
||||
|
||||
var stateInterceptorsDictionary = [String: DivStateInterceptor]()
|
||||
stateInterceptors.forEach {
|
||||
let id = $0.id
|
||||
if stateInterceptorsDictionary[id] != nil {
|
||||
DivKitLogger.failure("Duplicate DivStateInterceptor for: \(id)")
|
||||
return
|
||||
}
|
||||
stateInterceptorsDictionary[id] = $0
|
||||
}
|
||||
self.stateInterceptors = stateInterceptorsDictionary
|
||||
self.extensionHandlers = extensionHandlers
|
||||
self.stateInterceptors = stateInterceptors
|
||||
|
||||
let variableValueProvider: (String) -> Any? = {
|
||||
variablesStorage.getVariableValue(
|
||||
@@ -149,7 +193,7 @@ public struct DivBlockModelingContext {
|
||||
},
|
||||
persistentValuesStorage: persistentValuesStorage
|
||||
)
|
||||
expressionResolver = makeExpressionResolver(
|
||||
self.expressionResolver = makeExpressionResolver(
|
||||
variableValueProvider: variableValueProvider,
|
||||
functionsProvider: functionsProvider,
|
||||
parentPath: parentPath,
|
||||
@@ -211,6 +255,47 @@ public struct DivBlockModelingContext {
|
||||
}
|
||||
}
|
||||
|
||||
extension DivBlockModelingContext {
|
||||
func modifying(
|
||||
cardLogId: String? = nil,
|
||||
parentPath: UIElementPath? = nil,
|
||||
parentDivStatePath: DivStatePath? = nil,
|
||||
errorsStorage: DivErrorsStorage? = nil,
|
||||
sizeModifier: DivSizeModifier? = nil
|
||||
) -> Self {
|
||||
let expressionResolver: ExpressionResolver
|
||||
let parentPath = parentPath ?? self.parentPath
|
||||
let errorsStorage = errorsStorage ?? self.errorsStorage
|
||||
if parentPath == self.parentPath {
|
||||
expressionResolver = self.expressionResolver
|
||||
} else {
|
||||
expressionResolver = makeExpressionResolver(
|
||||
variableValueProvider: variableValueProvider,
|
||||
functionsProvider: functionsProvider,
|
||||
parentPath: parentPath,
|
||||
errorsStorage: errorsStorage,
|
||||
variableTracker: variableTracker
|
||||
)
|
||||
}
|
||||
return modified(self) {
|
||||
$0.cardLogId = cardLogId ?? self.cardLogId
|
||||
$0.parentPath = parentPath
|
||||
$0.parentDivStatePath = parentDivStatePath ?? self.parentDivStatePath
|
||||
$0.errorsStorage = errorsStorage
|
||||
$0.sizeModifier = sizeModifier ?? self.sizeModifier
|
||||
$0.expressionResolver = expressionResolver
|
||||
}
|
||||
}
|
||||
|
||||
func modifying(
|
||||
childrenA11yDescription: String?
|
||||
) -> Self {
|
||||
modified(self) {
|
||||
$0.childrenA11yDescription = childrenA11yDescription
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func makeExpressionResolver(
|
||||
variableValueProvider: @escaping AnyCalcExpression.ValueProvider,
|
||||
functionsProvider: FunctionsProvider,
|
||||
|
||||
@@ -8,10 +8,10 @@ extension Array where Element == Div {
|
||||
mappedBy modificator: (Div, Block) throws -> T
|
||||
) rethrows -> [T] {
|
||||
try iterativeFlatMap { div, index in
|
||||
let itemContext = modified(context) {
|
||||
$0.parentPath += index
|
||||
$0.sizeModifier = sizeModifier
|
||||
}
|
||||
let itemContext = context.modifying(
|
||||
parentPath: context.parentPath + index,
|
||||
sizeModifier: sizeModifier
|
||||
)
|
||||
let block: Block
|
||||
do {
|
||||
block = try modifyError({
|
||||
|
||||
@@ -7,9 +7,9 @@ extension DivContainer: DivBlockModeling {
|
||||
public func makeBlock(context: DivBlockModelingContext) throws -> Block {
|
||||
try applyBaseProperties(
|
||||
to: { try makeBaseBlock(context: context) },
|
||||
context: modified(context) {
|
||||
$0.childrenA11yDescription = resolveChildrenA11yDescription($0)
|
||||
},
|
||||
context: context.modifying(
|
||||
childrenA11yDescription: resolveChildrenA11yDescription(context)
|
||||
),
|
||||
actionsHolder: self
|
||||
)
|
||||
}
|
||||
@@ -17,11 +17,11 @@ extension DivContainer: DivBlockModeling {
|
||||
var nonNilItems: [Div] {
|
||||
items ?? []
|
||||
}
|
||||
|
||||
|
||||
private func makeBaseBlock(context: DivBlockModelingContext) throws -> Block {
|
||||
let childContext = modified(context) {
|
||||
$0.parentPath = $0.parentPath + (id ?? DivContainer.type)
|
||||
}
|
||||
let childContext = context.modifying(
|
||||
parentPath: context.parentPath + (id ?? DivContainer.type)
|
||||
)
|
||||
let expressionResolver = context.expressionResolver
|
||||
let orientation = resolveOrientation(expressionResolver)
|
||||
switch orientation {
|
||||
@@ -55,9 +55,9 @@ extension DivContainer: DivBlockModeling {
|
||||
vertical: resolveContentAlignmentVertical(expressionResolver).alignment
|
||||
)
|
||||
|
||||
let childrenContext = modified(context) {
|
||||
$0.errorsStorage = DivErrorsStorage(errors: [])
|
||||
}
|
||||
let childrenContext = context.modifying(
|
||||
errorsStorage: DivErrorsStorage(errors: [])
|
||||
)
|
||||
let children = nonNilItems.makeBlocks(
|
||||
context: childrenContext,
|
||||
sizeModifier: DivContainerSizeModifier(
|
||||
@@ -121,9 +121,9 @@ extension DivContainer: DivBlockModeling {
|
||||
uiLayoutDirection: context.layoutDirection
|
||||
)
|
||||
|
||||
let childrenContext = modified(context) {
|
||||
$0.errorsStorage = DivErrorsStorage(errors: [])
|
||||
}
|
||||
let childrenContext = context.modifying(
|
||||
errorsStorage: DivErrorsStorage(errors: [])
|
||||
)
|
||||
|
||||
// Before block's making we need to filter items and remove
|
||||
// what has "matchParent" for opposite directions
|
||||
|
||||
@@ -20,11 +20,12 @@ extension DivData: DivBlockModeling {
|
||||
let stateId = String(state.stateId)
|
||||
let statePath = DivStatePath(rawValue: UIElementPath(stateId))
|
||||
let div = state.div
|
||||
let divContext = modified(context) {
|
||||
$0.cardLogId = $0.cardLogId ?? logId
|
||||
$0.parentPath = $0.parentPath + stateId
|
||||
$0.parentDivStatePath = statePath
|
||||
}
|
||||
|
||||
let divContext = context.modifying(
|
||||
cardLogId: logId,
|
||||
parentPath: context.parentPath + stateId,
|
||||
parentDivStatePath: statePath
|
||||
)
|
||||
|
||||
stateManager.updateBlockIdsWithStateChangeTransition(
|
||||
statePath: statePath,
|
||||
|
||||
@@ -17,9 +17,7 @@ extension DivGallery: DivBlockModeling, DivGalleryProtocol {
|
||||
private func makeBaseBlock(context: DivBlockModelingContext) throws -> Block {
|
||||
let galleryPath = context.parentPath + (id ?? DivGallery.type)
|
||||
let expressionResolver = context.expressionResolver
|
||||
let galleryContext = modified(context) {
|
||||
$0.parentPath = galleryPath
|
||||
}
|
||||
let galleryContext = context.modifying(parentPath: galleryPath)
|
||||
let defaultAlignment = resolveCrossContentAlignment(expressionResolver)
|
||||
.blockAlignment
|
||||
let itemSpacing = resolveItemSpacing(expressionResolver)
|
||||
|
||||
@@ -21,9 +21,7 @@ extension DivGalleryProtocol {
|
||||
scrollbar: GalleryViewModel.Scrollbar = .none
|
||||
) throws -> GalleryViewModel {
|
||||
let expressionResolver = context.expressionResolver
|
||||
let childrenContext = modified(context) {
|
||||
$0.errorsStorage = DivErrorsStorage(errors: [])
|
||||
}
|
||||
let childrenContext = context.modifying(errorsStorage: DivErrorsStorage(errors: []))
|
||||
var children: [GalleryViewModel.Item] = items.makeBlocks(
|
||||
context: childrenContext,
|
||||
sizeModifier: DivGallerySizeModifier(
|
||||
|
||||
@@ -12,16 +12,12 @@ extension DivGrid: DivBlockModeling {
|
||||
|
||||
private func makeBaseBlock(context: DivBlockModelingContext) throws -> Block {
|
||||
let gridPath = context.parentPath + DivGrid.type
|
||||
let gridContext = modified(context) {
|
||||
$0.parentPath = gridPath
|
||||
}
|
||||
let gridItemsContext = modified(gridContext) {
|
||||
$0.errorsStorage = DivErrorsStorage(errors: [])
|
||||
}
|
||||
let gridContext = context.modifying(parentPath: gridPath)
|
||||
let gridItemsContext = gridContext.modifying(errorsStorage: DivErrorsStorage(errors: []))
|
||||
let gridItems = items.enumerated().compactMap { tuple in
|
||||
let itemContext = modified(gridItemsContext) {
|
||||
$0.parentPath = $0.parentPath + tuple.offset
|
||||
}
|
||||
let itemContext = gridItemsContext.modifying(
|
||||
parentPath: gridItemsContext.parentPath + tuple.offset
|
||||
)
|
||||
do {
|
||||
return try tuple.element.value.makeGridItem(
|
||||
context: itemContext
|
||||
|
||||
@@ -17,9 +17,7 @@ extension DivPager: DivBlockModeling, DivGalleryProtocol {
|
||||
private func makeBaseBlock(context: DivBlockModelingContext) throws -> Block {
|
||||
let pagerPath = context.parentPath + (id ?? DivPager.type)
|
||||
let expressionResolver = context.expressionResolver
|
||||
let itemContext = modified(context) {
|
||||
$0.parentPath = pagerPath
|
||||
}
|
||||
let itemContext = context.modifying(parentPath: pagerPath)
|
||||
let pagerModelPath = id.map {
|
||||
PagerPath(
|
||||
cardId: context.cardId.rawValue,
|
||||
|
||||
@@ -148,10 +148,10 @@ extension DivBlockModelingContext {
|
||||
id: String,
|
||||
stateId: String
|
||||
) -> DivBlockModelingContext {
|
||||
modified(self) {
|
||||
$0.parentPath = parentPath + id + stateId
|
||||
$0.parentDivStatePath = parentDivStatePath + id + stateId
|
||||
}
|
||||
modifying(
|
||||
parentPath: parentPath + id + stateId,
|
||||
parentDivStatePath: parentDivStatePath + id + stateId
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,12 +21,8 @@ extension DivTabs: DivBlockModeling {
|
||||
context: DivBlockModelingContext,
|
||||
tabsPath: UIElementPath
|
||||
) throws -> Block {
|
||||
let tabsContext = modified(context) {
|
||||
$0.parentPath = tabsPath
|
||||
}
|
||||
let tabsItemContext = modified(tabsContext) {
|
||||
$0.errorsStorage = DivErrorsStorage(errors: [])
|
||||
}
|
||||
let tabsContext = context.modifying(parentPath: tabsPath)
|
||||
let tabsItemContext = tabsContext.modifying(errorsStorage: DivErrorsStorage(errors: []))
|
||||
let tabs = items.iterativeFlatMap { item, index in
|
||||
do {
|
||||
return try item.makeTab(context: tabsItemContext, index: index)
|
||||
@@ -192,8 +188,8 @@ extension Typo {
|
||||
|
||||
extension DivTabs.Item {
|
||||
fileprivate func makeTab(context: DivBlockModelingContext, index: Int) throws -> Tab {
|
||||
let tabContext = modified(context) { $0.parentPath = $0.parentPath + index }
|
||||
let pageContext = modified(tabContext) { $0.parentPath += "page" }
|
||||
let tabContext = context.modifying(parentPath: context.parentPath + index)
|
||||
let pageContext = tabContext.modifying(parentPath: tabContext.parentPath + "page")
|
||||
let title = makeTitle(context: tabContext)
|
||||
let page = try div.value
|
||||
.makeBlock(context: pageContext)
|
||||
@@ -202,9 +198,9 @@ extension DivTabs.Item {
|
||||
}
|
||||
|
||||
private func makeTitle(context: DivBlockModelingContext) -> UILink {
|
||||
let titleContext = modified(context) {
|
||||
$0.parentPath += "title"
|
||||
}
|
||||
let titleContext = context.modifying(
|
||||
parentPath: context.parentPath + "title"
|
||||
)
|
||||
let action = titleClickAction?.uiAction(context: context)
|
||||
return UILink(
|
||||
text: resolveTitle(titleContext.expressionResolver) ?? "",
|
||||
|
||||
@@ -58,9 +58,9 @@ extension Optional where Wrapped == [DivTooltip] {
|
||||
context: DivBlockModelingContext
|
||||
) throws -> [BlockTooltip] {
|
||||
try self?.iterativeFlatMap { div, index in
|
||||
let tooltipContext = modified(context) {
|
||||
$0.parentPath = $0.parentPath + "tooltip" + index
|
||||
}
|
||||
let tooltipContext = context.modifying(
|
||||
parentPath: context.parentPath + "tooltip" + index
|
||||
)
|
||||
return try div.makeTooltip(context: tooltipContext)
|
||||
} ?? []
|
||||
}
|
||||
|
||||
@@ -43,9 +43,7 @@ extension DivVideo: DivBlockModeling {
|
||||
)
|
||||
|
||||
let videoPath = context.parentPath + (id ?? DivVideo.type)
|
||||
let videoContext = modified(context) {
|
||||
$0.parentPath = videoPath
|
||||
}
|
||||
let videoContext = context.modifying(parentPath: videoPath)
|
||||
|
||||
let state: VideoBlockViewState = videoContext.blockStateStorage
|
||||
.getState(videoContext.parentPath) ?? .init(state: autostart == true ? .playing : .paused)
|
||||
|
||||
Reference in New Issue
Block a user