]>
Commit | Line | Data |
---|---|---|
dd24f1bb C |
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' | |
42b40636 | 7 | import { logger } from '@root-helpers/logger' |
dd24f1bb | 8 | |
42b40636 | 9 | const debugLogger = debug('peertube:main:ScrollService') |
dd24f1bb C |
10 | |
11 | @Injectable() | |
12 | export class ScrollService { | |
13 | ||
14 | private resetScroll = true | |
15 | ||
16 | constructor ( | |
17 | private viewportScroller: ViewportScroller, | |
18 | private peertubeRouter: PeerTubeRouterService | |
19 | ) { } | |
20 | ||
21 | enableScrollRestoration () { | |
22 | // We'll manage scroll restoration ourselves | |
23 | this.viewportScroller.setHistoryScrollRestoration('manual') | |
24 | ||
25 | this.consumeScroll() | |
26 | this.produceScroll() | |
27 | } | |
28 | ||
29 | private produceScroll () { | |
30 | // When we add the a-state parameter, we don't want to alter the scroll | |
31 | this.peertubeRouter.getNavigationEndEvents().pipe(pairwise()) | |
32 | .subscribe(([ e1, e2 ]) => { | |
33 | try { | |
34 | this.resetScroll = false | |
35 | ||
36 | const previousUrl = new URL(window.location.origin + e1.urlAfterRedirects) | |
37 | const nextUrl = new URL(window.location.origin + e2.urlAfterRedirects) | |
38 | ||
39 | if (previousUrl.pathname !== nextUrl.pathname) { | |
40 | this.resetScroll = true | |
41 | return | |
42 | } | |
43 | ||
44 | if (this.peertubeRouter.hasRouteSetting(RouterSetting.DISABLE_SCROLL_RESTORE)) { | |
45 | this.resetScroll = false | |
46 | return | |
47 | } | |
48 | ||
49 | // Remove route settings from the comparison | |
50 | const nextSearchParams = nextUrl.searchParams | |
51 | nextSearchParams.delete(PeerTubeRouterService.ROUTE_SETTING_NAME) | |
52 | ||
53 | const previousSearchParams = previousUrl.searchParams | |
54 | ||
55 | nextSearchParams.sort() | |
56 | previousSearchParams.sort() | |
57 | ||
58 | if (nextSearchParams.toString() !== previousSearchParams.toString()) { | |
59 | this.resetScroll = true | |
60 | } | |
42b40636 C |
61 | } catch (err) { |
62 | logger.error('Cannot parse URL to check next scroll.', err) | |
dd24f1bb C |
63 | this.resetScroll = true |
64 | } | |
65 | }) | |
66 | } | |
67 | ||
68 | private consumeScroll () { | |
69 | // Handle anchors/restore position | |
70 | this.peertubeRouter.getScrollEvents().subscribe(e => { | |
42b40636 | 71 | debugLogger('Will schedule scroll after router event %o.', { e, resetScroll: this.resetScroll }) |
dd24f1bb C |
72 | |
73 | // scrollToAnchor first to preserve anchor position when using history navigation | |
74 | if (e.anchor) { | |
75 | setTimeout(() => this.viewportScroller.scrollToAnchor(e.anchor)) | |
76 | ||
77 | return | |
78 | } | |
79 | ||
80 | if (e.position) { | |
81 | setTimeout(() => this.viewportScroller.scrollToPosition(e.position)) | |
82 | ||
83 | return | |
84 | } | |
85 | ||
86 | if (this.resetScroll) { | |
87 | return this.viewportScroller.scrollToPosition([ 0, 0 ]) | |
88 | } | |
89 | }) | |
90 | } | |
91 | ||
92 | } |