Merge branch 'release/2.1.0'
This commit is contained in:
commit
16ec5e0833
15
CHANGELOG.md
15
CHANGELOG.md
|
@ -1,5 +1,20 @@
|
|||
# Changelog
|
||||
|
||||
## v2.1.1
|
||||
|
||||
### Bug fixes
|
||||
|
||||
* Fix youtube-dl in docker image
|
||||
* Fix playlist creation/update
|
||||
* Fix fetch of instance config in client
|
||||
* Manual approves followers only for the instance (and not accounts/channels)
|
||||
* Fix avatar update
|
||||
* Fix CSP for embeds
|
||||
* Fix scroll of the menu on mobile
|
||||
* Fix CPU usage of PostgreSQL
|
||||
* Fix embed for iOS
|
||||
|
||||
|
||||
## v2.1.0
|
||||
|
||||
**Since v2.0.0**
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "peertube-client",
|
||||
"version": "2.1.0",
|
||||
"version": "2.1.1",
|
||||
"private": true,
|
||||
"license": "AGPL-3.0",
|
||||
"author": {
|
||||
|
|
|
@ -159,8 +159,11 @@ export class ServerService {
|
|||
if (!this.configObservable) {
|
||||
this.configObservable = this.http.get<ServerConfig>(ServerService.BASE_CONFIG_URL)
|
||||
.pipe(
|
||||
tap(this.saveConfigLocally),
|
||||
tap(() => this.configLoaded = true),
|
||||
tap(config => this.saveConfigLocally(config)),
|
||||
tap(config => {
|
||||
this.config = config
|
||||
this.configLoaded = true
|
||||
}),
|
||||
tap(() => {
|
||||
if (this.configReset) {
|
||||
this.configReloaded.next()
|
||||
|
|
|
@ -254,6 +254,10 @@ menu {
|
|||
@media screen and (max-width: $mobile-view) {
|
||||
.menu-wrapper {
|
||||
width: 100% !important;
|
||||
|
||||
menu {
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.top-menu, .footer {
|
||||
|
|
|
@ -141,6 +141,8 @@ export class VideoPlaylistService {
|
|||
return this.authHttp.post<{ videoPlaylist: { id: number } }>(VideoPlaylistService.BASE_VIDEO_PLAYLIST_URL, data)
|
||||
.pipe(
|
||||
tap(res => {
|
||||
if (!this.myAccountPlaylistCache) return
|
||||
|
||||
this.myAccountPlaylistCache.total++
|
||||
|
||||
this.myAccountPlaylistCache.data.push({
|
||||
|
@ -161,6 +163,8 @@ export class VideoPlaylistService {
|
|||
.pipe(
|
||||
map(this.restExtractor.extractDataBool),
|
||||
tap(() => {
|
||||
if (!this.myAccountPlaylistCache) return
|
||||
|
||||
const playlist = this.myAccountPlaylistCache.data.find(p => p.id === videoPlaylist.id)
|
||||
playlist.displayName = body.displayName
|
||||
|
||||
|
@ -175,6 +179,8 @@ export class VideoPlaylistService {
|
|||
.pipe(
|
||||
map(this.restExtractor.extractDataBool),
|
||||
tap(() => {
|
||||
if (!this.myAccountPlaylistCache) return
|
||||
|
||||
this.myAccountPlaylistCache.total--
|
||||
this.myAccountPlaylistCache.data = this.myAccountPlaylistCache.data
|
||||
.filter(p => p.id !== videoPlaylist.id)
|
||||
|
|
|
@ -262,6 +262,9 @@ export class PeerTubeEmbed {
|
|||
|
||||
private async buildDock (videoInfo: VideoDetails, configResponse: Response) {
|
||||
if (this.controls) {
|
||||
// On webtorrent fallback, player may have been disposed
|
||||
if (!this.player.player_) return
|
||||
|
||||
const title = this.title ? videoInfo.name : undefined
|
||||
|
||||
const config: ServerConfig = await configResponse.json()
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "peertube",
|
||||
"description": "Federated (ActivityPub) video streaming platform using P2P (BitTorrent) directly in the web browser with WebTorrent and Angular.",
|
||||
"version": "2.1.0",
|
||||
"version": "2.1.1",
|
||||
"private": true,
|
||||
"licence": "AGPL-3.0",
|
||||
"engines": {
|
||||
|
|
|
@ -2,10 +2,11 @@ import * as express from 'express'
|
|||
import { join } from 'path'
|
||||
import { root } from '../helpers/core-utils'
|
||||
import { ACCEPT_HEADERS, STATIC_MAX_AGE } from '../initializers/constants'
|
||||
import { asyncMiddleware } from '../middlewares'
|
||||
import { asyncMiddleware, embedCSP } from '../middlewares'
|
||||
import { buildFileLocale, getCompleteLocale, is18nLocale, LOCALE_FILES } from '../../shared/models/i18n/i18n'
|
||||
import { ClientHtml } from '../lib/client-html'
|
||||
import { logger } from '../helpers/logger'
|
||||
import { CONFIG } from '@server/initializers/config'
|
||||
|
||||
const clientsRouter = express.Router()
|
||||
|
||||
|
@ -19,8 +20,13 @@ clientsRouter.use('/videos/watch/:id', asyncMiddleware(generateWatchHtmlPage))
|
|||
clientsRouter.use('/accounts/:nameWithHost', asyncMiddleware(generateAccountHtmlPage))
|
||||
clientsRouter.use('/video-channels/:nameWithHost', asyncMiddleware(generateVideoChannelHtmlPage))
|
||||
|
||||
const embedCSPMiddleware = CONFIG.CSP.ENABLED
|
||||
? embedCSP
|
||||
: (req: express.Request, res: express.Response, next: express.NextFunction) => next()
|
||||
|
||||
clientsRouter.use(
|
||||
'/videos/embed',
|
||||
embedCSPMiddleware,
|
||||
(req: express.Request, res: express.Response) => {
|
||||
res.removeHeader('X-Frame-Options')
|
||||
res.sendFile(embedPath)
|
||||
|
|
|
@ -176,8 +176,8 @@ async function updateActorAvatarInstance (actor: MActorDefault, info: AvatarInfo
|
|||
if (!info.name) return actor
|
||||
|
||||
if (actor.Avatar) {
|
||||
// Don't update the avatar if the filename did not change
|
||||
if (actor.Avatar.fileUrl === info.fileUrl) return actor
|
||||
// Don't update the avatar if the file URL did not change
|
||||
if (info.fileUrl && actor.Avatar.fileUrl === info.fileUrl) return actor
|
||||
|
||||
try {
|
||||
await actor.Avatar.destroy({ transaction: t })
|
||||
|
|
|
@ -59,7 +59,9 @@ async function processFollow (byActor: MActorSignature, targetActorURL: string)
|
|||
transaction: t
|
||||
})
|
||||
|
||||
if (actorFollow.state !== 'accepted' && CONFIG.FOLLOWERS.INSTANCE.MANUAL_APPROVAL === false) {
|
||||
// Set the follow as accepted if the remote actor follows a channel or account
|
||||
// Or if the instance automatically accepts followers
|
||||
if (actorFollow.state !== 'accepted' && (isFollowingInstance === false || CONFIG.FOLLOWERS.INSTANCE.MANUAL_APPROVAL === false)) {
|
||||
actorFollow.state = 'accepted'
|
||||
await actorFollow.save({ transaction: t })
|
||||
}
|
||||
|
|
|
@ -136,8 +136,7 @@ import {
|
|||
MVideoThumbnailBlacklist,
|
||||
MVideoWithAllFiles,
|
||||
MVideoWithFile,
|
||||
MVideoWithRights,
|
||||
MStreamingPlaylistFiles
|
||||
MVideoWithRights
|
||||
} from '../../typings/models'
|
||||
import { MVideoFile, MVideoFileStreamingPlaylistVideo } from '../../typings/models/video/video-file'
|
||||
import { MThumbnail } from '../../typings/models/video/thumbnail'
|
||||
|
@ -437,42 +436,31 @@ export type AvailableForListIDsOptions = {
|
|||
}
|
||||
|
||||
if (options.followerActorId) {
|
||||
let localVideosReq: WhereOptions = {}
|
||||
let localVideosReq = ''
|
||||
if (options.includeLocalVideos === true) {
|
||||
localVideosReq = { remote: false }
|
||||
localVideosReq = ' UNION ALL SELECT "video"."id" FROM "video" WHERE remote IS FALSE'
|
||||
}
|
||||
|
||||
// Force actorId to be a number to avoid SQL injections
|
||||
const actorIdNumber = parseInt(options.followerActorId.toString(), 10)
|
||||
whereAnd.push({
|
||||
[Op.or]: [
|
||||
{
|
||||
id: {
|
||||
[ Op.in ]: Sequelize.literal(
|
||||
'(' +
|
||||
'SELECT "videoShare"."videoId" AS "id" FROM "videoShare" ' +
|
||||
'INNER JOIN "actorFollow" ON "actorFollow"."targetActorId" = "videoShare"."actorId" ' +
|
||||
'WHERE "actorFollow"."actorId" = ' + actorIdNumber +
|
||||
')'
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
id: {
|
||||
[ Op.in ]: Sequelize.literal(
|
||||
'(' +
|
||||
'SELECT "video"."id" AS "id" FROM "video" ' +
|
||||
'INNER JOIN "videoChannel" ON "videoChannel"."id" = "video"."channelId" ' +
|
||||
'INNER JOIN "account" ON "account"."id" = "videoChannel"."accountId" ' +
|
||||
'INNER JOIN "actor" ON "account"."actorId" = "actor"."id" ' +
|
||||
'INNER JOIN "actorFollow" ON "actorFollow"."targetActorId" = "actor"."id" ' +
|
||||
'WHERE "actorFollow"."actorId" = ' + actorIdNumber +
|
||||
')'
|
||||
)
|
||||
}
|
||||
},
|
||||
localVideosReq
|
||||
]
|
||||
id: {
|
||||
[Op.in]: Sequelize.literal(
|
||||
'(' +
|
||||
'SELECT "videoShare"."videoId" AS "id" FROM "videoShare" ' +
|
||||
'INNER JOIN "actorFollow" ON "actorFollow"."targetActorId" = "videoShare"."actorId" ' +
|
||||
'WHERE "actorFollow"."actorId" = ' + actorIdNumber +
|
||||
' UNION ALL ' +
|
||||
'SELECT "video"."id" AS "id" FROM "video" ' +
|
||||
'INNER JOIN "videoChannel" ON "videoChannel"."id" = "video"."channelId" ' +
|
||||
'INNER JOIN "account" ON "account"."id" = "videoChannel"."accountId" ' +
|
||||
'INNER JOIN "actor" ON "account"."actorId" = "actor"."id" ' +
|
||||
'INNER JOIN "actorFollow" ON "actorFollow"."targetActorId" = "actor"."id" ' +
|
||||
'WHERE "actorFollow"."actorId" = ' + actorIdNumber +
|
||||
localVideosReq +
|
||||
')'
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
openapi: 3.0.0
|
||||
info:
|
||||
title: PeerTube
|
||||
version: 2.1.0
|
||||
version: 2.1.1
|
||||
contact:
|
||||
name: PeerTube Community
|
||||
url: 'https://joinpeertube.org'
|
||||
|
|
|
@ -7,7 +7,7 @@ ARG NPM_RUN_BUILD_OPTS
|
|||
|
||||
# Install dependencies
|
||||
RUN apt update \
|
||||
&& apt install -y --no-install-recommends openssl ffmpeg gnupg gosu \
|
||||
&& apt install -y --no-install-recommends openssl ffmpeg python ca-certificates gnupg gosu \
|
||||
&& gosu nobody true \
|
||||
&& rm /var/lib/apt/lists/* -fR
|
||||
|
||||
|
|
Loading…
Reference in New Issue