Created
February 3, 2023 00:21
-
-
Save crisrojas/130e36ffddde91f8696d5ad081597304 to your computer and use it in GitHub Desktop.
Simple demo counter implemented with the Khipu architecture
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import SwiftUI | |
fileprivate var store = createRamStore() | |
fileprivate var viewState = ViewState(store: store) | |
fileprivate var rootHandler = createCore(store: store) | |
@main | |
struct MyApp: App { | |
var body: some Scene { | |
WindowGroup { | |
ContentView( | |
viewState: viewState, | |
rootHandler: rootHandler | |
) | |
} | |
} | |
} | |
enum Message {case increase ; case decrease} | |
typealias Input = (Message) -> Void | |
typealias Core = (Message) -> Void | |
struct AppState { let count: Int } | |
extension AppState { enum Change { case increase ; case decrease } } | |
extension AppState { | |
func alter(_ change: Change) -> Self { | |
switch change { | |
case .increase: return .init(count: count + 1) | |
case .decrease: return .init(count: count - 1) | |
} | |
} | |
} | |
typealias Change = (AppState.Change) -> Void | |
typealias Callback = (@escaping()->()) -> Void | |
typealias Access = ( ) -> AppState | |
typealias StateStore = ( | |
state: Access, | |
change: Change, | |
updated: Callback | |
) | |
extension [()->()] { func call() {forEach {$0()}}} | |
func createRamStore() -> StateStore { | |
var state = AppState(count: 0) {didSet { | |
callbacks.call() | |
}} | |
var callbacks = [()->()]() | |
return ( | |
state: { state }, | |
change: { state = state.alter($0) }, | |
updated: { callbacks.append($0) } | |
) | |
} | |
func createCore(store: StateStore) -> Core {{ | |
if case .increase = $0 { store.change(.increase) } | |
if case .decrease = $0 { store.change(.decrease) } | |
}} | |
final class ViewState: ObservableObject { | |
@Published var count: Int? | |
init(store: StateStore) { | |
process(store.state()) | |
store.updated { | |
self.process(store.state()) | |
} | |
} | |
func process(_ state: AppState) { | |
count = state.count | |
} | |
} | |
struct ContentView: View { | |
@StateObject var viewState: ViewState | |
let rootHandler: Core | |
func increase() {rootHandler(.increase)} | |
func decrease() {rootHandler(.decrease)} | |
var body: some View { | |
if let count = viewState.count { | |
Stepper( | |
count.description, | |
onIncrement: increase, | |
onDecrement: decrease | |
) | |
.padding(.horizontal) | |
} else { | |
ProgressView() | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment