mirror of
https://github.com/Chocobozzz/PeerTube.git
synced 2024-11-24 09:40:28 -06:00
Redesign channel page
This commit is contained in:
parent
4097c6d66c
commit
60c35932f6
@ -1,22 +0,0 @@
|
||||
<div class="margin-content">
|
||||
<div *ngIf="videoChannel" class="row no-gutters">
|
||||
<div class="description col-md-6 col-sm-12 pr-2">
|
||||
<div class="block">
|
||||
<div i18n class="small-title">DESCRIPTION</div>
|
||||
<div class="content" [innerHtml]="getVideoChannelDescription()"></div>
|
||||
</div>
|
||||
|
||||
<div class="block" *ngIf="supportHTML">
|
||||
<div i18n class="small-title">SUPPORT THIS CHANNEL</div>
|
||||
<div class="content" [innerHtml]="supportHTML"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="stats col-md-6 col-sm-12">
|
||||
<div class="block">
|
||||
<div i18n class="small-title">STATS</div>
|
||||
<div i18n class="content">Created {{ videoChannel.createdAt | date }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -1,12 +0,0 @@
|
||||
@import '_variables';
|
||||
@import '_mixins';
|
||||
|
||||
.block {
|
||||
margin-bottom: 40px;
|
||||
|
||||
.small-title {
|
||||
@include in-content-small-title;
|
||||
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
import { Subscription } from 'rxjs'
|
||||
import { Component, OnDestroy, OnInit } from '@angular/core'
|
||||
import { MarkdownService } from '@app/core'
|
||||
import { VideoChannel, VideoChannelService } from '@app/shared/shared-main'
|
||||
|
||||
@Component({
|
||||
selector: 'my-video-channel-about',
|
||||
templateUrl: './video-channel-about.component.html',
|
||||
styleUrls: [ './video-channel-about.component.scss' ]
|
||||
})
|
||||
export class VideoChannelAboutComponent implements OnInit, OnDestroy {
|
||||
videoChannel: VideoChannel
|
||||
descriptionHTML = ''
|
||||
supportHTML = ''
|
||||
|
||||
private videoChannelSub: Subscription
|
||||
|
||||
constructor (
|
||||
private videoChannelService: VideoChannelService,
|
||||
private markdownService: MarkdownService
|
||||
) { }
|
||||
|
||||
ngOnInit () {
|
||||
// Parent get the video channel for us
|
||||
this.videoChannelSub = this.videoChannelService.videoChannelLoaded
|
||||
.subscribe(async videoChannel => {
|
||||
this.videoChannel = videoChannel
|
||||
|
||||
this.descriptionHTML = await this.markdownService.textMarkdownToHTML(this.videoChannel.description)
|
||||
this.supportHTML = await this.markdownService.enhancedMarkdownToHTML(this.videoChannel.support)
|
||||
})
|
||||
}
|
||||
|
||||
ngOnDestroy () {
|
||||
if (this.videoChannelSub) this.videoChannelSub.unsubscribe()
|
||||
}
|
||||
|
||||
getVideoChannelDescription () {
|
||||
if (this.descriptionHTML) return this.descriptionHTML
|
||||
|
||||
return $localize`No description`
|
||||
}
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
import { NgModule } from '@angular/core'
|
||||
import { RouterModule, Routes } from '@angular/router'
|
||||
import { MetaGuard } from '@ngx-meta/core'
|
||||
import { VideoChannelAboutComponent } from './video-channel-about/video-channel-about.component'
|
||||
import { VideoChannelPlaylistsComponent } from './video-channel-playlists/video-channel-playlists.component'
|
||||
import { VideoChannelVideosComponent } from './video-channel-videos/video-channel-videos.component'
|
||||
import { VideoChannelsComponent } from './video-channels.component'
|
||||
@ -38,15 +37,6 @@ const videoChannelsRoutes: Routes = [
|
||||
title: $localize`Video channel playlists`
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'about',
|
||||
component: VideoChannelAboutComponent,
|
||||
data: {
|
||||
meta: {
|
||||
title: $localize`About video channel`
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -1,50 +1,114 @@
|
||||
<div *ngIf="videoChannel" class="row">
|
||||
<div class="sub-menu">
|
||||
<div class="root" *ngIf="videoChannel">
|
||||
<div class="channel-info">
|
||||
|
||||
<div class="actor">
|
||||
<img [src]="videoChannel.avatarUrl" alt="Avatar" />
|
||||
<ng-template #buttonsTemplate>
|
||||
<a *ngIf="isManageable() && !isInSmallView()" [routerLink]="[ '/my-library/video-channels/update', videoChannel.nameWithHost ]" class="peertube-button-link orange-button" i18n>
|
||||
Manage channel
|
||||
</a>
|
||||
|
||||
<div class="actor-info">
|
||||
<div class="actor-names">
|
||||
<div class="actor-display-name">{{ videoChannel.displayName }}</div>
|
||||
<div class="actor-name">
|
||||
<span>{{ videoChannel.nameWithHost }}</span>
|
||||
<button [cdkCopyToClipboard]="videoChannel.nameWithHostForced" (click)="activateCopiedMessage()"
|
||||
class="btn btn-outline-secondary btn-sm copy-button"
|
||||
>
|
||||
<span class="glyphicon glyphicon-duplicate"></span>
|
||||
</button>
|
||||
<my-subscribe-button #subscribeButton [videoChannels]="[videoChannel]"></my-subscribe-button>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #ownerTemplate>
|
||||
<div class="owner-block">
|
||||
<div class="avatar-row">
|
||||
<img [src]="videoChannel.ownerAvatarUrl" alt="Owner account avatar" />
|
||||
|
||||
<div class="actor-info">
|
||||
<h4>{{ videoChannel.ownerAccount.displayName }}</h4>
|
||||
|
||||
<div class="actor-handle">@{{ videoChannel.ownerBy }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="right-buttons">
|
||||
<a *ngIf="isChannelManageable && !isInSmallView" [routerLink]="[ '/my-library/video-channels/update', videoChannel.nameWithHost ]" class="btn btn-outline-tertiary mr-2" i18n>
|
||||
Manage channel
|
||||
</a>
|
||||
<my-subscribe-button #subscribeButton [videoChannels]="[videoChannel]"></my-subscribe-button>
|
||||
<div class="owner-description">
|
||||
<div class="description-html" [innerHTML]="ownerDescriptionHTML"></div>
|
||||
</div>
|
||||
|
||||
<div class="actor-lower">
|
||||
<div class="actor-followers" i18n>{videoChannel.followersCount, plural, =1 {1 subscriber} other {{{ videoChannel.followersCount }} subscribers}}</div>
|
||||
<a class="view-account short" [routerLink]="[ '/accounts', videoChannel.ownerBy ]" i18n>
|
||||
View account
|
||||
</a>
|
||||
|
||||
<a [routerLink]="[ '/accounts', videoChannel.ownerBy ]" i18n-title title="Go the owner account page" class="actor-owner">
|
||||
<span class="d-inline-flex"><span i18n class="d-none d-sm-block mr-1">Created by</span>{{ videoChannel.ownerBy }}</span>
|
||||
<img [src]="videoChannel.ownerAvatarUrl" alt="Owner account avatar" />
|
||||
</a>
|
||||
<a class="view-account complete" [routerLink]="[ '/accounts', videoChannel.ownerBy ]" i18n>
|
||||
View owner account
|
||||
</a>
|
||||
</div>
|
||||
</ng-template>
|
||||
|
||||
<div class="channel-avatar-row">
|
||||
<img [src]="videoChannel.avatarUrl" alt="Avatar" />
|
||||
|
||||
<div>
|
||||
<div class="section-label" i18n>VIDEO CHANNEL</div>
|
||||
|
||||
<div class="actor-info">
|
||||
<div>
|
||||
<div class="actor-display-name">
|
||||
<h1>{{ videoChannel.displayName }}</h1>
|
||||
</div>
|
||||
|
||||
<div class="actor-handle">
|
||||
<span>@{{ videoChannel.nameWithHost }}</span>
|
||||
<button [cdkCopyToClipboard]="videoChannel.nameWithHostForced" (click)="activateCopiedMessage()"
|
||||
class="btn btn-outline-secondary btn-sm copy-button" title="Copy channel handle" i18n-title
|
||||
>
|
||||
<span class="glyphicon glyphicon-duplicate"></span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="actor-counters">
|
||||
<span i18n>{videoChannel.followersCount, plural, =1 {1 subscriber} other {{{ videoChannel.followersCount }} subscribers}}</span>
|
||||
|
||||
<span class="videos-count" *ngIf="channelVideosCount !== undefined" i18n>
|
||||
{channelVideosCount, plural, =1 {1 videos} other {{{ channelVideosCount }} videos}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="channel-buttons right">
|
||||
<ng-template *ngTemplateOutlet="buttonsTemplate"></ng-template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="links w-100">
|
||||
<ng-template #linkTemplate let-item="item">
|
||||
<a [routerLink]="item.routerLink" routerLinkActive="active" class="title-page">{{ item.label }}</a>
|
||||
</ng-template>
|
||||
<div class="channel-description" [ngClass]="{ expanded: channelDescriptionExpanded }">
|
||||
<div class="description-html" [innerHTML]="channelDescriptionHTML"></div>
|
||||
|
||||
<list-overflow [items]="links" [itemTemplate]="linkTemplate"></list-overflow>
|
||||
<div class="created-at" i18n>Channel created on {{ videoChannel.createdAt | date }}</div>
|
||||
</div>
|
||||
|
||||
<div *ngIf="!channelDescriptionExpanded" class="show-more" role="button"
|
||||
(click)="channelDescriptionExpanded = !channelDescriptionExpanded"
|
||||
title="Show the complete description" i18n-title i18n
|
||||
>
|
||||
Show more...
|
||||
</div>
|
||||
|
||||
<div class="channel-buttons bottom">
|
||||
<ng-template *ngTemplateOutlet="buttonsTemplate"></ng-template>
|
||||
</div>
|
||||
|
||||
<div class="owner-card">
|
||||
<div class="section-label" i18n>OWNER ACCOUNT</div>
|
||||
|
||||
<ng-template *ngTemplateOutlet="ownerTemplate"></ng-template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="margin-content">
|
||||
<router-outlet></router-outlet>
|
||||
<div class="bottom-owner">
|
||||
<div class="section-label" i18n>OWNER ACCOUNT</div>
|
||||
|
||||
<ng-template *ngTemplateOutlet="ownerTemplate"></ng-template>
|
||||
</div>
|
||||
|
||||
<div class="links">
|
||||
<ng-template #linkTemplate let-item="item">
|
||||
<a [routerLink]="item.routerLink" routerLinkActive="active" class="title-page">{{ item.label }}</a>
|
||||
</ng-template>
|
||||
|
||||
<list-overflow [items]="links" [itemTemplate]="linkTemplate"></list-overflow>
|
||||
</div>
|
||||
|
||||
<router-outlet></router-outlet>
|
||||
</div>
|
||||
|
@ -1,89 +1,345 @@
|
||||
// Bootstrap grid utilities require functions, variables and mixins
|
||||
@import 'node_modules/bootstrap/scss/functions';
|
||||
@import 'node_modules/bootstrap/scss/variables';
|
||||
@import 'node_modules/bootstrap/scss/mixins';
|
||||
@import 'node_modules/bootstrap/scss/grid';
|
||||
|
||||
@import '_variables';
|
||||
@import '_mixins';
|
||||
@import '_miniature';
|
||||
|
||||
.sub-menu {
|
||||
@include sub-menu-with-actor;
|
||||
.root {
|
||||
--myGlobalPadding: 60px;
|
||||
--myChannelImgMargin: 30px;
|
||||
--myFontSize: 16px;
|
||||
--myGreyChannelFontSize: 16px;
|
||||
--myGreyOwnerFontSize: 14px;
|
||||
}
|
||||
|
||||
.actor, .actor-info {
|
||||
width: 100%;
|
||||
.section-label {
|
||||
color: pvar(--mainColor);
|
||||
font-size: 12px;
|
||||
margin-bottom: 15px;
|
||||
font-weight: $font-bold;
|
||||
letter-spacing: 2.5px;
|
||||
}
|
||||
|
||||
.links {
|
||||
@include fluid-videos-miniature-layout;
|
||||
}
|
||||
|
||||
.channel-info {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr auto;
|
||||
grid-template-rows: auto auto;
|
||||
|
||||
background-color: pvar(--channelBackgroundColor);
|
||||
margin-bottom: 45px;
|
||||
padding: var(--myGlobalPadding) var(--myGlobalPadding) 0 var(--myGlobalPadding);
|
||||
font-size: var(--myFontSize);
|
||||
}
|
||||
|
||||
.channel-avatar-row {
|
||||
display: flex;
|
||||
grid-column: 1;
|
||||
margin-bottom: 30px;
|
||||
|
||||
img {
|
||||
@include channel-avatar(120px);
|
||||
}
|
||||
|
||||
> div {
|
||||
margin-left: var(--myChannelImgMargin);
|
||||
}
|
||||
|
||||
.actor-info {
|
||||
display: grid !important;
|
||||
grid-template-columns: 1fr auto;
|
||||
grid-template-rows: 1fr auto / 1fr auto;
|
||||
grid-template-areas: "name buttons" "lower buttons";
|
||||
display: flex;
|
||||
|
||||
@include media-breakpoint-down(lg) {
|
||||
grid-template-areas: "name name" "lower buttons";
|
||||
> div:first-child {
|
||||
flex-grow: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.actor-names {
|
||||
grid-area: name;
|
||||
.actor-display-name {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.actor-name {
|
||||
flex-grow: 1;
|
||||
h1 {
|
||||
font-size: 28px;
|
||||
font-weight: $font-bold;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.copy-button {
|
||||
border: none;
|
||||
padding: 5px;
|
||||
margin-top: -2px;
|
||||
}
|
||||
.actor-handle,
|
||||
.actor-counters {
|
||||
color: pvar(--greyForegroundColor);
|
||||
font-size: var(--myGreyChannelFontSize);
|
||||
}
|
||||
|
||||
.actor-counters > *:not(:last-child)::after {
|
||||
content: '•';
|
||||
margin: 0 10px;
|
||||
color: pvar(--mainColor);
|
||||
}
|
||||
}
|
||||
|
||||
.margin-content {
|
||||
// margin-content is required, but child views have their own margins
|
||||
// that match views outside the scope of accounts, so we only align
|
||||
// them with the margins of .sub-menu when required.
|
||||
margin: 0;
|
||||
.channel-description {
|
||||
grid-column: 1;
|
||||
}
|
||||
|
||||
.right-buttons {
|
||||
.show-more {
|
||||
display: none;
|
||||
color: pvar(--mainColor);
|
||||
cursor: pointer;
|
||||
margin: 10px auto 45px auto;
|
||||
}
|
||||
|
||||
|
||||
.channel-buttons {
|
||||
display: flex;
|
||||
height: max-content;
|
||||
margin-left: auto;
|
||||
margin-top: 10px;
|
||||
flex-wrap: wrap;
|
||||
|
||||
grid-row: buttons-start / span buttons-end;
|
||||
grid-column: buttons-start;
|
||||
> *:not(:last-child) {
|
||||
margin-right: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
@include media-breakpoint-down(lg) {
|
||||
flex-flow: column-reverse;
|
||||
.channel-buttons.right {
|
||||
margin-left: 45px;
|
||||
}
|
||||
|
||||
a {
|
||||
margin-top: 0.25rem;
|
||||
margin-right: 0 !important;
|
||||
// Only used by mobile
|
||||
.channel-buttons.bottom {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.created-at {
|
||||
margin-top: 15px;
|
||||
color: pvar(--greyForegroundColor);
|
||||
padding-bottom: 60px;
|
||||
}
|
||||
|
||||
.owner-card {
|
||||
margin-left: 105px;
|
||||
grid-column: 2;
|
||||
// Takes all the column
|
||||
grid-row: 1 / 3;
|
||||
place-self: end;
|
||||
}
|
||||
|
||||
// Only used on mobile
|
||||
.bottom-owner {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.owner-block {
|
||||
background-color: pvar(--mainBackgroundColor);
|
||||
padding: 30px;
|
||||
width: 300px;
|
||||
font-size: var(--myFontSize);
|
||||
|
||||
.avatar-row {
|
||||
display: flex;
|
||||
margin-bottom: 15px;
|
||||
|
||||
img {
|
||||
@include avatar(48px);
|
||||
}
|
||||
|
||||
.actor-info {
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 18px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.actor-handle {
|
||||
font-size: var(--myGreyOwnerFontSize);
|
||||
color: pvar(--greyForegroundColor);
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
@include peertube-button-outline;
|
||||
line-height: 1.8;
|
||||
.owner-description {
|
||||
height: 140px;
|
||||
|
||||
@include fade-text(120px, pvar(--mainBackgroundColor));
|
||||
}
|
||||
}
|
||||
|
||||
.view-account.short {
|
||||
@include peertube-button-link;
|
||||
@include orange-button-inverted;
|
||||
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.view-account.complete {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.copy-button {
|
||||
border: none;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1400px) {
|
||||
// Takes all the row width
|
||||
.channel-avatar-row {
|
||||
grid-column: 1 / 3;
|
||||
}
|
||||
|
||||
my-subscribe-button {
|
||||
height: min-content;
|
||||
.owner-card {
|
||||
grid-row: 2;
|
||||
margin-left: 60px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1100px) {
|
||||
.root {
|
||||
--myGlobalPadding: 45px;
|
||||
--myChannelImgMargin: 15px;
|
||||
}
|
||||
|
||||
.channel-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.channel-description:not(.expanded) {
|
||||
max-height: 70px;
|
||||
|
||||
@include fade-text(30px, pvar(--channelBackgroundColor));
|
||||
}
|
||||
|
||||
.show-more {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.channel-buttons.bottom {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.channel-buttons.right {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.owner-card {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.bottom-owner {
|
||||
display: block;
|
||||
width: 100%;
|
||||
border-bottom: 2px solid $separator-border-color;
|
||||
padding: var(--myGlobalPadding) 45px;
|
||||
margin-bottom: 60px;
|
||||
}
|
||||
|
||||
.owner-block {
|
||||
display: grid;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
|
||||
.avatar-row {
|
||||
grid-column: 1;
|
||||
margin-right: 30px;
|
||||
}
|
||||
|
||||
.owner-description {
|
||||
grid-column: 2;
|
||||
max-height: 70px;
|
||||
|
||||
@include fade-text(30px, pvar(--mainBackgroundColor));
|
||||
}
|
||||
|
||||
.view-account {
|
||||
grid-column: 2;
|
||||
}
|
||||
}
|
||||
|
||||
.view-account.complete {
|
||||
display: inline-block;
|
||||
margin-top: 10px;
|
||||
color: pvar(--mainColor);
|
||||
}
|
||||
|
||||
.view-account.short {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: $mobile-view) {
|
||||
.sub-menu {
|
||||
.actor {
|
||||
flex-direction: column;
|
||||
.root {
|
||||
--myGlobalPadding: 15px;
|
||||
--myFontSize: 14px;
|
||||
--myGreyChannelFontSize: 13px;
|
||||
--myGreyOwnerFontSize: 13px;
|
||||
}
|
||||
|
||||
.actor-info .actor-names {
|
||||
flex-direction: column;
|
||||
align-items: normal;
|
||||
.links {
|
||||
margin: auto !important;
|
||||
width: min-content;
|
||||
}
|
||||
|
||||
.section-label {
|
||||
font-size: 10px;
|
||||
letter-spacing: 2.1px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.channel-avatar-row {
|
||||
margin-bottom: 15px;
|
||||
|
||||
h1 {
|
||||
font-size: 22px;
|
||||
}
|
||||
|
||||
img {
|
||||
@include channel-avatar(80px);
|
||||
}
|
||||
}
|
||||
|
||||
.show-more {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.bottom-owner {
|
||||
padding: 15px;
|
||||
margin-bottom: 30px;
|
||||
|
||||
.section-label {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.owner-block {
|
||||
display: block;
|
||||
|
||||
.avatar-row {
|
||||
display: flex;
|
||||
flex-direction: row-reverse;
|
||||
margin: 0;
|
||||
|
||||
h4 {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.actor-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
justify-content: flex-end;
|
||||
margin-top: -5px;
|
||||
}
|
||||
|
||||
img {
|
||||
@include channel-avatar(64px);
|
||||
|
||||
margin: -30px 0 0 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.owner-description {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,8 +3,8 @@ import { Subscription } from 'rxjs'
|
||||
import { catchError, distinctUntilChanged, map, switchMap } from 'rxjs/operators'
|
||||
import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core'
|
||||
import { ActivatedRoute } from '@angular/router'
|
||||
import { AuthService, Notifier, RestExtractor, ScreenService } from '@app/core'
|
||||
import { ListOverflowItem, VideoChannel, VideoChannelService } from '@app/shared/shared-main'
|
||||
import { AuthService, MarkdownService, Notifier, RestExtractor, ScreenService } from '@app/core'
|
||||
import { ListOverflowItem, VideoChannel, VideoChannelService, VideoService } from '@app/shared/shared-main'
|
||||
import { SubscribeButtonComponent } from '@app/shared/shared-user-subscription'
|
||||
import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
|
||||
|
||||
@ -20,6 +20,11 @@ export class VideoChannelsComponent implements OnInit, OnDestroy {
|
||||
links: ListOverflowItem[] = []
|
||||
isChannelManageable = false
|
||||
|
||||
channelVideosCount: number
|
||||
ownerDescriptionHTML = ''
|
||||
channelDescriptionHTML = ''
|
||||
channelDescriptionExpanded = false
|
||||
|
||||
private routeSub: Subscription
|
||||
|
||||
constructor (
|
||||
@ -27,9 +32,11 @@ export class VideoChannelsComponent implements OnInit, OnDestroy {
|
||||
private notifier: Notifier,
|
||||
private authService: AuthService,
|
||||
private videoChannelService: VideoChannelService,
|
||||
private videoService: VideoService,
|
||||
private restExtractor: RestExtractor,
|
||||
private hotkeysService: HotkeysService,
|
||||
private screenService: ScreenService
|
||||
private screenService: ScreenService,
|
||||
private markdown: MarkdownService
|
||||
) { }
|
||||
|
||||
ngOnInit () {
|
||||
@ -43,16 +50,14 @@ export class VideoChannelsComponent implements OnInit, OnDestroy {
|
||||
HttpStatusCode.NOT_FOUND_404
|
||||
]))
|
||||
)
|
||||
.subscribe(videoChannel => {
|
||||
.subscribe(async videoChannel => {
|
||||
this.channelDescriptionHTML = await this.markdown.textMarkdownToHTML(videoChannel.description)
|
||||
this.ownerDescriptionHTML = await this.markdown.textMarkdownToHTML(videoChannel.ownerAccount.description)
|
||||
|
||||
// After the markdown renderer to avoid layout changes
|
||||
this.videoChannel = videoChannel
|
||||
|
||||
if (this.authService.isLoggedIn()) {
|
||||
this.authService.userInformationLoaded
|
||||
.subscribe(() => {
|
||||
const channelUserId = this.videoChannel.ownerAccount.userId
|
||||
this.isChannelManageable = channelUserId && channelUserId === this.authService.getUser().id
|
||||
})
|
||||
}
|
||||
this.loadChannelVideosCount()
|
||||
})
|
||||
|
||||
this.hotkeys = [
|
||||
@ -67,8 +72,7 @@ export class VideoChannelsComponent implements OnInit, OnDestroy {
|
||||
|
||||
this.links = [
|
||||
{ label: $localize`VIDEOS`, routerLink: 'videos' },
|
||||
{ label: $localize`VIDEO PLAYLISTS`, routerLink: 'video-playlists' },
|
||||
{ label: $localize`ABOUT`, routerLink: 'about' }
|
||||
{ label: $localize`VIDEO PLAYLISTS`, routerLink: 'video-playlists' }
|
||||
]
|
||||
}
|
||||
|
||||
@ -79,7 +83,7 @@ export class VideoChannelsComponent implements OnInit, OnDestroy {
|
||||
if (this.isUserLoggedIn()) this.hotkeysService.remove(this.hotkeys)
|
||||
}
|
||||
|
||||
get isInSmallView () {
|
||||
isInSmallView () {
|
||||
return this.screenService.isInSmallView()
|
||||
}
|
||||
|
||||
@ -87,12 +91,24 @@ export class VideoChannelsComponent implements OnInit, OnDestroy {
|
||||
return this.authService.isLoggedIn()
|
||||
}
|
||||
|
||||
get isManageable () {
|
||||
isManageable () {
|
||||
if (!this.isUserLoggedIn()) return false
|
||||
|
||||
return this.videoChannel.ownerAccount.userId === this.authService.getUser().id
|
||||
}
|
||||
|
||||
activateCopiedMessage () {
|
||||
this.notifier.success($localize`Username copied`)
|
||||
}
|
||||
|
||||
private loadChannelVideosCount () {
|
||||
this.videoService.getVideoChannelVideos({
|
||||
videoChannel: this.videoChannel,
|
||||
videoPagination: {
|
||||
currentPage: 1,
|
||||
itemsPerPage: 0
|
||||
},
|
||||
sort: '-publishedAt'
|
||||
}).subscribe(res => this.channelVideosCount = res.total)
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ import { SharedMainModule } from '@app/shared/shared-main'
|
||||
import { SharedUserSubscriptionModule } from '@app/shared/shared-user-subscription'
|
||||
import { SharedVideoMiniatureModule } from '@app/shared/shared-video-miniature'
|
||||
import { SharedVideoPlaylistModule } from '@app/shared/shared-video-playlist'
|
||||
import { VideoChannelAboutComponent } from './video-channel-about/video-channel-about.component'
|
||||
import { VideoChannelPlaylistsComponent } from './video-channel-playlists/video-channel-playlists.component'
|
||||
import { VideoChannelVideosComponent } from './video-channel-videos/video-channel-videos.component'
|
||||
import { VideoChannelsRoutingModule } from './video-channels-routing.module'
|
||||
@ -26,7 +25,6 @@ import { VideoChannelsComponent } from './video-channels.component'
|
||||
declarations: [
|
||||
VideoChannelsComponent,
|
||||
VideoChannelVideosComponent,
|
||||
VideoChannelAboutComponent,
|
||||
VideoChannelPlaylistsComponent
|
||||
],
|
||||
|
||||
|
@ -36,7 +36,9 @@ body {
|
||||
|
||||
--menuBackgroundColor: #{$menu-background};
|
||||
--menuForegroundColor: #{$menu-color};
|
||||
|
||||
--submenuColor: #{$sub-menu-color};
|
||||
--channelBackgroundColor: #{$channel-background-color};
|
||||
|
||||
--inputForegroundColor: #{$input-foreground-color};
|
||||
--inputBackgroundColor: #{$input-background-color};
|
||||
@ -277,11 +279,6 @@ my-input-toggle-hidden ::ng-deep input {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
from { transform: scale(1) rotate(0deg);}
|
||||
to { transform: scale(1) rotate(360deg);}
|
||||
}
|
||||
|
||||
// In tables, don't have a hover different background
|
||||
table {
|
||||
.action-button-edit, .action-button-delete {
|
||||
@ -468,3 +465,21 @@ ngx-loading-bar {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Utils
|
||||
|
||||
.peertube-button {
|
||||
@include peertube-button;
|
||||
}
|
||||
|
||||
.peertube-button-link {
|
||||
@include peertube-button-link;
|
||||
}
|
||||
|
||||
.orange-button {
|
||||
@include orange-button;
|
||||
}
|
||||
|
||||
.orange-button-inverted {
|
||||
@include orange-button-inverted;
|
||||
}
|
||||
|
@ -31,9 +31,19 @@
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
@mixin prefix($property, $parameters...) {
|
||||
@each $prefix in -webkit-, -moz-, -ms-, -o-, "" {
|
||||
#{$prefix}#{$property}: $parameters;
|
||||
@mixin fade-text ($fade-after, $background-color) {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
&:after {
|
||||
content: '';
|
||||
pointer-events: none;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
background: linear-gradient(transparent $fade-after, $background-color);
|
||||
}
|
||||
}
|
||||
|
||||
@ -138,6 +148,33 @@
|
||||
}
|
||||
}
|
||||
|
||||
@mixin orange-button-inverted {
|
||||
@include button-focus(pvar(--mainColorLightest));
|
||||
|
||||
border: 2px solid pvar(--mainColor);
|
||||
font-weight: $font-regular;
|
||||
|
||||
&, &:active, &:focus {
|
||||
color: pvar(--mainColor);
|
||||
background-color: pvar(--mainBackgroundColor);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: pvar(--mainColor);
|
||||
background-color: pvar(--mainColorLightest);
|
||||
}
|
||||
|
||||
&[disabled], &.disabled {
|
||||
cursor: default;
|
||||
color: pvar(--mainColor);
|
||||
background-color: #C6C6C6;
|
||||
}
|
||||
|
||||
my-global-icon {
|
||||
@include apply-svg-color(pvar(--mainColor))
|
||||
}
|
||||
}
|
||||
|
||||
@mixin tertiary-button {
|
||||
@include button-focus($grey-button-outline-color);
|
||||
|
||||
@ -509,6 +546,13 @@
|
||||
min-height: $size;
|
||||
}
|
||||
|
||||
@mixin channel-avatar ($size) {
|
||||
width: $size;
|
||||
height: $size;
|
||||
min-width: $size;
|
||||
min-height: $size;
|
||||
}
|
||||
|
||||
@mixin chevron ($size, $border-width) {
|
||||
border-style: solid;
|
||||
border-width: $border-width $border-width 0 0;
|
||||
|
@ -16,9 +16,10 @@ $grey-foreground-hover-color: #303030;
|
||||
$grey-button-outline-color: scale-color($grey-foreground-color, $alpha: -95%);
|
||||
|
||||
$main-color: hsl(24, 90%, 50%);
|
||||
$main-hover-color: lighten($main-color, 5%);
|
||||
$main-color-lighter: lighten($main-color, 10%);
|
||||
$main-color-lightest: lighten($main-color, 40%);
|
||||
$main-hover-color: lighten($main-color, 5%);
|
||||
|
||||
$secondary-color: hsl(187, 77%, 34%);
|
||||
|
||||
$support-button: inherit;
|
||||
@ -50,6 +51,8 @@ $menu-lateral-padding: 26px;
|
||||
$sub-menu-color: #F7F7F7;
|
||||
$sub-menu-height: 81px;
|
||||
|
||||
$channel-background-color: #f6ede8;
|
||||
|
||||
$footer-height: 30px;
|
||||
$footer-margin: 30px;
|
||||
|
||||
@ -98,7 +101,9 @@ $variables: (
|
||||
|
||||
--menuBackgroundColor: var(--menuBackgroundColor),
|
||||
--menuForegroundColor: var(--menuForegroundColor),
|
||||
|
||||
--submenuColor: var(--submenuColor),
|
||||
--channelBackgroundColor: var(--channelBackgroundColor),
|
||||
|
||||
--inputForegroundColor: var(--inputForegroundColor),
|
||||
--inputBackgroundColor: var(--inputBackgroundColor),
|
||||
|
Loading…
Reference in New Issue
Block a user