import { VideoBlockService } from '@app/shared/shared-moderation'
import { I18n } from '@ngx-translate/i18n-polyfill'
import { VideoBlacklist, VideoBlacklistType } from '@shared/models'
-import { buildVideoEmbed, buildVideoLink } from 'src/assets/player/utils'
+import { buildVideoOrPlaylistEmbed, buildVideoLink } from 'src/assets/player/utils'
import { environment } from 'src/environments/environment'
import { DomSanitizer } from '@angular/platform-browser'
}
getVideoEmbed (entry: VideoBlacklist) {
- return buildVideoEmbed(
+ return buildVideoOrPlaylistEmbed(
buildVideoLink({
baseUrl: `${environment.embedUrl}/videos/embed/${entry.video.uuid}`,
title: false,
this.comment.account = null
}
- if (this.isUserLoggedIn() && this.authService.getUser().account.id !== this.comment.account.id) {
+ if (this.isUserLoggedIn() && this.comment.isDeleted === false && this.authService.getUser().account.id !== this.comment.account.id) {
this.prependModerationActions = [
{
label: this.i18n('Report comment'),
<div class="modal-body">
+
<div class="playlist" *ngIf="hasPlaylist()">
<div class="title-page title-page-single" i18n>Share the playlist</div>
- <my-input-readonly-copy [value]="getPlaylistUrl()"></my-input-readonly-copy>
+ <div ngbNav #nav="ngbNav" class="nav-tabs" [(activeId)]="activePlaylistId">
+
+ <ng-container ngbNavItem="url">
+ <a ngbNavLink i18n>URL</a>
+
+ <ng-template ngbNavContent>
+ <div class="nav-content">
+
+ <my-input-readonly-copy [value]="getPlaylistUrl()"></my-input-readonly-copy>
+ </div>
+ </ng-template>
+ </ng-container>
+
+ <ng-container ngbNavItem="qrcode">
+ <a ngbNavLink i18n>QR-Code</a>
+
+ <ng-template ngbNavContent>
+ <div class="nav-content">
+ <qrcode [qrdata]="getPlaylistUrl()" [size]="256" level="Q"></qrcode>
+ </div>
+ </ng-template>
+ </ng-container>
+
+ <ng-container ngbNavItem="embed">
+ <a ngbNavLink i18n>Embed</a>
+
+ <ng-template ngbNavContent>
+ <div class="nav-content">
+ <my-input-readonly-copy [value]="getPlaylistIframeCode()"></my-input-readonly-copy>
+
+ <div i18n *ngIf="notSecure()" class="alert alert-warning">
+ The url is not secured (no HTTPS), so the embed video won't work on HTTPS websites (web browsers block non secured HTTP requests on HTTPS websites).
+ </div>
+ </div>
+ </ng-template>
+ </ng-container>
+
+ </div>
+
+ <div [ngbNavOutlet]="nav"></div>
<div class="filters">
<div class="form-group">
- <my-peertube-checkbox
- inputName="includeVideoInPlaylist" [(ngModel)]="includeVideoInPlaylist"
- i18n-labelText labelText="Share the playlist at this video position"
- ></my-peertube-checkbox>
+ <my-peertube-checkbox inputName="includeVideoInPlaylist" [(ngModel)]="includeVideoInPlaylist" i18n-labelText
+ labelText="Share the playlist at this video position"></my-peertube-checkbox>
</div>
</div>
<div class="video">
<div class="title-page title-page-single" *ngIf="hasPlaylist()" i18n>Share the video</div>
- <div ngbNav #nav="ngbNav" class="nav-tabs" [(activeId)]="activeId">
+ <div ngbNav #nav="ngbNav" class="nav-tabs" [(activeId)]="activeVideoId">
<ng-container ngbNavItem="url">
<a ngbNavLink i18n>URL</a>
</div>
</div>
- <ng-container *ngIf="isInEmbedTab()">
+ <ng-container *ngIf="isVideoInEmbedTab()">
<div class="form-group">
<my-peertube-checkbox
inputName="title" [(ngModel)]="customizations.title"
import { Component, ElementRef, Input, ViewChild } from '@angular/core'
-import { buildVideoEmbed, buildVideoLink } from '../../../../assets/player/utils'
+import { buildVideoOrPlaylistEmbed, buildVideoLink, buildPlaylistLink } from '../../../../assets/player/utils'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { VideoCaption } from '@shared/models'
import { VideoDetails } from '@app/shared/shared-main'
peertubeLink: boolean
}
+type TabId = 'url' | 'qrcode' | 'embed'
+
@Component({
selector: 'my-video-share',
templateUrl: './video-share.component.html',
@Input() videoCaptions: VideoCaption[] = []
@Input() playlist: VideoPlaylist = null
- activeId: 'url' | 'qrcode' | 'embed' = 'url'
+ activeVideoId: TabId = 'url'
+ activePlaylistId: TabId = 'url'
+
customizations: Customizations
isAdvancedCustomizationCollapsed = true
includeVideoInPlaylist = false
+ private playlistPosition: number = null
+
constructor (private modalService: NgbModal) { }
- show (currentVideoTimestamp?: number) {
+ show (currentVideoTimestamp?: number, currentPlaylistPosition?: number) {
let subtitle: string
if (this.videoCaptions.length !== 0) {
subtitle = this.videoCaptions[0].language.id
peertubeLink: true
}
+ this.playlistPosition = currentPlaylistPosition
+
this.modalService.open(this.modal, { centered: true })
}
getVideoIframeCode () {
- const options = this.getOptions(this.video.embedUrl)
+ const options = this.getVideoOptions(this.video.embedUrl)
const embedUrl = buildVideoLink(options)
- return buildVideoEmbed(embedUrl)
+ return buildVideoOrPlaylistEmbed(embedUrl)
+ }
+
+ getPlaylistIframeCode () {
+ const options = this.getPlaylistOptions(this.playlist.embedUrl)
+
+ const embedUrl = buildPlaylistLink(options)
+ return buildVideoOrPlaylistEmbed(embedUrl)
}
getVideoUrl () {
const baseUrl = window.location.origin + '/videos/watch/' + this.video.uuid
- const options = this.getOptions(baseUrl)
+ const options = this.getVideoOptions(baseUrl)
return buildVideoLink(options)
}
return window.location.protocol === 'http:'
}
- isInEmbedTab () {
- return this.activeId === 'embed'
+ isVideoInEmbedTab () {
+ return this.activeVideoId === 'embed'
}
hasPlaylist () {
return !!this.playlist
}
- private getOptions (baseUrl?: string) {
+ private getPlaylistOptions (baseUrl?: string) {
+ return {
+ baseUrl,
+
+ playlistPosition: this.playlistPosition || undefined
+ }
+ }
+
+ private getVideoOptions (baseUrl?: string) {
return {
baseUrl,
showShareModal () {
this.pausePlayer()
- this.videoShareModal.show(this.currentTime)
+ this.videoShareModal.show(this.currentTime, this.videoWatchPlaylist.currentPlaylistPosition)
}
isUserLoggedIn () {
import * as debug from 'debug'
import truncate from 'lodash-es/truncate'
import { SortMeta } from 'primeng/api'
-import { buildVideoEmbed, buildVideoLink } from 'src/assets/player/utils'
+import { buildVideoOrPlaylistEmbed, buildVideoLink } from 'src/assets/player/utils'
import { environment } from 'src/environments/environment'
import { AfterViewInit, Component, OnInit, ViewChild, Input } from '@angular/core'
import { DomSanitizer } from '@angular/platform-browser'
}
getVideoEmbed (abuse: AdminAbuse) {
- return buildVideoEmbed(
+ return buildVideoOrPlaylistEmbed(
buildVideoLink({
baseUrl: `${environment.embedUrl}/videos/embed/${abuse.video.uuid}`,
title: false,
import { mapValues, pickBy } from 'lodash-es'
-import { buildVideoEmbed, buildVideoLink } from 'src/assets/player/utils'
+import { buildVideoOrPlaylistEmbed, buildVideoLink } from 'src/assets/player/utils'
import { Component, Input, OnInit, ViewChild } from '@angular/core'
import { DomSanitizer, SafeHtml } from '@angular/platform-browser'
import { Notifier } from '@app/core'
getVideoEmbed () {
return this.sanitizer.bypassSecurityTrustHtml(
- buildVideoEmbed(
+ buildVideoOrPlaylistEmbed(
buildVideoLink({
baseUrl: this.video.embedUrl,
title: false,
-import { getAbsoluteAPIUrl } from '@app/helpers'
+import { getAbsoluteAPIUrl, getAbsoluteEmbedUrl } from '@app/helpers'
import { Actor } from '@app/shared/shared-main'
import { peertubeTranslate } from '@shared/core-utils/i18n'
import {
thumbnailUrl: string
+ embedPath: string
+ embedUrl: string
+
ownerBy: string
ownerAvatarUrl: string
this.thumbnailUrl = window.location.origin + '/client/assets/images/default-playlist.jpg'
}
+ this.embedPath = hash.embedPath
+ this.embedUrl = getAbsoluteEmbedUrl() + hash.embedPath
+
this.videosLength = hash.videosLength
this.type = hash.type
VideoJSPluginOptions
} from './peertube-videojs-typings'
import { TranslationsManager } from './translations-manager'
-import { buildVideoEmbed, buildVideoLink, copyToClipboard, getRtcConfig, isIOS, isSafari } from './utils'
+import { buildVideoOrPlaylistEmbed, buildVideoLink, copyToClipboard, getRtcConfig, isIOS, isSafari } from './utils'
// Change 'Playback Rate' to 'Speed' (smaller for our settings menu)
(videojs.getComponent('PlaybackRateMenuButton') as any).prototype.controlText_ = 'Speed'
{
label: player.localize('Copy embed code'),
listener: () => {
- copyToClipboard(buildVideoEmbed(videoEmbedUrl))
+ copyToClipboard(buildVideoOrPlaylistEmbed(videoEmbedUrl))
}
}
]
}
function buildVideoLink (options: {
- baseUrl?: string,
+ baseUrl?: string
- startTime?: number,
- stopTime?: number,
+ startTime?: number
+ stopTime?: number
- subtitle?: string,
+ subtitle?: string
- loop?: boolean,
- autoplay?: boolean,
- muted?: boolean,
+ loop?: boolean
+ autoplay?: boolean
+ muted?: boolean
// Embed options
- title?: boolean,
- warningTitle?: boolean,
+ title?: boolean
+ warningTitle?: boolean
controls?: boolean
peertubeLink?: boolean
} = {}) {
? baseUrl
: window.location.origin + window.location.pathname.replace('/embed/', '/watch/')
- const params = new URLSearchParams(window.location.search)
- // Remove these unused parameters when we are on a playlist page
- params.delete('videoId')
- params.delete('resume')
+ const params = generateParams(window.location.search)
if (options.startTime) {
const startTimeInt = Math.floor(options.startTime)
if (options.controls === false) params.set('controls', '0')
if (options.peertubeLink === false) params.set('peertubeLink', '0')
+ return buildUrl(url, params)
+}
+
+function buildPlaylistLink (options: {
+ baseUrl?: string
+
+ playlistPosition: number
+}) {
+ const { baseUrl } = options
+
+ const url = baseUrl
+ ? baseUrl
+ : window.location.origin + window.location.pathname.replace('/video-playlists/embed/', '/videos/watch/playlist/')
+
+ const params = generateParams(window.location.search)
+
+ if (options.playlistPosition) params.set('playlistPosition', '' + options.playlistPosition)
+
+ return buildUrl(url, params)
+}
+
+function buildUrl (url: string, params: URLSearchParams) {
let hasParams = false
params.forEach(() => hasParams = true)
return url
}
+function generateParams (url: string) {
+ const params = new URLSearchParams(window.location.search)
+ // Unused parameters in embed
+ params.delete('videoId')
+ params.delete('resume')
+
+ return params
+}
+
function timeToInt (time: number | string) {
if (!time) return 0
if (typeof time === 'number') return time
return time
}
-function buildVideoEmbed (embedUrl: string) {
+function buildVideoOrPlaylistEmbed (embedUrl: string) {
return '<iframe width="560" height="315" ' +
'sandbox="allow-same-origin allow-scripts allow-popups" ' +
'src="' + embedUrl + '" ' +
timeToInt,
secondsToTime,
isWebRTCDisabled,
+ buildPlaylistLink,
buildVideoLink,
- buildVideoEmbed,
+ buildVideoOrPlaylistEmbed,
videoFileMaxByResolution,
videoFileMinByResolution,
copyToClipboard,
},
thumbnailPath: this.getThumbnailStaticPath(),
+ embedPath: this.getEmbedStaticPath(),
type: {
id: this.type,
const playlistFromList = res.body.data[0] as VideoPlaylist
const res2 = await getVideoPlaylist(server.url, playlistFromList.uuid)
- const playlistFromGet = res2.body
+ const playlistFromGet = res2.body as VideoPlaylist
for (const playlist of [ playlistFromGet, playlistFromList ]) {
expect(playlist.id).to.be.a('number')
expect(playlist.privacy.label).to.equal('Public')
expect(playlist.type.id).to.equal(VideoPlaylistType.REGULAR)
expect(playlist.type.label).to.equal('Regular')
+ expect(playlist.embedPath).to.equal('/video-playlists/embed/' + playlist.uuid)
expect(playlist.videosLength).to.equal(0)
type: VideoConstant<VideoPlaylistType>
+ embedPath: string
+
createdAt: Date | string
updatedAt: Date | string