diff options
author | Rigel Kent <sendmemail@rigelk.eu> | 2021-01-22 00:12:44 +0100 |
---|---|---|
committer | Chocobozzz <chocobozzz@cpy.re> | 2021-01-28 15:55:34 +0100 |
commit | 5bcbcbe338ef5a1ed14f084311d013fbb25dabcf (patch) | |
tree | b0f6382b30b67f1f7adddaf7d12af9adae0c9f5d /client/src/app/shared/shared-video-miniature | |
parent | 7a4994873c0b3394d04e16e877fc7418bc8b146a (diff) | |
download | PeerTube-5bcbcbe338ef5a1ed14f084311d013fbb25dabcf.tar.gz PeerTube-5bcbcbe338ef5a1ed14f084311d013fbb25dabcf.tar.zst PeerTube-5bcbcbe338ef5a1ed14f084311d013fbb25dabcf.zip |
modularize abstract video list header and implement video hotness recommendation variant
Diffstat (limited to 'client/src/app/shared/shared-video-miniature')
7 files changed, 81 insertions, 17 deletions
diff --git a/client/src/app/shared/shared-video-miniature/abstract-video-list.html b/client/src/app/shared/shared-video-miniature/abstract-video-list.html index 368a7d70e..07f79cd6d 100644 --- a/client/src/app/shared/shared-video-miniature/abstract-video-list.html +++ b/client/src/app/shared/shared-video-miniature/abstract-video-list.html | |||
@@ -1,13 +1,9 @@ | |||
1 | <div class="margin-content"> | 1 | <div class="margin-content"> |
2 | <div class="videos-header"> | 2 | <div class="videos-header"> |
3 | <h1 *ngIf="titlePage" class="title-page title-page-single"> | 3 | <ng-template #videoListHeader></ng-template> |
4 | <div placement="bottom" [ngbTooltip]="titleTooltip" container="body"> | ||
5 | {{ titlePage }} | ||
6 | </div> | ||
7 | </h1> | ||
8 | 4 | ||
9 | <div class="action-block"> | 5 | <div class="action-block"> |
10 | <my-feed *ngIf="titlePage" [syndicationItems]="syndicationItems"></my-feed> | 6 | <my-feed *ngIf="syndicationItems" [syndicationItems]="syndicationItems"></my-feed> |
11 | <ng-container *ngFor="let action of actions"> | 7 | <ng-container *ngFor="let action of actions"> |
12 | <a *ngIf="action.routerLink" class="ml-2" [routerLink]="action.routerLink" routerLinkActive="active"> | 8 | <a *ngIf="action.routerLink" class="ml-2" [routerLink]="action.routerLink" routerLinkActive="active"> |
13 | <ng-container *ngTemplateOutlet="actionContent; context:{ $implicit: action }"></ng-container> | 9 | <ng-container *ngTemplateOutlet="actionContent; context:{ $implicit: action }"></ng-container> |
diff --git a/client/src/app/shared/shared-video-miniature/abstract-video-list.scss b/client/src/app/shared/shared-video-miniature/abstract-video-list.scss index 1c27c58c3..2eaf0dc70 100644 --- a/client/src/app/shared/shared-video-miniature/abstract-video-list.scss +++ b/client/src/app/shared/shared-video-miniature/abstract-video-list.scss | |||
@@ -5,16 +5,16 @@ | |||
5 | 5 | ||
6 | $iconSize: 16px; | 6 | $iconSize: 16px; |
7 | 7 | ||
8 | ::ng-deep .title-page.title-page-single { | ||
9 | display: flex; | ||
10 | flex-grow: 1; | ||
11 | } | ||
12 | |||
8 | .videos-header { | 13 | .videos-header { |
9 | display: flex; | 14 | display: flex; |
10 | justify-content: space-between; | 15 | justify-content: space-between; |
11 | align-items: center; | 16 | align-items: center; |
12 | 17 | ||
13 | .title-page.title-page-single { | ||
14 | display: flex; | ||
15 | flex-grow: 1; | ||
16 | } | ||
17 | |||
18 | .action-block { | 18 | .action-block { |
19 | ::ng-deep my-feed { | 19 | ::ng-deep my-feed { |
20 | my-global-icon { | 20 | my-global-icon { |
diff --git a/client/src/app/shared/shared-video-miniature/abstract-video-list.ts b/client/src/app/shared/shared-video-miniature/abstract-video-list.ts index a5f22585d..3e84589cd 100644 --- a/client/src/app/shared/shared-video-miniature/abstract-video-list.ts +++ b/client/src/app/shared/shared-video-miniature/abstract-video-list.ts | |||
@@ -1,6 +1,16 @@ | |||
1 | import { fromEvent, Observable, Subject, Subscription } from 'rxjs' | 1 | import { fromEvent, Observable, Subject, Subscription } from 'rxjs' |
2 | import { debounceTime, switchMap, tap } from 'rxjs/operators' | 2 | import { debounceTime, switchMap, tap } from 'rxjs/operators' |
3 | import { Directive, OnDestroy, OnInit } from '@angular/core' | 3 | import { |
4 | AfterContentInit, | ||
5 | ComponentFactoryResolver, | ||
6 | Directive, | ||
7 | Injector, | ||
8 | OnDestroy, | ||
9 | OnInit, | ||
10 | Type, | ||
11 | ViewChild, | ||
12 | ViewContainerRef | ||
13 | } from '@angular/core' | ||
4 | import { ActivatedRoute, Router } from '@angular/router' | 14 | import { ActivatedRoute, Router } from '@angular/router' |
5 | import { | 15 | import { |
6 | AuthService, | 16 | AuthService, |
@@ -19,6 +29,7 @@ import { ServerConfig, UserRight, VideoFilter, VideoSortField } from '@shared/mo | |||
19 | import { NSFWPolicyType } from '@shared/models/videos/nsfw-policy.type' | 29 | import { NSFWPolicyType } from '@shared/models/videos/nsfw-policy.type' |
20 | import { Syndication, Video } from '../shared-main' | 30 | import { Syndication, Video } from '../shared-main' |
21 | import { MiniatureDisplayOptions, OwnerDisplayType } from './video-miniature.component' | 31 | import { MiniatureDisplayOptions, OwnerDisplayType } from './video-miniature.component' |
32 | import { GenericHeaderComponent, VideoListHeaderComponent } from './video-list-header.component' | ||
22 | 33 | ||
23 | enum GroupDate { | 34 | enum GroupDate { |
24 | UNKNOWN = 0, | 35 | UNKNOWN = 0, |
@@ -32,7 +43,12 @@ enum GroupDate { | |||
32 | 43 | ||
33 | @Directive() | 44 | @Directive() |
34 | // tslint:disable-next-line: directive-class-suffix | 45 | // tslint:disable-next-line: directive-class-suffix |
35 | export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableForReuseHook { | 46 | export abstract class AbstractVideoList implements OnInit, OnDestroy, AfterContentInit, DisableForReuseHook { |
47 | @ViewChild('videoListHeader', { static: true, read: ViewContainerRef }) videoListHeader: ViewContainerRef | ||
48 | |||
49 | HeaderComponent: Type<GenericHeaderComponent> = VideoListHeaderComponent | ||
50 | headerComponentInjector: Injector | ||
51 | |||
36 | pagination: ComponentPaginationLight = { | 52 | pagination: ComponentPaginationLight = { |
37 | currentPage: 1, | 53 | currentPage: 1, |
38 | itemsPerPage: 25 | 54 | itemsPerPage: 25 |
@@ -92,6 +108,7 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableFor | |||
92 | protected abstract screenService: ScreenService | 108 | protected abstract screenService: ScreenService |
93 | protected abstract storageService: LocalStorageService | 109 | protected abstract storageService: LocalStorageService |
94 | protected abstract router: Router | 110 | protected abstract router: Router |
111 | protected abstract cfr: ComponentFactoryResolver | ||
95 | abstract titlePage: string | 112 | abstract titlePage: string |
96 | 113 | ||
97 | private resizeSubscription: Subscription | 114 | private resizeSubscription: Subscription |
@@ -153,6 +170,13 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableFor | |||
153 | if (this.resizeSubscription) this.resizeSubscription.unsubscribe() | 170 | if (this.resizeSubscription) this.resizeSubscription.unsubscribe() |
154 | } | 171 | } |
155 | 172 | ||
173 | ngAfterContentInit () { | ||
174 | if (this.videoListHeader) { | ||
175 | // some components don't use the header: they use their own template, like my-history.component.html | ||
176 | this.setHeader.apply(this, [ this.HeaderComponent, this.headerComponentInjector ]) | ||
177 | } | ||
178 | } | ||
179 | |||
156 | disableForReuse () { | 180 | disableForReuse () { |
157 | this.disabled = true | 181 | this.disabled = true |
158 | } | 182 | } |
@@ -268,7 +292,27 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableFor | |||
268 | } | 292 | } |
269 | 293 | ||
270 | toggleModerationDisplay () { | 294 | toggleModerationDisplay () { |
271 | throw new Error('toggleModerationDisplay is not implemented') | 295 | throw new Error('toggleModerationDisplay ' + $localize`function is not implemented`) |
296 | } | ||
297 | |||
298 | setHeader ( | ||
299 | t: Type<any> = this.HeaderComponent, | ||
300 | i: Injector = this.headerComponentInjector | ||
301 | ) { | ||
302 | const injector = i || Injector.create({ | ||
303 | providers: [{ | ||
304 | provide: 'data', | ||
305 | useValue: { | ||
306 | titlePage: this.titlePage, | ||
307 | titleTooltip: this.titleTooltip | ||
308 | } | ||
309 | }] | ||
310 | }) | ||
311 | const viewContainerRef = this.videoListHeader | ||
312 | viewContainerRef.clear() | ||
313 | |||
314 | const componentFactory = this.cfr.resolveComponentFactory(t) | ||
315 | viewContainerRef.createComponent(componentFactory, 0, injector) | ||
272 | } | 316 | } |
273 | 317 | ||
274 | // On videos hook for children that want to do something | 318 | // On videos hook for children that want to do something |
diff --git a/client/src/app/shared/shared-video-miniature/index.ts b/client/src/app/shared/shared-video-miniature/index.ts index 47ca6f51b..a8fd82bb9 100644 --- a/client/src/app/shared/shared-video-miniature/index.ts +++ b/client/src/app/shared/shared-video-miniature/index.ts | |||
@@ -3,5 +3,5 @@ export * from './video-actions-dropdown.component' | |||
3 | export * from './video-download.component' | 3 | export * from './video-download.component' |
4 | export * from './video-miniature.component' | 4 | export * from './video-miniature.component' |
5 | export * from './videos-selection.component' | 5 | export * from './videos-selection.component' |
6 | 6 | export * from './video-list-header.component' | |
7 | export * from './shared-video-miniature.module' | 7 | export * from './shared-video-miniature.module' |
diff --git a/client/src/app/shared/shared-video-miniature/shared-video-miniature.module.ts b/client/src/app/shared/shared-video-miniature/shared-video-miniature.module.ts index 3035bcfb3..7a7868853 100644 --- a/client/src/app/shared/shared-video-miniature/shared-video-miniature.module.ts +++ b/client/src/app/shared/shared-video-miniature/shared-video-miniature.module.ts | |||
@@ -12,6 +12,7 @@ import { VideoActionsDropdownComponent } from './video-actions-dropdown.componen | |||
12 | import { VideoDownloadComponent } from './video-download.component' | 12 | import { VideoDownloadComponent } from './video-download.component' |
13 | import { VideoMiniatureComponent } from './video-miniature.component' | 13 | import { VideoMiniatureComponent } from './video-miniature.component' |
14 | import { VideosSelectionComponent } from './videos-selection.component' | 14 | import { VideosSelectionComponent } from './videos-selection.component' |
15 | import { VideoListHeaderComponent } from './video-list-header.component' | ||
15 | 16 | ||
16 | @NgModule({ | 17 | @NgModule({ |
17 | imports: [ | 18 | imports: [ |
@@ -29,7 +30,8 @@ import { VideosSelectionComponent } from './videos-selection.component' | |||
29 | VideoActionsDropdownComponent, | 30 | VideoActionsDropdownComponent, |
30 | VideoDownloadComponent, | 31 | VideoDownloadComponent, |
31 | VideoMiniatureComponent, | 32 | VideoMiniatureComponent, |
32 | VideosSelectionComponent | 33 | VideosSelectionComponent, |
34 | VideoListHeaderComponent | ||
33 | ], | 35 | ], |
34 | 36 | ||
35 | exports: [ | 37 | exports: [ |
diff --git a/client/src/app/shared/shared-video-miniature/video-list-header.component.ts b/client/src/app/shared/shared-video-miniature/video-list-header.component.ts new file mode 100644 index 000000000..a07248b96 --- /dev/null +++ b/client/src/app/shared/shared-video-miniature/video-list-header.component.ts | |||
@@ -0,0 +1,20 @@ | |||
1 | import { Component, Inject } from '@angular/core' | ||
2 | |||
3 | export abstract class GenericHeaderComponent { | ||
4 | constructor (@Inject('data') public data: any) {} | ||
5 | } | ||
6 | |||
7 | @Component({ | ||
8 | selector: 'h1', | ||
9 | host: { 'class': 'title-page title-page-single' }, | ||
10 | template: ` | ||
11 | <div placement="bottom" [ngbTooltip]="data.titleTooltip" container="body"> | ||
12 | {{ data.titlePage }} | ||
13 | </div> | ||
14 | ` | ||
15 | }) | ||
16 | export class VideoListHeaderComponent extends GenericHeaderComponent { | ||
17 | constructor (@Inject('data') public data: any) { | ||
18 | super(data) | ||
19 | } | ||
20 | } | ||
diff --git a/client/src/app/shared/shared-video-miniature/videos-selection.component.ts b/client/src/app/shared/shared-video-miniature/videos-selection.component.ts index 2b060b130..ef59975d4 100644 --- a/client/src/app/shared/shared-video-miniature/videos-selection.component.ts +++ b/client/src/app/shared/shared-video-miniature/videos-selection.component.ts | |||
@@ -2,6 +2,7 @@ import { Observable } from 'rxjs' | |||
2 | import { | 2 | import { |
3 | AfterContentInit, | 3 | AfterContentInit, |
4 | Component, | 4 | Component, |
5 | ComponentFactoryResolver, | ||
5 | ContentChildren, | 6 | ContentChildren, |
6 | EventEmitter, | 7 | EventEmitter, |
7 | Input, | 8 | Input, |
@@ -51,7 +52,8 @@ export class VideosSelectionComponent extends AbstractVideoList implements OnIni | |||
51 | protected userService: UserService, | 52 | protected userService: UserService, |
52 | protected screenService: ScreenService, | 53 | protected screenService: ScreenService, |
53 | protected storageService: LocalStorageService, | 54 | protected storageService: LocalStorageService, |
54 | protected serverService: ServerService | 55 | protected serverService: ServerService, |
56 | protected cfr: ComponentFactoryResolver | ||
55 | ) { | 57 | ) { |
56 | super() | 58 | super() |
57 | } | 59 | } |