@import '_miniature';
.margin-content {
- @include adapt-margin-content-width;
+ @include fluid-videos-miniature-layout;
}
.section {
<div *ngIf="isVideo(result)" class="entry video">
<my-video-miniature
[video]="result" [user]="user" [displayAsRow]="true" [displayVideoActions]="!hideActions()"
- [useLazyLoadUrl]="advancedSearch.searchTarget === 'search-index'"
+ [displayOptions]="videoDisplayOptions" [useLazyLoadUrl]="advancedSearch.searchTarget === 'search-index'"
(videoBlocked)="removeVideoFromArray(result)" (videoRemoved)="removeVideoFromArray(result)"
></my-video-miniature>
</div>
import { immutableAssign } from '@app/shared/misc/utils'
import { ComponentPagination } from '@app/shared/rest/component-pagination.model'
import { VideoChannel } from '@app/shared/video-channel/video-channel.model'
+import { MiniatureDisplayOptions } from '@app/shared/video/video-miniature.component'
import { Video } from '@app/shared/video/video.model'
import { MetaService } from '@ngx-meta/core'
import { I18n } from '@ngx-translate/i18n-polyfill'
import { ServerConfig } from '@shared/models'
-import { UserService } from '@app/shared'
import { SearchTargetType } from '@shared/models/search/search-target-query.model'
@Component({
isSearchFilterCollapsed = true
currentSearch: string
+ videoDisplayOptions: MiniatureDisplayOptions = {
+ date: true,
+ views: true,
+ by: true,
+ avatar: false,
+ privacyLabel: false,
+ privacyText: false,
+ state: false,
+ blacklistInfo: false
+ }
+
errorMessage: string
serverConfig: ServerConfig
let numberOfVideos = 1
- if (screenWidth > 1850) numberOfVideos = 6
- else if (screenWidth > 1600) numberOfVideos = 5
- else if (screenWidth > 1370) numberOfVideos = 4
- else if (screenWidth > 1100) numberOfVideos = 3
- else if (screenWidth > 850) numberOfVideos = 2
+ if (screenWidth > 1850) numberOfVideos = 7
+ else if (screenWidth > 1600) numberOfVideos = 6
+ else if (screenWidth > 1370) numberOfVideos = 5
+ else if (screenWidth > 1100) numberOfVideos = 4
+ else if (screenWidth > 850) numberOfVideos = 3
return numberOfVideos
}
{{ getCurrentGroupedDateLabel(video) }}
</div>
- <my-video-miniature
- [fitWidth]="true"
- [video]="video" [user]="user" [ownerDisplayType]="ownerDisplayType"
- [displayVideoActions]="displayVideoActions" [displayOptions]="displayOptions"
- (videoBlocked)="removeVideoFromArray(video)" (videoRemoved)="removeVideoFromArray(video)"
- >
- </my-video-miniature>
+ <div class="video-wrapper">
+ <my-video-miniature
+ [fitWidth]="true"
+ [video]="video" [user]="user" [ownerDisplayType]="ownerDisplayType"
+ [displayVideoActions]="displayVideoActions" [displayOptions]="displayOptions"
+ (videoBlocked)="removeVideoFromArray(video)" (videoRemoved)="removeVideoFromArray(video)"
+ >
+ </my-video-miniature>
+ </div>
</ng-container>
</div>
</div>
@import '_mixins';
@import '_miniature';
-.videos {
- $column-width: #{$video-thumbnail-width - 25px};
-
- display: grid;
- column-gap: calc(10px + .2%);
- grid-template-columns: repeat(
- auto-fill,
- minmax(
- var(--miniature-min-width, #{$column-width}),
- 1fr
- )
- );
-
- @media screen and (min-width: #{breakpoint(fhd)}) {
- --miniature-min-width: #{$column-width + 100px};
- }
-}
-
.videos-header {
display: flex;
justify-content: space-between;
}
}
-:host-context(.main-col:not(.expanded)) .margin-content {
- @include adapt-margin-content-width($fluid: true);
+.margin-content {
+ @include fluid-videos-miniature-layout;
}
@media screen and (max-width: $mobile-view) {
flex-direction: column;
align-items: center;
height: auto;
+ margin-bottom: 10px;
.title-page {
margin-bottom: 10px;
date: true,
views: true,
by: true,
- avatar: true,
+ avatar: false,
privacyLabel: true,
privacyText: false,
state: false,
if (this.hasDoneFirstQuery) this.reloadVideos()
}
)
+
+ // Display avatar in mobile view
+ if (this.screenService.isInMobileView()) {
+ this.displayOptions.avatar = true
+ }
}
ngOnDestroy () {
<div class="video-bottom">
<div class="video-miniature-information">
- <a
- tabindex="-1"
- class="video-miniature-name"
- [routerLink]="videoLink" [attr.title]="video.name" [ngClass]="{ 'blur-filter': isVideoBlur }"
- >{{ video.name }}</a>
-
<div class="d-inline-flex">
- <avatar-channel *ngIf="displayOptions.avatar" class="mr-1 pt-1" [video]="video" size="sm"></avatar-channel>
+ <div *ngIf="displayOptions.avatar" class="avatar">
+ <img [src]="getAvatarUrl()" alt="Avatar" />
+ </div>
<div class="d-flex flex-column">
+ <a
+ tabindex="-1"
+ class="video-miniature-name"
+ [routerLink]="videoLink" [attr.title]="video.name" [ngClass]="{ 'blur-filter': isVideoBlur }"
+ >{{ video.name }}</a>
+
<span class="video-miniature-created-at-views">
<my-date-toggle *ngIf="displayOptions.date" [date]="video.publishedAt"></my-date-toggle>
-
+
<span class="views">
<ng-container *ngIf="displayOptions.date && displayOptions.views"> • </ng-container>
<ng-container i18n *ngIf="displayOptions.views">{video.views, plural, =1 {1 view} other {{{ video.views | myNumberFormatter }} views}}</ng-container>
</span>
</span>
-
+
<a tabindex="-1" *ngIf="displayOptions.by && displayOwnerAccount()" class="video-miniature-account" [routerLink]="[ '/accounts', video.byAccount ]">
{{ video.byAccount }}
</a>
<a tabindex="-1" *ngIf="displayOptions.by && displayOwnerVideoChannel()" class="video-miniature-channel" [routerLink]="[ '/video-channels', video.byVideoChannel ]">
{{ video.byVideoChannel }}
</a>
-
+
<div class="video-info-privacy">
<ng-container *ngIf="displayOptions.privacyText">{{ video.privacy.label }}</ng-container>
<ng-container *ngIf="displayOptions.privacyText && displayOptions.state && getStateLabel(video)"> - </ng-container>
.video-miniature-information {
width: $video-miniature-width - $more-button-width - $more-margin-right;
line-height: normal;
- font-size: 13px;
+
+ .avatar {
+ margin: 10px 10px 0 0;
+
+ img {
+ @include avatar(40px);
+ }
+ }
.video-miniature-name {
@include miniature-name;
- font-size: 110%;
}
.video-miniature-created-at-views {
display: block;
- font-size: 95%;
+ font-size: 13px;
}
.video-miniature-account,
@include ellipsis;
display: block;
- font-size: 95%;
+ font-size: 13px;
color: pvar(--greyForegroundColor);
&:hover {
return ''
}
+ getAvatarUrl () {
+ if (this.ownerDisplayTypeChosen === 'account') {
+ return this.video.accountAvatarUrl
+ }
+
+ return this.video.videoChannelAvatarUrl
+ }
+
loadActions () {
if (this.displayVideoActions) this.showActions = true
>
<ng-container *ngFor="let overview of overviews">
- <div class="section" *ngFor="let object of overview.categories">
+ <div class="section videos" *ngFor="let object of overview.categories">
<div class="section-title">
<a routerLink="/search" [queryParams]="{ categoryOneOf: [ object.category.id ] }">{{ object.category.label }}</a>
</div>
- <my-video-miniature class="pr-2" *ngFor="let video of buildVideos(object.videos)" [video]="video" [user]="user" [displayVideoActions]="false">
- </my-video-miniature>
+ <div class="video-wrapper" *ngFor="let video of buildVideos(object.videos)">
+ <my-video-miniature [video]="video" [fitWidth]="true" [user]="user" [displayVideoActions]="false">
+ </my-video-miniature>
+ </div>
</div>
- <div class="section" *ngFor="let object of overview.tags">
+ <div class="section videos" *ngFor="let object of overview.tags">
<div class="section-title">
<a routerLink="/search" [queryParams]="{ tagsOneOf: [ object.tag ] }">#{{ object.tag }}</a>
</div>
- <my-video-miniature class="pr-2" *ngFor="let video of buildVideos(object.videos)" [video]="video" [user]="user" [displayVideoActions]="false">
- </my-video-miniature>
+ <div class="video-wrapper" *ngFor="let video of buildVideos(object.videos)">
+ <my-video-miniature [video]="video" [fitWidth]="true" [user]="user" [displayVideoActions]="false">
+ </my-video-miniature>
+ </div>
</div>
- <div class="section channel" *ngFor="let object of overview.channels">
+ <div class="section channel videos" *ngFor="let object of overview.channels">
<div class="section-title">
<a [routerLink]="[ '/video-channels', buildVideoChannelBy(object) ]">
<img [src]="buildVideoChannelAvatarUrl(object)" alt="Avatar" />
</a>
</div>
- <my-video-miniature class="pr-2" *ngFor="let video of buildVideos(object.videos)" [video]="video" [user]="user" [displayVideoActions]="false">
- </my-video-miniature>
+ <div class="video-wrapper" *ngFor="let video of buildVideos(object.videos)">
+ <my-video-miniature [video]="video" [fitWidth]="true" [user]="user" [displayVideoActions]="false">
+ </my-video-miniature>
+ </div>
</div>
</ng-container>
@import '_mixins';
@import '_miniature';
+.section-title {
+ // make the element span a full grid row within .videos grid
+ grid-column: 1 / -1;
+}
+
.margin-content {
- @include adapt-margin-content-width;
+ @include fluid-videos-miniature-layout;
}
.section {
xxl: 1600px,
// SCREEN GROUP
- fhd: 1920px,
+ fhd: 1800px,
qhd: 2560px,
uhd: 3840px
);
color: #fff;
}
-@mixin video-miniature-small-screen {
- text-align: center;
-
- ::ng-deep .video-miniature {
- padding-right: 0;
- height: auto;
- width: 100%;
- margin-bottom: 20px;
-
- .video-miniature-information {
- width: 100% !important;
- text-align: left;
-
- span {
- width: 100%;
- }
- }
-
- .video-thumbnail {
- margin-bottom: 10px;
- width: 100%;
- height: calc(100% / #{$video-thumbnail-ratio});
- border-radius: 0;
-
- img {
- width: 100%;
- height: 100%;
- }
- }
- }
-}
-
@mixin miniature-rows {
&:first-child {
padding-top: 30px;
}
}
- my-video-miniature {
- text-align: left;
- }
-
.section-title {
font-size: 24px;
font-weight: $font-semibold;
max-height: initial;
overflow: initial;
- @include video-miniature-small-screen;
-
.section-title {
font-size: 17px;
+ margin-left: 10px;
}
}
}
-@mixin adapt-margin-content-width($fluid: false) {
- @if $fluid {
- margin-left: 3vw !important;
- margin-right: 3vw !important;
- } @else {
- width: $video-miniature-width * 6;
- margin: auto !important;
+@mixin fluid-videos-miniature-layout {
+ margin-left: 3vw !important;
+ margin-right: 3vw !important;
- @media screen and (max-width: 1800px) {
- width: $video-miniature-width * 5;
- }
+ @media screen and (max-width: $mobile-view) {
+ width: auto;
+ margin: 0 !important;
- @media screen and (max-width: 1800px - $video-miniature-width) {
- width: $video-miniature-width * 4;
- }
+ .videos {
+ text-align: center;
- @media screen and (max-width: 1800px - (2* $video-miniature-width)) {
- width: $video-miniature-width * 3;
- }
+ ::ng-deep .video-miniature {
+ padding-right: 0;
+ height: auto;
+ width: 100%;
+ margin-bottom: 25px;
- @media screen and (max-width: 1800px - (3* $video-miniature-width)) {
- width: $video-miniature-width * 2;
+ .video-miniature-information {
+ width: 100% !important;
+ text-align: left;
+
+ span {
+ width: 100%;
+ }
+ }
+
+ .video-thumbnail {
+ border-radius: 0;
+ }
+ }
}
+ }
+
+ @media screen and (min-width: #{breakpoint(fhd)}) {
+ margin-left: 6vw !important;
+ margin-right: 6vw !important;
+ }
- @media screen and (max-width: $mobile-view) {
- width: auto;
- margin: 0 !important;
+ @media screen and (min-width: $mobile-view) {
+
+ .videos {
+ --miniature-min-width: #{$video-thumbnail-width - 15px};
+ --miniature-max-width: #{$video-thumbnail-width};
+
+ display: grid;
+ column-gap: 5px;
+ grid-template-columns: repeat(
+ auto-fill,
+ minmax(
+ var(--miniature-min-width),
+ 1fr
+ )
+ );
+
+ @media screen and (min-width: #{breakpoint(fhd)}) {
+ column-gap: 1%;
+ --miniature-min-width: #{$video-thumbnail-width};
+ }
+
+ .video-wrapper {
+ margin: 0 auto;
+ width: 100%;
- .videos {
- @include video-miniature-small-screen;
+ my-video-miniature {
+ display: block;
+ min-width: var(--miniature-min-width);
+ max-width: var(--miniature-max-width);
+ }
}
}
}
$video-miniature-margin-bottom: 30px;
$video-thumbnail-height: 122px;
$video-thumbnail-width: 223px;
-$video-thumbnail-ratio: $video-thumbnail-width / $video-thumbnail-height;
$theater-bottom-space: 115px;