1
1
mirror of https://github.com/qvacua/vimr.git synced 2024-11-24 11:37:32 +03:00
vimr/VimR/Context.swift
2017-02-01 22:26:19 +01:00

92 lines
2.9 KiB
Swift

/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
import Foundation
import RxSwift
class StateContext {
let stateSource: Observable<AppState>
let actionEmitter = Emitter<Any>()
init() {
self.stateSource = self.stateSubject.asObservable()
let actionSource = self.actionEmitter.observable
self.httpServerService = HttpServerService(port: NetUtils.openPort())
Observable
.of(
actionSource
.mapOmittingNil { $0 as? AppDelegate.Action }
.map { StateActionPair(state: self.appState, action: $0, modified: false) }
.transform(by: self.appDelegateTransformer)
.filter { $0.modified }
.map { $0.state },
actionSource
.mapOmittingNil { $0 as? UuidAction<MainWindow.Action> }
.map { StateActionPair(state: self.appState, action: $0, modified: false) }
.transform(by: self.uiRootTransformer)
.filter { $0.modified }
.map { $0.state }
)
.merge()
.subscribe(onNext: { state in
self.appState = state
self.stateSubject.onNext(self.appState)
})
.addDisposableTo(self.disposeBag)
actionSource
.mapOmittingNil { $0 as? UuidAction<MainWindow.Action> }
.mapOmittingNil { action in
guard let mainWindowState = self.appState.mainWindows[action.uuid] else {
return nil
}
return StateActionPair(state: UuidState(uuid: action.uuid, state: mainWindowState),
action: action.payload,
modified: false)
}
.transform(by: self.mainWindowTransformer)
.transform(by: self.previewTransformer)
.filter { $0.modified }
.map { $0.state }
.applyState(to: self.httpServerService)
.subscribe(onNext: { state in
self.appState.mainWindows[state.uuid] = state.payload
self.stateSubject.onNext(self.appState)
})
.addDisposableTo(self.disposeBag)
actionSource.debug().subscribe().addDisposableTo(self.disposeBag)
stateSource.debug().subscribe().addDisposableTo(self.disposeBag)
}
fileprivate let stateSubject = PublishSubject<AppState>()
fileprivate let scheduler = SerialDispatchQueueScheduler(qos: .userInitiated)
fileprivate let disposeBag = DisposeBag()
fileprivate var appState = AppState.default
fileprivate let appDelegateTransformer = AppDelegateTransformer()
fileprivate let uiRootTransformer = UiRootTransformer()
fileprivate let mainWindowTransformer = MainWindowTransformer()
fileprivate let previewTransformer = PreviewTransformer()
fileprivate let httpServerService: HttpServerService
}
extension Observable {
fileprivate func transform<T: Transformer>(by transformer: T) -> Observable<Element> where T.Element == Element {
return transformer.transform(self)
}
fileprivate func applyState<S: Service>(to service: S) -> Observable<Element> where S.StateType == Element {
return service.apply(self)
}
}