Skip to content

Commit

Permalink
Store transformations (#16)
Browse files Browse the repository at this point in the history
* implemented store map, flatMap, compactMap

* store transform

* updated store transformations

* updated public Store API implemntation to use transformations under the hood

* added explicit weak/strong ref stores

* use weak store explicitly

* updated transformations to use strong stores
  • Loading branch information
KazaiMazai authored Apr 4, 2024
1 parent 74fbc5c commit 07cdd57
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 30 deletions.
19 changes: 12 additions & 7 deletions Sources/Puredux/Store/StateStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@ public struct StateStore<State, Action> {
let storeObject: any StoreProtocol<State, Action>

public func store() -> Store<State, Action> {
Store<State, Action>(
dispatcher: { [weak storeObject] in storeObject?.dispatch($0) },
subscribe: { [weak storeObject] in storeObject?.subscribe(observer: $0) })
weakStore()
}

public func dispatch(_ action: Action) {
Expand All @@ -29,6 +27,17 @@ public struct StateStore<State, Action> {
}

extension StateStore {
func weakStore() -> Store<State, Action> {
Store<State, Action>(
dispatcher: { [weak storeObject] in storeObject?.dispatch($0) },
subscribe: { [weak storeObject] in storeObject?.subscribe(observer: $0) })
}

func strongStore() -> Store<State, Action> {
Store<State, Action>(
dispatcher: dispatch,
subscribe: subscribe)
}

func createChildStore<LocalState, ResultState>(
initialState: LocalState,
Expand All @@ -45,8 +54,4 @@ extension StateStore {
)
)
}

}



24 changes: 3 additions & 21 deletions Sources/Puredux/Store/Store.swift
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public extension Store {
///
@available(*, deprecated, message: "Will be removed in the next major release. Consider migrating to scope(...)")
func proxy<LocalState>(_ toLocalState: @escaping (State) -> LocalState) -> Store<LocalState, Action> {
scope(to: toLocalState)
map(toLocalState)
}
}

Expand All @@ -99,18 +99,7 @@ public extension Store {
///
///
func scope<LocalState>(toOptional localState: @escaping (State) -> LocalState?) -> Store<LocalState, Action> {
Store<LocalState, Action>(
dispatcher: dispatch,
subscribe: { localStateObserver in
subscribe(observer: Observer<State>(id: localStateObserver.id) { state, complete in
guard let localState = localState(state) else {
complete(.active)
return
}

localStateObserver.send(localState, complete: complete)
})
})
compactMap(localState)
}

/// Initializes a new scope Store with state mapping to local substate.
Expand All @@ -123,14 +112,7 @@ public extension Store {
/// When the result local state is nill, subscribers are not triggered.
///
func scope<LocalState>(to localState: @escaping (State) -> LocalState) -> Store<LocalState, Action> {
Store<LocalState, Action>(
dispatcher: dispatch,
subscribe: { localStateObserver in
subscribe(observer: Observer<State>(id: localStateObserver.id) { state, complete in
let localState = localState(state)
localStateObserver.send(localState, complete: complete)
})
})
map(localState)
}
}

Expand Down
90 changes: 90 additions & 0 deletions Sources/Puredux/Store/Transformations.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
//
// File.swift
//
//
// Created by Sergey Kazakov on 04/04/2024.
//

import Foundation

extension Store {
func map<T>(_ transform: @escaping (State) -> T) -> Store<T, Action> {
Store<T, Action>(
dispatcher: dispatch,
subscribe: { localStateObserver in
subscribe(observer: Observer<State>(id: localStateObserver.id) { state, complete in
let localState = transform(state)
localStateObserver.send(localState, complete: complete)
})
}
)
}

func compactMap<T>(_ transform: @escaping (State) -> T?) -> Store<T, Action> {
Store<T, Action>(
dispatcher: dispatch,
subscribe: { localStateObserver in
subscribe(observer: Observer<State>(id: localStateObserver.id) { state, complete in
guard let localState = transform(state) else {
complete(.active)
return
}

localStateObserver.send(localState, complete: complete)
})
}
)
}

func flatMap<T>(_ transform: @escaping (State) -> T?) -> Store<T?, Action> {
Store<T?, Action>(
dispatcher: dispatch,
subscribe: { localStateObserver in
subscribe(observer: Observer<State>(id: localStateObserver.id) { state, complete in
let localState = transform(state)
localStateObserver.send(localState, complete: complete)
})
}
)
}
}

extension Store {
func map<T>(_ keyPath: KeyPath<State, T>) -> Store<T, Action> {
map { $0[keyPath: keyPath] }
}

func compactMap<T>(_ keyPath: KeyPath<State, T?>) -> Store<T, Action> {
compactMap { $0[keyPath: keyPath] }
}

func flatMap<T>(_ keyPath: KeyPath<State, T?>) -> Store<T?, Action> {
flatMap { $0[keyPath: keyPath] }
}
}

extension StateStore {
func map<T>(_ keyPath: KeyPath<State, T>) -> Store<T, Action> {
strongStore().map(keyPath)
}

func map<T>(_ transform: @escaping (State) -> T) -> Store<T, Action> {
strongStore().map(transform)
}

func compactMap<T>(_ keyPath: KeyPath<State, T?>) -> Store<T, Action> {
strongStore().compactMap(keyPath)
}

func compactMap<T>(_ transform: @escaping (State) -> T?) -> Store<T, Action> {
strongStore().compactMap(transform)
}

func flatMap<T>(_ keyPath: KeyPath<State, T?>) -> Store<T?, Action> {
strongStore().flatMap(keyPath)
}

func flatMap<T>(_ transform: @escaping (State) -> T?) -> Store<T?, Action> {
strongStore().flatMap(transform)
}
}
2 changes: 1 addition & 1 deletion Sources/Puredux/SwiftUI/Store/PublishingStoreObject.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public extension PublishingStoreObject {
/// PublishingStore is thread safe. Actions can be safely dispatched from any thread.
///
func store() -> PublishingStore<AppState, Action> {
let store = stateStore.store()
let store = stateStore.weakStore()
return PublishingStore(
statePublisher: statePublisher(),
dispatch: { store.dispatch($0) }
Expand Down
2 changes: 1 addition & 1 deletion Sources/Puredux/UIKit/Presentable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public extension Presentable {
presentationQueue: PresentationQueue = .sharedPresentationQueue,
removeStateDuplicates equating: Equating<State>? = nil) {

let weakRefStore = store.store()
let weakRefStore = store.weakStore()
let observer = Observer(
self,
removeStateDuplicates: equating,
Expand Down

0 comments on commit 07cdd57

Please sign in to comment.