diff options
author | Chocobozzz <me@florianbigard.com> | 2021-08-25 11:42:30 +0200 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2021-08-25 11:42:30 +0200 |
commit | fdec51e3846d50e3375612a6820ed3ab0b5fcd25 (patch) | |
tree | 17283e85a6794c9e8fe3f5d4478a406d8d188425 /client/src/app/core | |
parent | 59c8902a57991be29f0aacac1642389fb770c6ed (diff) | |
parent | dd24f1bb0a4b252e5342b251ba36853364da7b8e (diff) | |
download | PeerTube-fdec51e3846d50e3375612a6820ed3ab0b5fcd25.tar.gz PeerTube-fdec51e3846d50e3375612a6820ed3ab0b5fcd25.tar.zst PeerTube-fdec51e3846d50e3375612a6820ed3ab0b5fcd25.zip |
Merge branch 'feature/video-filters' into develop
Diffstat (limited to 'client/src/app/core')
-rw-r--r-- | client/src/app/core/core.module.ts | 14 | ||||
-rw-r--r-- | client/src/app/core/routing/custom-reuse-strategy.ts | 6 | ||||
-rw-r--r-- | client/src/app/core/routing/index.ts | 2 | ||||
-rw-r--r-- | client/src/app/core/routing/peertube-router.service.ts | 78 | ||||
-rw-r--r-- | client/src/app/core/routing/scroll.service.ts | 91 |
5 files changed, 189 insertions, 2 deletions
diff --git a/client/src/app/core/core.module.ts b/client/src/app/core/core.module.ts index 3e2056481..04be0671c 100644 --- a/client/src/app/core/core.module.ts +++ b/client/src/app/core/core.module.ts | |||
@@ -14,7 +14,17 @@ import { throwIfAlreadyLoaded } from './module-import-guard' | |||
14 | import { Notifier } from './notification' | 14 | import { Notifier } from './notification' |
15 | import { HtmlRendererService, LinkifierService, MarkdownService } from './renderer' | 15 | import { HtmlRendererService, LinkifierService, MarkdownService } from './renderer' |
16 | import { RestExtractor, RestService } from './rest' | 16 | import { RestExtractor, RestService } from './rest' |
17 | import { HomepageRedirectComponent, LoginGuard, MetaGuard, MetaService, RedirectService, UnloggedGuard, UserRightGuard } from './routing' | 17 | import { |
18 | HomepageRedirectComponent, | ||
19 | LoginGuard, | ||
20 | MetaGuard, | ||
21 | MetaService, | ||
22 | PeerTubeRouterService, | ||
23 | RedirectService, | ||
24 | ScrollService, | ||
25 | UnloggedGuard, | ||
26 | UserRightGuard | ||
27 | } from './routing' | ||
18 | import { CanDeactivateGuard } from './routing/can-deactivate-guard.service' | 28 | import { CanDeactivateGuard } from './routing/can-deactivate-guard.service' |
19 | import { ServerConfigResolver } from './routing/server-config-resolver.service' | 29 | import { ServerConfigResolver } from './routing/server-config-resolver.service' |
20 | import { ScopedTokensService } from './scoped-tokens' | 30 | import { ScopedTokensService } from './scoped-tokens' |
@@ -80,6 +90,8 @@ import { LocalStorageService, ScreenService, SessionStorageService } from './wra | |||
80 | PeerTubeSocket, | 90 | PeerTubeSocket, |
81 | ServerConfigResolver, | 91 | ServerConfigResolver, |
82 | CanDeactivateGuard, | 92 | CanDeactivateGuard, |
93 | PeerTubeRouterService, | ||
94 | ScrollService, | ||
83 | 95 | ||
84 | MetaService, | 96 | MetaService, |
85 | MetaGuard | 97 | MetaGuard |
diff --git a/client/src/app/core/routing/custom-reuse-strategy.ts b/client/src/app/core/routing/custom-reuse-strategy.ts index c2510f1df..3000093a8 100644 --- a/client/src/app/core/routing/custom-reuse-strategy.ts +++ b/client/src/app/core/routing/custom-reuse-strategy.ts | |||
@@ -1,5 +1,7 @@ | |||
1 | import { Injectable } from '@angular/core' | 1 | import { Injectable } from '@angular/core' |
2 | import { ActivatedRouteSnapshot, DetachedRouteHandle, RouteReuseStrategy } from '@angular/router' | 2 | import { ActivatedRouteSnapshot, DetachedRouteHandle, RouteReuseStrategy } from '@angular/router' |
3 | import { RouterSetting } from './' | ||
4 | import { PeerTubeRouterService } from './peertube-router.service' | ||
3 | 5 | ||
4 | @Injectable() | 6 | @Injectable() |
5 | export class CustomReuseStrategy implements RouteReuseStrategy { | 7 | export class CustomReuseStrategy implements RouteReuseStrategy { |
@@ -78,6 +80,8 @@ export class CustomReuseStrategy implements RouteReuseStrategy { | |||
78 | } | 80 | } |
79 | 81 | ||
80 | private isReuseEnabled (route: ActivatedRouteSnapshot) { | 82 | private isReuseEnabled (route: ActivatedRouteSnapshot) { |
81 | return route.data.reuse?.enabled && route.queryParams['a-state'] | 83 | // Cannot use peertube router here because of cyclic router dependency |
84 | return route.data.reuse?.enabled && | ||
85 | !!(route.queryParams[PeerTubeRouterService.ROUTE_SETTING_NAME] & RouterSetting.REUSE_COMPONENT) | ||
82 | } | 86 | } |
83 | } | 87 | } |
diff --git a/client/src/app/core/routing/index.ts b/client/src/app/core/routing/index.ts index d0c688a2f..3b1690ecc 100644 --- a/client/src/app/core/routing/index.ts +++ b/client/src/app/core/routing/index.ts | |||
@@ -5,9 +5,11 @@ export * from './homepage-redirect.component' | |||
5 | export * from './login-guard.service' | 5 | export * from './login-guard.service' |
6 | export * from './menu-guard.service' | 6 | export * from './menu-guard.service' |
7 | export * from './meta-guard.service' | 7 | export * from './meta-guard.service' |
8 | export * from './peertube-router.service' | ||
8 | export * from './meta.service' | 9 | export * from './meta.service' |
9 | export * from './preload-selected-modules-list' | 10 | export * from './preload-selected-modules-list' |
10 | export * from './redirect.service' | 11 | export * from './redirect.service' |
12 | export * from './scroll.service' | ||
11 | export * from './server-config-resolver.service' | 13 | export * from './server-config-resolver.service' |
12 | export * from './unlogged-guard.service' | 14 | export * from './unlogged-guard.service' |
13 | export * from './user-right-guard.service' | 15 | export * from './user-right-guard.service' |
diff --git a/client/src/app/core/routing/peertube-router.service.ts b/client/src/app/core/routing/peertube-router.service.ts new file mode 100644 index 000000000..35716cc79 --- /dev/null +++ b/client/src/app/core/routing/peertube-router.service.ts | |||
@@ -0,0 +1,78 @@ | |||
1 | import { filter } from 'rxjs/operators' | ||
2 | import { Injectable } from '@angular/core' | ||
3 | import { ActivatedRoute, ActivatedRouteSnapshot, Event, NavigationEnd, Router, Scroll } from '@angular/router' | ||
4 | import { ServerService } from '../server' | ||
5 | |||
6 | export const enum RouterSetting { | ||
7 | NONE = 0, | ||
8 | REUSE_COMPONENT = 1 << 0, | ||
9 | DISABLE_SCROLL_RESTORE = 1 << 1 | ||
10 | } | ||
11 | |||
12 | @Injectable() | ||
13 | export class PeerTubeRouterService { | ||
14 | static readonly ROUTE_SETTING_NAME = 's' | ||
15 | |||
16 | constructor ( | ||
17 | private route: ActivatedRoute, | ||
18 | private router: Router, | ||
19 | private server: ServerService | ||
20 | ) { } | ||
21 | |||
22 | addRouteSetting (toAdd: RouterSetting) { | ||
23 | if (this.hasRouteSetting(toAdd)) return | ||
24 | |||
25 | const current = this.getRouteSetting() | ||
26 | |||
27 | this.setRouteSetting(current | toAdd) | ||
28 | } | ||
29 | |||
30 | deleteRouteSetting (toDelete: RouterSetting) { | ||
31 | const current = this.getRouteSetting() | ||
32 | |||
33 | this.setRouteSetting(current & ~toDelete) | ||
34 | } | ||
35 | |||
36 | getRouteSetting (snapshot?: ActivatedRouteSnapshot) { | ||
37 | return (snapshot || this.route.snapshot).queryParams[PeerTubeRouterService.ROUTE_SETTING_NAME] | ||
38 | } | ||
39 | |||
40 | setRouteSetting (value: number) { | ||
41 | let path = window.location.pathname | ||
42 | if (!path || path === '/') path = this.server.getHTMLConfig().instance.defaultClientRoute | ||
43 | |||
44 | const queryParams = { [PeerTubeRouterService.ROUTE_SETTING_NAME]: value } | ||
45 | |||
46 | this.router.navigate([ path ], { queryParams, replaceUrl: true, queryParamsHandling: 'merge' }) | ||
47 | } | ||
48 | |||
49 | hasRouteSetting (setting: RouterSetting, snapshot?: ActivatedRouteSnapshot) { | ||
50 | return !!(this.getRouteSetting(snapshot) & setting) | ||
51 | } | ||
52 | |||
53 | getNavigationEndEvents () { | ||
54 | return this.router.events.pipe( | ||
55 | filter((e: Event): e is NavigationEnd => e instanceof NavigationEnd) | ||
56 | ) | ||
57 | } | ||
58 | |||
59 | getScrollEvents () { | ||
60 | return this.router.events.pipe( | ||
61 | filter((e: Event): e is Scroll => e instanceof Scroll) | ||
62 | ) | ||
63 | } | ||
64 | |||
65 | silentNavigate (baseRoute: string[], queryParams: { [id: string]: string }) { | ||
66 | let routeSetting = this.getRouteSetting() ?? RouterSetting.NONE | ||
67 | routeSetting |= RouterSetting.DISABLE_SCROLL_RESTORE | ||
68 | |||
69 | queryParams = { | ||
70 | ...queryParams, | ||
71 | |||
72 | [PeerTubeRouterService.ROUTE_SETTING_NAME]: routeSetting | ||
73 | } | ||
74 | |||
75 | return this.router.navigate(baseRoute, { queryParams }) | ||
76 | } | ||
77 | |||
78 | } | ||
diff --git a/client/src/app/core/routing/scroll.service.ts b/client/src/app/core/routing/scroll.service.ts new file mode 100644 index 000000000..bd5076502 --- /dev/null +++ b/client/src/app/core/routing/scroll.service.ts | |||
@@ -0,0 +1,91 @@ | |||
1 | import * as debug from 'debug' | ||
2 | import { pairwise } from 'rxjs' | ||
3 | import { ViewportScroller } from '@angular/common' | ||
4 | import { Injectable } from '@angular/core' | ||
5 | import { RouterSetting } from '../' | ||
6 | import { PeerTubeRouterService } from './peertube-router.service' | ||
7 | |||
8 | const logger = debug('peertube:main:ScrollService') | ||
9 | |||
10 | @Injectable() | ||
11 | export class ScrollService { | ||
12 | |||
13 | private resetScroll = true | ||
14 | |||
15 | constructor ( | ||
16 | private viewportScroller: ViewportScroller, | ||
17 | private peertubeRouter: PeerTubeRouterService | ||
18 | ) { } | ||
19 | |||
20 | enableScrollRestoration () { | ||
21 | // We'll manage scroll restoration ourselves | ||
22 | this.viewportScroller.setHistoryScrollRestoration('manual') | ||
23 | |||
24 | this.consumeScroll() | ||
25 | this.produceScroll() | ||
26 | } | ||
27 | |||
28 | private produceScroll () { | ||
29 | // When we add the a-state parameter, we don't want to alter the scroll | ||
30 | this.peertubeRouter.getNavigationEndEvents().pipe(pairwise()) | ||
31 | .subscribe(([ e1, e2 ]) => { | ||
32 | try { | ||
33 | this.resetScroll = false | ||
34 | |||
35 | const previousUrl = new URL(window.location.origin + e1.urlAfterRedirects) | ||
36 | const nextUrl = new URL(window.location.origin + e2.urlAfterRedirects) | ||
37 | |||
38 | if (previousUrl.pathname !== nextUrl.pathname) { | ||
39 | this.resetScroll = true | ||
40 | return | ||
41 | } | ||
42 | |||
43 | if (this.peertubeRouter.hasRouteSetting(RouterSetting.DISABLE_SCROLL_RESTORE)) { | ||
44 | this.resetScroll = false | ||
45 | return | ||
46 | } | ||
47 | |||
48 | // Remove route settings from the comparison | ||
49 | const nextSearchParams = nextUrl.searchParams | ||
50 | nextSearchParams.delete(PeerTubeRouterService.ROUTE_SETTING_NAME) | ||
51 | |||
52 | const previousSearchParams = previousUrl.searchParams | ||
53 | |||
54 | nextSearchParams.sort() | ||
55 | previousSearchParams.sort() | ||
56 | |||
57 | if (nextSearchParams.toString() !== previousSearchParams.toString()) { | ||
58 | this.resetScroll = true | ||
59 | } | ||
60 | } catch (e) { | ||
61 | console.error('Cannot parse URL to check next scroll.', e) | ||
62 | this.resetScroll = true | ||
63 | } | ||
64 | }) | ||
65 | } | ||
66 | |||
67 | private consumeScroll () { | ||
68 | // Handle anchors/restore position | ||
69 | this.peertubeRouter.getScrollEvents().subscribe(e => { | ||
70 | logger('Will schedule scroll after router event %o.', e) | ||
71 | |||
72 | // scrollToAnchor first to preserve anchor position when using history navigation | ||
73 | if (e.anchor) { | ||
74 | setTimeout(() => this.viewportScroller.scrollToAnchor(e.anchor)) | ||
75 | |||
76 | return | ||
77 | } | ||
78 | |||
79 | if (e.position) { | ||
80 | setTimeout(() => this.viewportScroller.scrollToPosition(e.position)) | ||
81 | |||
82 | return | ||
83 | } | ||
84 | |||
85 | if (this.resetScroll) { | ||
86 | return this.viewportScroller.scrollToPosition([ 0, 0 ]) | ||
87 | } | ||
88 | }) | ||
89 | } | ||
90 | |||
91 | } | ||