import { SortMeta } from 'primeng/api'
import { switchMap } from 'rxjs/operators'
-import { buildVideoLink, buildVideoOrPlaylistEmbed } from 'src/assets/player/utils'
+import { buildVideoEmbedLink, buildVideoOrPlaylistEmbed, decorateVideoLink } from 'src/assets/player/utils'
import { environment } from 'src/environments/environment'
import { Component, OnInit } from '@angular/core'
import { DomSanitizer } from '@angular/platform-browser'
getVideoEmbed (entry: VideoBlacklist) {
return buildVideoOrPlaylistEmbed(
- buildVideoLink({
- baseUrl: `${environment.originServerUrl}/videos/embed/${entry.video.uuid}`,
+ decorateVideoLink({
+ url: buildVideoEmbedLink(entry.video, environment.originServerUrl),
+
title: false,
warningTitle: false
}),
</ng-template>
</my-help>
- <my-markdown-textarea [truncate]="250" formControlName="description" [markdownVideo]="true"></my-markdown-textarea>
+ <my-markdown-textarea [truncate]="250" formControlName="description" [markdownVideo]="videoToUpdate"></my-markdown-textarea>
<div *ngIf="formErrors.description" class="form-error">
{{ formErrors.description }}
// Before HTML rendering restore line feed for markdown list compatibility
const commentText = this.comment.text.replace(/<br.?\/?>/g, '\r\n')
const html = await this.markdownService.textMarkdownToHTML(commentText, true, true)
- this.sanitizedCommentHTML = this.markdownService.processVideoTimestamps(html)
+ this.sanitizedCommentHTML = this.markdownService.processVideoTimestamps(this.video.shortUUID, html)
this.newParentComments = this.parentComments.concat([ this.comment ])
if (this.comment.account) {
private async setVideoDescriptionHTML () {
const html = await this.markdownService.textMarkdownToHTML(this.video.description)
- this.videoHTMLDescription = this.markdownService.processVideoTimestamps(html)
+
+ this.videoHTMLDescription = this.markdownService.processVideoTimestamps(this.video.shortUUID, html)
}
}
videoCaptions: playerCaptions,
+ videoShortUUID: video.shortUUID,
videoUUID: video.uuid
},
import * as MarkdownIt from 'markdown-it'
-import { buildVideoLink } from 'src/assets/player/utils'
+import { buildVideoLink, decorateVideoLink } from 'src/assets/player/utils'
import { Injectable } from '@angular/core'
import {
COMPLETE_RULES,
return this.render({ name: 'customPageMarkdownIt', markdown, withEmoji: true, additionalAllowedTags })
}
- processVideoTimestamps (html: string) {
+ processVideoTimestamps (videoShortUUID: string, html: string) {
return html.replace(/((\d{1,2}):)?(\d{1,2}):(\d{1,2})/g, function (str, _, h, m, s) {
const t = (3600 * +(h || 0)) + (60 * +(m || 0)) + (+(s || 0))
- const url = buildVideoLink({ startTime: t })
+
+ const url = decorateVideoLink({
+ url: buildVideoLink({ shortUUID: videoShortUUID }),
+ startTime: t
+ })
return `<a class="video-timestamp" href="${url}">${str}</a>`
})
}
import * as debug from 'debug'
import truncate from 'lodash-es/truncate'
import { SortMeta } from 'primeng/api'
-import { buildVideoLink, buildVideoOrPlaylistEmbed } from 'src/assets/player/utils'
+import { buildVideoEmbedLink, buildVideoOrPlaylistEmbed, decorateVideoLink } from 'src/assets/player/utils'
import { environment } from 'src/environments/environment'
import { Component, Input, OnInit, ViewChild } from '@angular/core'
import { DomSanitizer } from '@angular/platform-browser'
getVideoEmbed (abuse: AdminAbuse) {
return buildVideoOrPlaylistEmbed(
- buildVideoLink({
- baseUrl: `${environment.originServerUrl}/videos/embed/${abuse.video.uuid}`,
+ decorateVideoLink({
+ url: buildVideoEmbedLink(abuse.video, environment.originServerUrl),
title: false,
warningTitle: false,
startTime: abuse.video.startAt,
-import { buildPlaylistLink, buildVideoLink, buildVideoOrPlaylistEmbed } from 'src/assets/player/utils'
+import { buildPlaylistEmbedLink, buildVideoEmbedLink, buildVideoOrPlaylistEmbed } from 'src/assets/player/utils'
import { environment } from 'src/environments/environment'
import { Component, ElementRef, Input, OnInit } from '@angular/core'
import { CustomMarkupComponent } from './shared'
ngOnInit () {
const link = this.type === 'video'
- ? buildVideoLink({ baseUrl: `${environment.originServerUrl}/videos/embed/${this.uuid}` })
- : buildPlaylistLink({ baseUrl: `${environment.originServerUrl}/video-playlists/embed/${this.uuid}` })
+ ? buildVideoEmbedLink({ uuid: this.uuid }, environment.originServerUrl)
+ : buildPlaylistEmbedLink({ uuid: this.uuid }, environment.originServerUrl)
this.el.nativeElement.innerHTML = buildVideoOrPlaylistEmbed(link, this.uuid)
}
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'
import { SafeHtml } from '@angular/platform-browser'
import { MarkdownService, ScreenService } from '@app/core'
+import { Video } from '@shared/models'
@Component({
selector: 'my-markdown-textarea',
@Input() markdownType: 'text' | 'enhanced' = 'text'
@Input() customMarkdownRenderer?: (text: string) => Promise<string | HTMLElement>
- @Input() markdownVideo = false
+ @Input() markdownVideo: Video
@Input() name = 'description'
}
if (this.markdownVideo) {
- html = this.markdownService.processVideoTimestamps(html)
+ html = this.markdownService.processVideoTimestamps(this.markdownVideo.shortUUID, html)
}
return html
import { mapValues, pickBy } from 'lodash-es'
-import { buildVideoLink, buildVideoOrPlaylistEmbed } from 'src/assets/player/utils'
+import { buildVideoOrPlaylistEmbed, decorateVideoLink } 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(
buildVideoOrPlaylistEmbed(
- buildVideoLink({
- baseUrl: this.video.embedUrl,
+ decorateVideoLink({
+ url: this.video.embedUrl,
title: false,
warningTitle: false
}),
+
this.video.name
)
)
import { Component, ElementRef, Input, ViewChild } from '@angular/core'
-import { Video, VideoDetails } from '@app/shared/shared-main'
+import { VideoDetails } from '@app/shared/shared-main'
import { VideoPlaylist } from '@app/shared/shared-video-playlist'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { VideoCaption } from '@shared/models'
-import { buildPlaylistLink, buildVideoLink, buildVideoOrPlaylistEmbed } from '../../../assets/player/utils'
+import {
+ buildPlaylistLink,
+ buildVideoLink,
+ buildVideoOrPlaylistEmbed,
+ decoratePlaylistLink,
+ decorateVideoLink
+} from '../../../assets/player/utils'
type Customizations = {
startAtCheckbox: boolean
}
getVideoIframeCode () {
- const options = this.getVideoOptions(this.video.embedUrl)
+ const embedUrl = decorateVideoLink({ url: this.video.embedUrl, ...this.getVideoOptions() })
- const embedUrl = buildVideoLink(options)
return buildVideoOrPlaylistEmbed(embedUrl, this.video.name)
}
getPlaylistIframeCode () {
- const options = this.getPlaylistOptions(this.playlist.embedUrl)
+ const embedUrl = decoratePlaylistLink({ url: this.playlist.embedUrl, ...this.getPlaylistOptions() })
- const embedUrl = buildPlaylistLink(options)
return buildVideoOrPlaylistEmbed(embedUrl, this.playlist.displayName)
}
getVideoUrl () {
- let baseUrl = this.customizations.originUrl ? this.video.originInstanceUrl : window.location.origin
- baseUrl += Video.buildWatchUrl(this.video)
+ const baseUrl = this.customizations.originUrl
+ ? this.video.originInstanceUrl
+ : window.location.origin
- const options = this.getVideoOptions(baseUrl)
+ return decorateVideoLink({
+ url: buildVideoLink(this.video, baseUrl),
- return buildVideoLink(options)
+ ...this.getVideoOptions()
+ })
}
getPlaylistUrl () {
- const base = window.location.origin + VideoPlaylist.buildWatchUrl(this.playlist)
+ const url = buildPlaylistLink(this.playlist)
+ if (!this.includeVideoInPlaylist) return url
- if (!this.includeVideoInPlaylist) return base
-
- return base + '?playlistPosition=' + this.playlistPosition
+ return decoratePlaylistLink({ url, playlistPosition: this.playlistPosition })
}
notSecure () {
}
}
- private getVideoOptions (baseUrl?: string) {
+ private getVideoOptions () {
return {
- baseUrl,
-
startTime: this.customizations.startAtCheckbox ? this.customizations.startAt : undefined,
stopTime: this.customizations.stopAtCheckbox ? this.customizations.stopAt : undefined,
import {
NextPreviousVideoButtonOptions,
P2PMediaLoaderPluginOptions,
+ PeerTubeLinkButtonOptions,
PlaylistPluginOptions,
UserWatching,
VideoJSCaption,
VideoJSPluginOptions
} from './peertube-videojs-typings'
import { TranslationsManager } from './translations-manager'
-import { buildVideoLink, buildVideoOrPlaylistEmbed, getRtcConfig, isIOS, isSafari } from './utils'
+import { buildVideoLink, buildVideoOrPlaylistEmbed, decorateVideoLink, getRtcConfig, isIOS, isSafari } from './utils'
// Change 'Playback Rate' to 'Speed' (smaller for our settings menu)
(videojs.getComponent('PlaybackRateMenuButton') as any).prototype.controlText_ = 'Speed'
videoCaptions: VideoJSCaption[]
videoUUID: string
+ videoShortUUID: string
userWatching?: UserWatching
PeertubePlayerManager.alreadyPlayed = true
})
- self.addContextMenu(mode, player, options.common.embedUrl, options.common.embedTitle)
+ self.addContextMenu({
+ mode,
+ player,
+ videoShortUUID: options.common.videoShortUUID,
+ videoEmbedUrl: options.common.embedUrl,
+ videoEmbedTitle: options.common.embedTitle
+ })
player.bezels()
player.stats({
videojs(newVideoElement, videojsOptions, function (this: videojs.Player) {
const player = this
- self.addContextMenu(mode, player, options.common.embedUrl, options.common.embedTitle)
+ self.addContextMenu({
+ mode,
+ player,
+ videoShortUUID: options.common.videoShortUUID,
+ videoEmbedUrl: options.common.embedUrl,
+ videoEmbedTitle: options.common.embedTitle
+ })
PeertubePlayerManager.onPlayerChange(player)
})
controlBar: {
children: this.getControlBarChildren(mode, {
+ videoShortUUID: commonOptions.videoShortUUID,
+
captions: commonOptions.captions,
peertubeLink: commonOptions.peertubeLink,
theaterButton: commonOptions.theaterButton,
}
private static getControlBarChildren (mode: PlayerMode, options: {
+ videoShortUUID: string
+
peertubeLink: boolean
theaterButton: boolean
captions: boolean
if (options.peertubeLink === true) {
Object.assign(children, {
- 'peerTubeLinkButton': {}
+ 'peerTubeLinkButton': { shortUUID: options.videoShortUUID } as PeerTubeLinkButtonOptions
})
}
return children
}
- private static addContextMenu (mode: PlayerMode, player: videojs.Player, videoEmbedUrl: string, videoEmbedTitle: string) {
+ private static addContextMenu (options: {
+ mode: PlayerMode
+ player: videojs.Player
+ videoShortUUID: string
+ videoEmbedUrl: string
+ videoEmbedTitle: string
+ }) {
+ const { mode, player, videoEmbedTitle, videoEmbedUrl, videoShortUUID } = options
+
const content = () => {
const isLoopEnabled = player.options_['loop']
const items = [
{
label: player.localize('Copy the video URL'),
listener: function () {
- copyToClipboard(buildVideoLink())
+ copyToClipboard(buildVideoLink({ shortUUID: videoShortUUID }))
}
},
{
label: player.localize('Copy the video URL at the current time'),
listener: function (this: videojs.Player) {
- copyToClipboard(buildVideoLink({ startTime: this.currentTime() }))
+ const url = buildVideoLink({ shortUUID: videoShortUUID })
+
+ copyToClipboard(decorateVideoLink({ url, startTime: this.currentTime() }))
}
},
{
isDisabled: () => boolean
}
+type PeerTubeLinkButtonOptions = {
+ shortUUID: string
+}
+
type WebtorrentPluginOptions = {
playerElement: HTMLVideoElement
VideoJSPluginOptions,
LoadedQualityData,
QualityLevelRepresentation,
+ PeerTubeLinkButtonOptions,
QualityLevels
}
-import { VideoFile } from '@shared/models'
+import { Video, VideoFile, VideoPlaylist } from '@shared/models'
import { escapeHTML } from '@shared/core-utils/renderer'
function toTitleCase (str: string) {
return /iPhone|iPad|iPod|Android/i.test(navigator.userAgent)
}
-function buildVideoLink (options: {
- baseUrl?: string
+function buildPlaylistLink (playlist: Pick<VideoPlaylist, 'shortUUID'>, base?: string) {
+ return (base ?? window.location.origin) + '/w/p/' + playlist.shortUUID
+}
+
+function buildVideoLink (video: Pick<Video, 'shortUUID'>, base?: string) {
+ return (base ?? window.location.origin) + '/w/' + video.shortUUID
+}
+
+function buildPlaylistEmbedLink (playlist: Pick<VideoPlaylist, 'uuid'>, base?: string) {
+ return (base ?? window.location.origin) + '/video-playlists/embed/' + playlist.uuid
+}
+
+function buildVideoEmbedLink (video: Pick<Video, 'uuid'>, base?: string) {
+ return (base ?? window.location.origin) + '/videos/embed/' + video.uuid
+}
+
+function decorateVideoLink (options: {
+ url: string
startTime?: number
stopTime?: number
warningTitle?: boolean
controls?: boolean
peertubeLink?: boolean
-} = {}) {
- const { baseUrl } = options
-
- const url = baseUrl
- ? baseUrl
- : window.location.origin + window.location.pathname.replace('/embed/', '/w/')
+}) {
+ const { url } = options
const params = generateParams(window.location.search)
return buildUrl(url, params)
}
-function buildPlaylistLink (options: {
- baseUrl?: string
+function decoratePlaylistLink (options: {
+ url: string
playlistPosition?: number
}) {
- const { baseUrl } = options
-
- const url = baseUrl
- ? baseUrl
- : window.location.origin + window.location.pathname.replace('/video-playlists/embed/', '/w/p/')
+ const { url } = options
const params = generateParams(window.location.search)
timeToInt,
secondsToTime,
isWebRTCDisabled,
+
buildPlaylistLink,
buildVideoLink,
+ decorateVideoLink,
+ decoratePlaylistLink,
+ buildPlaylistEmbedLink,
+ buildVideoEmbedLink,
+
buildVideoOrPlaylistEmbed,
videoFileMaxByResolution,
videoFileMinByResolution,
-import { buildVideoLink } from '../utils'
import videojs from 'video.js'
+import { PeerTubeLinkButtonOptions } from '../peertube-videojs-typings'
+import { buildVideoLink, decorateVideoLink } from '../utils'
const Button = videojs.getComponent('Button')
class PeerTubeLinkButton extends Button {
+ private shortUUID: string
- constructor (player: videojs.Player, options?: videojs.ComponentOptions) {
- super(player, options)
+ constructor (player: videojs.Player, options?: PeerTubeLinkButtonOptions) {
+ super(player, options as any)
}
createEl () {
}
updateHref () {
- this.el().setAttribute('href', buildVideoLink({ startTime: this.player().currentTime() }))
+ this.el().setAttribute('href', this.buildLink())
}
handleClick () {
private buildElement () {
const el = videojs.dom.createEl('a', {
- href: buildVideoLink(),
+ href: this.buildLink(),
innerHTML: 'PeerTube',
title: this.player().localize('Video page (new window)'),
className: 'vjs-peertube-link',
return el as HTMLButtonElement
}
+
+ private buildLink () {
+ const url = buildVideoLink({ shortUUID: this.shortUUID })
+
+ return decorateVideoLink({ url, startTime: this.player().currentTime() })
+ }
}
videojs.registerComponent('PeerTubeLinkButton', PeerTubeLinkButton)
export * from './date'
export * from './miscs'
-export * from './types'
export * from './regexp'
+export * from './types'
+export * from './url
export * from './abuse'
+export * from './common'
export * from './i18n'
export * from './logs'
-export * from './miscs'
export * from './plugins'
export * from './renderer'
export * from './users'