]>
Commit | Line | Data |
---|---|---|
0af2a8c5 | 1 | import { ComponentRef, Injectable } from '@angular/core' |
9df52d66 | 2 | import { ActivatedRouteSnapshot, DetachedRouteHandle, RouteReuseStrategy } from '@angular/router' |
0af2a8c5 C |
3 | import { DisableForReuseHook } from './disable-for-reuse-hook' |
4 | import { PeerTubeRouterService, RouterSetting } from './peertube-router.service' | |
489290b8 | 5 | |
2f5d2ec5 | 6 | @Injectable() |
489290b8 C |
7 | export class CustomReuseStrategy implements RouteReuseStrategy { |
8 | storedRouteHandles = new Map<string, DetachedRouteHandle>() | |
9 | recentlyUsed: string | |
10 | ||
11 | private readonly MAX_SIZE = 2 | |
12 | ||
13 | // Decides if the route should be stored | |
14 | shouldDetach (route: ActivatedRouteSnapshot): boolean { | |
15 | return this.isReuseEnabled(route) | |
16 | } | |
17 | ||
18 | // Store the information for the route we're destructing | |
19 | store (route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void { | |
20 | if (!handle) return | |
21 | ||
22 | const key = this.generateKey(route) | |
23 | this.recentlyUsed = key | |
24 | ||
0af2a8c5 | 25 | console.log('Storing component %s to reuse later.', key) |
489290b8 | 26 | |
0af2a8c5 C |
27 | const componentRef = (handle as any).componentRef as ComponentRef<DisableForReuseHook> |
28 | componentRef.instance.disableForReuse() | |
29 | componentRef.changeDetectorRef.detectChanges() | |
489290b8 C |
30 | |
31 | this.storedRouteHandles.set(key, handle) | |
32 | ||
33 | this.gb() | |
34 | } | |
35 | ||
36 | // Return true if we have a stored route object for the next route | |
37 | shouldAttach (route: ActivatedRouteSnapshot): boolean { | |
38 | const key = this.generateKey(route) | |
39 | return this.isReuseEnabled(route) && this.storedRouteHandles.has(key) | |
40 | } | |
41 | ||
42 | // If we returned true in shouldAttach(), now return the actual route data for restoration | |
43 | retrieve (route: ActivatedRouteSnapshot): DetachedRouteHandle { | |
44 | if (!this.isReuseEnabled(route)) return undefined | |
45 | ||
46 | const key = this.generateKey(route) | |
47 | this.recentlyUsed = key | |
48 | ||
49 | console.log('Reusing component %s.', key) | |
50 | ||
51 | const handle = this.storedRouteHandles.get(key) | |
52 | if (!handle) return handle; | |
53 | ||
54 | (handle as any).componentRef.instance.enabledForReuse() | |
55 | ||
56 | return handle | |
57 | } | |
58 | ||
59 | // Reuse the route if we're going to and from the same route | |
60 | shouldReuseRoute (future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean { | |
d63e6d46 | 61 | return future.routeConfig === curr.routeConfig && future.routeConfig?.data?.reloadOnSameNavigation !== true |
489290b8 C |
62 | } |
63 | ||
64 | private gb () { | |
65 | if (this.storedRouteHandles.size >= this.MAX_SIZE) { | |
66 | this.storedRouteHandles.forEach((r, key) => { | |
67 | if (key === this.recentlyUsed) return | |
68 | ||
69 | console.log('Removing stored component %s.', key); | |
70 | ||
71 | (r as any).componentRef.destroy() | |
72 | this.storedRouteHandles.delete(key) | |
73 | }) | |
74 | } | |
75 | } | |
76 | ||
77 | private generateKey (route: ActivatedRouteSnapshot) { | |
78 | const reuse = route.data.reuse | |
79 | if (!reuse) return undefined | |
80 | ||
81 | return reuse.key + JSON.stringify(route.queryParams) | |
82 | } | |
83 | ||
84 | private isReuseEnabled (route: ActivatedRouteSnapshot) { | |
dd24f1bb C |
85 | // Cannot use peertube router here because of cyclic router dependency |
86 | return route.data.reuse?.enabled && | |
87 | !!(route.queryParams[PeerTubeRouterService.ROUTE_SETTING_NAME] & RouterSetting.REUSE_COMPONENT) | |
489290b8 C |
88 | } |
89 | } |