diff options
author | Rigel Kent <sendmemail@rigelk.eu> | 2019-12-20 17:49:57 +0100 |
---|---|---|
committer | Rigel Kent <sendmemail@rigelk.eu> | 2019-12-20 17:49:57 +0100 |
commit | 223b24e618146f85b20b5bf365bc18d14a5964cd (patch) | |
tree | 236fde34d190fa5d0d9a44c6760c0161594dd872 /client/src | |
parent | 1dc240a9488c66ad38205d08fcfdb32d35efceaa (diff) | |
download | PeerTube-223b24e618146f85b20b5bf365bc18d14a5964cd.tar.gz PeerTube-223b24e618146f85b20b5bf365bc18d14a5964cd.tar.zst PeerTube-223b24e618146f85b20b5bf365bc18d14a5964cd.zip |
Fix upnext, refactor avatar menu, add to playlist overflow
Diffstat (limited to 'client/src')
13 files changed, 108 insertions, 51 deletions
diff --git a/client/src/app/+accounts/accounts.component.html b/client/src/app/+accounts/accounts.component.html index 6269091df..70257162d 100644 --- a/client/src/app/+accounts/accounts.component.html +++ b/client/src/app/+accounts/accounts.component.html | |||
@@ -23,7 +23,7 @@ | |||
23 | <span *ngIf="account.mutedServerByInstance" class="badge badge-danger" i18n>Instance muted by your instance</span> | 23 | <span *ngIf="account.mutedServerByInstance" class="badge badge-danger" i18n>Instance muted by your instance</span> |
24 | 24 | ||
25 | <my-user-moderation-dropdown | 25 | <my-user-moderation-dropdown |
26 | buttonSize="small" [account]="account" [user]="user" | 26 | buttonSize="small" [account]="account" [user]="user" placement="bottom-right auto" |
27 | (userChanged)="onUserChanged()" (userDeleted)="onUserDeleted()" | 27 | (userChanged)="onUserChanged()" (userDeleted)="onUserDeleted()" |
28 | > | 28 | > |
29 | </my-user-moderation-dropdown> | 29 | </my-user-moderation-dropdown> |
diff --git a/client/src/app/menu/avatar-notification.component.html b/client/src/app/menu/avatar-notification.component.html index 1b6e6dcf8..8ffec46da 100644 --- a/client/src/app/menu/avatar-notification.component.html +++ b/client/src/app/menu/avatar-notification.component.html | |||
@@ -25,7 +25,7 @@ | |||
25 | </div> | 25 | </div> |
26 | </div> | 26 | </div> |
27 | 27 | ||
28 | <div *ngIf="!loaded" class="loader"> | 28 | <div *ngIf="!loaded" class="loader mt-4"> |
29 | <my-loader [loading]="!loaded"></my-loader> | 29 | <my-loader [loading]="!loaded"></my-loader> |
30 | </div> | 30 | </div> |
31 | 31 | ||
diff --git a/client/src/app/menu/avatar-notification.component.scss b/client/src/app/menu/avatar-notification.component.scss index 713ac7cb9..2ca7f24dc 100644 --- a/client/src/app/menu/avatar-notification.component.scss +++ b/client/src/app/menu/avatar-notification.component.scss | |||
@@ -45,7 +45,7 @@ | |||
45 | align-items: center; | 45 | align-items: center; |
46 | padding: 0 10px; | 46 | padding: 0 10px; |
47 | font-size: 16px; | 47 | font-size: 16px; |
48 | height: 50px; | 48 | min-height: 50px; |
49 | 49 | ||
50 | a { | 50 | a { |
51 | @include disable-default-a-behaviour; | 51 | @include disable-default-a-behaviour; |
diff --git a/client/src/app/menu/menu.component.html b/client/src/app/menu/menu.component.html index 3f406586e..848f9949f 100644 --- a/client/src/app/menu/menu.component.html +++ b/client/src/app/menu/menu.component.html | |||
@@ -5,8 +5,10 @@ | |||
5 | <my-avatar-notification [user]="user"></my-avatar-notification> | 5 | <my-avatar-notification [user]="user"></my-avatar-notification> |
6 | 6 | ||
7 | <div class="logged-in-info"> | 7 | <div class="logged-in-info"> |
8 | <a routerLink="/my-account/settings" class="logged-in-display-name">{{ user.account?.displayName }}</a> | 8 | <a *ngIf="user.account" [routerLink]="[ '/accounts', user.account.nameWithHost ]" class="logged-in-display-name">{{ user.account?.displayName }}</a> |
9 | <div class="logged-in-username">{{ user.username }}</div> | 9 | <a *ngIf="!user.account" routerLink="/my-account/settings" class="logged-in-display-name">{{ user.account?.displayName }}</a> |
10 | |||
11 | <div ngxClipboard [cbContent]="user.account?.nameWithHost" class="logged-in-username">{{ user.username }}</div> | ||
10 | </div> | 12 | </div> |
11 | 13 | ||
12 | <div class="logged-in-more" ngbDropdown placement="bottom-right auto"> | 14 | <div class="logged-in-more" ngbDropdown placement="bottom-right auto"> |
@@ -14,13 +16,21 @@ | |||
14 | 16 | ||
15 | <div ngbDropdownMenu> | 17 | <div ngbDropdownMenu> |
16 | <a *ngIf="user.account" [routerLink]="[ '/accounts', user.account.nameWithHost ]" class="dropdown-item"> | 18 | <a *ngIf="user.account" [routerLink]="[ '/accounts', user.account.nameWithHost ]" class="dropdown-item"> |
17 | <my-global-icon iconName="go"></my-global-icon> <ng-container i18n>My public profile</ng-container> | 19 | <my-global-icon iconName="go"></my-global-icon> <ng-container i18n>Public profile</ng-container> |
18 | </a> | 20 | </a> |
19 | 21 | ||
22 | <div class="dropdown-divider"></div> | ||
23 | |||
20 | <a routerLink="/my-account" class="dropdown-item"> | 24 | <a routerLink="/my-account" class="dropdown-item"> |
21 | <my-global-icon iconName="user"></my-global-icon> <ng-container i18n>My account</ng-container> | 25 | <my-global-icon iconName="user"></my-global-icon> <ng-container i18n>Account settings</ng-container> |
22 | </a> | 26 | </a> |
23 | 27 | ||
28 | <a routerLink="/my-account/video-channels" class="dropdown-item"> | ||
29 | <my-global-icon iconName="folder"></my-global-icon> <ng-container i18n>Channels settings</ng-container> | ||
30 | </a> | ||
31 | |||
32 | <div class="dropdown-divider"></div> | ||
33 | |||
24 | <a (click)="logout($event)" class="dropdown-item" href="#"> | 34 | <a (click)="logout($event)" class="dropdown-item" href="#"> |
25 | <my-global-icon iconName="sign-out"></my-global-icon> <ng-container i18n>Log out</ng-container> | 35 | <my-global-icon iconName="sign-out"></my-global-icon> <ng-container i18n>Log out</ng-container> |
26 | </a> | 36 | </a> |
diff --git a/client/src/app/menu/menu.component.scss b/client/src/app/menu/menu.component.scss index 79a28d258..2963d4d19 100644 --- a/client/src/app/menu/menu.component.scss +++ b/client/src/app/menu/menu.component.scss | |||
@@ -69,6 +69,7 @@ menu { | |||
69 | font-size: 13px; | 69 | font-size: 13px; |
70 | color: #C6C6C6; | 70 | color: #C6C6C6; |
71 | max-width: 140px; | 71 | max-width: 140px; |
72 | cursor: pointer; | ||
72 | } | 73 | } |
73 | } | 74 | } |
74 | 75 | ||
diff --git a/client/src/app/shared/misc/utils.ts b/client/src/app/shared/misc/utils.ts index f26240d21..b1d1fc0b5 100644 --- a/client/src/app/shared/misc/utils.ts +++ b/client/src/app/shared/misc/utils.ts | |||
@@ -169,6 +169,26 @@ function importModule (path: string) { | |||
169 | }) | 169 | }) |
170 | } | 170 | } |
171 | 171 | ||
172 | function isInViewport (el: HTMLElement) { | ||
173 | const bounding = el.getBoundingClientRect() | ||
174 | return ( | ||
175 | bounding.top >= 0 && | ||
176 | bounding.left >= 0 && | ||
177 | bounding.bottom <= (window.innerHeight || document.documentElement.clientHeight) && | ||
178 | bounding.right <= (window.innerWidth || document.documentElement.clientWidth) | ||
179 | ) | ||
180 | } | ||
181 | |||
182 | function isXPercentInViewport (el: HTMLElement, percentVisible: number) { | ||
183 | const rect = el.getBoundingClientRect() | ||
184 | const windowHeight = (window.innerHeight || document.documentElement.clientHeight) | ||
185 | |||
186 | return !( | ||
187 | Math.floor(100 - (((rect.top >= 0 ? 0 : rect.top) / +-(rect.height / 1)) * 100)) < percentVisible || | ||
188 | Math.floor(100 - ((rect.bottom - windowHeight) / rect.height) * 100) < percentVisible | ||
189 | ) | ||
190 | } | ||
191 | |||
172 | export { | 192 | export { |
173 | sortBy, | 193 | sortBy, |
174 | durationToString, | 194 | durationToString, |
@@ -183,5 +203,7 @@ export { | |||
183 | objectLineFeedToHtml, | 203 | objectLineFeedToHtml, |
184 | removeElementFromArray, | 204 | removeElementFromArray, |
185 | importModule, | 205 | importModule, |
186 | scrollToTop | 206 | scrollToTop, |
207 | isInViewport, | ||
208 | isXPercentInViewport | ||
187 | } | 209 | } |
diff --git a/client/src/app/shared/video-playlist/video-add-to-playlist.component.html b/client/src/app/shared/video-playlist/video-add-to-playlist.component.html index 648d580fa..0cc8af345 100644 --- a/client/src/app/shared/video-playlist/video-add-to-playlist.component.html +++ b/client/src/app/shared/video-playlist/video-add-to-playlist.component.html | |||
@@ -41,14 +41,16 @@ | |||
41 | </div> | 41 | </div> |
42 | </div> | 42 | </div> |
43 | 43 | ||
44 | <div class="playlist dropdown-item" *ngFor="let playlist of videoPlaylists" (click)="togglePlaylist($event, playlist)"> | 44 | <div class="playlists"> |
45 | <my-peertube-checkbox [inputName]="'in-playlist-' + playlist.id" [(ngModel)]="playlist.inPlaylist" [onPushWorkaround]="true"></my-peertube-checkbox> | 45 | <div class="playlist dropdown-item" *ngFor="let playlist of videoPlaylists" (click)="togglePlaylist($event, playlist)"> |
46 | <my-peertube-checkbox [inputName]="'in-playlist-' + playlist.id" [(ngModel)]="playlist.inPlaylist" [onPushWorkaround]="true"></my-peertube-checkbox> | ||
46 | 47 | ||
47 | <div class="display-name"> | 48 | <div class="display-name"> |
48 | {{ playlist.displayName }} | 49 | {{ playlist.displayName }} |
49 | 50 | ||
50 | <div *ngIf="playlist.inPlaylist && (playlist.startTimestamp || playlist.stopTimestamp)" class="timestamp-info"> | 51 | <div *ngIf="playlist.inPlaylist && (playlist.startTimestamp || playlist.stopTimestamp)" class="timestamp-info"> |
51 | {{ formatTimestamp(playlist) }} | 52 | {{ formatTimestamp(playlist) }} |
53 | </div> | ||
52 | </div> | 54 | </div> |
53 | </div> | 55 | </div> |
54 | </div> | 56 | </div> |
diff --git a/client/src/app/shared/video-playlist/video-add-to-playlist.component.scss b/client/src/app/shared/video-playlist/video-add-to-playlist.component.scss index c677fea6c..090b530cf 100644 --- a/client/src/app/shared/video-playlist/video-add-to-playlist.component.scss +++ b/client/src/app/shared/video-playlist/video-add-to-playlist.component.scss | |||
@@ -1,11 +1,6 @@ | |||
1 | @import '_variables'; | 1 | @import '_variables'; |
2 | @import '_mixins'; | 2 | @import '_mixins'; |
3 | 3 | ||
4 | .root { | ||
5 | max-height: 300px; | ||
6 | overflow-y: auto; | ||
7 | } | ||
8 | |||
9 | .header { | 4 | .header { |
10 | min-width: 240px; | 5 | min-width: 240px; |
11 | padding: 6px 24px 10px 24px; | 6 | padding: 6px 24px 10px 24px; |
@@ -53,6 +48,11 @@ | |||
53 | padding: 6px 24px; | 48 | padding: 6px 24px; |
54 | } | 49 | } |
55 | 50 | ||
51 | .playlists { | ||
52 | max-height: 180px; | ||
53 | overflow-y: auto; | ||
54 | } | ||
55 | |||
56 | .playlist { | 56 | .playlist { |
57 | display: flex; | 57 | display: flex; |
58 | cursor: pointer; | 58 | cursor: pointer; |
diff --git a/client/src/app/videos/+video-watch/video-watch.component.html b/client/src/app/videos/+video-watch/video-watch.component.html index 7a9f00a50..9e69033e1 100644 --- a/client/src/app/videos/+video-watch/video-watch.component.html +++ b/client/src/app/videos/+video-watch/video-watch.component.html | |||
@@ -114,9 +114,9 @@ | |||
114 | ></my-video-actions-dropdown> | 114 | ></my-video-actions-dropdown> |
115 | </div> | 115 | </div> |
116 | 116 | ||
117 | <div class="video-info-likes-dislikes-bar-outerContainer"> | 117 | <div class="video-info-likes-dislikes-bar-outer-container"> |
118 | <div | 118 | <div |
119 | class="video-info-likes-dislikes-bar-innerContainer" | 119 | class="video-info-likes-dislikes-bar-inner-container" |
120 | *ngIf="video.likes !== 0 || video.dislikes !== 0" | 120 | *ngIf="video.likes !== 0 || video.dislikes !== 0" |
121 | [ngbTooltip]="likesBarTooltipText" | 121 | [ngbTooltip]="likesBarTooltipText" |
122 | placement="bottom" | 122 | placement="bottom" |
diff --git a/client/src/app/videos/+video-watch/video-watch.component.scss b/client/src/app/videos/+video-watch/video-watch.component.scss index 180b7c6ad..f9ff83c34 100644 --- a/client/src/app/videos/+video-watch/video-watch.component.scss +++ b/client/src/app/videos/+video-watch/video-watch.component.scss | |||
@@ -297,13 +297,13 @@ $video-info-margin-left: 44px; | |||
297 | } | 297 | } |
298 | } | 298 | } |
299 | 299 | ||
300 | .video-info-likes-dislikes-bar-outerContainer { | 300 | .video-info-likes-dislikes-bar-outer-container { |
301 | position: relative; | 301 | position: relative; |
302 | } | 302 | } |
303 | 303 | ||
304 | .video-info-likes-dislikes-bar-innerContainer { | 304 | .video-info-likes-dislikes-bar-inner-container { |
305 | position: absolute; | 305 | position: absolute; |
306 | height: 30px; | 306 | height: 20px; |
307 | } | 307 | } |
308 | 308 | ||
309 | .video-info-likes-dislikes-bar { | 309 | .video-info-likes-dislikes-bar { |
diff --git a/client/src/app/videos/+video-watch/video-watch.component.ts b/client/src/app/videos/+video-watch/video-watch.component.ts index bad0144bf..dcceb1400 100644 --- a/client/src/app/videos/+video-watch/video-watch.component.ts +++ b/client/src/app/videos/+video-watch/video-watch.component.ts | |||
@@ -37,7 +37,7 @@ import { PluginService } from '@app/core/plugins/plugin.service' | |||
37 | import { HooksService } from '@app/core/plugins/hooks.service' | 37 | import { HooksService } from '@app/core/plugins/hooks.service' |
38 | import { PlatformLocation } from '@angular/common' | 38 | import { PlatformLocation } from '@angular/common' |
39 | import { RecommendedVideosComponent } from '../recommendations/recommended-videos.component' | 39 | import { RecommendedVideosComponent } from '../recommendations/recommended-videos.component' |
40 | import { scrollToTop } from '@app/shared/misc/utils' | 40 | import { scrollToTop, isInViewport, isXPercentInViewport } from '@app/shared/misc/utils' |
41 | 41 | ||
42 | @Component({ | 42 | @Component({ |
43 | selector: 'my-video-watch', | 43 | selector: 'my-video-watch', |
@@ -478,12 +478,18 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
478 | 478 | ||
479 | /** | 479 | /** |
480 | * replaces this.player.one('ended') | 480 | * replaces this.player.one('ended') |
481 | * define 'condition(next)' to return true to wait, false to stop | 481 | * 'condition()': true to make the upnext functionality trigger, |
482 | * false to disable the upnext functionality | ||
483 | * go to the next video in 'condition()' if you don't want of the timer. | ||
484 | * 'next': function triggered at the end of the timer. | ||
485 | * 'suspended': function used at each clic of the timer checking if we need | ||
486 | * to reset progress and wait until 'suspended' becomes truthy again. | ||
482 | */ | 487 | */ |
483 | this.player.upnext({ | 488 | this.player.upnext({ |
484 | timeout: 10000, // 10s | 489 | timeout: 10000, // 10s |
485 | headText: this.i18n('Up Next'), | 490 | headText: this.i18n('Up Next'), |
486 | cancelText: this.i18n('Cancel'), | 491 | cancelText: this.i18n('Cancel'), |
492 | suspendedText: this.i18n('Autoplay is suspended'), | ||
487 | getTitle: () => this.nextVideoTitle, | 493 | getTitle: () => this.nextVideoTitle, |
488 | next: () => this.zone.run(() => this.autoplayNext()), | 494 | next: () => this.zone.run(() => this.autoplayNext()), |
489 | condition: () => { | 495 | condition: () => { |
@@ -496,6 +502,12 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
496 | return true // upnext will trigger | 502 | return true // upnext will trigger |
497 | } | 503 | } |
498 | return false // upnext will not trigger, and instead leave the video stopping | 504 | return false // upnext will not trigger, and instead leave the video stopping |
505 | }, | ||
506 | suspended: () => { | ||
507 | return ( | ||
508 | !isXPercentInViewport(this.player.el(), 80) || | ||
509 | !document.getElementById('content').contains(document.activeElement) | ||
510 | ) | ||
499 | } | 511 | } |
500 | }) | 512 | }) |
501 | 513 | ||
diff --git a/client/src/assets/player/upnext/upnext-plugin.ts b/client/src/assets/player/upnext/upnext-plugin.ts index ba9afbe3d..a3747b25f 100644 --- a/client/src/assets/player/upnext/upnext-plugin.ts +++ b/client/src/assets/player/upnext/upnext-plugin.ts | |||
@@ -18,6 +18,7 @@ function getMainTemplate (options: any) { | |||
18 | <span class="vjs-upnext-cancel"> | 18 | <span class="vjs-upnext-cancel"> |
19 | <button class="vjs-upnext-cancel-button" tabindex="0" aria-label="Cancel autoplay">${options.cancelText}</button> | 19 | <button class="vjs-upnext-cancel-button" tabindex="0" aria-label="Cancel autoplay">${options.cancelText}</button> |
20 | </span> | 20 | </span> |
21 | <span class="vjs-upnext-suspended">${options.suspendedText}</span> | ||
21 | </span> | 22 | </span> |
22 | ` | 23 | ` |
23 | } | 24 | } |
@@ -26,40 +27,34 @@ function getMainTemplate (options: any) { | |||
26 | const Component = videojs.getComponent('Component') | 27 | const Component = videojs.getComponent('Component') |
27 | class EndCard extends Component { | 28 | class EndCard extends Component { |
28 | options_: any | 29 | options_: any |
29 | getTitle: Function | ||
30 | next: Function | ||
31 | condition: Function | ||
32 | dashOffsetTotal = 586 | 30 | dashOffsetTotal = 586 |
33 | dashOffsetStart = 293 | 31 | dashOffsetStart = 293 |
34 | interval = 50 | 32 | interval = 50 |
35 | upNextEvents = new videojs.EventTarget() | 33 | upNextEvents = new videojs.EventTarget() |
36 | chunkSize: number | 34 | ticks = 0 |
35 | totalTicks: number | ||
37 | 36 | ||
38 | container: HTMLElement | 37 | container: HTMLElement |
39 | title: HTMLElement | 38 | title: HTMLElement |
40 | autoplayRing: HTMLElement | 39 | autoplayRing: HTMLElement |
41 | cancelButton: HTMLElement | 40 | cancelButton: HTMLElement |
41 | suspendedMessage: HTMLElement | ||
42 | nextButton: HTMLElement | 42 | nextButton: HTMLElement |
43 | 43 | ||
44 | constructor (player: videojs.Player, options: any) { | 44 | constructor (player: videojs.Player, options: any) { |
45 | super(player, options) | 45 | super(player, options) |
46 | this.options_ = options | ||
47 | 46 | ||
48 | this.getTitle = this.options_.getTitle | 47 | this.totalTicks = this.options_.timeout / this.interval |
49 | this.next = this.options_.next | ||
50 | this.condition = this.options_.condition | ||
51 | |||
52 | this.chunkSize = (this.dashOffsetTotal - this.dashOffsetStart) / (this.options_.timeout / this.interval) | ||
53 | 48 | ||
54 | player.on('ended', (_: any) => { | 49 | player.on('ended', (_: any) => { |
55 | if (!this.condition()) return | 50 | if (!this.options_.condition()) return |
56 | 51 | ||
57 | player.addClass('vjs-upnext--showing') | 52 | player.addClass('vjs-upnext--showing') |
58 | this.showCard((canceled: boolean) => { | 53 | this.showCard((canceled: boolean) => { |
59 | player.removeClass('vjs-upnext--showing') | 54 | player.removeClass('vjs-upnext--showing') |
60 | this.container.style.display = 'none' | 55 | this.container.style.display = 'none' |
61 | if (!canceled) { | 56 | if (!canceled) { |
62 | this.next() | 57 | this.options_.next() |
63 | } | 58 | } |
64 | }) | 59 | }) |
65 | }) | 60 | }) |
@@ -81,6 +76,7 @@ class EndCard extends Component { | |||
81 | this.autoplayRing = container.getElementsByClassName('vjs-upnext-svg-autoplay-ring')[0] | 76 | this.autoplayRing = container.getElementsByClassName('vjs-upnext-svg-autoplay-ring')[0] |
82 | this.title = container.getElementsByClassName('vjs-upnext-title')[0] | 77 | this.title = container.getElementsByClassName('vjs-upnext-title')[0] |
83 | this.cancelButton = container.getElementsByClassName('vjs-upnext-cancel-button')[0] | 78 | this.cancelButton = container.getElementsByClassName('vjs-upnext-cancel-button')[0] |
79 | this.suspendedMessage = container.getElementsByClassName('vjs-upnext-suspended')[0] | ||
84 | this.nextButton = container.getElementsByClassName('vjs-upnext-autoplay-icon')[0] | 80 | this.nextButton = container.getElementsByClassName('vjs-upnext-autoplay-icon')[0] |
85 | 81 | ||
86 | this.cancelButton.onclick = () => { | 82 | this.cancelButton.onclick = () => { |
@@ -96,14 +92,11 @@ class EndCard extends Component { | |||
96 | 92 | ||
97 | showCard (cb: Function) { | 93 | showCard (cb: Function) { |
98 | let timeout: any | 94 | let timeout: any |
99 | let start: number | ||
100 | let now: number | ||
101 | let newOffset: number | ||
102 | 95 | ||
103 | this.autoplayRing.setAttribute('stroke-dasharray', '' + this.dashOffsetStart) | 96 | this.autoplayRing.setAttribute('stroke-dasharray', '' + this.dashOffsetStart) |
104 | this.autoplayRing.setAttribute('stroke-dashoffset', '' + -this.dashOffsetStart) | 97 | this.autoplayRing.setAttribute('stroke-dashoffset', '' + -this.dashOffsetStart) |
105 | 98 | ||
106 | this.title.innerHTML = this.getTitle() | 99 | this.title.innerHTML = this.options_.getTitle() |
107 | 100 | ||
108 | this.upNextEvents.one('cancel', () => { | 101 | this.upNextEvents.one('cancel', () => { |
109 | clearTimeout(timeout) | 102 | clearTimeout(timeout) |
@@ -120,23 +113,32 @@ class EndCard extends Component { | |||
120 | cb(false) | 113 | cb(false) |
121 | }) | 114 | }) |
122 | 115 | ||
123 | const update = () => { | 116 | const goToPercent = (percent: number) => { |
124 | now = this.options_.timeout - (new Date().getTime() - start) | 117 | const newOffset = Math.max(-this.dashOffsetTotal, - this.dashOffsetStart - percent * this.dashOffsetTotal / 2 / 100) |
118 | this.autoplayRing.setAttribute('stroke-dashoffset', '' + newOffset) | ||
119 | } | ||
125 | 120 | ||
126 | if (now <= 0) { | 121 | const tick = () => { |
122 | goToPercent((this.ticks++) * 100 / this.totalTicks) | ||
123 | } | ||
124 | |||
125 | const update = () => { | ||
126 | if (this.options_.suspended()) { | ||
127 | this.suspendedMessage.innerText = this.options_.suspendedText | ||
128 | goToPercent(0) | ||
129 | this.ticks = 0 | ||
130 | timeout = setTimeout(update.bind(this), 300) // checks once supsended can be a bit longer | ||
131 | } else if (this.ticks >= this.totalTicks) { | ||
127 | clearTimeout(timeout) | 132 | clearTimeout(timeout) |
128 | cb(false) | 133 | cb(false) |
129 | } else { | 134 | } else { |
130 | const strokeDashOffset = parseInt(this.autoplayRing.getAttribute('stroke-dashoffset'), 10) | 135 | this.suspendedMessage.innerText = '' |
131 | newOffset = Math.max(-this.dashOffsetTotal, strokeDashOffset - this.chunkSize) | 136 | tick() |
132 | this.autoplayRing.setAttribute('stroke-dashoffset', '' + newOffset) | ||
133 | timeout = setTimeout(update.bind(this), this.interval) | 137 | timeout = setTimeout(update.bind(this), this.interval) |
134 | } | 138 | } |
135 | |||
136 | } | 139 | } |
137 | 140 | ||
138 | this.container.style.display = 'block' | 141 | this.container.style.display = 'block' |
139 | start = new Date().getTime() | ||
140 | timeout = setTimeout(update.bind(this), this.interval) | 142 | timeout = setTimeout(update.bind(this), this.interval) |
141 | } | 143 | } |
142 | } | 144 | } |
@@ -153,7 +155,9 @@ class UpNextPlugin extends Plugin { | |||
153 | timeout: options.timeout || 5000, | 155 | timeout: options.timeout || 5000, |
154 | cancelText: options.cancelText || 'Cancel', | 156 | cancelText: options.cancelText || 'Cancel', |
155 | headText: options.headText || 'Up Next', | 157 | headText: options.headText || 'Up Next', |
156 | condition: options.condition | 158 | suspendedText: options.suspendedText || 'Autoplay is suspended', |
159 | condition: options.condition, | ||
160 | suspended: options.suspended | ||
157 | } | 161 | } |
158 | 162 | ||
159 | super(player, settings) | 163 | super(player, settings) |
diff --git a/client/src/sass/player/upnext.scss b/client/src/sass/player/upnext.scss index f1f2e0fe2..7614bb3b6 100644 --- a/client/src/sass/player/upnext.scss +++ b/client/src/sass/player/upnext.scss | |||
@@ -40,12 +40,18 @@ $browser-context: 16; | |||
40 | margin-top: 52px; | 40 | margin-top: 52px; |
41 | } | 41 | } |
42 | 42 | ||
43 | .vjs-upnext-suspended, | ||
43 | .vjs-upnext-cancel { | 44 | .vjs-upnext-cancel { |
44 | display: block; | 45 | display: block; |
45 | float: none; | 46 | float: none; |
46 | text-align: center; | 47 | text-align: center; |
47 | } | 48 | } |
48 | 49 | ||
50 | .vjs-upnext-suspended { | ||
51 | font-size: 50%; | ||
52 | margin-top: 1rem; | ||
53 | } | ||
54 | |||
49 | .vjs-upnext-headtext { | 55 | .vjs-upnext-headtext { |
50 | display: block; | 56 | display: block; |
51 | font-size: 14px; | 57 | font-size: 14px; |