mirror of https://github.com/Chocobozzz/PeerTube
Correct colors
parent
5ce1470b9e
commit
c3aaee5dff
|
@ -11,12 +11,12 @@
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p i18n>
|
<p i18n>
|
||||||
It is free and open-source software, under <a class="link-orange" href="https://github.com/Chocobozzz/PeerTube/blob/develop/LICENSE">AGPLv3
|
It is free and open-source software, under <a class="link-primary" href="https://github.com/Chocobozzz/PeerTube/blob/develop/LICENSE">AGPLv3
|
||||||
licence</a>.
|
licence</a>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p i18n>
|
<p i18n>
|
||||||
For more information, please visit <a class="link-orange" target="_blank" rel="noopener noreferrer" href="https://joinpeertube.org">joinpeertube.org</a>.
|
For more information, please visit <a class="link-primary" target="_blank" rel="noopener noreferrer" href="https://joinpeertube.org">joinpeertube.org</a>.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="card-title">
|
<div class="card-title">
|
||||||
<a i18n class="link-orange" target="_blank" rel="noopener noreferrer" href="https://docs.joinpeertube.org/use/setup-account">Use PeerTube documentation</a>
|
<a i18n class="link-primary" target="_blank" rel="noopener noreferrer" href="https://docs.joinpeertube.org/use/setup-account">Use PeerTube documentation</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div i18n class="card-text">
|
<div i18n class="card-text">
|
||||||
|
@ -37,7 +37,7 @@
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="card-title">
|
<div class="card-title">
|
||||||
<a i18n class="link-orange" target="_blank" rel="noopener noreferrer" href="https://docs.joinpeertube.org/use/third-party-application">PeerTube Applications</a>
|
<a i18n class="link-primary" target="_blank" rel="noopener noreferrer" href="https://docs.joinpeertube.org/use/third-party-application">PeerTube Applications</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div i18n class="card-text">
|
<div i18n class="card-text">
|
||||||
|
@ -49,7 +49,7 @@
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="card-title">
|
<div class="card-title">
|
||||||
<a i18n class="link-orange" target="_blank" rel="noopener noreferrer" href="https://docs.joinpeertube.org/contribute/getting-started">Contribute on PeerTube</a>
|
<a i18n class="link-primary" target="_blank" rel="noopener noreferrer" href="https://docs.joinpeertube.org/contribute/getting-started">Contribute on PeerTube</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div i18n class="card-text">
|
<div i18n class="card-text">
|
||||||
|
@ -112,7 +112,7 @@
|
||||||
Web peers are not publicly accessible: because we use the websocket transport, the protocol is different from classic BitTorrent tracker.
|
Web peers are not publicly accessible: because we use the websocket transport, the protocol is different from classic BitTorrent tracker.
|
||||||
When you are in a web browser, you send a signal containing your IP address to the tracker that will randomly choose other peers
|
When you are in a web browser, you send a signal containing your IP address to the tracker that will randomly choose other peers
|
||||||
to forward the information to.
|
to forward the information to.
|
||||||
See <a class="link-orange" href="https://github.com/yciabaud/webtorrent/blob/beps/bep_webrtc.rst">this document</a> for more information
|
See <a class="link-primary" href="https://github.com/yciabaud/webtorrent/blob/beps/bep_webrtc.rst">this document</a> for more information
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
></my-video-miniature>
|
></my-video-miniature>
|
||||||
|
|
||||||
<div *ngIf="getTotalVideosOf(videoChannel)" class="miniature-show-channel">
|
<div *ngIf="getTotalVideosOf(videoChannel)" class="miniature-show-channel">
|
||||||
<a class="link-orange" i18n [routerLink]="getVideoChannelLink(videoChannel)">SHOW THIS CHANNEL ></a>
|
<a class="link-primary" i18n [routerLink]="getVideoChannelLink(videoChannel)">SHOW THIS CHANNEL ></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<h2 i18n>APPEARANCE</h2>
|
<h2 i18n>APPEARANCE</h2>
|
||||||
|
|
||||||
<div i18n class="inner-form-description">
|
<div i18n class="inner-form-description">
|
||||||
Use <a class="link-orange" routerLink="/admin/settings/plugins">plugins & themes</a> for more involved changes, or add slight <a class="link-orange" routerLink="/admin/settings/config/edit-custom" fragment="advanced-configuration">customizations</a>.
|
Use <a class="link-primary" routerLink="/admin/settings/plugins">plugins & themes</a> for more involved changes, or add slight <a class="link-primary" routerLink="/admin/settings/config/edit-custom" fragment="advanced-configuration">customizations</a>.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -14,13 +14,7 @@
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label i18n for="themeDefault">Theme</label>
|
<label i18n for="themeDefault">Theme</label>
|
||||||
|
|
||||||
<div class="peertube-select-container">
|
<my-select-options formControlName="default" inputId="themeDefault" [items]="availableThemes"></my-select-options>
|
||||||
<select formControlName="default" id="themeDefault" class="form-control">
|
|
||||||
<option i18n value="default">{{ getDefaultThemeLabel() }}</option>
|
|
||||||
|
|
||||||
<option *ngFor="let theme of availableThemes" [value]="theme.id">{{ theme.label }}</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
|
@ -151,7 +145,7 @@
|
||||||
<div class="title-col">
|
<div class="title-col">
|
||||||
<h2 i18n>NEW USERS</h2>
|
<h2 i18n>NEW USERS</h2>
|
||||||
<div i18n class="inner-form-description">
|
<div i18n class="inner-form-description">
|
||||||
Manage <a class="link-orange" routerLink="/admin/overview/users">users</a> to set their quota individually.
|
Manage <a class="link-primary" routerLink="/admin/overview/users">users</a> to set their quota individually.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -296,7 +290,7 @@
|
||||||
i18n-labelText labelText="Allow import with HTTP URL (e.g. YouTube)"
|
i18n-labelText labelText="Allow import with HTTP URL (e.g. YouTube)"
|
||||||
>
|
>
|
||||||
<ng-container ngProjectAs="description">
|
<ng-container ngProjectAs="description">
|
||||||
<span i18n>⚠️ If enabled, we recommend to use <a class="link-orange" href="https://docs.joinpeertube.org/maintain/configuration#security">a HTTP proxy</a> to prevent private URL access from your PeerTube server</span>
|
<span i18n>⚠️ If enabled, we recommend to use <a class="link-primary" href="https://docs.joinpeertube.org/maintain/configuration#security">a HTTP proxy</a> to prevent private URL access from your PeerTube server</span>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</my-peertube-checkbox>
|
</my-peertube-checkbox>
|
||||||
</div>
|
</div>
|
||||||
|
@ -472,7 +466,7 @@
|
||||||
<div i18n>⚠️ This functionality depends heavily on the moderation of instances followed by the search index you select.</div>
|
<div i18n>⚠️ This functionality depends heavily on the moderation of instances followed by the search index you select.</div>
|
||||||
|
|
||||||
<div i18n>
|
<div i18n>
|
||||||
You should only use moderated search indexes in production, or <a class="link-orange" href="https://framagit.org/framasoft/peertube/search-index">host your own</a>.
|
You should only use moderated search indexes in production, or <a class="link-primary" href="https://framagit.org/framasoft/peertube/search-index">host your own</a>.
|
||||||
</div>
|
</div>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
|
@ -595,7 +589,7 @@
|
||||||
<div class="title-col">
|
<div class="title-col">
|
||||||
<h2 i18n>FEDERATION</h2>
|
<h2 i18n>FEDERATION</h2>
|
||||||
<div i18n class="inner-form-description">
|
<div i18n class="inner-form-description">
|
||||||
Manage <a class="link-orange" routerLink="/admin/settings/follows">relations</a> with other instances.
|
Manage <a class="link-primary" routerLink="/admin/settings/follows">relations</a> with other instances.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -646,7 +640,7 @@
|
||||||
<div i18n>⚠️ This functionality requires a lot of attention and extra moderation.</div>
|
<div i18n>⚠️ This functionality requires a lot of attention and extra moderation.</div>
|
||||||
|
|
||||||
<span i18n>
|
<span i18n>
|
||||||
See <a class="link-orange" href="https://docs.joinpeertube.org/admin/following-instances#automatically-follow-other-instances" rel="noopener noreferrer" target="_blank">the documentation</a> for more information about the expected URL
|
See <a class="link-primary" href="https://docs.joinpeertube.org/admin/following-instances#automatically-follow-other-instances" rel="noopener noreferrer" target="_blank">the documentation</a> for more information about the expected URL
|
||||||
</span>
|
</span>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { NgClass, NgFor, NgIf } from '@angular/common'
|
||||||
import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core'
|
import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core'
|
||||||
import { FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms'
|
import { FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms'
|
||||||
import { RouterLink } from '@angular/router'
|
import { RouterLink } from '@angular/router'
|
||||||
import { MenuService, ThemeService } from '@app/core'
|
import { ThemeService } from '@app/core'
|
||||||
import { AlertComponent } from '@app/shared/shared-main/common/alert.component'
|
import { AlertComponent } from '@app/shared/shared-main/common/alert.component'
|
||||||
import { HTMLServerConfig } from '@peertube/peertube-models'
|
import { HTMLServerConfig } from '@peertube/peertube-models'
|
||||||
import { pairwise } from 'rxjs/operators'
|
import { pairwise } from 'rxjs/operators'
|
||||||
|
@ -12,7 +12,6 @@ import { PeertubeCheckboxComponent } from '../../../shared/shared-forms/peertube
|
||||||
import { SelectCustomValueComponent } from '../../../shared/shared-forms/select/select-custom-value.component'
|
import { SelectCustomValueComponent } from '../../../shared/shared-forms/select/select-custom-value.component'
|
||||||
import { SelectOptionsComponent } from '../../../shared/shared-forms/select/select-options.component'
|
import { SelectOptionsComponent } from '../../../shared/shared-forms/select/select-options.component'
|
||||||
import { HelpComponent } from '../../../shared/shared-main/buttons/help.component'
|
import { HelpComponent } from '../../../shared/shared-main/buttons/help.component'
|
||||||
import { PeerTubeTemplateDirective } from '../../../shared/shared-main/common/peertube-template.directive'
|
|
||||||
import { UserRealQuotaInfoComponent } from '../../shared/user-real-quota-info.component'
|
import { UserRealQuotaInfoComponent } from '../../shared/user-real-quota-info.component'
|
||||||
import { ConfigService } from '../shared/config.service'
|
import { ConfigService } from '../shared/config.service'
|
||||||
|
|
||||||
|
@ -34,7 +33,6 @@ import { ConfigService } from '../shared/config.service'
|
||||||
NgClass,
|
NgClass,
|
||||||
UserRealQuotaInfoComponent,
|
UserRealQuotaInfoComponent,
|
||||||
SelectOptionsComponent,
|
SelectOptionsComponent,
|
||||||
PeerTubeTemplateDirective,
|
|
||||||
AlertComponent
|
AlertComponent
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
@ -53,7 +51,6 @@ export class EditBasicConfigurationComponent implements OnInit, OnChanges {
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
private configService: ConfigService,
|
private configService: ConfigService,
|
||||||
private menuService: MenuService,
|
|
||||||
private themeService: ThemeService
|
private themeService: ThemeService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
@ -62,7 +59,11 @@ export class EditBasicConfigurationComponent implements OnInit, OnChanges {
|
||||||
this.checkSignupField()
|
this.checkSignupField()
|
||||||
this.checkImportSyncField()
|
this.checkImportSyncField()
|
||||||
|
|
||||||
this.availableThemes = this.themeService.buildAvailableThemes()
|
this.availableThemes = [
|
||||||
|
this.themeService.getDefaultThemeItem(),
|
||||||
|
|
||||||
|
...this.themeService.buildAvailableThemes()
|
||||||
|
]
|
||||||
|
|
||||||
this.exportExpirationOptions = [
|
this.exportExpirationOptions = [
|
||||||
{ id: 1000 * 3600 * 24, label: $localize`1 day` },
|
{ id: 1000 * 3600 * 24, label: $localize`1 day` },
|
||||||
|
@ -174,10 +175,6 @@ export class EditBasicConfigurationComponent implements OnInit, OnChanges {
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
getDefaultThemeLabel () {
|
|
||||||
return this.themeService.getDefaultThemeLabel()
|
|
||||||
}
|
|
||||||
|
|
||||||
private checkImportSyncField () {
|
private checkImportSyncField () {
|
||||||
const importSyncControl = this.form.get('import.videoChannelSynchronization.enabled')
|
const importSyncControl = this.form.get('import.videoChannelSynchronization.enabled')
|
||||||
const importVideosHttpControl = this.form.get('import.videos.http.enabled')
|
const importVideosHttpControl = this.form.get('import.videos.http.enabled')
|
||||||
|
|
|
@ -106,7 +106,7 @@
|
||||||
<div class="title-col">
|
<div class="title-col">
|
||||||
<h2 i18n>MODERATION & NSFW</h2>
|
<h2 i18n>MODERATION & NSFW</h2>
|
||||||
<div i18n class="inner-form-description">
|
<div i18n class="inner-form-description">
|
||||||
Manage <a class="link-orange" routerLink="/admin/overview/users">users</a> to build a moderation team.
|
Manage <a class="link-primary" routerLink="/admin/overview/users">users</a> to build a moderation team.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<div class="title-col"></div>
|
<div class="title-col"></div>
|
||||||
<div class="content-col">
|
<div class="content-col">
|
||||||
|
|
||||||
<div class="callout callout-orange">
|
<div class="callout callout-primary">
|
||||||
<span i18n>
|
<span i18n>
|
||||||
Estimating a server's capacity to transcode and stream videos isn't easy and we can't tune PeerTube automatically.
|
Estimating a server's capacity to transcode and stream videos isn't easy and we can't tune PeerTube automatically.
|
||||||
</span>
|
</span>
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
<span i18n>
|
<span i18n>
|
||||||
However, you may want to read <a class="link-orange" target="_blank" rel="noopener noreferrer" href="https://docs.joinpeertube.org/admin/configuration#vod-transcoding">our guidelines</a> before tweaking the following values.
|
However, you may want to read <a class="link-primary" target="_blank" rel="noopener noreferrer" href="https://docs.joinpeertube.org/admin/configuration#vod-transcoding">our guidelines</a> before tweaking the following values.
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -22,25 +22,25 @@
|
||||||
|
|
||||||
@if (signupAllowed) {
|
@if (signupAllowed) {
|
||||||
<p i18n>
|
<p i18n>
|
||||||
This instance allows registration. However, be careful to check the <a class="link-orange terms-anchor d-inline" (click)="onTermsClick($event, instanceInformation)" href="/about/instance#terms">Terms</a><a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">Terms</a> before creating an account.
|
This instance allows registration. However, be careful to check the <a class="link-primary terms-anchor d-inline" (click)="onTermsClick($event, instanceInformation)" href="/about/instance#terms">Terms</a><a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">Terms</a> before creating an account.
|
||||||
You may also search for another instance to match your exact needs at: <a class="link-orange" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">https://joinpeertube.org/instances</a>.
|
You may also search for another instance to match your exact needs at: <a class="link-primary" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">https://joinpeertube.org/instances</a>.
|
||||||
</p>
|
</p>
|
||||||
} @else {
|
} @else {
|
||||||
<p i18n>
|
<p i18n>
|
||||||
Currently this instance doesn't allow for user registration, you may check the <a class="link-orange terms-anchor d-inline" (click)="onTermsClick($event, instanceInformation)" href="/about/instance#terms">Terms</a><a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">Terms</a> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there.
|
Currently this instance doesn't allow for user registration, you may check the <a class="link-primary terms-anchor d-inline" (click)="onTermsClick($event, instanceInformation)" href="/about/instance#terms">Terms</a><a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">Terms</a> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there.
|
||||||
Find yours among multiple instances at: <a class="link-orange" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">https://joinpeertube.org/instances</a>.
|
Find yours among multiple instances at: <a class="link-primary" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">https://joinpeertube.org/instances</a>.
|
||||||
</p>
|
</p>
|
||||||
}
|
}
|
||||||
</my-alert>
|
</my-alert>
|
||||||
|
|
||||||
<my-alert type="danger" i18n *ngIf="externalAuthError">
|
<my-alert type="danger" i18n *ngIf="externalAuthError">
|
||||||
Sorry but there was an issue with the external login process. Please <a class="link-orange" routerLink="/about">contact an administrator</a>.
|
Sorry but there was an issue with the external login process. Please <a class="link-primary" routerLink="/about">contact an administrator</a>.
|
||||||
</my-alert>
|
</my-alert>
|
||||||
|
|
||||||
<my-alert *ngIf="error" type="danger">
|
<my-alert *ngIf="error" type="danger">
|
||||||
{{ error }}
|
{{ error }}
|
||||||
|
|
||||||
<a *ngIf="error === 'User email is not verified.'" class="ms-1 link-orange" i18n routerLink="/verify-account/ask-send-email">
|
<a *ngIf="error === 'User email is not verified.'" class="ms-1 link-primary" i18n routerLink="/verify-account/ask-send-email">
|
||||||
Request new verification email
|
Request new verification email
|
||||||
</a>
|
</a>
|
||||||
</my-alert>
|
</my-alert>
|
||||||
|
@ -90,13 +90,13 @@
|
||||||
<input type="submit" class="peertube-button primary-button w-100" i18n-value value="Login" [disabled]="!form.valid">
|
<input type="submit" class="peertube-button primary-button w-100" i18n-value value="Login" [disabled]="!form.valid">
|
||||||
|
|
||||||
<div *ngIf="!otpStep" class="additional-links d-flex justify-content-center mt-4 mb-5 text-center">
|
<div *ngIf="!otpStep" class="additional-links d-flex justify-content-center mt-4 mb-5 text-center">
|
||||||
<button type="button" i18n class="button-unstyle link-orange mx-3" (click)="openForgotPasswordModal()" i18n-title title="Click here to reset your password">
|
<button type="button" i18n class="button-unstyle link-primary mx-3" (click)="openForgotPasswordModal()" i18n-title title="Click here to reset your password">
|
||||||
I forgot my password
|
I forgot my password
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<ng-container *ngIf="signupAllowed">
|
<ng-container *ngIf="signupAllowed">
|
||||||
<span class="lh-1">·</span>
|
<span class="lh-1">·</span>
|
||||||
<a i18n routerLink="/signup" class="link-orange mx-3">Create an account</a>
|
<a i18n routerLink="/signup" class="link-primary mx-3">Create an account</a>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
<p i18n>You can already follow {{ instanceName }} using your favorite tool.</p>
|
<p i18n>You can already follow {{ instanceName }} using your favorite tool.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="callout callout-orange callout-light">
|
<div class="callout callout-primary callout-light">
|
||||||
<div class="mascot-container" style="min-width: 140px">
|
<div class="mascot-container" style="min-width: 140px">
|
||||||
<img class="mascot" width="140px" height="160px" src="/client/assets/images/mascot/happy.svg" alt="mascot"/>
|
<img class="mascot" width="140px" height="160px" src="/client/assets/images/mascot/happy.svg" alt="mascot"/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -40,8 +40,8 @@
|
||||||
<h4 i18>This website is a GAFAM alternative</h4>
|
<h4 i18>This website is a GAFAM alternative</h4>
|
||||||
|
|
||||||
<p i18n>
|
<p i18n>
|
||||||
{{ instanceName }} has been created using <a class="link-orange" target="_blank" rel="noopener noreferrer" href="https://joinpeertube.org">PeerTube</a>, a video creation platform developed by Framasoft.
|
{{ instanceName }} has been created using <a class="link-primary" target="_blank" rel="noopener noreferrer" href="https://joinpeertube.org">PeerTube</a>, a video creation platform developed by Framasoft.
|
||||||
<a class="link-orange" target="_blank" rel="noopener noreferrer" href="https://framasoft.org">Framasoft</a> is a french non-profit organization that offers alternatives to Big Tech's digital tools
|
<a class="link-primary" target="_blank" rel="noopener noreferrer" href="https://framasoft.org">Framasoft</a> is a french non-profit organization that offers alternatives to Big Tech's digital tools
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -16,8 +16,8 @@
|
||||||
<ng-template ptTemplate="label">
|
<ng-template ptTemplate="label">
|
||||||
<ng-container i18n>
|
<ng-container i18n>
|
||||||
I am at least {{ minimumAge }} years old and agree
|
I am at least {{ minimumAge }} years old and agree
|
||||||
to the <a class="link-orange" (click)="onTermsClick($event)" href='#'>Terms</a>
|
to the <a class="link-primary" (click)="onTermsClick($event)" href='#'>Terms</a>
|
||||||
<ng-container *ngIf="hasCodeOfConduct"> and to the <a class="link-orange" (click)="onCodeOfConductClick($event)" href='#'>Code of Conduct</a></ng-container>
|
<ng-container *ngIf="hasCodeOfConduct"> and to the <a class="link-primary" (click)="onCodeOfConductClick($event)" href='#'>Code of Conduct</a></ng-container>
|
||||||
of {{ instanceName }}
|
of {{ instanceName }}
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<my-alert type="danger" *ngIf="failed">
|
<my-alert type="danger" *ngIf="failed">
|
||||||
<span i18n>An error occurred.</span>
|
<span i18n>An error occurred.</span>
|
||||||
|
|
||||||
<a i18n class="ms-1 link-orange" routerLink="/verify-account/ask-send-email">
|
<a i18n class="ms-1 link-primary" routerLink="/verify-account/ask-send-email">
|
||||||
Request a new verification email
|
Request a new verification email
|
||||||
</a>
|
</a>
|
||||||
</my-alert>
|
</my-alert>
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
<p i18n>Your email has been verified and your account has been created!</p>
|
<p i18n>Your email has been verified and your account has been created!</p>
|
||||||
|
|
||||||
<p i18n>
|
<p i18n>
|
||||||
If you need help using PeerTube, you can have a look at the <a class="link-orange" href="https://docs.joinpeertube.org/use/setup-account" target="_blank" rel="noopener noreferrer">documentation</a>.
|
If you need help using PeerTube, you can have a look at the <a class="link-primary" href="https://docs.joinpeertube.org/use/setup-account" target="_blank" rel="noopener noreferrer">documentation</a>.
|
||||||
</p>
|
</p>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</my-alert>
|
</my-alert>
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p *ngIf="!requiresApproval" i18n>
|
<p *ngIf="!requiresApproval" i18n>
|
||||||
If you need help using PeerTube, you can have a look at the <a class="link-orange" href="https://docs.joinpeertube.org/use/setup-account" target="_blank" rel="noopener noreferrer">documentation</a>.
|
If you need help using PeerTube, you can have a look at the <a class="link-primary" href="https://docs.joinpeertube.org/use/setup-account" target="_blank" rel="noopener noreferrer">documentation</a>.
|
||||||
</p>
|
</p>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</my-alert>
|
</my-alert>
|
||||||
|
|
|
@ -49,7 +49,7 @@
|
||||||
View account
|
View account
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a class="view-account link-orange complete" [routerLink]="getAccountUrl()" i18n>
|
<a class="view-account link-primary complete" [routerLink]="getAccountUrl()" i18n>
|
||||||
View owner account
|
View owner account
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<a class="link-orange" i18n i18n-title title="Get more information" target="_blank" rel="noopener noreferrer" href="/about/peertube#privacy">More information</a>
|
<a class="link-primary" i18n i18n-title title="Get more information" target="_blank" rel="noopener noreferrer" href="/about/peertube#privacy">More information</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button i18n class="ms-2 peertube-button primary-button" (click)="acceptedPrivacyConcern()">
|
<button i18n class="ms-2 peertube-button primary-button" (click)="acceptedPrivacyConcern()">
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
<div class="main-row">
|
<div class="main-row">
|
||||||
|
|
||||||
<div *ngIf="broadcastMessage" class="broadcast-message alert" [ngClass]="broadcastMessage.class">
|
<div *ngIf="broadcastMessage" class="broadcast-message alert margin-content" [ngClass]="broadcastMessage.class">
|
||||||
<div [innerHTML]="broadcastMessage.message"></div>
|
<div [innerHTML]="broadcastMessage.message"></div>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
|
|
|
@ -42,8 +42,7 @@
|
||||||
.broadcast-message {
|
.broadcast-message {
|
||||||
min-height: 50px;
|
min-height: 50px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin-bottom: 0;
|
margin-bottom: 2rem;
|
||||||
border-radius: 0;
|
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr 30px;
|
grid-template-columns: 1fr 30px;
|
||||||
column-gap: 10px;
|
column-gap: 10px;
|
||||||
|
@ -55,7 +54,7 @@
|
||||||
margin: auto;
|
margin: auto;
|
||||||
|
|
||||||
> my-global-icon {
|
> my-global-icon {
|
||||||
width: 20px;
|
@include global-icon-size(20px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@ import { MenuComponent } from './menu/menu.component'
|
||||||
import { ConfirmComponent } from './modal/confirm.component'
|
import { ConfirmComponent } from './modal/confirm.component'
|
||||||
import { GlobalIconComponent, GlobalIconName } from './shared/shared-icons/global-icon.component'
|
import { GlobalIconComponent, GlobalIconName } from './shared/shared-icons/global-icon.component'
|
||||||
import { InstanceService } from './shared/shared-main/instance/instance.service'
|
import { InstanceService } from './shared/shared-main/instance/instance.service'
|
||||||
|
import { ButtonComponent } from './shared/shared-main/buttons/button.component'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-app',
|
selector: 'my-app',
|
||||||
|
@ -61,11 +62,12 @@ import { InstanceService } from './shared/shared-main/instance/instance.service'
|
||||||
AccountSetupWarningModalComponent,
|
AccountSetupWarningModalComponent,
|
||||||
AdminWelcomeModalComponent,
|
AdminWelcomeModalComponent,
|
||||||
InstanceConfigWarningModalComponent,
|
InstanceConfigWarningModalComponent,
|
||||||
CustomModalComponent
|
CustomModalComponent,
|
||||||
|
ButtonComponent
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class AppComponent implements OnInit, AfterViewInit {
|
export class AppComponent implements OnInit, AfterViewInit {
|
||||||
private static BROADCAST_MESSAGE_KEY = 'app-broadcast-message-dismissed'
|
private static LS_BROADCAST_MESSAGE = 'app-broadcast-message-dismissed'
|
||||||
|
|
||||||
@ViewChild('accountSetupWarningModal') accountSetupWarningModal: AccountSetupWarningModalComponent
|
@ViewChild('accountSetupWarningModal') accountSetupWarningModal: AccountSetupWarningModalComponent
|
||||||
@ViewChild('adminWelcomeModal') adminWelcomeModal: AdminWelcomeModalComponent
|
@ViewChild('adminWelcomeModal') adminWelcomeModal: AdminWelcomeModalComponent
|
||||||
|
@ -159,7 +161,7 @@ export class AppComponent implements OnInit, AfterViewInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
hideBroadcastMessage () {
|
hideBroadcastMessage () {
|
||||||
peertubeLocalStorage.setItem(AppComponent.BROADCAST_MESSAGE_KEY, this.serverConfig.broadcastMessage.message)
|
peertubeLocalStorage.setItem(AppComponent.LS_BROADCAST_MESSAGE, this.serverConfig.broadcastMessage.message)
|
||||||
|
|
||||||
this.broadcastMessage = null
|
this.broadcastMessage = null
|
||||||
this.screenService.isBroadcastMessageDisplayed = false
|
this.screenService.isBroadcastMessageDisplayed = false
|
||||||
|
@ -214,7 +216,7 @@ export class AppComponent implements OnInit, AfterViewInit {
|
||||||
|
|
||||||
if (messageConfig.enabled) {
|
if (messageConfig.enabled) {
|
||||||
// Already dismissed this message?
|
// Already dismissed this message?
|
||||||
if (messageConfig.dismissable && localStorage.getItem(AppComponent.BROADCAST_MESSAGE_KEY) === messageConfig.message) {
|
if (messageConfig.dismissable && localStorage.getItem(AppComponent.LS_BROADCAST_MESSAGE) === messageConfig.message) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Injectable } from '@angular/core'
|
import { Injectable } from '@angular/core'
|
||||||
import { HTMLServerConfig, ServerConfigTheme } from '@peertube/peertube-models'
|
import { HTMLServerConfig, ServerConfig, ServerConfigTheme } from '@peertube/peertube-models'
|
||||||
import { logger } from '@root-helpers/logger'
|
import { logger } from '@root-helpers/logger'
|
||||||
import { capitalizeFirstLetter } from '@root-helpers/string'
|
import { capitalizeFirstLetter } from '@root-helpers/string'
|
||||||
import { UserLocalStorageKeys } from '@root-helpers/users'
|
import { UserLocalStorageKeys } from '@root-helpers/users'
|
||||||
|
@ -11,6 +11,8 @@ import { PluginService } from '../plugins/plugin.service'
|
||||||
import { ServerService } from '../server'
|
import { ServerService } from '../server'
|
||||||
import { UserService } from '../users/user.service'
|
import { UserService } from '../users/user.service'
|
||||||
import { LocalStorageService } from '../wrappers/storage.service'
|
import { LocalStorageService } from '../wrappers/storage.service'
|
||||||
|
import { sortBy } from '@peertube/peertube-core-utils'
|
||||||
|
import { toInteger } from '@ng-bootstrap/ng-bootstrap/util/util'
|
||||||
|
|
||||||
const debugLogger = debug('peertube:theme')
|
const debugLogger = debug('peertube:theme')
|
||||||
|
|
||||||
|
@ -50,29 +52,29 @@ export class ThemeService {
|
||||||
this.listenUserTheme()
|
this.listenUserTheme()
|
||||||
}
|
}
|
||||||
|
|
||||||
getDefaultThemeLabel () {
|
getDefaultThemeItem () {
|
||||||
if (this.hasDarkTheme()) {
|
return {
|
||||||
return $localize`Light (Orange) or Dark (Brown)`
|
label: $localize`Light (Beige) or Dark (Brown)`,
|
||||||
|
id: 'default',
|
||||||
|
description: $localize`PeerTube selects the appropriate theme depending on web browser preferences`
|
||||||
}
|
}
|
||||||
|
|
||||||
return $localize`Light (Orange)`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
buildAvailableThemes () {
|
buildAvailableThemes () {
|
||||||
return [
|
return [
|
||||||
...this.serverConfig.theme.registered.map(t => ({ id: t.name, label: capitalizeFirstLetter(t.name) })),
|
|
||||||
|
|
||||||
...this.serverConfig.theme.builtIn.map(t => {
|
...this.serverConfig.theme.builtIn.map(t => {
|
||||||
if (t.name === 'peertube-core-dark') {
|
if (t.name === 'peertube-core-dark-brown') {
|
||||||
return { id: t.name, label: $localize`Dark (Brown)` }
|
return { id: t.name, label: $localize`Dark (Brown)` }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t.name === 'peertube-core-light') {
|
if (t.name === 'peertube-core-light-beige') {
|
||||||
return { id: t.name, label: $localize`Light (Orange)` }
|
return { id: t.name, label: $localize`Light (Beige)` }
|
||||||
}
|
}
|
||||||
|
|
||||||
return { id: t.name, label: capitalizeFirstLetter(t.name) }
|
return { id: t.name, label: capitalizeFirstLetter(t.name) }
|
||||||
})
|
}),
|
||||||
|
|
||||||
|
...this.serverConfig.theme.registered.map(t => ({ id: t.name, label: capitalizeFirstLetter(t.name) }))
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,8 +119,8 @@ export class ThemeService {
|
||||||
if (instanceTheme !== 'default') return instanceTheme
|
if (instanceTheme !== 'default') return instanceTheme
|
||||||
|
|
||||||
// Default to dark theme if available and wanted by the user
|
// Default to dark theme if available and wanted by the user
|
||||||
if (this.hasDarkTheme() && window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||||
return 'dark'
|
return 'peertube-core-dark-brown' satisfies ServerConfig['theme']['builtIn'][0]['name']
|
||||||
}
|
}
|
||||||
|
|
||||||
return instanceTheme
|
return instanceTheme
|
||||||
|
@ -164,7 +166,7 @@ export class ThemeService {
|
||||||
this.localStorageService.removeItem(UserLocalStorageKeys.LAST_ACTIVE_THEME, false)
|
this.localStorageService.removeItem(UserLocalStorageKeys.LAST_ACTIVE_THEME, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.injectColorPalette()
|
setTimeout(() => this.injectColorPalette(), 0)
|
||||||
|
|
||||||
this.oldThemeName = currentTheme
|
this.oldThemeName = currentTheme
|
||||||
}
|
}
|
||||||
|
@ -187,6 +189,9 @@ export class ThemeService {
|
||||||
]
|
]
|
||||||
|
|
||||||
const darkTheme = this.isDarkTheme(computedStyle)
|
const darkTheme = this.isDarkTheme(computedStyle)
|
||||||
|
if (darkTheme) {
|
||||||
|
debugLogger('Detected dark theme')
|
||||||
|
}
|
||||||
|
|
||||||
for (const { prefix, invertIfDark, fallbacks = {} } of toProcess) {
|
for (const { prefix, invertIfDark, fallbacks = {} } of toProcess) {
|
||||||
const mainColor = computedStyle.getPropertyValue('--' + prefix)
|
const mainColor = computedStyle.getPropertyValue('--' + prefix)
|
||||||
|
@ -200,35 +205,61 @@ export class ThemeService {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
const mainColorParsed = parse(mainColor)
|
const mainColorHSL = toHSLA(parse(mainColor))
|
||||||
const mainColorHSL = toHSLA(mainColorParsed)
|
|
||||||
|
|
||||||
for (let i = -9; i <= 9; i++) {
|
let lastColorHSL = { ...mainColorHSL }
|
||||||
const suffix = 500 + (50 * i)
|
|
||||||
|
// Inject in alphabetical order for easy debug
|
||||||
|
const toInject: { id: number, key: string, value: string }[] = [
|
||||||
|
{ id: 500, key: `--${prefix}-500`, value: this.toHSLStr(mainColorHSL) }
|
||||||
|
]
|
||||||
|
|
||||||
|
for (const j of [ -1, 1 ]) {
|
||||||
|
for (let i = 1; i <= 9; i++) {
|
||||||
|
const suffix = 500 + (50 * i * j)
|
||||||
const key = `--${prefix}-${suffix}`
|
const key = `--${prefix}-${suffix}`
|
||||||
|
|
||||||
const existingValue = computedStyle.getPropertyValue(key)
|
const existingValue = computedStyle.getPropertyValue(key)
|
||||||
if (!existingValue || existingValue === '0') {
|
if (!existingValue || existingValue === '0') {
|
||||||
const newLuminance = Math.max(Math.min(100, Math.round(mainColorHSL.l + (i * 5 * -1 * darkInverter))), 0)
|
const newLuminance = this.buildNewLuminance(lastColorHSL, j, darkInverter)
|
||||||
const newColor = `hsl(${Math.round(mainColorHSL.h)} ${Math.round(mainColorHSL.s)}% ${newLuminance}% / ${mainColorHSL.a})`
|
const newColorHSL = { ...lastColorHSL, l: newLuminance }
|
||||||
|
|
||||||
|
const newColorStr = this.toHSLStr(newColorHSL)
|
||||||
|
|
||||||
const value = fallbacks[key]
|
const value = fallbacks[key]
|
||||||
? `var(${fallbacks[key]}, ${newColor})`
|
? `var(${fallbacks[key]}, ${newColorStr})`
|
||||||
: newColor
|
: newColorStr
|
||||||
|
|
||||||
rootStyle.setProperty(key, value)
|
toInject.push({ id: suffix, key, value })
|
||||||
this.oldInjectedProperties.push(key)
|
|
||||||
|
lastColorHSL = newColorHSL
|
||||||
|
|
||||||
debugLogger(`Injected theme palette ${key} -> ${value}`)
|
debugLogger(`Injected theme palette ${key} -> ${value}`)
|
||||||
|
} else {
|
||||||
|
lastColorHSL = toHSLA(parse(existingValue))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const { key, value } of sortBy(toInject, 'id')) {
|
||||||
|
rootStyle.setProperty(key, value)
|
||||||
|
this.oldInjectedProperties.push(key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
document.body.dataset.bsTheme = darkTheme
|
document.body.dataset.bsTheme = darkTheme
|
||||||
? 'dark'
|
? 'dark'
|
||||||
: ''
|
: ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private buildNewLuminance (base: { l: number }, factor: number, darkInverter: number) {
|
||||||
|
return Math.max(Math.min(100, Math.round(base.l + (factor * 5 * -1 * darkInverter))), 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
private toHSLStr (c: { h: number, s: number, l: number, a: number }) {
|
||||||
|
return `hsl(${Math.round(c.h)} ${Math.round(c.s)}% ${Math.round(c.l)}% / ${Math.round(c.a)})`
|
||||||
|
}
|
||||||
|
|
||||||
private isDarkTheme (computedStyle: CSSStyleDeclaration) {
|
private isDarkTheme (computedStyle: CSSStyleDeclaration) {
|
||||||
const deprecatedFG = computedStyle.getPropertyValue('--mainForegroundColor')
|
const deprecatedFG = computedStyle.getPropertyValue('--mainForegroundColor')
|
||||||
const deprecatedBG = computedStyle.getPropertyValue('--mainBackgroundColor')
|
const deprecatedBG = computedStyle.getPropertyValue('--mainBackgroundColor')
|
||||||
|
@ -318,8 +349,4 @@ export class ThemeService {
|
||||||
private getTheme (name: string) {
|
private getTheme (name: string) {
|
||||||
return this.themes.find(t => t.name === name)
|
return this.themes.find(t => t.name === name)
|
||||||
}
|
}
|
||||||
|
|
||||||
private hasDarkTheme () {
|
|
||||||
return this.serverConfig.theme.registered.some(t => t.name === 'dark')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,6 @@
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-size: contain;
|
background-size: contain;
|
||||||
|
|
||||||
@include margin-left(18px);
|
|
||||||
@include margin-right(10px);
|
@include margin-right(10px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ input {
|
||||||
left: 3px;
|
left: 3px;
|
||||||
width: 14px;
|
width: 14px;
|
||||||
height: 14px;
|
height: 14px;
|
||||||
background: pvar(--bg);
|
background: pvar(--on-primary);
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
transition: 0.3s ease-out;
|
transition: 0.3s ease-out;
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ input {
|
||||||
}
|
}
|
||||||
|
|
||||||
&:checked + label {
|
&:checked + label {
|
||||||
background: pvar(--border-primary);
|
background: pvar(--primary);
|
||||||
|
|
||||||
&::after {
|
&::after {
|
||||||
left: calc(100% - 3px);
|
left: calc(100% - 3px);
|
||||||
|
@ -45,6 +45,6 @@ input {
|
||||||
}
|
}
|
||||||
|
|
||||||
&:focus-visible + label {
|
&:focus-visible + label {
|
||||||
outline: 2px solid;
|
box-shadow: $focus-box-shadow-form;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,14 +3,7 @@
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label i18n for="theme">Theme</label>
|
<label i18n for="theme">Theme</label>
|
||||||
|
|
||||||
<div class="peertube-select-container">
|
<my-select-options inputId="theme" formControlName="theme" [items]="availableThemes"></my-select-options>
|
||||||
<select formControlName="theme" id="theme" class="form-control">
|
|
||||||
<option i18n value="instance-default">{{ instanceName }} default theme ({{ getDefaultInstanceThemeLabel() }})</option>
|
|
||||||
<option i18n value="default">{{ getDefaultThemeLabel() }}</option>
|
|
||||||
|
|
||||||
<option *ngFor="let theme of availableThemes" [value]="theme.id">{{ theme.label }}</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<input *ngIf="!reactiveUpdate" type="submit" class="peertube-button primary-button" i18n-value value="Save interface settings" [disabled]="!form.valid">
|
<input *ngIf="!reactiveUpdate" type="submit" class="peertube-button primary-button" i18n-value value="Save interface settings" [disabled]="!form.valid">
|
||||||
|
|
|
@ -7,13 +7,14 @@ import { HTMLServerConfig, User, UserUpdateMe } from '@peertube/peertube-models'
|
||||||
import { SelectOptionsItem } from 'src/types'
|
import { SelectOptionsItem } from 'src/types'
|
||||||
import { NgFor, NgIf } from '@angular/common'
|
import { NgFor, NgIf } from '@angular/common'
|
||||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
|
||||||
|
import { SelectOptionsComponent } from '../shared-forms/select/select-options.component'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-user-interface-settings',
|
selector: 'my-user-interface-settings',
|
||||||
templateUrl: './user-interface-settings.component.html',
|
templateUrl: './user-interface-settings.component.html',
|
||||||
styleUrls: [ './user-interface-settings.component.scss' ],
|
styleUrls: [ './user-interface-settings.component.scss' ],
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [ FormsModule, ReactiveFormsModule, NgFor, NgIf ]
|
imports: [ FormsModule, ReactiveFormsModule, NgFor, NgIf, SelectOptionsComponent ]
|
||||||
})
|
})
|
||||||
export class UserInterfaceSettingsComponent extends FormReactive implements OnInit, OnDestroy {
|
export class UserInterfaceSettingsComponent extends FormReactive implements OnInit, OnDestroy {
|
||||||
@Input() user: User
|
@Input() user: User
|
||||||
|
@ -44,7 +45,13 @@ export class UserInterfaceSettingsComponent extends FormReactive implements OnIn
|
||||||
ngOnInit () {
|
ngOnInit () {
|
||||||
this.serverConfig = this.serverService.getHTMLConfig()
|
this.serverConfig = this.serverService.getHTMLConfig()
|
||||||
|
|
||||||
this.availableThemes = this.themeService.buildAvailableThemes()
|
this.availableThemes = [
|
||||||
|
{ id: 'instance-default', label: $localize`${this.instanceName} theme`, description: this.getDefaultInstanceThemeLabel() },
|
||||||
|
|
||||||
|
this.themeService.getDefaultThemeItem(),
|
||||||
|
|
||||||
|
...this.themeService.buildAvailableThemes()
|
||||||
|
]
|
||||||
|
|
||||||
this.buildForm({
|
this.buildForm({
|
||||||
theme: null
|
theme: null
|
||||||
|
@ -66,20 +73,6 @@ export class UserInterfaceSettingsComponent extends FormReactive implements OnIn
|
||||||
this.formValuesWatcher?.unsubscribe()
|
this.formValuesWatcher?.unsubscribe()
|
||||||
}
|
}
|
||||||
|
|
||||||
getDefaultThemeLabel () {
|
|
||||||
return this.themeService.getDefaultThemeLabel()
|
|
||||||
}
|
|
||||||
|
|
||||||
getDefaultInstanceThemeLabel () {
|
|
||||||
const theme = this.serverConfig.theme.default
|
|
||||||
|
|
||||||
if (theme === 'default') {
|
|
||||||
return this.getDefaultThemeLabel()
|
|
||||||
}
|
|
||||||
|
|
||||||
return theme
|
|
||||||
}
|
|
||||||
|
|
||||||
updateInterfaceSettings () {
|
updateInterfaceSettings () {
|
||||||
const theme = this.form.value['theme']
|
const theme = this.form.value['theme']
|
||||||
|
|
||||||
|
@ -105,4 +98,15 @@ export class UserInterfaceSettingsComponent extends FormReactive implements OnIn
|
||||||
this.userService.updateMyAnonymousProfile(details)
|
this.userService.updateMyAnonymousProfile(details)
|
||||||
if (this.notifyOnUpdate) this.notifier.success($localize`Interface settings updated.`)
|
if (this.notifyOnUpdate) this.notifier.success($localize`Interface settings updated.`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getDefaultInstanceThemeLabel () {
|
||||||
|
const theme = this.serverConfig.theme.default
|
||||||
|
|
||||||
|
if (theme === 'default') {
|
||||||
|
return this.themeService.getDefaultThemeItem().label
|
||||||
|
}
|
||||||
|
|
||||||
|
return theme
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@
|
||||||
i18n-labelText labelText="Help share videos being played"
|
i18n-labelText labelText="Help share videos being played"
|
||||||
>
|
>
|
||||||
<ng-container ngProjectAs="description">
|
<ng-container ngProjectAs="description">
|
||||||
<span i18n>The <a class="link-orange" routerLink="/about/peertube" fragment="privacy" target="_blank">sharing system</a> implies that some technical information about your system (such as a public IP address) can be sent to other peers, but greatly helps to reduce server load.</span>
|
<span i18n>The <a class="link-primary" routerLink="/about/peertube" fragment="privacy" target="_blank">sharing system</a> implies that some technical information about your system (such as a public IP address) can be sent to other peers, but greatly helps to reduce server load.</span>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</my-peertube-checkbox>
|
</my-peertube-checkbox>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<p i18n>
|
<p i18n>
|
||||||
See <a class="link-orange" href="https://docs.joinpeertube.org/use/create-upload-video#publish-a-live" target="_blank" rel="noopener noreferrer">the documentation</a>
|
See <a class="link-primary" href="https://docs.joinpeertube.org/use/create-upload-video#publish-a-live" target="_blank" rel="noopener noreferrer">the documentation</a>
|
||||||
to learn how to use the PeerTube live streaming feature.
|
to learn how to use the PeerTube live streaming feature.
|
||||||
</p>
|
</p>
|
||||||
|
|
|
@ -15,7 +15,8 @@
|
||||||
@for (quickFilter of quickFilters; track quickFilter) {
|
@for (quickFilter of quickFilters; track quickFilter) {
|
||||||
<my-button
|
<my-button
|
||||||
theme="secondary" [icon]="quickFilter.iconName" class="me-2 mb-2"
|
theme="secondary" [icon]="quickFilter.iconName" class="me-2 mb-2"
|
||||||
ptRouterLink="." [ptQueryParams]="quickFilter.queryParams" [active]="quickFilter.isActive()" ptQueryParamsHandling="merge"
|
ptRouterLink="." [ptQueryParams]="quickFilter.filters" [active]="quickFilter.isActive()" ptQueryParamsHandling="merge"
|
||||||
|
(click)="onQuickFilter($event, quickFilter)"
|
||||||
>{{ quickFilter.label }} </my-button>
|
>{{ quickFilter.label }} </my-button>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -18,6 +18,7 @@ import { ButtonComponent } from '../shared-main/buttons/button.component'
|
||||||
import { PeertubeModalService } from '../shared-main/peertube-modal/peertube-modal.service'
|
import { PeertubeModalService } from '../shared-main/peertube-modal/peertube-modal.service'
|
||||||
import { VideoFilterActive, VideoFilters } from './video-filters.model'
|
import { VideoFilterActive, VideoFilters } from './video-filters.model'
|
||||||
import { InstanceFollowService } from '../shared-instance/instance-follow.service'
|
import { InstanceFollowService } from '../shared-instance/instance-follow.service'
|
||||||
|
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
|
||||||
|
|
||||||
const debugLogger = debug('peertube:videos:VideoFiltersHeaderComponent')
|
const debugLogger = debug('peertube:videos:VideoFiltersHeaderComponent')
|
||||||
|
|
||||||
|
@ -25,7 +26,7 @@ type QuickFilter = {
|
||||||
iconName: GlobalIconName
|
iconName: GlobalIconName
|
||||||
label: string
|
label: string
|
||||||
isActive: () => boolean
|
isActive: () => boolean
|
||||||
queryParams: Params
|
filters: Partial<AttributesOnly<VideoFilters>>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
@ -49,7 +50,7 @@ type QuickFilter = {
|
||||||
],
|
],
|
||||||
providers: [ InstanceFollowService ]
|
providers: [ InstanceFollowService ]
|
||||||
})
|
})
|
||||||
export class VideoFiltersHeaderComponent implements OnInit, OnDestroy {
|
export class VideoFiltersHeaderComponent implements OnInit {
|
||||||
@Input() filters: VideoFilters
|
@Input() filters: VideoFilters
|
||||||
@Input() displayModerationBlock = false
|
@Input() displayModerationBlock = false
|
||||||
@Input() hideScope = false
|
@Input() hideScope = false
|
||||||
|
@ -71,15 +72,12 @@ export class VideoFiltersHeaderComponent implements OnInit, OnDestroy {
|
||||||
private videoCategories: VideoConstant<number>[] = []
|
private videoCategories: VideoConstant<number>[] = []
|
||||||
private videoLanguages: VideoConstant<string>[] = []
|
private videoLanguages: VideoConstant<string>[] = []
|
||||||
|
|
||||||
private routeSub: Subscription
|
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
private auth: AuthService,
|
private auth: AuthService,
|
||||||
private serverService: ServerService,
|
private serverService: ServerService,
|
||||||
private fb: FormBuilder,
|
private fb: FormBuilder,
|
||||||
private modalService: PeertubeModalService,
|
private modalService: PeertubeModalService,
|
||||||
private redirectService: RedirectService,
|
private redirectService: RedirectService,
|
||||||
private route: ActivatedRoute,
|
|
||||||
private server: ServerService,
|
private server: ServerService,
|
||||||
private followService: InstanceFollowService
|
private followService: InstanceFollowService
|
||||||
) {
|
) {
|
||||||
|
@ -100,11 +98,6 @@ export class VideoFiltersHeaderComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
this.patchForm(false)
|
this.patchForm(false)
|
||||||
|
|
||||||
this.routeSub = this.route.queryParams.subscribe(query => {
|
|
||||||
this.filters.load(query)
|
|
||||||
this.filtersChanged.emit()
|
|
||||||
})
|
|
||||||
|
|
||||||
this.filters.onChange(() => {
|
this.filters.onChange(() => {
|
||||||
this.patchForm(false)
|
this.patchForm(false)
|
||||||
})
|
})
|
||||||
|
@ -134,10 +127,6 @@ export class VideoFiltersHeaderComponent implements OnInit, OnDestroy {
|
||||||
this.buildQuickFilters()
|
this.buildQuickFilters()
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy () {
|
|
||||||
if (this.routeSub) this.routeSub.unsubscribe()
|
|
||||||
}
|
|
||||||
|
|
||||||
canSeeAllVideos () {
|
canSeeAllVideos () {
|
||||||
if (!this.auth.isLoggedIn()) return false
|
if (!this.auth.isLoggedIn()) return false
|
||||||
if (!this.displayModerationBlock) return false
|
if (!this.displayModerationBlock) return false
|
||||||
|
@ -147,6 +136,13 @@ export class VideoFiltersHeaderComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
onQuickFilter (e: Event, quickFilter: QuickFilter) {
|
||||||
|
e.preventDefault()
|
||||||
|
|
||||||
|
this.filters.load(quickFilter.filters)
|
||||||
|
this.filtersChanged.emit()
|
||||||
|
}
|
||||||
|
|
||||||
private buildQuickFilters () {
|
private buildQuickFilters () {
|
||||||
const trendingSort = this.redirectService.getDefaultTrendingSort()
|
const trendingSort = this.redirectService.getDefaultTrendingSort()
|
||||||
|
|
||||||
|
@ -155,14 +151,14 @@ export class VideoFiltersHeaderComponent implements OnInit, OnDestroy {
|
||||||
label: $localize`Recently added`,
|
label: $localize`Recently added`,
|
||||||
iconName: 'add',
|
iconName: 'add',
|
||||||
isActive: () => this.filters.sort === '-publishedAt',
|
isActive: () => this.filters.sort === '-publishedAt',
|
||||||
queryParams: { sort: '-publishedAt' }
|
filters: { sort: '-publishedAt' }
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
label: $localize`Trending`,
|
label: $localize`Trending`,
|
||||||
iconName: 'trending',
|
iconName: 'trending',
|
||||||
isActive: () => this.filters.sort === trendingSort,
|
isActive: () => this.filters.sort === trendingSort,
|
||||||
queryParams: { sort: trendingSort }
|
filters: { sort: trendingSort }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,8 +50,8 @@
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>Allow JavaScript in your browser</li>
|
<li>Allow JavaScript in your browser</li>
|
||||||
<li>Use one of the <a class="link-orange" href="https://docs.joinpeertube.org/use/third-party-application" target="_blank">third-party applications</a> to browse this instance</li>
|
<li>Use one of the <a class="link-primary" href="https://docs.joinpeertube.org/use/third-party-application" target="_blank">third-party applications</a> to browse this instance</li>
|
||||||
<li>Review the source code on <a class="link-orange" href="https://github.com/Chocobozzz/PeerTube" target="_blank">GitHub</a> or <a class="link-orange" href="https://framagit.org/framasoft/peertube/PeerTube" target="_blank">Framasoft's GitLab</a>, and ask for modifications from the instance owner.
|
<li>Review the source code on <a class="link-primary" href="https://github.com/Chocobozzz/PeerTube" target="_blank">GitHub</a> or <a class="link-primary" href="https://framagit.org/framasoft/peertube/PeerTube" target="_blank">Framasoft's GitLab</a>, and ask for modifications from the instance owner.
|
||||||
</ul>
|
</ul>
|
||||||
</noscript>
|
</noscript>
|
||||||
|
|
||||||
|
@ -62,8 +62,8 @@
|
||||||
<p>We are sorry but it seems that PeerTube is not compatible with your web browser.</p>
|
<p>We are sorry but it seems that PeerTube is not compatible with your web browser.</p>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
<p>Please try with the latest version of <a class="link-orange" href="https://www.mozilla.org" target="_blank">Mozilla Firefox</a>.</p>
|
<p>Please try with the latest version of <a class="link-primary" href="https://www.mozilla.org" target="_blank">Mozilla Firefox</a>.</p>
|
||||||
<p class="mb-0">If you think this is a mistake, please <a class="link-orange" href="https://github.com/Chocobozzz/PeerTube/issues/new" target="_blank">report it</a>.</p>
|
<p class="mb-0">If you think this is a mistake, please <a class="link-primary" href="https://github.com/Chocobozzz/PeerTube/issues/new" target="_blank">report it</a>.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
|
|
@ -83,7 +83,7 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Light theme
|
// Light theme
|
||||||
&[data-pt-theme=peertube-core-light],
|
&[data-pt-theme=peertube-core-light-beige],
|
||||||
&[data-pt-theme=default] {
|
&[data-pt-theme=default] {
|
||||||
--is-dark: 0;
|
--is-dark: 0;
|
||||||
|
|
||||||
|
@ -92,11 +92,15 @@ body {
|
||||||
|
|
||||||
--fg: hsl(0 14% 2%);
|
--fg: hsl(0 14% 2%);
|
||||||
|
|
||||||
--bg: hsl(0 10% 96%);
|
--bg: hsl(250 5% 96%);
|
||||||
--bg-secondary: hsl(0 10% 76%);
|
--bg-secondary: hsl(0 12% 72%);
|
||||||
|
--bg-secondary-500: hsl(0 12% 72%);
|
||||||
|
--bg-secondary-450: hsl(0 13% 81%);
|
||||||
|
--bg-secondary-400: hsl(0 19% 89%);
|
||||||
|
--bg-secondary-350: hsl(0 13% 92%);
|
||||||
|
|
||||||
--secondary-icon-color: #8F7676;
|
--secondary-icon-color: hsl(0, 9%, 51%);
|
||||||
--input-placeholder: #8F7676;
|
--input-placeholder: hsl(0, 9%, 51%);
|
||||||
|
|
||||||
--alert-primary-fg: #{pvar(--on-primary)};
|
--alert-primary-fg: #{pvar(--on-primary)};
|
||||||
--alert-primary-bg: #{pvar(--primary-200)};
|
--alert-primary-bg: #{pvar(--primary-200)};
|
||||||
|
@ -104,7 +108,7 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Brown
|
// Brown
|
||||||
&[data-pt-theme=peertube-core-dark] {
|
&[data-pt-theme=peertube-core-dark-brown] {
|
||||||
--is-dark: 1;
|
--is-dark: 1;
|
||||||
|
|
||||||
--primary: #FD9C50;
|
--primary: #FD9C50;
|
||||||
|
@ -237,8 +241,7 @@ code {
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-open,
|
.modal-open,
|
||||||
.main-col.expanded,
|
.main-col.expanded {
|
||||||
.menu-open {
|
|
||||||
overflow: hidden !important;
|
overflow: hidden !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,6 +267,10 @@ my-global-icon[iconName=external-link] {
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: $menu-overlay-view) {
|
@media screen and (max-width: $menu-overlay-view) {
|
||||||
|
.menu-open {
|
||||||
|
overflow: hidden !important;
|
||||||
|
}
|
||||||
|
|
||||||
.main-col {
|
.main-col {
|
||||||
@include main-col-expanded();
|
@include main-col-expanded();
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,22 @@
|
||||||
@import 'bootstrap/scss/tooltip';
|
@import 'bootstrap/scss/tooltip';
|
||||||
@import 'bootstrap/scss/popover';
|
@import 'bootstrap/scss/popover';
|
||||||
@import 'bootstrap/scss/spinners';
|
@import 'bootstrap/scss/spinners';
|
||||||
@import 'bootstrap/scss/helpers';
|
|
||||||
|
/* stylelint-disable-next-line at-rule-empty-line-before */
|
||||||
|
@import 'bootstrap/scss/helpers/clearfix';
|
||||||
|
@import 'bootstrap/scss/helpers/color-bg';
|
||||||
|
// @import 'bootstrap/scss/helpers/colored-links';
|
||||||
|
@import 'bootstrap/scss/helpers/focus-ring';
|
||||||
|
@import 'bootstrap/scss/helpers/icon-link';
|
||||||
|
@import 'bootstrap/scss/helpers/ratio';
|
||||||
|
@import 'bootstrap/scss/helpers/position';
|
||||||
|
@import 'bootstrap/scss/helpers/stacks';
|
||||||
|
@import 'bootstrap/scss/helpers/visually-hidden';
|
||||||
|
@import 'bootstrap/scss/helpers/stretched-link';
|
||||||
|
@import 'bootstrap/scss/helpers/text-truncation';
|
||||||
|
@import 'bootstrap/scss/helpers/vr';
|
||||||
|
|
||||||
|
/* stylelint-disable-next-line at-rule-empty-line-before */
|
||||||
@import 'bootstrap/scss/utilities/api';
|
@import 'bootstrap/scss/utilities/api';
|
||||||
|
|
||||||
body {
|
body {
|
||||||
|
|
|
@ -68,7 +68,7 @@
|
||||||
border-left-width: 0.25rem;
|
border-left-width: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.callout-orange {
|
&.callout-primary {
|
||||||
border-color: pvar(--primary-100);
|
border-color: pvar(--primary-100);
|
||||||
|
|
||||||
&:not(.callout-light) {
|
&:not(.callout-light) {
|
||||||
|
|
|
@ -65,7 +65,7 @@
|
||||||
font-weight: $font-semibold;
|
font-weight: $font-semibold;
|
||||||
}
|
}
|
||||||
|
|
||||||
.link-orange {
|
.link-primary {
|
||||||
color: pvar(--fg);
|
color: pvar(--fg);
|
||||||
font-weight: $font-semibold;
|
font-weight: $font-semibold;
|
||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
|
|
|
@ -224,8 +224,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&:checked + span {
|
&:checked + span {
|
||||||
border-color: pvar(--fg);
|
background: pvar(--fg-400);
|
||||||
background: pvar(--fg);
|
|
||||||
animation: jelly 0.6s ease;
|
animation: jelly 0.6s ease;
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
|
@ -235,7 +234,7 @@
|
||||||
background: pvar(--primary);
|
background: pvar(--primary);
|
||||||
position: absolute;
|
position: absolute;
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
border: 2px solid pvar(--on-primary);
|
border: 2px solid transparent;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -124,7 +124,7 @@ export interface ServerConfig {
|
||||||
theme: {
|
theme: {
|
||||||
registered: ServerConfigTheme[]
|
registered: ServerConfigTheme[]
|
||||||
|
|
||||||
builtIn: { name: 'peertube-core-light' | 'peertube-core-dark' }[]
|
builtIn: { name: 'peertube-core-light-beige' | 'peertube-core-dark-brown' }[]
|
||||||
|
|
||||||
default: string
|
default: string
|
||||||
}
|
}
|
||||||
|
|
|
@ -374,10 +374,10 @@ class ServerConfigManager {
|
||||||
getBuiltInThemes () {
|
getBuiltInThemes () {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
name: 'peertube-core-dark' as 'peertube-core-dark'
|
name: 'peertube-core-dark-brown' as 'peertube-core-dark-brown'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'peertube-core-light' as 'peertube-core-light'
|
name: 'peertube-core-light-beige' as 'peertube-core-light-beige'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue