Merge branch 'release/v8.1.x' into develop

This commit is contained in:
Chocobozzz
2026-04-10 14:41:43 +02:00
13 changed files with 100 additions and 19 deletions
+13
View File
@@ -1,5 +1,18 @@
# Changelog
## v8.1.5
### IMPORTANT NOTES
* Follow v8.1.0 IMPORTANT NOTES if you upgrade from PeerTube <= v8.0.2
### Bug fixes
* Fix infinite loop when processing some GIF images
* Correctly inject custom admin colors in dark theme
* Fix broken player when loading the page in background
## v8.1.4
### IMPORTANT NOTES
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "peertube-client",
"version": "8.1.4",
"version": "8.1.5",
"private": true,
"license": "AGPL-3.0",
"author": {
@@ -95,7 +95,7 @@
"jschannel": "^1.0.2",
"linkify-html": "^4.3.2",
"linkifyjs": "^4.3.2",
"lodash-es": "^4.17.23",
"lodash-es": "^4.18.1",
"markdown-it": "14.1.1",
"markdown-it-emoji": "^3.0.0",
"ngx-uploadx": "^7.0.1",
@@ -196,7 +196,7 @@ export class AdminConfigCustomizationComponent implements OnInit, OnDestroy, Can
ngOnDestroy () {
if (this.customConfigSub) this.customConfigSub.unsubscribe()
this.themeService.updateColorPalette(this.customConfig.theme)
this.themeService.updateColorPalette({ builtIn: this.serverService.getHTMLConfig().theme.builtIn, ...this.customConfig.theme })
}
canDeactivate () {
@@ -216,6 +216,8 @@ export class AdminConfigCustomizationComponent implements OnInit, OnDestroy, Can
this.themeService.updateColorPalette({
...this.customConfig.theme,
builtIn: this.serverService.getHTMLConfig().theme.builtIn,
customization: this.buildNewCustomization(formValues)
})
})
@@ -321,6 +323,13 @@ export class AdminConfigCustomizationComponent implements OnInit, OnDestroy, Can
return this.availableThemes.find(t => t.id === this.getDefaultThemeName())?.label
}
isUsingDefaultTheme () {
this.themeService.isUsingDefaultTheme({
currentTheme: this.getCurrentThemeName(),
config: this.serverService.getHTMLConfig().theme
})
}
hasDefaultCustomizationValue (field: ThemeCustomizationKey) {
return this.customizationResetFields.has(field)
}
@@ -331,6 +340,8 @@ export class AdminConfigCustomizationComponent implements OnInit, OnDestroy, Can
this.themeService.updateColorPalette({
...this.customConfig.theme,
builtIn: this.serverService.getHTMLConfig().theme.builtIn,
customization: this.buildNewCustomization(this.form.get('theme.customization').value)
})
@@ -118,6 +118,13 @@ export class ThemeService {
return instanceTheme
}
isUsingDefaultTheme (options: {
currentTheme: string
config: Pick<ColorPaletteThemeConfig, 'default' | 'builtIn'>
}) {
return this.themeManager.isUsingDefaultTheme(options)
}
private updateCurrentTheme () {
const currentThemeName = this.getCurrentThemeName()
if (this.oldThemeName === currentThemeName) return
+20 -3
View File
@@ -9,7 +9,7 @@ const debugLogger = debug('peertube:theme')
type ConfigCSSVariableMap = Record<keyof ServerConfig['theme']['customization'], string>
export type ThemeCustomizationKey = keyof ConfigCSSVariableMap
export type ColorPaletteThemeConfig = Pick<HTMLServerConfig['theme'], 'default' | 'customization'>
export type ColorPaletteThemeConfig = Pick<HTMLServerConfig['theme'], 'default' | 'customization' | 'builtIn'>
export class ThemeManager {
private configVariablesStyle: HTMLStyleElement
@@ -54,8 +54,8 @@ export class ThemeManager {
this.configuredCSSVariables.clear()
this.configVariablesStyle.textContent = ''
// Only inject config variables for the default theme
if (currentTheme !== config.default) return
// Only inject config variables for the default theme, otherwise we may override the theme colors with wrong values
if (!this.isUsingDefaultTheme({ currentTheme, config })) return
const computedStyle = getComputedStyle(document.documentElement)
@@ -148,6 +148,23 @@ export class ThemeManager {
this.getHeadElement().removeChild(linkEl)
}
isUsingDefaultTheme (options: {
currentTheme: string
config: Pick<ColorPaletteThemeConfig, 'default' | 'builtIn'>
}) {
const { currentTheme, config } = options
if (currentTheme === config.default) return true
// Only inject config variables for the default theme
if (config.default === 'default') {
// Accept built-in themes
return config.builtIn.some(t => t.name === currentTheme)
}
return false
}
private canInjectCoreColorPalette () {
const computedStyle = getComputedStyle(document.documentElement)
const isDark = computedStyle.getPropertyValue('--is-dark')
+2 -2
View File
@@ -1,7 +1,7 @@
{
"name": "peertube",
"description": "PeerTube, an ActivityPub-federated video streaming platform using P2P directly in your web browser.",
"version": "8.1.4",
"version": "8.1.5",
"private": true,
"licence": "AGPL-3.0",
"engines": {
@@ -162,7 +162,7 @@
"jsonld": "~9.0.0",
"jsonwebtoken": "^9.0.3",
"linkify-it": "^5.0.0",
"lodash-es": "^4.17.23",
"lodash-es": "^4.18.1",
"lru-cache": "^11.2.6",
"magnet-uri": "^7.0.7",
"markdown-it": "^14.1.1",
Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

+36 -3
View File
@@ -1,12 +1,13 @@
/* oxlint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
import { buildAbsoluteFixturePath, root } from '@peertube/peertube-node-utils'
import { execPromise } from '@peertube/peertube-server/core/helpers/core-utils.js'
import { processImage } from '@peertube/peertube-server/core/helpers/image-utils.js'
import { expect } from 'chai'
import { remove } from 'fs-extra/esm'
import { readFile } from 'fs/promises'
import { join } from 'path'
import { buildAbsoluteFixturePath, root } from '@peertube/peertube-node-utils'
import { execPromise } from '@peertube/peertube-server/core/helpers/core-utils.js'
import { processImage } from '@peertube/peertube-server/core/helpers/image-utils.js'
import sharp from 'sharp'
async function checkBuffers (path1: string, path2: string, equals: boolean) {
const [ buf1, buf2 ] = await Promise.all([
@@ -84,6 +85,38 @@ describe('Image helpers', function () {
expect(await hasTitleExif(imageDestPNG)).to.be.false
})
it('Should process animated gif', async function () {
const ext = '.gif'
const input = buildAbsoluteFixturePath(`animated${ext}`)
const dest = join(imageDestDir, `animated${ext}`)
await processImage({ path: input, destination: dest, newSize: thumbnailSize, keepOriginal: true })
const inputBuffer = await readFile(dest)
const sharpInstance = sharp(inputBuffer, { animated: true })
const metadata = await sharpInstance.metadata()
expect(metadata.pages).to.equal(25)
})
it('Should not process animated gif/webp with too many frames', async function () {
const ext = '.gif'
const input = buildAbsoluteFixturePath(`animated-many-frames${ext}`)
const dest = join(imageDestDir, `animated-many-frames${ext}`)
await processImage({ path: input, destination: dest, newSize: thumbnailSize, keepOriginal: true })
const inputBuffer = await readFile(dest)
const sharpInstance = sharp(inputBuffer, { animated: true })
const metadata = await sharpInstance.metadata()
expect(metadata.pages).to.equal(1)
})
after(async function () {
await remove(imageDestDir)
})
+7 -7
View File
@@ -246,8 +246,8 @@ importers:
specifier: ^5.0.0
version: 5.0.0
lodash-es:
specifier: ^4.17.23
version: 4.17.23
specifier: ^4.18.1
version: 4.18.1
lru-cache:
specifier: ^11.2.6
version: 11.2.6
@@ -779,8 +779,8 @@ importers:
specifier: ^4.3.2
version: 4.3.2
lodash-es:
specifier: ^4.17.23
version: 4.17.23
specifier: ^4.18.1
version: 4.18.1
markdown-it:
specifier: 14.1.1
version: 14.1.1
@@ -8017,8 +8017,8 @@ packages:
resolution: {integrity: sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
lodash-es@4.17.23:
resolution: {integrity: sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg==}
lodash-es@4.18.1:
resolution: {integrity: sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==}
lodash.camelcase@4.3.0:
resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==}
@@ -19983,7 +19983,7 @@ snapshots:
dependencies:
p-locate: 6.0.0
lodash-es@4.17.23: {}
lodash-es@4.18.1: {}
lodash.camelcase@4.3.0: {}
+1 -1
View File
@@ -80,7 +80,7 @@ async function sharpProcessor (options: {
const metadata = await sharpInstance.metadata()
if (metadata.pages > 200) {
if (animated && metadata.pages > 200) {
logger.info('Too much frames in animated image ' + path + ', skipping animation')
return sharpProcessor({ ...options, animated: false })