Skip to content

Instantly share code, notes, and snippets.

@taskcruncher
Last active December 3, 2022 21:58
Show Gist options
  • Save taskcruncher/34a4ca10d1409dd8eff6f56410004860 to your computer and use it in GitHub Desktop.
Save taskcruncher/34a4ca10d1409dd8eff6f56410004860 to your computer and use it in GitHub Desktop.
//
// ContentView.swift
// scopetest
//
// Created by Steedman Bass on 11/6/22.
//
import ComposableArchitecture
import SwiftUI
@dynamicMemberLookup
struct TCASharedState<State: Equatable>: Equatable {
var sharedState: SharedState
var state: State
init(sharedState: SharedState, state: State){
self.sharedState = sharedState
self.state = state
}
//https://www.swiftbysundell.com/tips/combining-dynamic-member-lookup-with-key-paths/
subscript<T>(dynamicMember keyPath: WritableKeyPath<State, T>) -> T {
get { state[keyPath: keyPath] }
set { state[keyPath: keyPath] = newValue }
}
}
struct TCAApp: ReducerProtocol {
struct State: Equatable {
var sharedState: SharedState
var onlyPerson = Person()
var personState: PersonPlusSharedState.State {
get {
PersonPlusSharedState.State(baseState: TCASharedState(sharedState: sharedState, state: onlyPerson))
}
set {
sharedState = newValue.baseState.sharedState
onlyPerson = newValue.baseState.state
}
}
var dog: Dog.State
}
enum Action: Equatable {
case dogAction(Dog.Action)
case personAction( PersonPlusSharedState.Action)
case changeOnlineStatus
}
var body: some ReducerProtocol<State, Action> {
Reduce{(state, action) -> Effect<Action, Never> in
switch action {
case .changeOnlineStatus:
state.sharedState.onlineStatus.online.toggle()
return .none
default: return .none
}
}
Scope(state: \State.personState, action: /Action.personAction) {
PersonPlusSharedState()
}
Scope(state: \State.dog, action: /Action.dogAction) {
Dog()
}
}
}
struct SharedState: Equatable {
var onlineStatus: OnlineStatus = OnlineStatus()
var simperium: Simperium = Simperium()
}
class DogColor: Equatable {
static func == (lhs: DogColor, rhs: DogColor) -> Bool {
lhs.color == rhs.color
}
var color = "Blue"
}
struct Simperium : Equatable {
var authToken = "aabb"
}
struct OnlineStatus: Equatable {
var online = false
}
struct PersonPlusSharedState: ReducerProtocol {
func reduce(into state: inout State, action: Action) -> EffectTask<Action> {
switch action {
case .updateName: if state.baseState.state.name == "bill" {state.baseState.state.name = "fred"} else {state.baseState.state.name = "bill"}
}
return .none
}
@dynamicMemberLookup
struct State: Equatable {
var baseState: TCASharedState<Person>
subscript<T>(dynamicMember keyPath: WritableKeyPath<TCASharedState<Person>, T>) -> T {
get { baseState[keyPath: keyPath] }
set { baseState[keyPath: keyPath] = newValue }
}
}
enum Action: Equatable {
case updateName
}
}
struct Person: Equatable {
var name = "Bob"
var age = 12
enum Action: Equatable {
case updateName
}
}
struct Dog: ReducerProtocol {
func reduce(into state: inout State, action: Action) -> EffectTask<Action> {
switch action {
case let .changeName(name: name): state.name = name
default: break
}
return .none
}
struct State: Equatable {
var name = "Bob"
var age = "12"
var dogColor = DogColor()
}
enum Action: Equatable {
case changeName(name: String)
case changeColor(color: String)
}
}
struct PersonView: View {
let store: StoreOf<PersonPlusSharedState>
var body: some View {
WithViewStore(self.store, observe: {$0}){vs in
Text(vs.state.baseState.name)
}
}
}
struct ContentView: View {
let store: StoreOf<TCAApp>
var body: some View {
WithViewStore(self.store.scope(state: \.personState, action: {TCAApp.Action.personAction($0)})) {vs in
Text(vs.name)
Button("changeName", action: {vs.send(.updateName)})
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment