More code based on Equatable props
This commit is contained in:
parent
f96157340d
commit
4289c4ee88
|
@ -8,100 +8,49 @@
|
|||
|
||||
import UIKit
|
||||
|
||||
protocol KeyPathListable {
|
||||
// require empty init as the implementation use the mirroring API, which require
|
||||
// to be used on an instance. So we need to be able to create a new instance of the
|
||||
// type.
|
||||
init()
|
||||
|
||||
var _keyPathReadableFormat: [String: Any] { get }
|
||||
static var allKeyPaths: [KeyPath<Foo, Any?>] { get }
|
||||
protocol Default {
|
||||
init()
|
||||
}
|
||||
|
||||
extension KeyPathListable {
|
||||
var _keyPathReadableFormat: [String: Any] {
|
||||
let mirror = Mirror(reflecting: self)
|
||||
var description: [String: Any] = [:]
|
||||
for case let (label?, value) in mirror.children {
|
||||
description[label] = value
|
||||
}
|
||||
return description
|
||||
}
|
||||
class BaseComponent<P: Equatable, S: Default> {
|
||||
private(set) var props: P
|
||||
private(set) var state: S
|
||||
|
||||
static var allKeyPaths: [KeyPath<Self, Any?>] {
|
||||
var keyPaths: [KeyPath<Self, Any?>] = []
|
||||
let instance = Self()
|
||||
for (key, _) in instance._keyPathReadableFormat {
|
||||
keyPaths.append(\Self._keyPathReadableFormat[key])
|
||||
}
|
||||
return keyPaths
|
||||
}
|
||||
init(props: P, state: S) {
|
||||
self.props = props
|
||||
self.state = state
|
||||
}
|
||||
|
||||
static func node(_ p: P,
|
||||
_ c: [NodeType] = []) -> NodeType {
|
||||
return Node(component: self, props: p, children: c)
|
||||
}
|
||||
}
|
||||
|
||||
protocol Diffable: KeyPathListable {
|
||||
protocol NodeType {
|
||||
}
|
||||
|
||||
struct Foo: KeyPathListable {
|
||||
var x: Int
|
||||
var y: Int
|
||||
struct Node<P, S>: NodeType
|
||||
where P: Equatable, S: Default {
|
||||
let component: BaseComponent<P, S>.Type
|
||||
let props: P
|
||||
let children: [NodeType]
|
||||
}
|
||||
|
||||
protocol GluonProp: Hashable {
|
||||
extension UIControl.State: Hashable {
|
||||
public func hash(into hasher: inout Hasher) {
|
||||
hasher.combine(rawValue)
|
||||
}
|
||||
}
|
||||
|
||||
protocol GluonState {
|
||||
init()
|
||||
}
|
||||
final class Button: BaseComponent<Button.Props, Button.State> {
|
||||
struct Props: Equatable {
|
||||
let backgroundColor: UIColor
|
||||
let titles: [UIControl.State: String]
|
||||
}
|
||||
|
||||
protocol AnyBaseComponent {
|
||||
}
|
||||
|
||||
protocol AnyComponent {
|
||||
func render() -> AnyGluonNode
|
||||
}
|
||||
|
||||
class BaseComponent<P: GluonProp, S: GluonState>: AnyBaseComponent {
|
||||
var props: Set<P> = []
|
||||
var state = S()
|
||||
}
|
||||
|
||||
typealias Component<P: GluonProp, S: GluonState> = BaseComponent<P, S> & AnyComponent
|
||||
|
||||
// protocol Gluon: Component {
|
||||
// func render() -> AnyGluonNode
|
||||
// }
|
||||
|
||||
extension BaseComponent {
|
||||
static func node(_ props: Set<P> = [],
|
||||
_ children: [AnyGluonNode] = []) -> GluonNode<P> {
|
||||
return GluonNode(self, props, children)
|
||||
}
|
||||
}
|
||||
|
||||
protocol AnyGluonNode {}
|
||||
|
||||
struct GluonNode<P>: AnyGluonNode
|
||||
where P: GluonProp {
|
||||
let component: AnyBaseComponent.Type
|
||||
let props: Set<P>
|
||||
let children: [AnyGluonNode]
|
||||
|
||||
init(_ component: AnyBaseComponent.Type,
|
||||
_ props: Set<P>,
|
||||
_ children: [AnyGluonNode]) {
|
||||
self.component = component
|
||||
self.props = props
|
||||
self.children = children
|
||||
}
|
||||
}
|
||||
|
||||
extension String: AnyGluonNode {
|
||||
}
|
||||
|
||||
enum ButtonProp: GluonProp {
|
||||
case backgroundColor(UIColor)
|
||||
case textColor(UIColor)
|
||||
case disabled(Bool)
|
||||
struct State: Default {
|
||||
}
|
||||
}
|
||||
|
||||
//final class Button: BaseComponent<ButtonProp> {
|
||||
|
|
Loading…
Reference in New Issue