Updated schema for iOS

This commit is contained in:
pkurchatov
2023-06-28 12:45:19 +03:00
parent 94f6431a19
commit 30ba75090d
17 changed files with 236 additions and 23 deletions
@@ -57,7 +57,7 @@ extension DivAccessibility.Kind {
return .tabBar
case .none:
return .none
case .list:
case .list, .select:
DivKitLogger.warning("Unsupported accessibility type")
return .none
}
@@ -300,6 +300,8 @@ extension Collection where Element == DivVariable {
let name = DivVariableName(rawValue: urlVariable.name)
if variables.keys.contains(name) { return }
variables[name] = .url(urlVariable.value)
case .dictVariable:
DivKitLogger.warning("Unsupported variable type: dict")
}
}
return variables
@@ -0,0 +1,46 @@
// Generated code. Do not modify.
import CommonCorePublic
import Foundation
import Serialization
public final class DictVariable {
public static let type: String = "dict"
public let name: String // at least 1 char
public let value: [String: Any]
static let nameValidator: AnyValueValidator<String> =
makeStringValidator(minLength: 1)
init(
name: String,
value: [String: Any]
) {
self.name = name
self.value = value
}
}
#if DEBUG
// WARNING: this == is incomplete because of [String: Any] in class fields
extension DictVariable: Equatable {
public static func ==(lhs: DictVariable, rhs: DictVariable) -> Bool {
guard
lhs.name == rhs.name
else {
return false
}
return true
}
}
#endif
extension DictVariable: Serializable {
public func toDictionary() -> [String: ValidSerializationValue] {
var result: [String: ValidSerializationValue] = [:]
result["type"] = Self.type
result["name"] = name
result["value"] = value
return result
}
}
@@ -0,0 +1,123 @@
// Generated code. Do not modify.
import CommonCorePublic
import Foundation
import Serialization
public final class DictVariableTemplate: TemplateValue {
public static let type: String = "dict"
public let parent: String? // at least 1 char
public let name: Field<String>? // at least 1 char
public let value: Field<[String: Any]>?
static let parentValidator: AnyValueValidator<String> =
makeStringValidator(minLength: 1)
public convenience init(dictionary: [String: Any], templateToType: [TemplateName: String]) throws {
do {
self.init(
parent: try dictionary.getOptionalField("type", validator: Self.parentValidator),
name: try dictionary.getOptionalField("name"),
value: try dictionary.getOptionalField("value")
)
} catch let DeserializationError.invalidFieldRepresentation(field: field, representation: representation) {
throw DeserializationError.invalidFieldRepresentation(field: "dict_variable_template." + field, representation: representation)
}
}
init(
parent: String?,
name: Field<String>? = nil,
value: Field<[String: Any]>? = nil
) {
self.parent = parent
self.name = name
self.value = value
}
private static func resolveOnlyLinks(context: TemplatesContext, parent: DictVariableTemplate?) -> DeserializationResult<DictVariable> {
let nameValue = parent?.name?.resolveValue(context: context, validator: ResolvedValue.nameValidator) ?? .noValue
let valueValue = parent?.value?.resolveValue(context: context) ?? .noValue
var errors = mergeErrors(
nameValue.errorsOrWarnings?.map { .nestedObjectError(field: "name", error: $0) },
valueValue.errorsOrWarnings?.map { .nestedObjectError(field: "value", error: $0) }
)
if case .noValue = nameValue {
errors.append(.requiredFieldIsMissing(field: "name"))
}
if case .noValue = valueValue {
errors.append(.requiredFieldIsMissing(field: "value"))
}
guard
let nameNonNil = nameValue.value,
let valueNonNil = valueValue.value
else {
return .failure(NonEmptyArray(errors)!)
}
let result = DictVariable(
name: nameNonNil,
value: valueNonNil
)
return errors.isEmpty ? .success(result) : .partialSuccess(result, warnings: NonEmptyArray(errors)!)
}
public static func resolveValue(context: TemplatesContext, parent: DictVariableTemplate?, useOnlyLinks: Bool) -> DeserializationResult<DictVariable> {
if useOnlyLinks {
return resolveOnlyLinks(context: context, parent: parent)
}
var nameValue: DeserializationResult<String> = parent?.name?.value(validatedBy: ResolvedValue.nameValidator) ?? .noValue
var valueValue: DeserializationResult<[String: Any]> = parent?.value?.value() ?? .noValue
context.templateData.forEach { key, __dictValue in
switch key {
case "name":
nameValue = deserialize(__dictValue, validator: ResolvedValue.nameValidator).merged(with: nameValue)
case "value":
valueValue = deserialize(__dictValue).merged(with: valueValue)
case parent?.name?.link:
nameValue = nameValue.merged(with: deserialize(__dictValue, validator: ResolvedValue.nameValidator))
case parent?.value?.link:
valueValue = valueValue.merged(with: deserialize(__dictValue))
default: break
}
}
var errors = mergeErrors(
nameValue.errorsOrWarnings?.map { .nestedObjectError(field: "name", error: $0) },
valueValue.errorsOrWarnings?.map { .nestedObjectError(field: "value", error: $0) }
)
if case .noValue = nameValue {
errors.append(.requiredFieldIsMissing(field: "name"))
}
if case .noValue = valueValue {
errors.append(.requiredFieldIsMissing(field: "value"))
}
guard
let nameNonNil = nameValue.value,
let valueNonNil = valueValue.value
else {
return .failure(NonEmptyArray(errors)!)
}
let result = DictVariable(
name: nameNonNil,
value: valueNonNil
)
return errors.isEmpty ? .success(result) : .partialSuccess(result, warnings: NonEmptyArray(errors)!)
}
private func mergedWithParent(templates: [TemplateName: Any]) throws -> DictVariableTemplate {
guard let parent = parent, parent != Self.type else { return self }
guard let parentTemplate = templates[parent] as? DictVariableTemplate else {
throw DeserializationError.unknownType(type: parent)
}
let mergedParent = try parentTemplate.mergedWithParent(templates: templates)
return DictVariableTemplate(
parent: nil,
name: name ?? mergedParent.name,
value: value ?? mergedParent.value
)
}
public func resolveParent(templates: [TemplateName: Any]) throws -> DictVariableTemplate {
return try mergedWithParent(templates: templates)
}
}
@@ -15,6 +15,7 @@ public final class DivAccessibility {
case header = "header"
case tabBar = "tab_bar"
case list = "list"
case select = "select"
}
@frozen
@@ -4,7 +4,7 @@ import CommonCorePublic
import Foundation
import Serialization
public final class DivDisappearAction {
public final class DivDisappearAction: DivSightAction {
public let disappearDuration: Expression<Int> // constraint: number >= 0; default value: 800
public let downloadCallbacks: DivDownloadCallbacks?
public let logId: String // at least 1 char
@@ -61,7 +61,7 @@ public final class DivInput: DivBase {
public let selectAllOnFocus: Expression<Bool> // default value: false
public let selectedActions: [DivAction]? // at least 1 elements
public let textAlignmentHorizontal: Expression<DivAlignmentHorizontal> // default value: left
public let textAlignmentVertical: Expression<DivAlignmentVertical> // default value: bottom
public let textAlignmentVertical: Expression<DivAlignmentVertical> // default value: center
public let textColor: Expression<Color> // default value: #FF000000
public let textVariable: String // at least 1 char
public let tooltips: [DivTooltip]? // at least 1 elements
@@ -149,7 +149,7 @@ public final class DivInput: DivBase {
}
public func resolveTextAlignmentVertical(_ resolver: ExpressionResolver) -> DivAlignmentVertical {
resolver.resolveStringBasedValue(expression: textAlignmentVertical, initializer: DivAlignmentVertical.init(rawValue:)) ?? DivAlignmentVertical.bottom
resolver.resolveStringBasedValue(expression: textAlignmentVertical, initializer: DivAlignmentVertical.init(rawValue:)) ?? DivAlignmentVertical.center
}
public func resolveTextColor(_ resolver: ExpressionResolver) -> Color {
@@ -370,7 +370,7 @@ public final class DivInput: DivBase {
self.selectAllOnFocus = selectAllOnFocus ?? .value(false)
self.selectedActions = selectedActions
self.textAlignmentHorizontal = textAlignmentHorizontal ?? .value(.left)
self.textAlignmentVertical = textAlignmentVertical ?? .value(.bottom)
self.textAlignmentVertical = textAlignmentVertical ?? .value(.center)
self.textColor = textColor ?? .value(Color.colorWithARGBHexCode(0xFF000000))
self.textVariable = textVariable
self.tooltips = tooltips
@@ -118,7 +118,7 @@ public final class DivInputTemplate: TemplateValue {
public let selectAllOnFocus: Field<Expression<Bool>>? // default value: false
public let selectedActions: Field<[DivActionTemplate]>? // at least 1 elements
public let textAlignmentHorizontal: Field<Expression<DivAlignmentHorizontal>>? // default value: left
public let textAlignmentVertical: Field<Expression<DivAlignmentVertical>>? // default value: bottom
public let textAlignmentVertical: Field<Expression<DivAlignmentVertical>>? // default value: center
public let textColor: Field<Expression<Color>>? // default value: #FF000000
public let textVariable: Field<String>? // at least 1 char
public let tooltips: Field<[DivTooltipTemplate]>? // at least 1 elements
@@ -7,7 +7,7 @@ import Serialization
public final class DivInputValidatorExpression {
public static let type: String = "expression"
public let allowEmpty: Expression<Bool> // default value: false
public let condition: Expression<String> // at least 1 char
public let condition: Expression<Bool>
public let labelId: Expression<String> // at least 1 char
public let variable: String // at least 1 char
@@ -15,8 +15,8 @@ public final class DivInputValidatorExpression {
resolver.resolveNumericValue(expression: allowEmpty) ?? false
}
public func resolveCondition(_ resolver: ExpressionResolver) -> String? {
resolver.resolveStringBasedValue(expression: condition, initializer: { $0 })
public func resolveCondition(_ resolver: ExpressionResolver) -> Bool? {
resolver.resolveNumericValue(expression: condition)
}
public func resolveLabelId(_ resolver: ExpressionResolver) -> String? {
@@ -26,9 +26,6 @@ public final class DivInputValidatorExpression {
static let allowEmptyValidator: AnyValueValidator<Bool> =
makeNoOpValueValidator()
static let conditionValidator: AnyValueValidator<String> =
makeStringValidator(minLength: 1)
static let labelIdValidator: AnyValueValidator<String> =
makeStringValidator(minLength: 1)
@@ -37,7 +34,7 @@ public final class DivInputValidatorExpression {
init(
allowEmpty: Expression<Bool>? = nil,
condition: Expression<String>,
condition: Expression<Bool>,
labelId: Expression<String>,
variable: String
) {
@@ -8,7 +8,7 @@ public final class DivInputValidatorExpressionTemplate: TemplateValue {
public static let type: String = "expression"
public let parent: String? // at least 1 char
public let allowEmpty: Field<Expression<Bool>>? // default value: false
public let condition: Field<Expression<String>>? // at least 1 char
public let condition: Field<Expression<Bool>>?
public let labelId: Field<Expression<String>>? // at least 1 char
public let variable: Field<String>? // at least 1 char
@@ -32,7 +32,7 @@ public final class DivInputValidatorExpressionTemplate: TemplateValue {
init(
parent: String?,
allowEmpty: Field<Expression<Bool>>? = nil,
condition: Field<Expression<String>>? = nil,
condition: Field<Expression<Bool>>? = nil,
labelId: Field<Expression<String>>? = nil,
variable: Field<String>? = nil
) {
@@ -45,7 +45,7 @@ public final class DivInputValidatorExpressionTemplate: TemplateValue {
private static func resolveOnlyLinks(context: TemplatesContext, parent: DivInputValidatorExpressionTemplate?) -> DeserializationResult<DivInputValidatorExpression> {
let allowEmptyValue = parent?.allowEmpty?.resolveOptionalValue(context: context, validator: ResolvedValue.allowEmptyValidator) ?? .noValue
let conditionValue = parent?.condition?.resolveValue(context: context, validator: ResolvedValue.conditionValidator) ?? .noValue
let conditionValue = parent?.condition?.resolveValue(context: context) ?? .noValue
let labelIdValue = parent?.labelId?.resolveValue(context: context, validator: ResolvedValue.labelIdValidator) ?? .noValue
let variableValue = parent?.variable?.resolveValue(context: context, validator: ResolvedValue.variableValidator) ?? .noValue
var errors = mergeErrors(
@@ -84,7 +84,7 @@ public final class DivInputValidatorExpressionTemplate: TemplateValue {
return resolveOnlyLinks(context: context, parent: parent)
}
var allowEmptyValue: DeserializationResult<Expression<Bool>> = parent?.allowEmpty?.value() ?? .noValue
var conditionValue: DeserializationResult<Expression<String>> = parent?.condition?.value() ?? .noValue
var conditionValue: DeserializationResult<Expression<Bool>> = parent?.condition?.value() ?? .noValue
var labelIdValue: DeserializationResult<Expression<String>> = parent?.labelId?.value() ?? .noValue
var variableValue: DeserializationResult<String> = parent?.variable?.value(validatedBy: ResolvedValue.variableValidator) ?? .noValue
context.templateData.forEach { key, __dictValue in
@@ -92,7 +92,7 @@ public final class DivInputValidatorExpressionTemplate: TemplateValue {
case "allow_empty":
allowEmptyValue = deserialize(__dictValue, validator: ResolvedValue.allowEmptyValidator).merged(with: allowEmptyValue)
case "condition":
conditionValue = deserialize(__dictValue, validator: ResolvedValue.conditionValidator).merged(with: conditionValue)
conditionValue = deserialize(__dictValue).merged(with: conditionValue)
case "label_id":
labelIdValue = deserialize(__dictValue, validator: ResolvedValue.labelIdValidator).merged(with: labelIdValue)
case "variable":
@@ -100,7 +100,7 @@ public final class DivInputValidatorExpressionTemplate: TemplateValue {
case parent?.allowEmpty?.link:
allowEmptyValue = allowEmptyValue.merged(with: deserialize(__dictValue, validator: ResolvedValue.allowEmptyValidator))
case parent?.condition?.link:
conditionValue = conditionValue.merged(with: deserialize(__dictValue, validator: ResolvedValue.conditionValidator))
conditionValue = conditionValue.merged(with: deserialize(__dictValue))
case parent?.labelId?.link:
labelIdValue = labelIdValue.merged(with: deserialize(__dictValue, validator: ResolvedValue.labelIdValidator))
case parent?.variable?.link:
@@ -0,0 +1,17 @@
// Generated code. Do not modify.
import CommonCorePublic
import Foundation
import Serialization
public protocol DivSightAction {
var downloadCallbacks: DivDownloadCallbacks? { get }
var logId: String { get } // at least 1 char
var logLimit: Expression<Int> { get } // constraint: number >= 0; default value: 1
var payload: [String: Any]? { get }
var referer: Expression<URL>? { get }
var url: Expression<URL>? { get }
func resolveLogLimit(_ resolver: ExpressionResolver) -> Int
func resolveReferer(_ resolver: ExpressionResolver) -> URL?
func resolveUrl(_ resolver: ExpressionResolver) -> URL?
}
@@ -12,6 +12,7 @@ public enum DivVariable {
case booleanVariable(BooleanVariable)
case colorVariable(ColorVariable)
case urlVariable(UrlVariable)
case dictVariable(DictVariable)
public var value: Serializable {
switch self {
@@ -27,6 +28,8 @@ public enum DivVariable {
return value
case let .urlVariable(value):
return value
case let .dictVariable(value):
return value
}
}
}
@@ -47,6 +50,8 @@ extension DivVariable: Equatable {
return l == r
case let (.urlVariable(l), .urlVariable(r)):
return l == r
case let (.dictVariable(l), .dictVariable(r)):
return l == r
default:
return false
}
@@ -12,6 +12,7 @@ public enum DivVariableTemplate: TemplateValue {
case booleanVariableTemplate(BooleanVariableTemplate)
case colorVariableTemplate(ColorVariableTemplate)
case urlVariableTemplate(UrlVariableTemplate)
case dictVariableTemplate(DictVariableTemplate)
public var value: Any {
switch self {
@@ -27,6 +28,8 @@ public enum DivVariableTemplate: TemplateValue {
return value
case let .urlVariableTemplate(value):
return value
case let .dictVariableTemplate(value):
return value
}
}
@@ -44,6 +47,8 @@ public enum DivVariableTemplate: TemplateValue {
return .colorVariableTemplate(try value.resolveParent(templates: templates))
case let .urlVariableTemplate(value):
return .urlVariableTemplate(try value.resolveParent(templates: templates))
case let .dictVariableTemplate(value):
return .dictVariableTemplate(try value.resolveParent(templates: templates))
}
}
@@ -105,6 +110,14 @@ public enum DivVariableTemplate: TemplateValue {
case let .failure(errors): return .failure(errors)
case .noValue: return .noValue
}
case let .dictVariableTemplate(value):
let result = value.resolveValue(context: context, useOnlyLinks: useOnlyLinks)
switch result {
case let .success(value): return .success(.dictVariable(value))
case let .partialSuccess(value, warnings): return .partialSuccess(.dictVariable(value), warnings: warnings)
case let .failure(errors): return .failure(errors)
case .noValue: return .noValue
}
}
}
@@ -162,6 +175,14 @@ public enum DivVariableTemplate: TemplateValue {
case let .failure(errors): return .failure(errors)
case .noValue: return .noValue
}
case DictVariable.type:
let result = DictVariableTemplate.resolveValue(context: context, useOnlyLinks: useOnlyLinks)
switch result {
case let .success(value): return .success(.dictVariable(value))
case let .partialSuccess(value, warnings): return .partialSuccess(.dictVariable(value), warnings: warnings)
case let .failure(errors): return .failure(errors)
case .noValue: return .noValue
}
default:
return .failure(NonEmptyArray(.requiredFieldIsMissing(field: "type")))
}
@@ -185,6 +206,8 @@ extension DivVariableTemplate {
self = .colorVariableTemplate(try ColorVariableTemplate(dictionary: dictionary, templateToType: templateToType))
case UrlVariableTemplate.type:
self = .urlVariableTemplate(try UrlVariableTemplate(dictionary: dictionary, templateToType: templateToType))
case DictVariableTemplate.type:
self = .dictVariableTemplate(try DictVariableTemplate(dictionary: dictionary, templateToType: templateToType))
default:
throw DeserializationError.invalidFieldRepresentation(field: "div-variable_template", representation: dictionary)
}
@@ -4,7 +4,7 @@ import CommonCorePublic
import Foundation
import Serialization
public final class DivVisibilityAction {
public final class DivVisibilityAction: DivSightAction {
public let downloadCallbacks: DivDownloadCallbacks?
public let logId: String // at least 1 char
public let logLimit: Expression<Int> // constraint: number >= 0; default value: 1
+1
View File
@@ -7,6 +7,7 @@
{
"properties": {
"visibility_percentage": {
"type": "integer",
"constraint": "number >= 0 && number < 100",
"default_value": "0",
"$description": "translations.json#/div_disappear_action_visibility_percentage"
-3
View File
@@ -12,9 +12,6 @@
},
{
"properties": {
"visibility_percentage": {
"type": "integer"
},
"log_limit": {
"$ref": "common.json#/non_negative_integer",
"default_value": "1",
+1
View File
@@ -7,6 +7,7 @@
{
"properties": {
"visibility_percentage": {
"type": "integer",
"constraint": "number > 0 && number <= 100",
"default_value": "50",
"$description": "translations.json#/div_visibility_action_visibility_percentage"