Correct colors

Chocobozzz 2024-11-22 11:34:58 +01:00
parent 5ce1470b9e
commit c3aaee5dff
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
34 changed files with 193 additions and 160 deletions

View File

@ -11,12 +11,12 @@
</p>
<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>.
</p>
<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>
</div>
@ -25,7 +25,7 @@
<div class="card">
<div class="card-body">
<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 i18n class="card-text">
@ -37,7 +37,7 @@
<div class="card">
<div class="card-body">
<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 i18n class="card-text">
@ -49,7 +49,7 @@
<div class="card">
<div class="card-body">
<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 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.
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.
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>
</ul>

View File

@ -47,7 +47,7 @@
></my-video-miniature>
<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>

View File

@ -4,7 +4,7 @@
<h2 i18n>APPEARANCE</h2>
<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>
@ -14,13 +14,7 @@
<div class="form-group">
<label i18n for="themeDefault">Theme</label>
<div class="peertube-select-container">
<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>
<my-select-options formControlName="default" inputId="themeDefault" [items]="availableThemes"></my-select-options>
</div>
</ng-container>
@ -151,7 +145,7 @@
<div class="title-col">
<h2 i18n>NEW USERS</h2>
<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>
@ -296,7 +290,7 @@
i18n-labelText labelText="Allow import with HTTP URL (e.g. YouTube)"
>
<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>
</my-peertube-checkbox>
</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>
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>
</ng-container>
@ -595,7 +589,7 @@
<div class="title-col">
<h2 i18n>FEDERATION</h2>
<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>
@ -646,7 +640,7 @@
<div i18n>⚠️ This functionality requires a lot of attention and extra moderation.</div>
<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>
</ng-container>

View File

