mirror of
https://github.com/divkit/divkit.git
synced 2026-06-06 20:07:59 +00:00
e0efba60b9
commit_hash:9357f968304ae7bad3b9e7541b6b03a90bfd0b6e
269 lines
6.1 KiB
Swift
269 lines
6.1 KiB
Swift
import Foundation
|
|
import VGSL
|
|
|
|
public struct UserInterfaceAction: Equatable, Codable {
|
|
@frozen
|
|
public enum Payload: Equatable {
|
|
case empty // means just analytics logging
|
|
case url(URL)
|
|
case menu(Menu)
|
|
case divAction(params: DivActionParams)
|
|
}
|
|
|
|
public struct DivActionParams: Equatable {
|
|
public let action: JSONObject
|
|
public let path: UIElementPath
|
|
public let source: DivActionSource
|
|
public let url: URL?
|
|
public let localValues: [String: AnyHashable]
|
|
|
|
public var cardId: String {
|
|
path.root
|
|
}
|
|
|
|
public init(
|
|
action: JSONObject,
|
|
path: UIElementPath,
|
|
source: DivActionSource,
|
|
url: URL?,
|
|
localValues: [String: AnyHashable] = [:]
|
|
) {
|
|
self.action = action
|
|
self.path = path
|
|
self.source = source
|
|
self.url = url
|
|
self.localValues = localValues
|
|
}
|
|
}
|
|
|
|
@frozen
|
|
public enum DivActionSource: String {
|
|
case tap
|
|
case visibility
|
|
case disappear
|
|
case timer
|
|
case trigger
|
|
case callback
|
|
case property
|
|
}
|
|
|
|
public let payload: Payload
|
|
public let path: UIElementPath
|
|
public let accessibilityElement: AccessibilityElement?
|
|
|
|
public var url: URL? {
|
|
payload.url
|
|
}
|
|
|
|
public init(
|
|
payload: Payload,
|
|
path: UIElementPath,
|
|
accessibilityElement: AccessibilityElement?
|
|
) {
|
|
self.payload = payload
|
|
self.path = path
|
|
self.accessibilityElement = accessibilityElement
|
|
}
|
|
|
|
public init(
|
|
payload: Payload,
|
|
path: UIElementPath
|
|
) {
|
|
self.init(
|
|
payload: payload,
|
|
path: path,
|
|
accessibilityElement: nil
|
|
)
|
|
}
|
|
|
|
public init(
|
|
url: URL,
|
|
path: UIElementPath,
|
|
accessibilityElement: AccessibilityElement? = nil
|
|
) {
|
|
self.init(
|
|
payload: .url(url),
|
|
path: path,
|
|
accessibilityElement: accessibilityElement
|
|
)
|
|
}
|
|
|
|
public init(
|
|
menu: Menu,
|
|
path: UIElementPath,
|
|
accessibilityElement: AccessibilityElement? = nil
|
|
) {
|
|
self.init(
|
|
payload: .menu(menu),
|
|
path: path,
|
|
accessibilityElement: accessibilityElement
|
|
)
|
|
}
|
|
|
|
public init(path: UIElementPath, accessibilityElement: AccessibilityElement? = nil) {
|
|
self.init(payload: .empty, path: path, accessibilityElement: accessibilityElement)
|
|
}
|
|
}
|
|
|
|
extension UserInterfaceAction.Payload: Codable {
|
|
private enum Kind: String {
|
|
case empty
|
|
case url
|
|
case menu
|
|
case divAction
|
|
}
|
|
|
|
private enum CodingKeys: String, CodingKey {
|
|
case kind
|
|
case url
|
|
case menu
|
|
case json
|
|
case path
|
|
case divActionSource
|
|
}
|
|
|
|
private var kind: Kind {
|
|
switch self {
|
|
case .empty:
|
|
.empty
|
|
case .url:
|
|
.url
|
|
case .menu:
|
|
.menu
|
|
case .divAction:
|
|
.divAction
|
|
}
|
|
}
|
|
|
|
public init(from decoder: Decoder) throws {
|
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
|
|
|
let kindString = try container.decode(String.self, forKey: .kind)
|
|
let kind = Kind(rawValue: kindString)
|
|
|
|
switch kind {
|
|
case .none:
|
|
throw DecodingError.dataCorrupted(
|
|
DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "")
|
|
)
|
|
case .empty?:
|
|
self = .empty
|
|
case .url?:
|
|
let url = try container.decode(URL.self, forKey: .url)
|
|
self = .url(url)
|
|
case .menu?:
|
|
let menu = try container.decode(Menu.self, forKey: .menu)
|
|
self = .menu(menu)
|
|
case .divAction?:
|
|
let source = try container.decodeIfPresent(String.self, forKey: .divActionSource)
|
|
let params = try UserInterfaceAction.DivActionParams(
|
|
action: container.decode(JSONObject.self, forKey: .json),
|
|
path: UIElementPath.parse(container.decode(String.self, forKey: .path)),
|
|
source: UserInterfaceAction.DivActionSource(rawValue: source ?? "") ?? .tap,
|
|
url: container.decodeIfPresent(URL.self, forKey: .url),
|
|
localValues: [:]
|
|
)
|
|
self = .divAction(params: params)
|
|
}
|
|
}
|
|
|
|
public func encode(to encoder: Encoder) throws {
|
|
var container = encoder.container(keyedBy: CodingKeys.self)
|
|
|
|
try container.encode(kind.rawValue, forKey: .kind)
|
|
|
|
switch self {
|
|
case .empty:
|
|
break
|
|
case let .url(url):
|
|
try container.encode(url, forKey: .url)
|
|
case let .menu(menu):
|
|
try container.encode(menu, forKey: .menu)
|
|
case let .divAction(params):
|
|
try container.encode(params.action, forKey: .json)
|
|
try container.encode(params.path.description, forKey: .path)
|
|
try container.encode(params.source.rawValue, forKey: .divActionSource)
|
|
try container.encodeIfPresent(params.url, forKey: .url)
|
|
}
|
|
}
|
|
}
|
|
|
|
extension UserInterfaceAction.Payload: CustomDebugStringConvertible {
|
|
public var debugDescription: String {
|
|
switch self {
|
|
case .empty:
|
|
"Empty"
|
|
case let .url(value):
|
|
"URL: \(value)"
|
|
case let .menu(value):
|
|
"Menu: \(value)"
|
|
case let .divAction(params):
|
|
"DivAction: \(params.action)"
|
|
}
|
|
}
|
|
}
|
|
|
|
extension URL? {
|
|
public func action(
|
|
with path: UIElementPath,
|
|
accessibilityElement: AccessibilityElement? = nil
|
|
) -> UserInterfaceAction? {
|
|
flatMap { $0.action(with: path, accessibilityElement: accessibilityElement) }
|
|
}
|
|
}
|
|
|
|
extension URL {
|
|
public func action(
|
|
with path: UIElementPath,
|
|
accessibilityElement: AccessibilityElement? = nil
|
|
) -> UserInterfaceAction {
|
|
UserInterfaceAction(
|
|
url: self,
|
|
path: path,
|
|
accessibilityElement: accessibilityElement
|
|
)
|
|
}
|
|
}
|
|
|
|
extension UserInterfaceAction.Payload {
|
|
public enum Error: Swift.Error {
|
|
case notAnURL
|
|
}
|
|
|
|
public var url: URL? {
|
|
switch self {
|
|
case let .url(value):
|
|
value
|
|
case let .divAction(params):
|
|
params.source == .visibility ? nil : params.url
|
|
case .empty, .menu:
|
|
nil
|
|
}
|
|
}
|
|
|
|
public func getComposedURLs() throws -> [URL] {
|
|
switch self {
|
|
case let .url(url):
|
|
return [url]
|
|
case let .divAction(params):
|
|
guard let url = params.url else {
|
|
throw Error.notAnURL
|
|
}
|
|
return [url]
|
|
case .empty:
|
|
return []
|
|
case .menu:
|
|
throw Error.notAnURL
|
|
}
|
|
}
|
|
|
|
public var divActionParams: UserInterfaceAction.DivActionParams? {
|
|
switch self {
|
|
case let .divAction(params):
|
|
params
|
|
case .empty, .menu, .url:
|
|
nil
|
|
}
|
|
}
|
|
}
|