diff options
Diffstat (limited to 'client/src/app/core')
-rw-r--r-- | client/src/app/core/routing/custom-reuse-strategy.ts | 81 | ||||
-rw-r--r-- | client/src/app/core/routing/disable-for-reuse-hook.ts | 7 |
2 files changed, 88 insertions, 0 deletions
diff --git a/client/src/app/core/routing/custom-reuse-strategy.ts b/client/src/app/core/routing/custom-reuse-strategy.ts new file mode 100644 index 000000000..a9f61acec --- /dev/null +++ b/client/src/app/core/routing/custom-reuse-strategy.ts | |||
@@ -0,0 +1,81 @@ | |||
1 | import { ActivatedRouteSnapshot, DetachedRouteHandle, RouteReuseStrategy } from '@angular/router' | ||
2 | |||
3 | export class CustomReuseStrategy implements RouteReuseStrategy { | ||
4 | storedRouteHandles = new Map<string, DetachedRouteHandle>() | ||
5 | recentlyUsed: string | ||
6 | |||
7 | private readonly MAX_SIZE = 2 | ||
8 | |||
9 | // Decides if the route should be stored | ||
10 | shouldDetach (route: ActivatedRouteSnapshot): boolean { | ||
11 | return this.isReuseEnabled(route) | ||
12 | } | ||
13 | |||
14 | // Store the information for the route we're destructing | ||
15 | store (route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void { | ||
16 | if (!handle) return | ||
17 | |||
18 | const key = this.generateKey(route) | ||
19 | this.recentlyUsed = key | ||
20 | |||
21 | console.log('Storing component %s to reuse later.', key); | ||
22 | |||
23 | (handle as any).componentRef.instance.disableForReuse() | ||
24 | |||
25 | this.storedRouteHandles.set(key, handle) | ||
26 | |||
27 | this.gb() | ||
28 | } | ||
29 | |||
30 | // Return true if we have a stored route object for the next route | ||
31 | shouldAttach (route: ActivatedRouteSnapshot): boolean { | ||
32 | const key = this.generateKey(route) | ||
33 | return this.isReuseEnabled(route) && this.storedRouteHandles.has(key) | ||
34 | } | ||
35 | |||
36 | // If we returned true in shouldAttach(), now return the actual route data for restoration | ||
37 | retrieve (route: ActivatedRouteSnapshot): DetachedRouteHandle { | ||
38 | if (!this.isReuseEnabled(route)) return undefined | ||
39 | |||
40 | const key = this.generateKey(route) | ||
41 | this.recentlyUsed = key | ||
42 | |||
43 | console.log('Reusing component %s.', key) | ||
44 | |||
45 | const handle = this.storedRouteHandles.get(key) | ||
46 | if (!handle) return handle; | ||
47 | |||
48 | (handle as any).componentRef.instance.enabledForReuse() | ||
49 | |||
50 | return handle | ||
51 | } | ||
52 | |||
53 | // Reuse the route if we're going to and from the same route | ||
54 | shouldReuseRoute (future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean { | ||
55 | return future.routeConfig === curr.routeConfig | ||
56 | } | ||
57 | |||
58 | private gb () { | ||
59 | if (this.storedRouteHandles.size >= this.MAX_SIZE) { | ||
60 | this.storedRouteHandles.forEach((r, key) => { | ||
61 | if (key === this.recentlyUsed) return | ||
62 | |||
63 | console.log('Removing stored component %s.', key); | ||
64 | |||
65 | (r as any).componentRef.destroy() | ||
66 | this.storedRouteHandles.delete(key) | ||
67 | }) | ||
68 | } | ||
69 | } | ||
70 | |||
71 | private generateKey (route: ActivatedRouteSnapshot) { | ||
72 | const reuse = route.data.reuse | ||
73 | if (!reuse) return undefined | ||
74 | |||
75 | return reuse.key + JSON.stringify(route.queryParams) | ||
76 | } | ||
77 | |||
78 | private isReuseEnabled (route: ActivatedRouteSnapshot) { | ||
79 | return route.data.reuse && route.data.reuse.enabled && route.queryParams['a-state'] | ||
80 | } | ||
81 | } | ||
diff --git a/client/src/app/core/routing/disable-for-reuse-hook.ts b/client/src/app/core/routing/disable-for-reuse-hook.ts new file mode 100644 index 000000000..c5eb5c578 --- /dev/null +++ b/client/src/app/core/routing/disable-for-reuse-hook.ts | |||
@@ -0,0 +1,7 @@ | |||
1 | export interface DisableForReuseHook { | ||
2 | |||
3 | disableForReuse (): void | ||
4 | |||
5 | enabledForReuse (): void | ||
6 | |||
7 | } | ||