-
-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathTimelineRecorderMiddleware.swift
More file actions
53 lines (42 loc) · 1.43 KB
/
TimelineRecorderMiddleware.swift
File metadata and controls
53 lines (42 loc) · 1.43 KB
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
//
// TimelineRecorderMiddleware.swift
// ReduxDemo
//
// Created by Wojciech Kulik on 02/12/2021.
//
import Combine
import Foundation
final class TimelineRecorderMiddleware {
var totalSteps: Int { timeline.count }
var totalLength: TimeInterval { timeline.map(\.timeOffset).reduce(0.0, +) }
private var timeline: [(timeOffset: TimeInterval, state: AppState)] = []
private var shouldRecord = true
private var lastStateChangeDate = Date()
init() {
timeline = [(0.0, AppState())]
}
func middleware(state: AppState, action: Action) -> AnyPublisher<Action, Never> {
if shouldRecord {
timeline.append((timeline.isEmpty ? 0.0 : Date().timeIntervalSince(lastStateChangeDate), state))
}
lastStateChangeDate = Date()
return Empty().eraseToAnyPublisher()
}
func replayTimeline(completion: @escaping () -> ()) {
shouldRecord = false
store.isEnabled = false
replayNextStep(completion: completion)
}
private func replayNextStep(completion: @escaping () -> ()) {
guard let step = timeline.first else {
store.isEnabled = true
shouldRecord = true
return completion()
}
timeline.remove(at: 0)
DispatchQueue.main.asyncAfter(deadline: .now() + step.timeOffset) {
store.restoreState(step.state)
self.replayNextStep(completion: completion)
}
}
}