@ -2,7 +2,7 @@ import { NgClass, NgFor, NgIf } from '@angular/common'
import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core'
import { FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms'
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 { HTMLServerConfig } from '@peertube/peertube-models'
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 { SelectOptionsComponent } from '../../../shared/shared-forms/select/select-options.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 { ConfigService } from '../shared/config.service'
@ -34,7 +33,6 @@ import { ConfigService } from '../shared/config.service'
NgClass,
UserRealQuotaInfoComponent,
SelectOptionsComponent,
PeerTubeTemplateDirective,
AlertComponent
]
})
@ -53,7 +51,6 @@ export class EditBasicConfigurationComponent implements OnInit, OnChanges {
constructor (
private configService: ConfigService,
private menuService: MenuService,
private themeService: ThemeService
) {}
@ -62,7 +59,11 @@ export class EditBasicConfigurationComponent implements OnInit, OnChanges {
this.checkSignupField()
this.checkImportSyncField()
this.availableThemes = this.themeService.buildAvailableThemes()
this.availableThemes = [
this.themeService.getDefaultThemeItem(),
...this.themeService.buildAvailableThemes()
]
this.exportExpirationOptions = [
{ 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 () {
const importSyncControl = this.form.get('import.videoChannelSynchronization.enabled')
const importVideosHttpControl = this.form.get('import.videos.http.enabled')

View File

@ -106,7 +106,7 @@
<div class="title-col">
<h2 i18n>MODERATION & NSFW</h2>
<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>

View File

@ -4,7 +4,7 @@
<div class="title-col"></div>
<div class="content-col">
<div class="callout callout-orange">
<div class="callout callout-primary">
<span i18n>
Estimating a server's capacity to transcode and stream videos isn't easy and we can't tune PeerTube automatically.
</span>
@ -12,7 +12,7 @@
<br />
<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>
</div>
</div>

View File

@ -22,25 +22,25 @@
@if (signupAllowed) {
<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.
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>.
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-primary" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">https://joinpeertube.org/instances</a>.
</p>
} @else {
<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.
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>.
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-primary" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">https://joinpeertube.org/instances</a>.
</p>
}
</my-alert>
<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 *ngIf="error" type="danger">
{{ 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
</a>
</my-alert>
@ -90,13 +90,13 @@
<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">
<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
</button>
<ng-container *ngIf="signupAllowed">
<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>
</div>
</form>

View File

@ -31,7 +31,7 @@
<p i18n>You can already follow {{ instanceName }} using your favorite tool.</p>
</div>
<div class="callout callout-orange callout-light">
<div class="callout callout-primary callout-light">
<div class="mascot-container" style="min-width: 140px">
<img class="mascot" width="140px" height="160px" src="/client/assets/images/mascot/happy.svg" alt="mascot"/>
</div>
@ -40,8 +40,8 @@
<h4 i18>This website is a GAFAM alternative</h4>
<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.
<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
{{ 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-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>
</div>
</div>

View File

@ -16,8 +16,8 @@
<ng-template ptTemplate="label">
<ng-container i18n>
I am at least {{ minimumAge }} years old and agree
to the <a class="link-orange" (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>
to the <a class="link-primary" (click)="onTermsClick($event)" href='#'>Terms</a>
<ng-container *ngIf="hasCodeOfConduct"> and to the <a class="link-primary" (click)="onCodeOfConductClick($event)" href='#'>Code of Conduct</a></ng-container>
of {{ instanceName }}
</ng-container>
</ng-template>

View File

@ -12,7 +12,7 @@
<my-alert type="danger" *ngIf="failed">
<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
</a>
</my-alert>

View File

@ -15,7 +15,7 @@
<p i18n>Your email has been verified and your account has been created!</p>
<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>
</ng-container>
</my-alert>

View File

@ -29,7 +29,7 @@
</p>
<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>
</ng-container>
</my-alert>

View File

@ -49,7 +49,7 @@
View account
</a>
<a class="view-account link-orange complete" [routerLink]="getAccountUrl()" i18n>
<a class="view-account link-primary complete" [routerLink]="getAccountUrl()" i18n>
View owner account
</a>
</div>

View File

@ -7,7 +7,7 @@
</ng-container>
</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>
<button i18n class="ms-2 peertube-button primary-button" (click)="acceptedPrivacyConcern()">

View File

@ -19,7 +19,7 @@
<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>
<button

View File

@ -42,8 +42,7 @@
.broadcast-message {
min-height: 50px;
text-align: center;
margin-bottom: 0;
border-radius: 0;
margin-bottom: 2rem;
display: grid;
grid-template-columns: 1fr 30px;
column-gap: 10px;
@ -55,7 +54,7 @@
margin: auto;
> my-global-icon {
width: 20px;
@include global-icon-size(20px);
}
}
}

View File

@ -39,6 +39,7 @@ import { MenuComponent } from './menu/menu.component'
import { ConfirmComponent } from './modal/confirm.component'
import { GlobalIconComponent, GlobalIconName } from './shared/shared-icons/global-icon.component'
import { InstanceService } from './shared/shared-main/instance/instance.service'
import { ButtonComponent } from './shared/shared-main/buttons/button.component'
@Component({
selector: 'my-app',
@ -61,11 +62,12 @@ import { InstanceService } from './shared/shared-main/instance/instance.service'
AccountSetupWarningModalComponent,
AdminWelcomeModalComponent,
InstanceConfigWarningModalComponent,
CustomModalComponent
CustomModalComponent,
ButtonComponent
]
})
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('adminWelcomeModal') adminWelcomeModal: AdminWelcomeModalComponent
@ -159,7 +161,7 @@ export class AppComponent implements OnInit, AfterViewInit {
}
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.screenService.isBroadcastMessageDisplayed = false
@ -214,7 +216,7 @@ export class AppComponent implements OnInit, AfterViewInit {
if (messageConfig.enabled) {
// 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
}

View File

@ -1,5 +1,5 @@
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 { capitalizeFirstLetter } from '@root-helpers/string'
import { UserLocalStorageKeys } from '@root-helpers/users'
@ -11,6 +11,8 @@ import { PluginService } from '../plugins/plugin.service'
import { ServerService } from '../server'
import { UserService } from '../users/user.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')
@ -50,29 +52,29 @@ export class ThemeService {
this.listenUserTheme()
}
getDefaultThemeLabel () {
if (this.hasDarkTheme()) {
return $localize`Light (Orange) or Dark (Brown)`
getDefaultThemeItem () {
return {
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 () {
return [
...this.serverConfig.theme.registered.map(t => ({ id: t.name, label: capitalizeFirstLetter(t.name) })),
...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)` }
}
if (t.name === 'peertube-core-light') {
return { id: t.name, label: $localize`Light (Orange)` }
if (t.name === 'peertube-core-light-beige') {
return { id: t.name, label: $localize`Light (Beige)` }
}
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
// Default to dark theme if available and wanted by the user
if (this.hasDarkTheme() && window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
return 'dark'
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
return 'peertube-core-dark-brown' satisfies ServerConfig['theme']['builtIn'][0]['name']
}
return instanceTheme
@ -164,7 +166,7 @@ export class ThemeService {
this.localStorageService.removeItem(UserLocalStorageKeys.LAST_ACTIVE_THEME, false)
}
this.injectColorPalette()
setTimeout(() => this.injectColorPalette(), 0)
this.oldThemeName = currentTheme
}
@ -187,6 +189,9 @@ export class ThemeService {
]
const darkTheme = this.isDarkTheme(computedStyle)
if (darkTheme) {
debugLogger('Detected dark theme')
}
for (const { prefix, invertIfDark, fallbacks = {} } of toProcess) {
const mainColor = computedStyle.getPropertyValue('--' + prefix)
@ -200,28 +205,46 @@ export class ThemeService {
continue
}
const mainColorParsed = parse(mainColor)
const mainColorHSL = toHSLA(mainColorParsed)
const mainColorHSL = toHSLA(parse(mainColor))
for (let i = -9; i <= 9; i++) {
const suffix = 500 + (50 * i)
const key = `--${prefix}-${suffix}`
let lastColorHSL = { ...mainColorHSL }
const existingValue = computedStyle.getPropertyValue(key)
if (!existingValue || existingValue === '0') {
const newLuminance = Math.max(Math.min(100, Math.round(mainColorHSL.l + (i * 5 * -1 * darkInverter))), 0)
const newColor = `hsl(${Math.round(mainColorHSL.h)} ${Math.round(mainColorHSL.s)}% ${newLuminance}% / ${mainColorHSL.a})`
// Inject in alphabetical order for easy debug
const toInject: { id: number, key: string, value: string }[] = [
{ id: 500, key: `--${prefix}-500`, value: this.toHSLStr(mainColorHSL) }
]
const value = fallbacks[key]
? `var(${fallbacks[key]}, ${newColor})`
: newColor
for (const j of [ -1, 1 ]) {
for (let i = 1; i <= 9; i++) {
const suffix = 500 + (50 * i * j)
const key = `--${prefix}-${suffix}`
rootStyle.setProperty(key, value)
this.oldInjectedProperties.push(key)
const existingValue = computedStyle.getPropertyValue(key)
if (!existingValue || existingValue === '0') {
const newLuminance = this.buildNewLuminance(lastColorHSL, j, darkInverter)
const newColorHSL = { ...lastColorHSL, l: newLuminance }
debugLogger(`Injected theme palette ${key} -> ${value}`)
const newColorStr = this.toHSLStr(newColorHSL)
const value = fallbacks[key]
? `var(${fallbacks[key]}, ${newColorStr})`
: newColorStr
toInject.push({ id: suffix, key, value })
lastColorHSL = newColorHSL
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
@ -229,6 +252,14 @@ export class ThemeService {
: ''
}
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) {
const deprecatedFG = computedStyle.getPropertyValue('--mainForegroundColor')
const deprecatedBG = computedStyle.getPropertyValue('--mainBackgroundColor')
@ -318,8 +349,4 @@ export class ThemeService {
private getTheme (name: string) {
return this.themes.find(t => t.name === name)
}
private hasDarkTheme () {
return this.serverConfig.theme.registered.some(t => t.name === 'dark')
}
}

View File

@ -46,7 +46,6 @@
background-repeat: no-repeat;
background-size: contain;
@include margin-left(18px);
@include margin-right(10px);
}

View File

@ -25,7 +25,7 @@ input {
left: 3px;
width: 14px;
height: 14px;
background: pvar(--bg);
background: pvar(--on-primary);
border-radius: 50%;
transition: 0.3s ease-out;
}
@ -36,7 +36,7 @@ input {
}
&:checked + label {
background: pvar(--border-primary);
background: pvar(--primary);
&::after {
left: calc(100% - 3px);
@ -45,6 +45,6 @@ input {
}
&:focus-visible + label {
outline: 2px solid;
box-shadow: $focus-box-shadow-form;
}
}

View File

@ -3,14 +3,7 @@
<div class="form-group">
<label i18n for="theme">Theme</label>
<div class="peertube-select-container">
<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>
<my-select-options inputId="theme" formControlName="theme" [items]="availableThemes"></my-select-options>
</div>
<input *ngIf="!reactiveUpdate" type="submit" class="peertube-button primary-button" i18n-value value="Save interface settings" [disabled]="!form.valid">

View File

@ -7,13 +7,14 @@ import { HTMLServerConfig, User, UserUpdateMe } from '@peertube/peertube-models'
import { SelectOptionsItem } from 'src/types'
import { NgFor, NgIf } from '@angular/common'
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
import { SelectOptionsComponent } from '../shared-forms/select/select-options.component'
@Component({
selector: 'my-user-interface-settings',
templateUrl: './user-interface-settings.component.html',
styleUrls: [ './user-interface-settings.component.scss' ],
standalone: true,
imports: [ FormsModule, ReactiveFormsModule, NgFor, NgIf ]
imports: [ FormsModule, ReactiveFormsModule, NgFor, NgIf, SelectOptionsComponent ]
})
export class UserInterfaceSettingsComponent extends FormReactive implements OnInit, OnDestroy {
@Input() user: User
@ -44,7 +45,13 @@ export class UserInterfaceSettingsComponent extends FormReactive implements OnIn
ngOnInit () {
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({
theme: null
@ -66,20 +73,6 @@ export class UserInterfaceSettingsComponent extends FormReactive implements OnIn
this.formValuesWatcher?.unsubscribe()
}
getDefaultThemeLabel () {
return this.themeService.getDefaultThemeLabel()
}
getDefaultInstanceThemeLabel () {
const theme = this.serverConfig.theme.default
if (theme === 'default') {
return this.getDefaultThemeLabel()
}
return theme
}
updateInterfaceSettings () {
const theme = this.form.value['theme']
@ -105,4 +98,15 @@ export class UserInterfaceSettingsComponent extends FormReactive implements OnIn
this.userService.updateMyAnonymousProfile(details)
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
}
}

View File

@ -42,7 +42,7 @@
i18n-labelText labelText="Help share videos being played"
>
<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>
</my-peertube-checkbox>
</div>

View File

@ -1,4 +1,4 @@
<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.
</p>

View File

@ -15,7 +15,8 @@
@for (quickFilter of quickFilters; track quickFilter) {
<my-button
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>
}
</div>

View File

@ -18,6 +18,7 @@ import { ButtonComponent } from '../shared-main/buttons/button.component'
import { PeertubeModalService } from '../shared-main/peertube-modal/peertube-modal.service'
import { VideoFilterActive, VideoFilters } from './video-filters.model'
import { InstanceFollowService } from '../shared-instance/instance-follow.service'
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
const debugLogger = debug('peertube:videos:VideoFiltersHeaderComponent')
@ -25,7 +26,7 @@ type QuickFilter = {
iconName: GlobalIconName
label: string
isActive: () => boolean
queryParams: Params
filters: Partial<AttributesOnly<VideoFilters>>
}
@Component({
@ -49,7 +50,7 @@ type QuickFilter = {
],
providers: [ InstanceFollowService ]
})
export class VideoFiltersHeaderComponent implements OnInit, OnDestroy {
export class VideoFiltersHeaderComponent implements OnInit {
@Input() filters: VideoFilters
@Input() displayModerationBlock = false
@Input() hideScope = false
@ -71,15 +72,12 @@ export class VideoFiltersHeaderComponent implements OnInit, OnDestroy {
private videoCategories: VideoConstant<number>[] = []
private videoLanguages: VideoConstant<string>[] = []
private routeSub: Subscription
constructor (
private auth: AuthService,
private serverService: ServerService,
private fb: FormBuilder,
private modalService: PeertubeModalService,
private redirectService: RedirectService,
private route: ActivatedRoute,
private server: ServerService,
private followService: InstanceFollowService
) {
@ -100,11 +98,6 @@ export class VideoFiltersHeaderComponent implements OnInit, OnDestroy {
this.patchForm(false)
this.routeSub = this.route.queryParams.subscribe(query => {
this.filters.load(query)
this.filtersChanged.emit()
})
this.filters.onChange(() => {
this.patchForm(false)
})
@ -134,10 +127,6 @@ export class VideoFiltersHeaderComponent implements OnInit, OnDestroy {
this.buildQuickFilters()
}
ngOnDestroy () {
if (this.routeSub) this.routeSub.unsubscribe()
}
canSeeAllVideos () {
if (!this.auth.isLoggedIn()) 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 () {
const trendingSort = this.redirectService.getDefaultTrendingSort()
@ -155,14 +151,14 @@ export class VideoFiltersHeaderComponent implements OnInit, OnDestroy {
label: $localize`Recently added`,
iconName: 'add',
isActive: () => this.filters.sort === '-publishedAt',
queryParams: { sort: '-publishedAt' }
filters: { sort: '-publishedAt' }
},
{
label: $localize`Trending`,
iconName: 'trending',
isActive: () => this.filters.sort === trendingSort,
queryParams: { sort: trendingSort }
filters: { sort: trendingSort }
}
]
}

View File

@ -50,8 +50,8 @@
<ul>
<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>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>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-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>
</noscript>
@ -62,8 +62,8 @@
<p>We are sorry but it seems that PeerTube is not compatible with your web browser.</p>
<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 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>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-primary" href="https://github.com/Chocobozzz/PeerTube/issues/new" target="_blank">report it</a>.</p>
</div>
<script type="text/javascript">

View File

@ -83,7 +83,7 @@ body {
}
// Light theme
&[data-pt-theme=peertube-core-light],
&[data-pt-theme=peertube-core-light-beige],
&[data-pt-theme=default] {
--is-dark: 0;
@ -92,11 +92,15 @@ body {
--fg: hsl(0 14% 2%);
--bg: hsl(0 10% 96%);
--bg-secondary: hsl(0 10% 76%);
--bg: hsl(250 5% 96%);
--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;
--input-placeholder: #8F7676;
--secondary-icon-color: hsl(0, 9%, 51%);
--input-placeholder: hsl(0, 9%, 51%);
--alert-primary-fg: #{pvar(--on-primary)};
--alert-primary-bg: #{pvar(--primary-200)};
@ -104,7 +108,7 @@ body {
}
// Brown
&[data-pt-theme=peertube-core-dark] {
&[data-pt-theme=peertube-core-dark-brown] {
--is-dark: 1;
--primary: #FD9C50;
@ -237,8 +241,7 @@ code {
}
.modal-open,
.main-col.expanded,
.menu-open {
.main-col.expanded {
overflow: hidden !important;
}
@ -264,6 +267,10 @@ my-global-icon[iconName=external-link] {
}
@media screen and (max-width: $menu-overlay-view) {
.menu-open {
overflow: hidden !important;
}
.main-col {
@include main-col-expanded();
}

View File

@ -25,7 +25,22 @@
@import 'bootstrap/scss/tooltip';
@import 'bootstrap/scss/popover';
@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';
body {

View File

@ -68,7 +68,7 @@
border-left-width: 0.25rem;
}
&.callout-orange {
&.callout-primary {
border-color: pvar(--primary-100);
&:not(.callout-light) {

View File

@ -65,7 +65,7 @@
font-weight: $font-semibold;
}
.link-orange {
.link-primary {
color: pvar(--fg);
font-weight: $font-semibold;
line-height: 1.1;

View File

@ -224,8 +224,7 @@
}
&:checked + span {
border-color: pvar(--fg);
background: pvar(--fg);
background: pvar(--fg-400);
animation: jelly 0.6s ease;
&::before {
@ -235,7 +234,7 @@
background: pvar(--primary);
position: absolute;
transition: all 0.2s ease;
border: 2px solid pvar(--on-primary);
border: 2px solid transparent;
border-radius: 2px;
}

View File

@ -124,7 +124,7 @@ export interface ServerConfig {
theme: {
registered: ServerConfigTheme[]
builtIn: { name: 'peertube-core-light' | 'peertube-core-dark' }[]
builtIn: { name: 'peertube-core-light-beige' | 'peertube-core-dark-brown' }[]
default: string
}

View File

@ -374,10 +374,10 @@ class ServerConfigManager {
getBuiltInThemes () {
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'
}
]
}