mirror of
https://github.com/divkit/divkit.git
synced 2026-06-06 20:07:59 +00:00
e0efea91d0
commit_hash:0e61cb86c4ecce349d6b76477d5f025a5896aa81
147 lines
4.2 KiB
Swift
147 lines
4.2 KiB
Swift
import LayoutKit
|
|
import Serialization
|
|
import VGSL
|
|
|
|
extension DivData: DivBlockModeling {
|
|
public var id: String? {
|
|
nil
|
|
}
|
|
|
|
public static var type: String {
|
|
"DivData"
|
|
}
|
|
|
|
static let rootPath = DivStatePath(rawValue: UIElementPath("{root}"))
|
|
|
|
public func makeBlock(context: DivBlockModelingContext) throws -> Block {
|
|
guard let state = getCurrentState(context: context) else {
|
|
throw DivBlockModelingError("DivData has no states", path: context.path)
|
|
}
|
|
|
|
let stateManager = context.stateManager
|
|
if let previousRootState = getPreviousRootState(stateManager: stateManager) {
|
|
context.lastVisibleBoundsCache.dropVisibleBounds(
|
|
prefix: context.path + previousRootState.rawValue
|
|
)
|
|
}
|
|
|
|
let stateId = String(state.stateId)
|
|
let statePath = DivStatePath(rawValue: UIElementPath(stateId))
|
|
let stateBlockPath: DivStatePath
|
|
let parentDivStatePath: DivStatePath
|
|
if let tooltipId = context.viewId.additionalId {
|
|
stateBlockPath = DivStatePath(rawValue: UIElementPath(tooltipId))
|
|
parentDivStatePath = stateBlockPath + stateId
|
|
} else {
|
|
stateBlockPath = DivData.rootPath
|
|
parentDivStatePath = statePath
|
|
}
|
|
|
|
let divContext = context
|
|
.modifying(
|
|
cardLogId: logId,
|
|
pathSuffix: String(stateId),
|
|
parentDivStatePath: parentDivStatePath
|
|
)
|
|
|
|
let div = state.div
|
|
stateManager.updateBlockIdsWithStateChangeTransition(
|
|
statePath: statePath,
|
|
div: div
|
|
)
|
|
let block = try div.value.makeBlock(context: divContext)
|
|
stateManager.setState(
|
|
stateBlockPath: stateBlockPath,
|
|
stateID: DivStateID(rawValue: stateId)
|
|
)
|
|
return block
|
|
.addingStateBlock(
|
|
ids: stateManager.getVisibleIds(statePath: statePath)
|
|
)
|
|
.addingDebugInfo(context: divContext)
|
|
}
|
|
|
|
private func getCurrentState(context: DivBlockModelingContext) -> DivData.State? {
|
|
guard let item = context.stateManager.get(stateBlockPath: DivData.rootPath) else {
|
|
return states.first
|
|
}
|
|
|
|
let stateId = item.currentStateID.rawValue
|
|
if let state = states.first(where: { String($0.stateId) == stateId }) {
|
|
return state
|
|
}
|
|
|
|
context.addError(message: "DivData.State not found: \(stateId)")
|
|
return states.first
|
|
}
|
|
|
|
private func getPreviousRootState(stateManager: DivStateManager) -> DivStateID? {
|
|
guard let item = stateManager.get(stateBlockPath: DivData.rootPath) else {
|
|
return nil
|
|
}
|
|
|
|
switch item.previousState {
|
|
case .empty, .initial:
|
|
return nil
|
|
case let .withID(id):
|
|
if item.currentStateID != id {
|
|
return id
|
|
}
|
|
return nil
|
|
}
|
|
}
|
|
}
|
|
|
|
extension DivData {
|
|
public static func resolve(
|
|
card cardDict: [String: Any],
|
|
templates templatesDict: [String: Any]?,
|
|
flagsInfo: DivFlagsInfo = .default
|
|
) -> DeserializationResult<DivData> {
|
|
if flagsInfo.useUntypedTemplateResolver {
|
|
let resolver = UntypedDivTemplateResolver(templates: templatesDict)
|
|
let parsingContext = ParsingContext(
|
|
templateResolver: { resolver.resolveFlat($0) }
|
|
)
|
|
|
|
let divDataResult: DeserializationResult<DivData>
|
|
do {
|
|
divDataResult = try .success(DivData(dictionary: cardDict, context: parsingContext))
|
|
} catch {
|
|
divDataResult = .noValue
|
|
}
|
|
|
|
let contextErrors = parsingContext.errors
|
|
let contextWarnings = parsingContext.warnings
|
|
|
|
switch divDataResult {
|
|
case .success(let value), .partialSuccess(let value, _):
|
|
if let warnings = NonEmptyArray(contextErrors + contextWarnings) {
|
|
return .partialSuccess(value, warnings: warnings)
|
|
}
|
|
return .success(value)
|
|
default:
|
|
if let errors = NonEmptyArray(contextErrors) {
|
|
return .failure(errors)
|
|
}
|
|
return .failure(NonEmptyArray(.generic))
|
|
}
|
|
}
|
|
|
|
let divTemplates = templatesDict.map(DivTemplates.init) ?? .empty
|
|
return divTemplates.parseValue(type: DivDataTemplate.self, from: cardDict)
|
|
}
|
|
}
|
|
|
|
extension DivData {
|
|
public func flatMap<T>(_ transform: (Div) -> T) -> [T] {
|
|
var result: [T] = []
|
|
func traverse(div: Div) {
|
|
result.append(transform(div))
|
|
div.children.forEach(traverse(div:))
|
|
}
|
|
states.map(\.div).forEach(traverse(div:))
|
|
return result
|
|
}
|
|
}
|