-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathReMVVMExtension.swift
99 lines (81 loc) · 4.16 KB
/
ReMVVMExtension.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
//
// ReMVVMExtension.swift
// ReMVVMExt
//
// Created by Dariusz Grzeszczak on 07/06/2019.
//
import ReMVVMCore
import UIKit
public struct NavigationStateIOS<ApplicationState>: NavigationState {
public let navigation: Navigation
public let appState: ApplicationState
public var factory: ViewModelFactory {
let factory: CompositeViewModelFactory
if let f = navigation.factory as? CompositeViewModelFactory {
factory = f
} else {
factory = CompositeViewModelFactory(with: navigation.factory)
}
return factory
}
public init(appState: ApplicationState,
navigation: Navigation = Navigation(root: NavigationRoot(current: NavigationRoot.Main.single,
stacks: [(NavigationRoot.Main.single, [])]),
modals: [])) {
self.appState = appState
self.navigation = navigation
}
}
private enum AppNavigationReducer<State, R>: Reducer where R: Reducer, R.State == State, R.Action == StoreAction {
static func reduce(state: NavigationStateIOS<State>, with action: StoreAction) -> NavigationStateIOS<State> {
NavigationStateIOS<State>(
appState: R.reduce(state: state.appState, with: action),
navigation: NavigationReducer.reduce(state: state.navigation, with: action)
)
}
}
// todo rename to ReMVVM
public enum ReMVVMExtension {
public static func initialize<ApplicationState, R>(with state: ApplicationState,
window: UIWindow,
uiStateConfig: UIStateConfig,
stateMappers: [StateMapper<ApplicationState>] = [],
reducer: R.Type,
middleware: [AnyMiddleware],
logger: Logger = .noLogger) -> AnyStore where R: Reducer, R.State == ApplicationState, R.Action == StoreAction {
let appMapper = StateMapper<NavigationStateIOS<ApplicationState>>(for: \.appState)
let stateMappers = [appMapper] + stateMappers.map { $0.map(with: \.appState) }
return self.initialize(with: NavigationStateIOS(appState: state),
window: window,
uiStateConfig: uiStateConfig,
stateMappers: stateMappers,
reducer: AppNavigationReducer<ApplicationState, R>.self,
middleware: middleware,
logger: logger)
}
public static func initialize<State, R>(with state: State,
window: UIWindow,
uiStateConfig: UIStateConfig,
stateMappers: [StateMapper<State>] = [],
reducer: R.Type,
middleware: [AnyMiddleware],
logger: Logger = .noLogger) -> AnyStore where State: NavigationState, R: Reducer, R.State == State, R.Action == StoreAction {
let uiState = UIState(window: window, config: uiStateConfig)
let middleware = [
SynchronizeStateMiddleware<State>(uiState: uiState),
ShowModalMiddleware<State>(uiState: uiState),
DismissModalMiddleware<State>(uiState: uiState),
ShowOnRootMiddleware<State>(uiState: uiState),
ShowMiddleware<State>(uiState: uiState),
PushMiddleware<State>(uiState: uiState),
PopMiddleware<State>(uiState: uiState)
] + middleware
let store = Store<State>(with: state,
reducer: reducer,
middleware: middleware,
stateMappers: stateMappers,
logger: logger)
ReMVVM.initialize(with: store)
return store.any
}
}