diff options
author | Chocobozzz <me@florianbigard.com> | 2019-03-14 14:05:36 +0100 |
---|---|---|
committer | Chocobozzz <chocobozzz@cpy.re> | 2019-03-18 11:17:59 +0100 |
commit | bce47964f6241ae56f61089d144b29eb9b5da6d3 (patch) | |
tree | cad0a5ef17bc7851d483969453f7b8c2e6edad57 /client/src/app/shared | |
parent | 2a10aab3d7634a252a2acc946974df903e6025be (diff) | |
download | PeerTube-bce47964f6241ae56f61089d144b29eb9b5da6d3.tar.gz PeerTube-bce47964f6241ae56f61089d144b29eb9b5da6d3.tar.zst PeerTube-bce47964f6241ae56f61089d144b29eb9b5da6d3.zip |
Add video channel view
Diffstat (limited to 'client/src/app/shared')
7 files changed, 85 insertions, 17 deletions
diff --git a/client/src/app/shared/video-playlist/video-playlist-element-miniature.component.html b/client/src/app/shared/video-playlist/video-playlist-element-miniature.component.html index 1f178675f..4764fc0e1 100644 --- a/client/src/app/shared/video-playlist/video-playlist-element-miniature.component.html +++ b/client/src/app/shared/video-playlist/video-playlist-element-miniature.component.html | |||
@@ -2,7 +2,7 @@ | |||
2 | <a [routerLink]="buildRouterLink()" [queryParams]="buildRouterQuery()"> | 2 | <a [routerLink]="buildRouterLink()" [queryParams]="buildRouterQuery()"> |
3 | <div class="position"> | 3 | <div class="position"> |
4 | <my-global-icon *ngIf="playing" iconName="play"></my-global-icon> | 4 | <my-global-icon *ngIf="playing" iconName="play"></my-global-icon> |
5 | <ng-container *ngIf="!playing">{{ video.playlistElement.position }}</ng-container> | 5 | <ng-container *ngIf="!playing">{{ position }}</ng-container> |
6 | </div> | 6 | </div> |
7 | 7 | ||
8 | <my-video-thumbnail | 8 | <my-video-thumbnail |
diff --git a/client/src/app/shared/video-playlist/video-playlist-element-miniature.component.scss b/client/src/app/shared/video-playlist/video-playlist-element-miniature.component.scss index eb869f69a..f57fd2e1c 100644 --- a/client/src/app/shared/video-playlist/video-playlist-element-miniature.component.scss +++ b/client/src/app/shared/video-playlist/video-playlist-element-miniature.component.scss | |||
@@ -34,7 +34,7 @@ | |||
34 | font-weight: $font-semibold; | 34 | font-weight: $font-semibold; |
35 | margin-right: 10px; | 35 | margin-right: 10px; |
36 | color: $grey-foreground-color; | 36 | color: $grey-foreground-color; |
37 | min-width: 20px; | 37 | min-width: 25px; |
38 | 38 | ||
39 | my-global-icon { | 39 | my-global-icon { |
40 | @include apply-svg-color($grey-foreground-color); | 40 | @include apply-svg-color($grey-foreground-color); |
@@ -59,7 +59,7 @@ | |||
59 | 59 | ||
60 | a { | 60 | a { |
61 | color: var(--mainForegroundColor); | 61 | color: var(--mainForegroundColor); |
62 | width: fit-content; | 62 | width: auto; |
63 | 63 | ||
64 | &:hover { | 64 | &:hover { |
65 | text-decoration: underline !important; | 65 | text-decoration: underline !important; |
diff --git a/client/src/app/shared/video-playlist/video-playlist-element-miniature.component.ts b/client/src/app/shared/video-playlist/video-playlist-element-miniature.component.ts index c0cfd855d..6cc5b87b4 100644 --- a/client/src/app/shared/video-playlist/video-playlist-element-miniature.component.ts +++ b/client/src/app/shared/video-playlist/video-playlist-element-miniature.component.ts | |||
@@ -1,4 +1,4 @@ | |||
1 | import { Component, EventEmitter, Input, Output, ViewChild } from '@angular/core' | 1 | import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, OnChanges, Output, ViewChild } from '@angular/core' |
2 | import { Video } from '@app/shared/video/video.model' | 2 | import { Video } from '@app/shared/video/video.model' |
3 | import { VideoPlaylistElementUpdate } from '@shared/models' | 3 | import { VideoPlaylistElementUpdate } from '@shared/models' |
4 | import { AuthService, ConfirmService, Notifier, ServerService } from '@app/core' | 4 | import { AuthService, ConfirmService, Notifier, ServerService } from '@app/core' |
@@ -13,7 +13,8 @@ import { secondsToTime } from '../../../assets/player/utils' | |||
13 | @Component({ | 13 | @Component({ |
14 | selector: 'my-video-playlist-element-miniature', | 14 | selector: 'my-video-playlist-element-miniature', |
15 | styleUrls: [ './video-playlist-element-miniature.component.scss' ], | 15 | styleUrls: [ './video-playlist-element-miniature.component.scss' ], |
16 | templateUrl: './video-playlist-element-miniature.component.html' | 16 | templateUrl: './video-playlist-element-miniature.component.html', |
17 | changeDetection: ChangeDetectionStrategy.OnPush | ||
17 | }) | 18 | }) |
18 | export class VideoPlaylistElementMiniatureComponent { | 19 | export class VideoPlaylistElementMiniatureComponent { |
19 | @ViewChild('moreDropdown') moreDropdown: NgbDropdown | 20 | @ViewChild('moreDropdown') moreDropdown: NgbDropdown |
@@ -24,6 +25,7 @@ export class VideoPlaylistElementMiniatureComponent { | |||
24 | @Input() playing = false | 25 | @Input() playing = false |
25 | @Input() rowLink = false | 26 | @Input() rowLink = false |
26 | @Input() accountLink = true | 27 | @Input() accountLink = true |
28 | @Input() position: number | ||
27 | 29 | ||
28 | @Output() elementRemoved = new EventEmitter<Video>() | 30 | @Output() elementRemoved = new EventEmitter<Video>() |
29 | 31 | ||
@@ -44,7 +46,8 @@ export class VideoPlaylistElementMiniatureComponent { | |||
44 | private route: ActivatedRoute, | 46 | private route: ActivatedRoute, |
45 | private i18n: I18n, | 47 | private i18n: I18n, |
46 | private videoService: VideoService, | 48 | private videoService: VideoService, |
47 | private videoPlaylistService: VideoPlaylistService | 49 | private videoPlaylistService: VideoPlaylistService, |
50 | private cdr: ChangeDetectorRef | ||
48 | ) {} | 51 | ) {} |
49 | 52 | ||
50 | buildRouterLink () { | 53 | buildRouterLink () { |
@@ -95,6 +98,8 @@ export class VideoPlaylistElementMiniatureComponent { | |||
95 | 98 | ||
96 | video.playlistElement.startTimestamp = body.startTimestamp | 99 | video.playlistElement.startTimestamp = body.startTimestamp |
97 | video.playlistElement.stopTimestamp = body.stopTimestamp | 100 | video.playlistElement.stopTimestamp = body.stopTimestamp |
101 | |||
102 | this.cdr.detectChanges() | ||
98 | }, | 103 | }, |
99 | 104 | ||
100 | err => this.notifier.error(err.message) | 105 | err => this.notifier.error(err.message) |
@@ -145,5 +150,10 @@ export class VideoPlaylistElementMiniatureComponent { | |||
145 | this.timestampOptions.stopTimestamp = video.playlistElement.stopTimestamp | 150 | this.timestampOptions.stopTimestamp = video.playlistElement.stopTimestamp |
146 | } | 151 | } |
147 | } | 152 | } |
153 | |||
154 | // FIXME: why do we have to use setTimeout here? | ||
155 | setTimeout(() => { | ||
156 | this.cdr.detectChanges() | ||
157 | }) | ||
148 | } | 158 | } |
149 | } | 159 | } |
diff --git a/client/src/app/shared/video-playlist/video-playlist-miniature.component.html b/client/src/app/shared/video-playlist/video-playlist-miniature.component.html index a136f9233..c01c73012 100644 --- a/client/src/app/shared/video-playlist/video-playlist-miniature.component.html +++ b/client/src/app/shared/video-playlist/video-playlist-miniature.component.html | |||
@@ -1,6 +1,6 @@ | |||
1 | <div class="miniature" [ngClass]="{ 'no-videos': playlist.videosLength === 0, 'to-manage': toManage }"> | 1 | <div class="miniature" [ngClass]="{ 'no-videos': playlist.videosLength === 0, 'to-manage': toManage }"> |
2 | <a | 2 | <a |
3 | [routerLink]="getPlaylistUrl()" [attr.title]="playlist.displayName" | 3 | [routerLink]="getPlaylistUrl()" [attr.title]="playlist.description" |
4 | class="miniature-thumbnail" | 4 | class="miniature-thumbnail" |
5 | > | 5 | > |
6 | <img alt="" [attr.aria-labelledby]="playlist.displayName" [attr.src]="playlist.thumbnailUrl" /> | 6 | <img alt="" [attr.aria-labelledby]="playlist.displayName" [attr.src]="playlist.thumbnailUrl" /> |
@@ -14,9 +14,21 @@ | |||
14 | </div> | 14 | </div> |
15 | </a> | 15 | </a> |
16 | 16 | ||
17 | <div class="miniature-bottom"> | 17 | <div class="miniature-info"> |
18 | <a tabindex="-1" class="miniature-name" [routerLink]="getPlaylistUrl()" [attr.title]="playlist.displayName"> | 18 | <a tabindex="-1" class="miniature-name" [routerLink]="getPlaylistUrl()" [attr.title]="playlist.description"> |
19 | {{ playlist.displayName }} | 19 | {{ playlist.displayName }} |
20 | </a> | 20 | </a> |
21 | |||
22 | <div class="video-info-privacy" *ngIf="displayPrivacy">{{ playlist.privacy.label }}</div> | ||
23 | |||
24 | <div class="video-info-by-date"> | ||
25 | <a i18n [routerLink]="[ '/video-channels', playlist.videoChannelBy ]" class="by" *ngIf="displayChannel && playlist.videoChannelBy"> | ||
26 | {{ playlist.videoChannelBy }} | ||
27 | </a> | ||
28 | |||
29 | <div i18n class="updated-at">Updated {{ playlist.updatedAt | myFromNow }}</div> | ||
30 | </div> | ||
31 | |||
32 | <div *ngIf="displayDescription" class="video-info-description">{{ playlist.description }}</div> | ||
21 | </div> | 33 | </div> |
22 | </div> | 34 | </div> |
diff --git a/client/src/app/shared/video-playlist/video-playlist-miniature.component.scss b/client/src/app/shared/video-playlist/video-playlist-miniature.component.scss index 72158eb10..94edd1177 100644 --- a/client/src/app/shared/video-playlist/video-playlist-miniature.component.scss +++ b/client/src/app/shared/video-playlist/video-playlist-miniature.component.scss | |||
@@ -11,9 +11,11 @@ | |||
11 | } | 11 | } |
12 | } | 12 | } |
13 | 13 | ||
14 | &.to-manage .play-overlay, | 14 | &.to-manage, |
15 | &.no-videos { | 15 | &.no-videos { |
16 | display: none; | 16 | .play-overlay { |
17 | display: none; | ||
18 | } | ||
17 | } | 19 | } |
18 | 20 | ||
19 | .miniature-thumbnail { | 21 | .miniature-thumbnail { |
@@ -34,7 +36,7 @@ | |||
34 | } | 36 | } |
35 | } | 37 | } |
36 | 38 | ||
37 | .miniature-bottom { | 39 | .miniature-info { |
38 | width: 200px; | 40 | width: 200px; |
39 | margin-top: 2px; | 41 | margin-top: 2px; |
40 | line-height: normal; | 42 | line-height: normal; |
@@ -42,5 +44,33 @@ | |||
42 | .miniature-name { | 44 | .miniature-name { |
43 | @include miniature-name; | 45 | @include miniature-name; |
44 | } | 46 | } |
47 | |||
48 | .video-info-by-date { | ||
49 | display: flex; | ||
50 | font-size: 13px; | ||
51 | margin: 5px 0; | ||
52 | |||
53 | .by { | ||
54 | @include disable-default-a-behaviour; | ||
55 | |||
56 | display: block; | ||
57 | color: var(--mainForegroundColor); | ||
58 | |||
59 | &::after { | ||
60 | content: '-'; | ||
61 | margin: 0 3px; | ||
62 | } | ||
63 | } | ||
64 | } | ||
65 | |||
66 | .video-info-privacy { | ||
67 | font-size: 13px; | ||
68 | font-weight: $font-semibold; | ||
69 | } | ||
70 | |||
71 | .video-info-description { | ||
72 | margin-top: 10px; | ||
73 | color: $grey-foreground-color; | ||
74 | } | ||
45 | } | 75 | } |
46 | } | 76 | } |
diff --git a/client/src/app/shared/video-playlist/video-playlist-miniature.component.ts b/client/src/app/shared/video-playlist/video-playlist-miniature.component.ts index cb5803400..523e96f2a 100644 --- a/client/src/app/shared/video-playlist/video-playlist-miniature.component.ts +++ b/client/src/app/shared/video-playlist/video-playlist-miniature.component.ts | |||
@@ -9,6 +9,9 @@ import { VideoPlaylist } from '@app/shared/video-playlist/video-playlist.model' | |||
9 | export class VideoPlaylistMiniatureComponent { | 9 | export class VideoPlaylistMiniatureComponent { |
10 | @Input() playlist: VideoPlaylist | 10 | @Input() playlist: VideoPlaylist |
11 | @Input() toManage = false | 11 | @Input() toManage = false |
12 | @Input() displayChannel = false | ||
13 | @Input() displayDescription = false | ||
14 | @Input() displayPrivacy = false | ||
12 | 15 | ||
13 | getPlaylistUrl () { | 16 | getPlaylistUrl () { |
14 | if (this.toManage) return [ '/my-account/video-playlists', this.playlist.uuid ] | 17 | if (this.toManage) return [ '/my-account/video-playlists', this.playlist.uuid ] |
diff --git a/client/src/app/shared/video/infinite-scroller.directive.ts b/client/src/app/shared/video/infinite-scroller.directive.ts index 186597a3a..a9e75007c 100644 --- a/client/src/app/shared/video/infinite-scroller.directive.ts +++ b/client/src/app/shared/video/infinite-scroller.directive.ts | |||
@@ -1,5 +1,5 @@ | |||
1 | import { distinct, distinctUntilChanged, filter, map, share, startWith, throttleTime } from 'rxjs/operators' | 1 | import { distinct, distinctUntilChanged, filter, map, share, startWith, throttleTime } from 'rxjs/operators' |
2 | import { Directive, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core' | 2 | import { Directive, ElementRef, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core' |
3 | import { fromEvent, Subscription } from 'rxjs' | 3 | import { fromEvent, Subscription } from 'rxjs' |
4 | 4 | ||
5 | @Directive({ | 5 | @Directive({ |
@@ -11,7 +11,7 @@ export class InfiniteScrollerDirective implements OnInit, OnDestroy { | |||
11 | @Input() firstLoadedPage = 1 | 11 | @Input() firstLoadedPage = 1 |
12 | @Input() percentLimit = 70 | 12 | @Input() percentLimit = 70 |
13 | @Input() autoInit = false | 13 | @Input() autoInit = false |
14 | @Input() container = document.body | 14 | @Input() onItself = false |
15 | 15 | ||
16 | @Output() nearOfBottom = new EventEmitter<void>() | 16 | @Output() nearOfBottom = new EventEmitter<void>() |
17 | @Output() nearOfTop = new EventEmitter<void>() | 17 | @Output() nearOfTop = new EventEmitter<void>() |
@@ -24,8 +24,9 @@ export class InfiniteScrollerDirective implements OnInit, OnDestroy { | |||
24 | private scrollUpSub: Subscription | 24 | private scrollUpSub: Subscription |
25 | private pageChangeSub: Subscription | 25 | private pageChangeSub: Subscription |
26 | private middleScreen: number | 26 | private middleScreen: number |
27 | private container: HTMLElement | ||
27 | 28 | ||
28 | constructor () { | 29 | constructor (private el: ElementRef) { |
29 | this.decimalLimit = this.percentLimit / 100 | 30 | this.decimalLimit = this.percentLimit / 100 |
30 | } | 31 | } |
31 | 32 | ||
@@ -40,16 +41,20 @@ export class InfiniteScrollerDirective implements OnInit, OnDestroy { | |||
40 | } | 41 | } |
41 | 42 | ||
42 | initialize () { | 43 | initialize () { |
44 | if (this.onItself) { | ||
45 | this.container = this.el.nativeElement | ||
46 | } | ||
47 | |||
43 | this.middleScreen = window.innerHeight / 2 | 48 | this.middleScreen = window.innerHeight / 2 |
44 | 49 | ||
45 | // Emit the last value | 50 | // Emit the last value |
46 | const throttleOptions = { leading: true, trailing: true } | 51 | const throttleOptions = { leading: true, trailing: true } |
47 | 52 | ||
48 | const scrollObservable = fromEvent(window, 'scroll') | 53 | const scrollObservable = fromEvent(this.container || window, 'scroll') |
49 | .pipe( | 54 | .pipe( |
50 | startWith(null), | 55 | startWith(null), |
51 | throttleTime(200, undefined, throttleOptions), | 56 | throttleTime(200, undefined, throttleOptions), |
52 | map(() => ({ current: window.scrollY, maximumScroll: this.container.clientHeight - window.innerHeight })), | 57 | map(() => this.getScrollInfo()), |
53 | distinctUntilChanged((o1, o2) => o1.current === o2.current), | 58 | distinctUntilChanged((o1, o2) => o1.current === o2.current), |
54 | share() | 59 | share() |
55 | ) | 60 | ) |
@@ -102,4 +107,12 @@ export class InfiniteScrollerDirective implements OnInit, OnDestroy { | |||
102 | // Offset page | 107 | // Offset page |
103 | return page + (this.firstLoadedPage - 1) | 108 | return page + (this.firstLoadedPage - 1) |
104 | } | 109 | } |
110 | |||
111 | private getScrollInfo () { | ||
112 | if (this.container) { | ||
113 | return { current: this.container.scrollTop, maximumScroll: this.container.scrollHeight } | ||
114 | } | ||
115 | |||
116 | return { current: window.scrollY, maximumScroll: document.body.clientHeight - window.innerHeight } | ||
117 | } | ||
105 | } | 118 | } |