-
Notifications
You must be signed in to change notification settings - Fork 506
/
RoutingManager.ts
94 lines (75 loc) · 2.47 KB
/
RoutingManager.ts
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
import { InstantSearch, UiState, Router, StateMapping } from '../types';
import { Index } from '../widgets/index/index';
type RoutingManagerProps = {
instantSearchInstance: InstantSearch;
router: Router;
stateMapping: StateMapping;
};
const walk = (current: Index, callback: (index: Index) => void) => {
callback(current);
current
.getWidgets()
.filter(function(widget): widget is Index {
return widget.$$type === 'ais.index';
})
.forEach(innerIndex => {
walk(innerIndex, callback);
});
};
class RoutingManager {
private readonly instantSearchInstance: InstantSearch;
private readonly router: Router;
private readonly stateMapping: StateMapping;
public constructor({
router,
stateMapping,
instantSearchInstance,
}: RoutingManagerProps) {
this.router = router;
this.stateMapping = stateMapping;
this.instantSearchInstance = instantSearchInstance;
this.createURL = this.createURL.bind(this);
}
public applyStateFromRoute(): void {
const currentUiState = this.stateMapping.routeToState(this.router.read());
walk(this.instantSearchInstance.mainIndex, current => {
const widgets = current.getWidgets();
const indexUiState = currentUiState[current.getIndexId()] || {};
const searchParameters = widgets.reduce((parameters, widget) => {
if (!widget.getWidgetSearchParameters) {
return parameters;
}
return widget.getWidgetSearchParameters(parameters, {
uiState: indexUiState,
});
}, current.getHelper()!.state);
current
.getHelper()!
.overrideStateWithoutTriggeringChangeEvent(searchParameters);
this.instantSearchInstance.scheduleSearch();
});
// @TODO: Update state on external route update (popState)
// this.router.onUpdate(route => {});
}
public write({ state }: { state: UiState }) {
const route = this.stateMapping.stateToRoute(state);
this.router.write(route);
}
public dispose({ helper, state }): void {
if (this.router.dispose) {
this.router.dispose({ helper, state });
}
}
public createURL(nextState: UiState): string {
const uiState = Object.keys(nextState).reduce(
(acc, indexId) => ({
...acc,
[indexId]: nextState[indexId],
}),
this.instantSearchInstance.mainIndex.getWidgetState({})
);
const route = this.stateMapping.stateToRoute(uiState);
return this.router.createURL(route);
}
}
export default RoutingManager;