diff --git a/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.html b/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.html
index 96629940f..8be8a66cc 100644
--- a/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.html
+++ b/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.html
@@ -15,6 +15,11 @@
+
+
{
this.form.patchValue({
nsfwPolicy: this.user.nsfwPolicy,
+ webTorrentEnabled: this.user.webTorrentEnabled,
autoPlayVideo: this.user.autoPlayVideo === true
})
})
@@ -42,9 +44,11 @@ export class MyAccountVideoSettingsComponent extends FormReactive implements OnI
updateDetails () {
const nsfwPolicy = this.form.value['nsfwPolicy']
+ const webTorrentEnabled = this.form.value['webTorrentEnabled']
const autoPlayVideo = this.form.value['autoPlayVideo']
const details: UserUpdateMe = {
nsfwPolicy,
+ webTorrentEnabled,
autoPlayVideo
}
diff --git a/client/src/app/core/auth/auth-user.model.ts b/client/src/app/core/auth/auth-user.model.ts
index 74ed1c580..acd13d9c5 100644
--- a/client/src/app/core/auth/auth-user.model.ts
+++ b/client/src/app/core/auth/auth-user.model.ts
@@ -72,6 +72,7 @@ export class AuthUser extends User {
EMAIL: 'email',
USERNAME: 'username',
NSFW_POLICY: 'nsfw_policy',
+ WEBTORRENT_ENABLED: 'peertube-videojs-' + 'webtorrent_enabled',
AUTO_PLAY_VIDEO: 'auto_play_video'
}
@@ -87,6 +88,7 @@ export class AuthUser extends User {
email: peertubeLocalStorage.getItem(this.KEYS.EMAIL),
role: parseInt(peertubeLocalStorage.getItem(this.KEYS.ROLE), 10) as UserRole,
nsfwPolicy: peertubeLocalStorage.getItem(this.KEYS.NSFW_POLICY) as NSFWPolicyType,
+ webTorrentEnabled: peertubeLocalStorage.getItem(this.KEYS.WEBTORRENT_ENABLED) === 'true',
autoPlayVideo: peertubeLocalStorage.getItem(this.KEYS.AUTO_PLAY_VIDEO) === 'true'
},
Tokens.load()
@@ -101,6 +103,7 @@ export class AuthUser extends User {
peertubeLocalStorage.removeItem(this.KEYS.ID)
peertubeLocalStorage.removeItem(this.KEYS.ROLE)
peertubeLocalStorage.removeItem(this.KEYS.NSFW_POLICY)
+ peertubeLocalStorage.removeItem(this.KEYS.WEBTORRENT_ENABLED)
peertubeLocalStorage.removeItem(this.KEYS.AUTO_PLAY_VIDEO)
peertubeLocalStorage.removeItem(this.KEYS.EMAIL)
Tokens.flush()
@@ -138,6 +141,7 @@ export class AuthUser extends User {
peertubeLocalStorage.setItem(AuthUser.KEYS.EMAIL, this.email)
peertubeLocalStorage.setItem(AuthUser.KEYS.ROLE, this.role.toString())
peertubeLocalStorage.setItem(AuthUser.KEYS.NSFW_POLICY, this.nsfwPolicy.toString())
+ peertubeLocalStorage.setItem(AuthUser.KEYS.WEBTORRENT_ENABLED, JSON.stringify(this.webTorrentEnabled))
peertubeLocalStorage.setItem(AuthUser.KEYS.AUTO_PLAY_VIDEO, JSON.stringify(this.autoPlayVideo))
this.tokens.save()
}
diff --git a/client/src/app/shared/users/user.model.ts b/client/src/app/shared/users/user.model.ts
index 877f1bf3a..7c840ffa7 100644
--- a/client/src/app/shared/users/user.model.ts
+++ b/client/src/app/shared/users/user.model.ts
@@ -18,6 +18,7 @@ export type UserConstructorHash = {
videoQuota?: number,
videoQuotaDaily?: number,
nsfwPolicy?: NSFWPolicyType,
+ webTorrentEnabled?: boolean,
autoPlayVideo?: boolean,
createdAt?: Date,
account?: AccountServerModel,
@@ -32,6 +33,7 @@ export class User implements UserServerModel {
email: string
role: UserRole
nsfwPolicy: NSFWPolicyType
+ webTorrentEnabled: boolean
autoPlayVideo: boolean
videoQuota: number
videoQuotaDaily: number
@@ -52,6 +54,7 @@ export class User implements UserServerModel {
this.videoQuota = hash.videoQuota
this.videoQuotaDaily = hash.videoQuotaDaily
this.nsfwPolicy = hash.nsfwPolicy
+ this.webTorrentEnabled = hash.webTorrentEnabled
this.autoPlayVideo = hash.autoPlayVideo
this.createdAt = hash.createdAt
this.blocked = hash.blocked
diff --git a/client/src/assets/player/peertube-player-local-storage.ts b/client/src/assets/player/peertube-player-local-storage.ts
index dac54c5a4..3ac5fe58a 100644
--- a/client/src/assets/player/peertube-player-local-storage.ts
+++ b/client/src/assets/player/peertube-player-local-storage.ts
@@ -10,6 +10,13 @@ function getStoredVolume () {
return undefined
}
+function getStoredWebTorrentEnabled (): boolean {
+ const value = getLocalStorage('webtorrent_enabled')
+ if (value !== null && value !== undefined) return value === 'true'
+
+ return false
+}
+
function getStoredMute () {
const value = getLocalStorage('mute')
if (value !== null && value !== undefined) return value === 'true'
@@ -56,6 +63,7 @@ function getAverageBandwidthInStore () {
export {
getStoredVolume,
+ getStoredWebTorrentEnabled,
getStoredMute,
getStoredTheater,
saveVolumeInStore,
diff --git a/client/src/assets/player/peertube-videojs-plugin.ts b/client/src/assets/player/peertube-videojs-plugin.ts
index 2330f476f..5cebab6d9 100644
--- a/client/src/assets/player/peertube-videojs-plugin.ts
+++ b/client/src/assets/player/peertube-videojs-plugin.ts
@@ -11,11 +11,18 @@ import {
getAverageBandwidthInStore,
getStoredMute,
getStoredVolume,
+ getStoredWebTorrentEnabled,
saveAverageBandwidth,
saveMuteInStore,
saveVolumeInStore
} from './peertube-player-local-storage'
+type PlayOptions = {
+ forcePlay?: boolean,
+ seek?: number,
+ delay?: number
+}
+
const Plugin: VideoJSComponentInterface = videojs.getPlugin('plugin')
class PeerTubePlugin extends Plugin {
private readonly playerElement: HTMLVideoElement
@@ -64,6 +71,7 @@ class PeerTubePlugin extends Plugin {
private autoResolution = true
private forbidAutoResolution = false
private isAutoResolutionObservation = false
+ private playerRefusedP2P = false
private videoViewInterval
private torrentInfoInterval
@@ -80,6 +88,7 @@ class PeerTubePlugin extends Plugin {
// Disable auto play on iOS
this.autoplay = options.autoplay && this.isIOS() === false
+ this.playerRefusedP2P = !getStoredWebTorrentEnabled()
this.startTime = timeToInt(options.startTime)
this.videoFiles = options.videoFiles
@@ -178,6 +187,15 @@ class PeerTubePlugin extends Plugin {
const previousVideoFile = this.currentVideoFile
this.currentVideoFile = videoFile
+ // Don't try on iOS that does not support MediaSource
+ // Or don't use P2P if webtorrent is disabled
+ if (this.isIOS() || this.playerRefusedP2P) {
+ return this.fallbackToHttp(options, () => {
+ this.player.playbackRate(oldPlaybackRate)
+ return done()
+ })
+ }
+
this.addTorrent(this.currentVideoFile.magnetUri, previousVideoFile, options, () => {
this.player.playbackRate(oldPlaybackRate)
return done()
@@ -248,11 +266,7 @@ class PeerTubePlugin extends Plugin {
private addTorrent (
magnetOrTorrentUrl: string,
previousVideoFile: VideoFile,
- options: {
- forcePlay?: boolean,
- seek?: number,
- delay?: number
- },
+ options: PlayOptions,
done: Function
) {
console.log('Adding ' + magnetOrTorrentUrl + '.')
@@ -288,7 +302,7 @@ class PeerTubePlugin extends Plugin {
renderVideo(torrent.files[ 0 ], this.playerElement, renderVideoOptions, (err, renderer) => {
this.renderer = renderer
- if (err) return this.fallbackToHttp(done)
+ if (err) return this.fallbackToHttp(options, done)
return this.tryToPlay(err => {
if (err) return done(err)
@@ -296,7 +310,7 @@ class PeerTubePlugin extends Plugin {
if (options.seek) this.seek(options.seek)
if (options.forcePlay === false && paused === true) this.player.pause()
- return done(err)
+ return done()
})
})
}, options.delay || 0)
@@ -432,12 +446,6 @@ class PeerTubePlugin extends Plugin {
return this.updateVideoFile(undefined, { forcePlay: true, seek: this.startTime })
}
- // Don't try on iOS that does not support MediaSource
- if (this.isIOS()) {
- this.currentVideoFile = this.pickAverageVideoFile()
- return this.fallbackToHttp(undefined, false)
- }
-
// Proxy first play
const oldPlay = this.player.play.bind(this.player)
this.player.play = () => {
@@ -567,7 +575,9 @@ class PeerTubePlugin extends Plugin {
return fetch(url, { method: 'PUT', body, headers })
}
- private fallbackToHttp (done?: Function, play = true) {
+ private fallbackToHttp (options: PlayOptions, done?: Function) {
+ const paused = this.player.paused()
+
this.disableAutoResolution(true)
this.flushVideoFile(this.currentVideoFile, true)
@@ -579,9 +589,15 @@ class PeerTubePlugin extends Plugin {
const httpUrl = this.currentVideoFile.fileUrl
this.player.src = this.savePlayerSrcFunction
this.player.src(httpUrl)
- if (play) this.tryToPlay()
- if (done) return done()
+ return this.tryToPlay(err => {
+ if (err && done) return done(err)
+
+ if (options.seek) this.seek(options.seek)
+ if (options.forcePlay === false && paused === true) this.player.pause()
+
+ if (done) return done()
+ })
}
private handleError (err: Error | string) {
diff --git a/server/controllers/api/users/me.ts b/server/controllers/api/users/me.ts
index ebe668110..82299747d 100644
--- a/server/controllers/api/users/me.ts
+++ b/server/controllers/api/users/me.ts
@@ -328,6 +328,7 @@ async function updateMe (req: express.Request, res: express.Response, next: expr
if (body.password !== undefined) user.password = body.password
if (body.email !== undefined) user.email = body.email
if (body.nsfwPolicy !== undefined) user.nsfwPolicy = body.nsfwPolicy
+ if (body.webTorrentEnabled !== undefined) user.webTorrentEnabled = body.webTorrentEnabled
if (body.autoPlayVideo !== undefined) user.autoPlayVideo = body.autoPlayVideo
await sequelizeTypescript.transaction(async t => {
diff --git a/server/helpers/custom-validators/users.ts b/server/helpers/custom-validators/users.ts
index 90fc74a48..1cb5e5b0f 100644
--- a/server/helpers/custom-validators/users.ts
+++ b/server/helpers/custom-validators/users.ts
@@ -42,6 +42,10 @@ function isUserNSFWPolicyValid (value: any) {
return exists(value) && nsfwPolicies.indexOf(value) !== -1
}
+function isUserWebTorrentEnabledValid (value: any) {
+ return isBooleanValid(value)
+}
+
function isUserAutoPlayVideoValid (value: any) {
return isBooleanValid(value)
}
@@ -78,6 +82,7 @@ export {
isUserUsernameValid,
isUserEmailVerifiedValid,
isUserNSFWPolicyValid,
+ isUserWebTorrentEnabledValid,
isUserAutoPlayVideoValid,
isUserDisplayNameValid,
isUserDescriptionValid,
diff --git a/server/initializers/constants.ts b/server/initializers/constants.ts
index cf00da2c7..03158e356 100644
--- a/server/initializers/constants.ts
+++ b/server/initializers/constants.ts
@@ -16,7 +16,7 @@ let config: IConfig = require('config')
// ---------------------------------------------------------------------------
-const LAST_MIGRATION_VERSION = 275
+const LAST_MIGRATION_VERSION = 280
// ---------------------------------------------------------------------------
diff --git a/server/initializers/migrations/0280-webtorrent-policy-user.ts b/server/initializers/migrations/0280-webtorrent-policy-user.ts
new file mode 100644
index 000000000..e6488356a
--- /dev/null
+++ b/server/initializers/migrations/0280-webtorrent-policy-user.ts
@@ -0,0 +1,28 @@
+import * as Sequelize from 'sequelize'
+
+async function up (utils: {
+ transaction: Sequelize.Transaction
+ queryInterface: Sequelize.QueryInterface
+ sequelize: Sequelize.Sequelize
+}): Promise {
+ {
+ const data = {
+ type: Sequelize.BOOLEAN,
+ allowNull: false,
+ defaultValue: true
+ }
+
+ await utils.queryInterface.addColumn('user', 'webTorrentEnabled', data)
+ }
+
+}
+
+async function down (utils: {
+ transaction: Sequelize.Transaction
+ queryInterface: Sequelize.QueryInterface
+ sequelize: Sequelize.Sequelize
+}): Promise {
+ await utils.queryInterface.removeColumn('user', 'webTorrentEnabled')
+}
+
+export { up, down }
diff --git a/server/models/account/user.ts b/server/models/account/user.ts
index 39654cfcf..4b4a562fa 100644
--- a/server/models/account/user.ts
+++ b/server/models/account/user.ts
@@ -31,7 +31,8 @@ import {
isUserRoleValid,
isUserUsernameValid,
isUserVideoQuotaDailyValid,
- isUserVideoQuotaValid
+ isUserVideoQuotaValid,
+ isUserWebTorrentEnabledValid
} from '../../helpers/custom-validators/users'
import { comparePassword, cryptPassword } from '../../helpers/peertube-crypto'
import { OAuthTokenModel } from '../oauth/oauth-token'
@@ -107,6 +108,11 @@ export class UserModel extends Model {
@Column(DataType.ENUM(values(NSFW_POLICY_TYPES)))
nsfwPolicy: NSFWPolicyType
+ @AllowNull(false)
+ @Is('UserWebTorrentEnabled', value => throwIfNotValid(value, isUserWebTorrentEnabledValid, 'WebTorrent enabled'))
+ @Column
+ webTorrentEnabled: boolean
+
@AllowNull(false)
@Default(true)
@Is('UserAutoPlayVideo', value => throwIfNotValid(value, isUserAutoPlayVideoValid, 'auto play video boolean'))
@@ -355,6 +361,7 @@ export class UserModel extends Model {
email: this.email,
emailVerified: this.emailVerified,
nsfwPolicy: this.nsfwPolicy,
+ webTorrentEnabled: this.webTorrentEnabled,
autoPlayVideo: this.autoPlayVideo,
role: this.role,
roleLabel: USER_ROLE_LABELS[ this.role ],
diff --git a/shared/models/users/user-update-me.model.ts b/shared/models/users/user-update-me.model.ts
index bbffe1487..10edeee2e 100644
--- a/shared/models/users/user-update-me.model.ts
+++ b/shared/models/users/user-update-me.model.ts
@@ -3,7 +3,8 @@ import { NSFWPolicyType } from '../videos/nsfw-policy.type'
export interface UserUpdateMe {
displayName?: string
description?: string
- nsfwPolicy?: NSFWPolicyType
+ nsfwPolicy?: NSFWPolicyType,
+ webTorrentEnabled?: boolean,
autoPlayVideo?: boolean
email?: string
currentPassword?: string