diff options
author | Kimsible <1877318+kimsible@users.noreply.github.com> | 2020-11-17 14:04:44 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-11-17 14:04:44 +0100 |
commit | f3081d6401b63da41b03376f9f952bf1cca8303d (patch) | |
tree | 90ec91babde1544ca0a3423b031c9e10dfcac596 /client | |
parent | 901c36d5f44e02436da5f5c2899666329ff2eb5b (diff) | |
download | PeerTube-f3081d6401b63da41b03376f9f952bf1cca8303d.tar.gz PeerTube-f3081d6401b63da41b03376f9f952bf1cca8303d.tar.zst PeerTube-f3081d6401b63da41b03376f9f952bf1cca8303d.zip |
small refactor + clipboard copy on anchor click in instance page (#3318)
* Refacto scrollTo top and anchors
* Add on click clipboard copy and notifier to anchors about/instance page
* Fix margin top anchor middle title about page
* Use viewportscroller for scrolltoanchor
* Add to Link copied notification on instance page
Co-authored-by: kimsible <kimsible@users.noreply.github.com>
Diffstat (limited to 'client')
8 files changed, 117 insertions, 41 deletions
diff --git a/client/src/app/+about/about-instance/about-instance.component.html b/client/src/app/+about/about-instance/about-instance.component.html index d759c4343..045bb3fbc 100644 --- a/client/src/app/+about/about-instance/about-instance.component.html +++ b/client/src/app/+about/about-instance/about-instance.component.html | |||
@@ -23,7 +23,10 @@ | |||
23 | <a | 23 | <a |
24 | *ngIf="html.administrator || maintenanceLifetime || businessModel" | 24 | *ngIf="html.administrator || maintenanceLifetime || businessModel" |
25 | class="anchor-link" | 25 | class="anchor-link" |
26 | routerLink="/about/instance" fragment="administrators-and-sustainability" | 26 | routerLink="/about/instance" |
27 | fragment="administrators-and-sustainability" | ||
28 | #anchorLink | ||
29 | (click)="onClickCopyLink(anchorLink)" | ||
27 | > | 30 | > |
28 | <h2 i18n class="middle-title"> | 31 | <h2 i18n class="middle-title"> |
29 | ADMINISTRATORS & SUSTAINABILITY | 32 | ADMINISTRATORS & SUSTAINABILITY |
@@ -32,7 +35,12 @@ | |||
32 | 35 | ||
33 | <div class="block administrator" *ngIf="html.administrator"> | 36 | <div class="block administrator" *ngIf="html.administrator"> |
34 | <div class="anchor" id="administrators"></div> | 37 | <div class="anchor" id="administrators"></div> |
35 | <a class="anchor-link" routerLink="/about/instance" fragment="administrators"> | 38 | <a |
39 | class="anchor-link" | ||
40 | routerLink="/about/instance" | ||
41 | fragment="administrators" | ||
42 | #anchorLink | ||
43 | (click)="onClickCopyLink(anchorLink)"> | ||
36 | <h3 i18n class="section-title">Who we are</h3> | 44 | <h3 i18n class="section-title">Who we are</h3> |
37 | </a> | 45 | </a> |
38 | 46 | ||
@@ -41,7 +49,12 @@ | |||
41 | 49 | ||
42 | <div class="block creation-reason" *ngIf="creationReason"> | 50 | <div class="block creation-reason" *ngIf="creationReason"> |
43 | <div class="anchor" id="creation-reason"></div> | 51 | <div class="anchor" id="creation-reason"></div> |
44 | <a class="anchor-link" routerLink="/about/instance" fragment="creation-reason"> | 52 | <a |
53 | class="anchor-link" | ||
54 | routerLink="/about/instance" | ||
55 | fragment="creation-reason" | ||
56 | #anchorLink | ||
57 | (click)="onClickCopyLink(anchorLink)"> | ||
45 | <h3 i18n class="section-title">Why we created this instance</h3> | 58 | <h3 i18n class="section-title">Why we created this instance</h3> |
46 | </a> | 59 | </a> |
47 | 60 | ||
@@ -50,7 +63,12 @@ | |||
50 | 63 | ||
51 | <div class="block maintenance-lifetime" *ngIf="maintenanceLifetime"> | 64 | <div class="block maintenance-lifetime" *ngIf="maintenanceLifetime"> |
52 | <div class="anchor" id="maintenance-lifetime"></div> | 65 | <div class="anchor" id="maintenance-lifetime"></div> |
53 | <a class="anchor-link" routerLink="/about/instance" fragment="maintenance-lifetime"> | 66 | <a |
67 | class="anchor-link" | ||
68 | routerLink="/about/instance" | ||
69 | fragment="maintenance-lifetime" | ||
70 | #anchorLink | ||
71 | (click)="onClickCopyLink(anchorLink)"> | ||
54 | <h3 i18n class="section-title">How long we plan to maintain this instance</h3> | 72 | <h3 i18n class="section-title">How long we plan to maintain this instance</h3> |
55 | </a> | 73 | </a> |
56 | 74 | ||
@@ -58,8 +76,13 @@ | |||
58 | </div> | 76 | </div> |
59 | 77 | ||
60 | <div class="block business-model" *ngIf="businessModel"> | 78 | <div class="block business-model" *ngIf="businessModel"> |
61 | <div class="anchor" id="buisiness-model"></div> | 79 | <div class="anchor" id="business-model"></div> |
62 | <a class="anchor-link" routerLink="/about/instance" fragment="buisiness-model"> | 80 | <a |
81 | class="anchor-link" | ||
82 | routerLink="/about/instance" | ||
83 | fragment="business-model" | ||
84 | #anchorLink | ||
85 | (click)="onClickCopyLink(anchorLink)"> | ||
63 | <h3 i18n class="section-title">How we will pay for this instance</h3> | 86 | <h3 i18n class="section-title">How we will pay for this instance</h3> |
64 | </a> | 87 | </a> |
65 | 88 | ||
@@ -67,7 +90,13 @@ | |||
67 | </div> | 90 | </div> |
68 | 91 | ||
69 | <div class="anchor" id="information"></div> | 92 | <div class="anchor" id="information"></div> |
70 | <a *ngIf="html.description" class="anchor-link" routerLink="/about/instance" fragment="information"> | 93 | <a |
94 | *ngIf="html.description" | ||
95 | class="anchor-link" | ||
96 | routerLink="/about/instance" | ||
97 | fragment="information" | ||
98 | #anchorLink | ||
99 | (click)="onClickCopyLink(anchorLink)"> | ||
71 | <h2 i18n class="middle-title"> | 100 | <h2 i18n class="middle-title"> |
72 | INFORMATION | 101 | INFORMATION |
73 | </h2> | 102 | </h2> |
@@ -75,7 +104,12 @@ | |||
75 | 104 | ||
76 | <div class="block description"> | 105 | <div class="block description"> |
77 | <div class="anchor" id="description"></div> | 106 | <div class="anchor" id="description"></div> |
78 | <a class="anchor-link" routerLink="/about/instance" fragment="description"> | 107 | <a |
108 | class="anchor-link" | ||
109 | routerLink="/about/instance" | ||
110 | fragment="description" | ||
111 | #anchorLink | ||
112 | (click)="onClickCopyLink(anchorLink)"> | ||
79 | <h3 i18n class="section-title">Description</h3> | 113 | <h3 i18n class="section-title">Description</h3> |
80 | </a> | 114 | </a> |
81 | 115 | ||
@@ -85,8 +119,11 @@ | |||
85 | <div class="anchor" id="moderation"></div> | 119 | <div class="anchor" id="moderation"></div> |
86 | <a | 120 | <a |
87 | *ngIf="html.moderationInformation || html.codeOfConduct || html.terms" | 121 | *ngIf="html.moderationInformation || html.codeOfConduct || html.terms" |
88 | class="anchor-link" routerLink="/about/instance" fragment="moderation" | 122 | class="anchor-link" |
89 | > | 123 | routerLink="/about/instance" |
124 | fragment="moderation" | ||
125 | #anchorLink | ||
126 | (click)="onClickCopyLink(anchorLink)"> | ||
90 | <h2 i18n class="middle-title"> | 127 | <h2 i18n class="middle-title"> |
91 | MODERATION | 128 | MODERATION |
92 | </h2> | 129 | </h2> |
@@ -94,7 +131,12 @@ | |||
94 | 131 | ||
95 | <div class="block moderation-information" *ngIf="html.moderationInformation"> | 132 | <div class="block moderation-information" *ngIf="html.moderationInformation"> |
96 | <div class="anchor" id="moderation-information"></div> | 133 | <div class="anchor" id="moderation-information"></div> |
97 | <a class="anchor-link" routerLink="/about/instance" fragment="moderation-information"> | 134 | <a |
135 | class="anchor-link" | ||
136 | routerLink="/about/instance" | ||
137 | fragment="moderation-information" | ||
138 | #anchorLink | ||
139 | (click)="onClickCopyLink(anchorLink)"> | ||
98 | <h3 i18n class="section-title">Moderation information</h3> | 140 | <h3 i18n class="section-title">Moderation information</h3> |
99 | </a> | 141 | </a> |
100 | 142 | ||
@@ -103,7 +145,12 @@ | |||
103 | 145 | ||
104 | <div class="block code-of-conduct" *ngIf="html.codeOfConduct"> | 146 | <div class="block code-of-conduct" *ngIf="html.codeOfConduct"> |
105 | <div class="anchor" id="code-of-conduct"></div> | 147 | <div class="anchor" id="code-of-conduct"></div> |
106 | <a class="anchor-link" routerLink="/about/instance" fragment="code-of-conduct"> | 148 | <a |
149 | class="anchor-link" | ||
150 | routerLink="/about/instance" | ||
151 | fragment="code-of-conduct" | ||
152 | #anchorLink | ||
153 | (click)="onClickCopyLink(anchorLink)"> | ||
107 | <h3 i18n class="section-title">Code of conduct</h3> | 154 | <h3 i18n class="section-title">Code of conduct</h3> |
108 | </a> | 155 | </a> |
109 | 156 | ||
@@ -112,7 +159,12 @@ | |||
112 | 159 | ||
113 | <div class="block terms"> | 160 | <div class="block terms"> |
114 | <div class="anchor" id="terms"></div> | 161 | <div class="anchor" id="terms"></div> |
115 | <a class="anchor-link" routerLink="/about/instance" fragment="terms"> | 162 | <a |
163 | class="anchor-link" | ||
164 | routerLink="/about/instance" | ||
165 | fragment="terms" | ||
166 | #anchorLink | ||
167 | (click)="onClickCopyLink(anchorLink)"> | ||
116 | <h3 i18n class="section-title">Terms</h3> | 168 | <h3 i18n class="section-title">Terms</h3> |
117 | </a> | 169 | </a> |
118 | 170 | ||
@@ -120,7 +172,13 @@ | |||
120 | </div> | 172 | </div> |
121 | 173 | ||
122 | <div class="anchor" id="other-information"></div> | 174 | <div class="anchor" id="other-information"></div> |
123 | <a *ngIf="html.hardwareInformation" class="anchor-link" routerLink="/about/instance" fragment="other-information"> | 175 | <a |
176 | *ngIf="html.hardwareInformation" | ||
177 | class="anchor-link" | ||
178 | routerLink="/about/instance" | ||
179 | fragment="other-information" | ||
180 | #anchorLink | ||
181 | (click)="onClickCopyLink(anchorLink)"> | ||
124 | <h2 i18n class="middle-title"> | 182 | <h2 i18n class="middle-title"> |
125 | OTHER INFORMATION | 183 | OTHER INFORMATION |
126 | </h2> | 184 | </h2> |
@@ -128,7 +186,12 @@ | |||
128 | 186 | ||
129 | <div class="block hardware-information" *ngIf="html.hardwareInformation"> | 187 | <div class="block hardware-information" *ngIf="html.hardwareInformation"> |
130 | <div class="anchor" id="hardware-information"></div> | 188 | <div class="anchor" id="hardware-information"></div> |
131 | <a class="anchor-link" routerLink="/about/instance" fragment="hardware-information"> | 189 | <a |
190 | class="anchor-link" | ||
191 | routerLink="/about/instance" | ||
192 | fragment="hardware-information" | ||
193 | #anchorLink | ||
194 | (click)="onClickCopyLink(anchorLink)"> | ||
132 | <h3 i18n class="section-title">Hardware information</h3> | 195 | <h3 i18n class="section-title">Hardware information</h3> |
133 | </a> | 196 | </a> |
134 | 197 | ||
@@ -143,7 +206,12 @@ | |||
143 | 206 | ||
144 | <div class="col"> | 207 | <div class="col"> |
145 | <div class="anchor" id="statistics"></div> | 208 | <div class="anchor" id="statistics"></div> |
146 | <a class="anchor-link" routerLink="/about/instance" fragment="statistics"> | 209 | <a |
210 | class="anchor-link" | ||
211 | routerLink="/about/instance" | ||
212 | fragment="statistics" | ||
213 | #anchorLink | ||
214 | (click)="onClickCopyLink(anchorLink)"> | ||
147 | <h2 i18n class="middle-title">STATISTICS</h2> | 215 | <h2 i18n class="middle-title">STATISTICS</h2> |
148 | </a> | 216 | </a> |
149 | <my-instance-statistics></my-instance-statistics> | 217 | <my-instance-statistics></my-instance-statistics> |
diff --git a/client/src/app/+about/about-instance/about-instance.component.scss b/client/src/app/+about/about-instance/about-instance.component.scss index 2e77ade9b..fe3ce22b0 100644 --- a/client/src/app/+about/about-instance/about-instance.component.scss +++ b/client/src/app/+about/about-instance/about-instance.component.scss | |||
@@ -43,12 +43,12 @@ | |||
43 | .middle-title { | 43 | .middle-title { |
44 | @include in-content-small-title; | 44 | @include in-content-small-title; |
45 | 45 | ||
46 | margin-top: 45px; | 46 | margin-top: 0; |
47 | margin-bottom: 25px; | 47 | margin-bottom: 25px; |
48 | } | 48 | } |
49 | 49 | ||
50 | .block { | 50 | .block { |
51 | margin-bottom: 30px; | 51 | margin-bottom: 75px; |
52 | font-size: 15px; | 52 | font-size: 15px; |
53 | } | 53 | } |
54 | 54 | ||
diff --git a/client/src/app/+about/about-instance/about-instance.component.ts b/client/src/app/+about/about-instance/about-instance.component.ts index bd587fa26..e74b5daeb 100644 --- a/client/src/app/+about/about-instance/about-instance.component.ts +++ b/client/src/app/+about/about-instance/about-instance.component.ts | |||
@@ -2,7 +2,8 @@ import { ViewportScroller } from '@angular/common' | |||
2 | import { AfterViewChecked, Component, OnInit, ViewChild } from '@angular/core' | 2 | import { AfterViewChecked, Component, OnInit, ViewChild } from '@angular/core' |
3 | import { ActivatedRoute } from '@angular/router' | 3 | import { ActivatedRoute } from '@angular/router' |
4 | import { ContactAdminModalComponent } from '@app/+about/about-instance/contact-admin-modal.component' | 4 | import { ContactAdminModalComponent } from '@app/+about/about-instance/contact-admin-modal.component' |
5 | import { ServerService } from '@app/core' | 5 | import { Notifier } from '@app/core' |
6 | import { copyToClipboard } from '../../../assets/player/utils' | ||
6 | import { InstanceService } from '@app/shared/shared-instance' | 7 | import { InstanceService } from '@app/shared/shared-instance' |
7 | import { ServerConfig } from '@shared/models' | 8 | import { ServerConfig } from '@shared/models' |
8 | import { ResolverData } from './about-instance.resolver' | 9 | import { ResolverData } from './about-instance.resolver' |
@@ -42,6 +43,7 @@ export class AboutInstanceComponent implements OnInit, AfterViewChecked { | |||
42 | constructor ( | 43 | constructor ( |
43 | private viewportScroller: ViewportScroller, | 44 | private viewportScroller: ViewportScroller, |
44 | private route: ActivatedRoute, | 45 | private route: ActivatedRoute, |
46 | private notifier: Notifier, | ||
45 | private instanceService: InstanceService | 47 | private instanceService: InstanceService |
46 | ) {} | 48 | ) {} |
47 | 49 | ||
@@ -87,4 +89,10 @@ export class AboutInstanceComponent implements OnInit, AfterViewChecked { | |||
87 | openContactModal () { | 89 | openContactModal () { |
88 | return this.contactAdminModal.show() | 90 | return this.contactAdminModal.show() |
89 | } | 91 | } |
92 | |||
93 | onClickCopyLink (anchor: HTMLAnchorElement) { | ||
94 | const link = anchor.href | ||
95 | copyToClipboard(link) | ||
96 | this.notifier.success(link, $localize `Link copied`) | ||
97 | } | ||
90 | } | 98 | } |
diff --git a/client/src/app/app.component.ts b/client/src/app/app.component.ts index edec3216e..da51040ad 100644 --- a/client/src/app/app.component.ts +++ b/client/src/app/app.component.ts | |||
@@ -121,7 +121,7 @@ export class AppComponent implements OnInit, AfterViewInit { | |||
121 | // scrollToAnchor first to preserve anchor position when using history navigation | 121 | // scrollToAnchor first to preserve anchor position when using history navigation |
122 | if (e.anchor) { | 122 | if (e.anchor) { |
123 | setTimeout(() => { | 123 | setTimeout(() => { |
124 | document.getElementById(e.anchor).scrollIntoView({ behavior: 'smooth', inline: 'nearest' }) | 124 | this.viewportScroller.scrollToAnchor(e.anchor) |
125 | }) | 125 | }) |
126 | 126 | ||
127 | return | 127 | return |
diff --git a/client/src/app/helpers/utils.ts b/client/src/app/helpers/utils.ts index d9007dd77..a22507f46 100644 --- a/client/src/app/helpers/utils.ts +++ b/client/src/app/helpers/utils.ts | |||
@@ -144,8 +144,12 @@ function sortBy (obj: any[], key1: string, key2?: string) { | |||
144 | }) | 144 | }) |
145 | } | 145 | } |
146 | 146 | ||
147 | function scrollToTop () { | 147 | function scrollToTop (behavior: 'auto' | 'smooth' = 'auto') { |
148 | window.scroll(0, 0) | 148 | window.scrollTo({ |
149 | left: 0, | ||
150 | top: 0, | ||
151 | behavior | ||
152 | }) | ||
149 | } | 153 | } |
150 | 154 | ||
151 | function isInViewport (el: HTMLElement) { | 155 | function isInViewport (el: HTMLElement) { |
diff --git a/client/src/app/menu/menu.component.html b/client/src/app/menu/menu.component.html index a5985a301..88e3d60db 100644 --- a/client/src/app/menu/menu.component.html +++ b/client/src/app/menu/menu.component.html | |||
@@ -3,7 +3,7 @@ | |||
3 | <div class="top-menu"> | 3 | <div class="top-menu"> |
4 | <div *ngIf="isLoggedIn" class="logged-in-block"> | 4 | <div *ngIf="isLoggedIn" class="logged-in-block"> |
5 | <div> | 5 | <div> |
6 | <my-avatar-notification [user]="user" (navigate)="onSameUrlRestoreScrollPosition($event)"></my-avatar-notification> | 6 | <my-avatar-notification [user]="user" (navigate)="onActiveLinkScrollToAnchor($event)"></my-avatar-notification> |
7 | 7 | ||
8 | <div class="logged-in-info"> | 8 | <div class="logged-in-info"> |
9 | <a *ngIf="user.account" [routerLink]="[ '/accounts', user.account.nameWithHost ]" class="logged-in-display-name">{{ user.account?.displayName }}</a> | 9 | <a *ngIf="user.account" [routerLink]="[ '/accounts', user.account.nameWithHost ]" class="logged-in-display-name">{{ user.account?.displayName }}</a> |
@@ -22,7 +22,8 @@ | |||
22 | 22 | ||
23 | <div class="dropdown-divider"></div> | 23 | <div class="dropdown-divider"></div> |
24 | 24 | ||
25 | <a ngbDropdownItem ngbDropdownToggle class="dropdown-item" routerLink="/my-account/notifications"> | 25 | <a ngbDropdownItem ngbDropdownToggle class="dropdown-item" routerLink="/my-account/notifications" |
26 | #notifications (click)="onActiveLinkScrollToAnchor(notifications)"> | ||
26 | <my-global-icon iconName="inbox-full" aria-hidden="true"></my-global-icon> <ng-container i18n>My notifications</ng-container> | 27 | <my-global-icon iconName="inbox-full" aria-hidden="true"></my-global-icon> <ng-container i18n>My notifications</ng-container> |
27 | </a> | 28 | </a> |
28 | 29 | ||
@@ -35,7 +36,7 @@ | |||
35 | </a> | 36 | </a> |
36 | 37 | ||
37 | <a ngbDropdownItem ngbDropdownToggle class="dropdown-item" routerLink="/my-account/settings" fragment="video-languages-subtitles" | 38 | <a ngbDropdownItem ngbDropdownToggle class="dropdown-item" routerLink="/my-account/settings" fragment="video-languages-subtitles" |
38 | #settingsLanguagesSubtitles (click)="onSameUrlRestoreScrollPosition(settingsLanguagesSubtitles)"> | 39 | #settingsLanguagesSubtitles (click)="onActiveLinkScrollToAnchor(settingsLanguagesSubtitles)"> |
39 | <my-global-icon iconName="video-lang" aria-hidden="true"></my-global-icon> | 40 | <my-global-icon iconName="video-lang" aria-hidden="true"></my-global-icon> |
40 | <span i18n>Videos:</span> | 41 | <span i18n>Videos:</span> |
41 | <span class="ml-auto text-muted">{{ videoLanguages.join(', ') }}</span> | 42 | <span class="ml-auto text-muted">{{ videoLanguages.join(', ') }}</span> |
@@ -43,7 +44,7 @@ | |||
43 | 44 | ||
44 | <a ngbDropdownItem ngbDropdownToggle class="dropdown-item" routerLink="/my-account/settings" | 45 | <a ngbDropdownItem ngbDropdownToggle class="dropdown-item" routerLink="/my-account/settings" |
45 | fragment="video-sensitive-content-policy" #settingsSensitiveContentPolicy | 46 | fragment="video-sensitive-content-policy" #settingsSensitiveContentPolicy |
46 | (click)="onSameUrlRestoreScrollPosition(settingsSensitiveContentPolicy)"> | 47 | (click)="onActiveLinkScrollToAnchor(settingsSensitiveContentPolicy)"> |
47 | <my-global-icon class="hover-display-toggle" [ngClass]="{ 'not-displayed': user.nsfwPolicy === 'display' }" iconName="sensitive" aria-hidden="true"></my-global-icon> | 48 | <my-global-icon class="hover-display-toggle" [ngClass]="{ 'not-displayed': user.nsfwPolicy === 'display' }" iconName="sensitive" aria-hidden="true"></my-global-icon> |
48 | <my-global-icon class="hover-display-toggle" [ngClass]="{ 'not-displayed': user.nsfwPolicy !== 'display' }" iconName="unsensitive" aria-hidden="true"></my-global-icon> | 49 | <my-global-icon class="hover-display-toggle" [ngClass]="{ 'not-displayed': user.nsfwPolicy !== 'display' }" iconName="unsensitive" aria-hidden="true"></my-global-icon> |
49 | <span i18n>Sensitive:</span> | 50 | <span i18n>Sensitive:</span> |
@@ -72,12 +73,12 @@ | |||
72 | </div> | 73 | </div> |
73 | 74 | ||
74 | <div class="logged-in-menu"> | 75 | <div class="logged-in-menu"> |
75 | <a routerLink="/my-account" routerLinkActive="active" #settingsLink (click)="onSameUrlRestoreScrollPosition(settingsLink)"> | 76 | <a routerLink="/my-account" routerLinkActive="active" #settingsLink (click)="onActiveLinkScrollToAnchor(settingsLink)"> |
76 | <my-global-icon iconName="user" aria-hidden="true"></my-global-icon> | 77 | <my-global-icon iconName="user" aria-hidden="true"></my-global-icon> |
77 | <ng-container i18n>My account</ng-container> | 78 | <ng-container i18n>My account</ng-container> |
78 | </a> | 79 | </a> |
79 | 80 | ||
80 | <a routerLink="/my-library" routerLinkActive="active" #libraryLink (click)="onSameUrlRestoreScrollPosition(libraryLink)"> | 81 | <a routerLink="/my-library" routerLinkActive="active" #libraryLink (click)="onActiveLinkScrollToAnchor(libraryLink)"> |
81 | <my-global-icon iconName="channel" aria-hidden="true"></my-global-icon> | 82 | <my-global-icon iconName="channel" aria-hidden="true"></my-global-icon> |
82 | <ng-container i18n>My library</ng-container> | 83 | <ng-container i18n>My library</ng-container> |
83 | </a> | 84 | </a> |
diff --git a/client/src/app/menu/menu.component.ts b/client/src/app/menu/menu.component.ts index 48ed91973..97a3b6d24 100644 --- a/client/src/app/menu/menu.component.ts +++ b/client/src/app/menu/menu.component.ts | |||
@@ -1,8 +1,10 @@ | |||
1 | import { ViewportScroller } from '@angular/common' | ||
1 | import { HotkeysService } from 'angular2-hotkeys' | 2 | import { HotkeysService } from 'angular2-hotkeys' |
2 | import * as debug from 'debug' | 3 | import * as debug from 'debug' |
3 | import { switchMap } from 'rxjs/operators' | 4 | import { switchMap } from 'rxjs/operators' |
4 | import { Component, OnInit, ViewChild } from '@angular/core' | 5 | import { Component, OnInit, ViewChild } from '@angular/core' |
5 | import { Router } from '@angular/router' | 6 | import { Router } from '@angular/router' |
7 | import { scrollToTop } from '@app/helpers' | ||
6 | import { AuthService, AuthStatus, AuthUser, MenuService, RedirectService, ScreenService, ServerService, UserService } from '@app/core' | 8 | import { AuthService, AuthStatus, AuthUser, MenuService, RedirectService, ScreenService, ServerService, UserService } from '@app/core' |
7 | import { LanguageChooserComponent } from '@app/menu/language-chooser.component' | 9 | import { LanguageChooserComponent } from '@app/menu/language-chooser.component' |
8 | import { QuickSettingsModalComponent } from '@app/modal/quick-settings-modal.component' | 10 | import { QuickSettingsModalComponent } from '@app/modal/quick-settings-modal.component' |
@@ -39,6 +41,7 @@ export class MenuComponent implements OnInit { | |||
39 | } | 41 | } |
40 | 42 | ||
41 | constructor ( | 43 | constructor ( |
44 | private viewportScroller: ViewportScroller, | ||
42 | private authService: AuthService, | 45 | private authService: AuthService, |
43 | private userService: UserService, | 46 | private userService: UserService, |
44 | private serverService: ServerService, | 47 | private serverService: ServerService, |
@@ -199,23 +202,18 @@ export class MenuComponent implements OnInit { | |||
199 | return this.languages.find(lang => lang.id === localeId).label | 202 | return this.languages.find(lang => lang.id === localeId).label |
200 | } | 203 | } |
201 | 204 | ||
202 | onSameUrlRestoreScrollPosition (link: HTMLAnchorElement) { | 205 | onActiveLinkScrollToAnchor (link: HTMLAnchorElement) { |
203 | const linkURL = link.getAttribute('href') | 206 | const linkURL = link.getAttribute('href') |
204 | const linkHash = link.getAttribute('fragment') | 207 | const linkHash = link.getAttribute('fragment') |
205 | 208 | ||
206 | // On same url without fragment restore top scroll position | 209 | // On same url without fragment restore top scroll position |
207 | if (!linkHash && this.router.url.includes(linkURL)) { | 210 | if (!linkHash && this.router.url.includes(linkURL)) { |
208 | window.scrollTo({ | 211 | scrollToTop('smooth') |
209 | left: 0, | ||
210 | top: 0, | ||
211 | behavior: 'smooth' | ||
212 | }) | ||
213 | } | 212 | } |
214 | 213 | ||
215 | // On same url with fragment restore anchor scroll position | 214 | // On same url with fragment restore anchor scroll position |
216 | if (linkHash && this.router.url === linkURL) { | 215 | if (linkHash && this.router.url === linkURL) { |
217 | const anchor = document.getElementById(link.getAttribute('fragment')) | 216 | this.viewportScroller.scrollToAnchor(linkHash) |
218 | anchor.scrollIntoView({ behavior: 'smooth', inline: 'nearest' }) | ||
219 | } | 217 | } |
220 | 218 | ||
221 | if (this.screenService.isInSmallView()) { | 219 | if (this.screenService.isInSmallView()) { |
diff --git a/client/src/app/shared/shared-main/misc/top-menu-dropdown.component.ts b/client/src/app/shared/shared-main/misc/top-menu-dropdown.component.ts index ba5568595..2cafb6c55 100644 --- a/client/src/app/shared/shared-main/misc/top-menu-dropdown.component.ts +++ b/client/src/app/shared/shared-main/misc/top-menu-dropdown.component.ts | |||
@@ -3,6 +3,7 @@ import { filter } from 'rxjs/operators' | |||
3 | import { Component, Input, OnDestroy, OnInit, ViewChild } from '@angular/core' | 3 | import { Component, Input, OnDestroy, OnInit, ViewChild } from '@angular/core' |
4 | import { NavigationEnd, Router } from '@angular/router' | 4 | import { NavigationEnd, Router } from '@angular/router' |
5 | import { MenuService, ScreenService } from '@app/core' | 5 | import { MenuService, ScreenService } from '@app/core' |
6 | import { scrollToTop } from '@app/helpers' | ||
6 | import { GlobalIconName } from '@app/shared/shared-icons' | 7 | import { GlobalIconName } from '@app/shared/shared-icons' |
7 | import { NgbDropdown, NgbModal } from '@ng-bootstrap/ng-bootstrap' | 8 | import { NgbDropdown, NgbModal } from '@ng-bootstrap/ng-bootstrap' |
8 | 9 | ||
@@ -96,11 +97,7 @@ export class TopMenuDropdownComponent implements OnInit, OnDestroy { | |||
96 | 97 | ||
97 | onActiveLinkScrollToTop (link: HTMLAnchorElement) { | 98 | onActiveLinkScrollToTop (link: HTMLAnchorElement) { |
98 | if (!this.isBroadcastMessageDisplayed && this.router.url.includes(link.getAttribute('href'))) { | 99 | if (!this.isBroadcastMessageDisplayed && this.router.url.includes(link.getAttribute('href'))) { |
99 | window.scrollTo({ | 100 | scrollToTop('smooth') |
100 | left: 0, | ||
101 | top: 0, | ||
102 | behavior: 'smooth' | ||
103 | }) | ||
104 | } | 101 | } |
105 | } | 102 | } |
106 | 103 | ||