aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/src/standalone
diff options
context:
space:
mode:
Diffstat (limited to 'client/src/standalone')
-rw-r--r--client/src/standalone/player/definitions.ts2
-rw-r--r--client/src/standalone/player/events.ts14
-rw-r--r--client/src/standalone/player/player.ts31
-rw-r--r--client/src/standalone/videos/embed-api.ts19
-rw-r--r--client/src/standalone/videos/embed.ts47
-rw-r--r--client/src/standalone/videos/test-embed.ts20
6 files changed, 71 insertions, 62 deletions
diff --git a/client/src/standalone/player/definitions.ts b/client/src/standalone/player/definitions.ts
index cc5203ed5..495f1a98c 100644
--- a/client/src/standalone/player/definitions.ts
+++ b/client/src/standalone/player/definitions.ts
@@ -21,5 +21,5 @@ export type PeerTubeTextTrack = {
21 id: string 21 id: string
22 label: string 22 label: string
23 src: string 23 src: string
24 mode: 'showing' | 'disabled' 24 mode: TextTrackMode
25} 25}
diff --git a/client/src/standalone/player/events.ts b/client/src/standalone/player/events.ts
index 28a13c727..7a8e9dbec 100644
--- a/client/src/standalone/player/events.ts
+++ b/client/src/standalone/player/events.ts
@@ -1,7 +1,7 @@
1import { EventHandler } from './definitions' 1import { EventHandler } from './definitions'
2 2
3interface PlayerEventRegistrar { 3interface PlayerEventRegistrar {
4 registrations: Function[] 4 registrations: EventHandler<any>[]
5} 5}
6 6
7interface PlayerEventRegistrationMap { 7interface PlayerEventRegistrationMap {
@@ -20,28 +20,28 @@ export class EventRegistrar {
20 20
21 public registerTypes (names: string[]) { 21 public registerTypes (names: string[]) {
22 for (const name of names) { 22 for (const name of names) {
23 this.eventRegistrations[ name ] = { registrations: [] } 23 this.eventRegistrations[name] = { registrations: [] }
24 } 24 }
25 } 25 }
26 26
27 public fire<T> (name: string, event: T) { 27 public fire<T> (name: string, event: T) {
28 this.eventRegistrations[ name ].registrations.forEach(x => x(event)) 28 this.eventRegistrations[name].registrations.forEach(x => x(event))
29 } 29 }
30 30
31 public addListener<T> (name: string, handler: EventHandler<T>) { 31 public addListener<T> (name: string, handler: EventHandler<T>) {
32 if (!this.eventRegistrations[ name ]) { 32 if (!this.eventRegistrations[name]) {
33 console.warn(`PeerTube: addEventListener(): The event '${name}' is not supported`) 33 console.warn(`PeerTube: addEventListener(): The event '${name}' is not supported`)
34 return false 34 return false
35 } 35 }
36 36
37 this.eventRegistrations[ name ].registrations.push(handler) 37 this.eventRegistrations[name].registrations.push(handler)
38 return true 38 return true
39 } 39 }
40 40
41 public removeListener<T> (name: string, handler: EventHandler<T>) { 41 public removeListener<T> (name: string, handler: EventHandler<T>) {
42 if (!this.eventRegistrations[ name ]) return false 42 if (!this.eventRegistrations[name]) return false
43 43
44 this.eventRegistrations[ name ].registrations = this.eventRegistrations[ name ].registrations.filter(x => x === handler) 44 this.eventRegistrations[name].registrations = this.eventRegistrations[name].registrations.filter(x => x === handler)
45 45
46 return true 46 return true
47 } 47 }
diff --git a/client/src/standalone/player/player.ts b/client/src/standalone/player/player.ts
index 9776fda12..bbe37a42b 100644
--- a/client/src/standalone/player/player.ts
+++ b/client/src/standalone/player/player.ts
@@ -17,7 +17,7 @@ const PASSTHROUGH_EVENTS = [
17 */ 17 */
18export class PeerTubePlayer { 18export class PeerTubePlayer {
19 19
20 private eventRegistrar: EventRegistrar = new EventRegistrar() 20 private readonly eventRegistrar: EventRegistrar = new EventRegistrar()
21 private channel: Channel.MessagingChannel 21 private channel: Channel.MessagingChannel
22 private readyPromise: Promise<void> 22 private readyPromise: Promise<void>
23 23
@@ -31,8 +31,8 @@ export class PeerTubePlayer {
31 * @param scope 31 * @param scope
32 */ 32 */
33 constructor ( 33 constructor (
34 private embedElement: HTMLIFrameElement, 34 private readonly embedElement: HTMLIFrameElement,
35 private scope?: string 35 private readonly scope?: string
36 ) { 36 ) {
37 this.eventRegistrar.registerTypes(PASSTHROUGH_EVENTS) 37 this.eventRegistrar.registerTypes(PASSTHROUGH_EVENTS)
38 38
@@ -90,6 +90,7 @@ export class PeerTubePlayer {
90 90
91 /** 91 /**
92 * Tell the embed to change the audio volume 92 * Tell the embed to change the audio volume
93 *
93 * @param value A number from 0 to 1 94 * @param value A number from 0 to 1
94 */ 95 */
95 async setVolume (value: number) { 96 async setVolume (value: number) {
@@ -98,14 +99,16 @@ export class PeerTubePlayer {
98 99
99 /** 100 /**
100 * Get the current volume level in the embed. 101 * Get the current volume level in the embed.
102 *
101 * @param value A number from 0 to 1 103 * @param value A number from 0 to 1
102 */ 104 */
103 async getVolume (): Promise<number> { 105 async getVolume (): Promise<number> {
104 return this.sendMessage<void, number>('getVolume') 106 return this.sendMessage<undefined, number>('getVolume')
105 } 107 }
106 108
107 /** 109 /**
108 * Tell the embed to change the current caption 110 * Tell the embed to change the current caption
111 *
109 * @param value Caption id 112 * @param value Caption id
110 */ 113 */
111 async setCaption (value: string) { 114 async setCaption (value: string) {
@@ -116,11 +119,12 @@ export class PeerTubePlayer {
116 * Get video captions 119 * Get video captions
117 */ 120 */
118 async getCaptions (): Promise<PeerTubeTextTrack[]> { 121 async getCaptions (): Promise<PeerTubeTextTrack[]> {
119 return this.sendMessage<void, PeerTubeTextTrack[]>('getCaptions') 122 return this.sendMessage<undefined, PeerTubeTextTrack[]>('getCaptions')
120 } 123 }
121 124
122 /** 125 /**
123 * Tell the embed to seek to a specific position (in seconds) 126 * Tell the embed to seek to a specific position (in seconds)
127 *
124 * @param seconds 128 * @param seconds
125 */ 129 */
126 async seek (seconds: number) { 130 async seek (seconds: number) {
@@ -143,21 +147,21 @@ export class PeerTubePlayer {
143 * resolutions change. 147 * resolutions change.
144 */ 148 */
145 async getResolutions (): Promise<PeerTubeResolution[]> { 149 async getResolutions (): Promise<PeerTubeResolution[]> {
146 return this.sendMessage<void, PeerTubeResolution[]>('getResolutions') 150 return this.sendMessage<undefined, PeerTubeResolution[]>('getResolutions')
147 } 151 }
148 152
149 /** 153 /**
150 * Retrieve a list of available playback rates. 154 * Retrieve a list of available playback rates.
151 */ 155 */
152 async getPlaybackRates (): Promise<number[]> { 156 async getPlaybackRates (): Promise<number[]> {
153 return this.sendMessage<void, number[]>('getPlaybackRates') 157 return this.sendMessage<undefined, number[]>('getPlaybackRates')
154 } 158 }
155 159
156 /** 160 /**
157 * Get the current playback rate. Defaults to 1 (1x playback rate). 161 * Get the current playback rate. Defaults to 1 (1x playback rate).
158 */ 162 */
159 async getPlaybackRate (): Promise<number> { 163 async getPlaybackRate (): Promise<number> {
160 return this.sendMessage<void, number>('getPlaybackRate') 164 return this.sendMessage<undefined, number>('getPlaybackRate')
161 } 165 }
162 166
163 /** 167 /**
@@ -188,7 +192,7 @@ export class PeerTubePlayer {
188 * Get video position currently played (starts from 1) 192 * Get video position currently played (starts from 1)
189 */ 193 */
190 async getCurrentPosition () { 194 async getCurrentPosition () {
191 return this.sendMessage<void, number>('getCurrentPosition') 195 return this.sendMessage<undefined, number>('getCurrentPosition')
192 } 196 }
193 197
194 private constructChannel () { 198 private constructChannel () {
@@ -201,8 +205,8 @@ export class PeerTubePlayer {
201 } 205 }
202 206
203 private prepareToBeReady () { 207 private prepareToBeReady () {
204 let readyResolve: Function 208 let readyResolve: () => void
205 let readyReject: Function 209 let readyReject: () => void
206 210
207 this.readyPromise = new Promise<void>((res, rej) => { 211 this.readyPromise = new Promise<void>((res, rej) => {
208 readyResolve = res 212 readyResolve = res
@@ -219,7 +223,8 @@ export class PeerTubePlayer {
219 private sendMessage<TIn, TOut> (method: string, params?: TIn): Promise<TOut> { 223 private sendMessage<TIn, TOut> (method: string, params?: TIn): Promise<TOut> {
220 return new Promise<TOut>((resolve, reject) => { 224 return new Promise<TOut>((resolve, reject) => {
221 this.channel.call({ 225 this.channel.call({
222 method, params, 226 method,
227 params,
223 success: result => resolve(result), 228 success: result => resolve(result),
224 error: error => reject(error) 229 error: error => reject(error)
225 }) 230 })
@@ -228,4 +233,4 @@ export class PeerTubePlayer {
228} 233}
229 234
230// put it on the window as well as the export 235// put it on the window as well as the export
231(window[ 'PeerTubePlayer' ] as any) = PeerTubePlayer 236(window['PeerTubePlayer'] as any) = PeerTubePlayer
diff --git a/client/src/standalone/videos/embed-api.ts b/client/src/standalone/videos/embed-api.ts
index 75174f2f8..b5c9da431 100644
--- a/client/src/standalone/videos/embed-api.ts
+++ b/client/src/standalone/videos/embed-api.ts
@@ -13,7 +13,8 @@ export class PeerTubeEmbedApi {
13 private isReady = false 13 private isReady = false
14 private resolutions: PeerTubeResolution[] = [] 14 private resolutions: PeerTubeResolution[] = []
15 15
16 constructor (private embed: PeerTubeEmbed) { 16 constructor (private readonly embed: PeerTubeEmbed) {
17
17 } 18 }
18 19
19 initialize () { 20 initialize () {
@@ -45,7 +46,7 @@ export class PeerTubeEmbedApi {
45 channel.bind('getResolutions', (txn, params) => this.resolutions) 46 channel.bind('getResolutions', (txn, params) => this.resolutions)
46 47
47 channel.bind('getCaptions', (txn, params) => this.getCaptions()) 48 channel.bind('getCaptions', (txn, params) => this.getCaptions())
48 channel.bind('setCaption', (txn, id) => this.setCaption(id)), 49 channel.bind('setCaption', (txn, id) => this.setCaption(id))
49 50
50 channel.bind('setPlaybackRate', (txn, playbackRate) => this.embed.player.playbackRate(playbackRate)) 51 channel.bind('setPlaybackRate', (txn, playbackRate) => this.embed.player.playbackRate(playbackRate))
51 channel.bind('getPlaybackRate', (txn, params) => this.embed.player.playbackRate()) 52 channel.bind('getPlaybackRate', (txn, params) => this.embed.player.playbackRate())
@@ -79,14 +80,12 @@ export class PeerTubeEmbedApi {
79 } 80 }
80 81
81 private getCaptions (): PeerTubeTextTrack[] { 82 private getCaptions (): PeerTubeTextTrack[] {
82 return this.embed.player.textTracks().tracks_.map(t => { 83 return this.embed.player.textTracks().tracks_.map(t => ({
83 return { 84 id: t.id,
84 id: t.id, 85 src: t.src,
85 src: t.src, 86 label: t.label,
86 label: t.label, 87 mode: t.mode
87 mode: t.mode as any 88 }))
88 }
89 })
90 } 89 }
91 90
92 private setCaption (id: string) { 91 private setCaption (id: string) {
diff --git a/client/src/standalone/videos/embed.ts b/client/src/standalone/videos/embed.ts
index c9a4e541c..dad717108 100644
--- a/client/src/standalone/videos/embed.ts
+++ b/client/src/standalone/videos/embed.ts
@@ -64,17 +64,11 @@ export class PeerTubeEmbed {
64 private playlistElements: VideoPlaylistElement[] 64 private playlistElements: VideoPlaylistElement[]
65 private currentPlaylistElement: VideoPlaylistElement 65 private currentPlaylistElement: VideoPlaylistElement
66 66
67 private wrapperElement: HTMLElement 67 private readonly wrapperElement: HTMLElement
68 68
69 private pluginsManager: PluginsManager 69 private pluginsManager: PluginsManager
70 70
71 static async main () { 71 constructor (private readonly videoWrapperId: string) {
72 const videoContainerId = 'video-wrapper'
73 const embed = new PeerTubeEmbed(videoContainerId)
74 await embed.init()
75 }
76
77 constructor (private videoWrapperId: string) {
78 this.wrapperElement = document.getElementById(this.videoWrapperId) 72 this.wrapperElement = document.getElementById(this.videoWrapperId)
79 73
80 try { 74 try {
@@ -84,6 +78,12 @@ export class PeerTubeEmbed {
84 } 78 }
85 } 79 }
86 80
81 static async main () {
82 const videoContainerId = 'video-wrapper'
83 const embed = new PeerTubeEmbed(videoContainerId)
84 await embed.init()
85 }
86
87 getVideoUrl (id: string) { 87 getVideoUrl (id: string) {
88 return window.location.origin + '/api/v1/videos/' + id 88 return window.location.origin + '/api/v1/videos/' + id
89 } 89 }
@@ -316,7 +316,7 @@ export class PeerTubeEmbed {
316 while (total > elements.length && i < 10) { 316 while (total > elements.length && i < 10) {
317 const result = await this.loadPlaylistElements(playlistId, elements.length) 317 const result = await this.loadPlaylistElements(playlistId, elements.length)
318 318
319 const json = await result.json() as ResultList<VideoPlaylistElement> 319 const json = await result.json()
320 total = json.total 320 total = json.total
321 321
322 elements = elements.concat(json.data) 322 elements = elements.concat(json.data)
@@ -469,7 +469,7 @@ export class PeerTubeEmbed {
469 // Issue when we parsed config from HTML, fallback to API 469 // Issue when we parsed config from HTML, fallback to API
470 if (!this.config) { 470 if (!this.config) {
471 this.config = await this.refreshFetch('/api/v1/config') 471 this.config = await this.refreshFetch('/api/v1/config')
472 .then(res => res.json()) 472 .then(res => res.json())
473 } 473 }
474 474
475 const videoInfoPromise = videoResponse.json() 475 const videoInfoPromise = videoResponse.json()
@@ -506,7 +506,7 @@ export class PeerTubeEmbed {
506 this.currentPlaylistElement = videoPlaylistElement 506 this.currentPlaylistElement = videoPlaylistElement
507 507
508 this.loadVideoAndBuildPlayer(this.currentPlaylistElement.video.uuid) 508 this.loadVideoAndBuildPlayer(this.currentPlaylistElement.video.uuid)
509 .catch(err => console.error(err)) 509 .catch(err => console.error(err))
510 } 510 }
511 } 511 }
512 : undefined 512 : undefined
@@ -542,7 +542,9 @@ export class PeerTubeEmbed {
542 isLive: videoInfo.isLive, 542 isLive: videoInfo.isLive,
543 543
544 playerElement: this.playerElement, 544 playerElement: this.playerElement,
545 onPlayerElementChange: (element: HTMLVideoElement) => this.playerElement = element, 545 onPlayerElementChange: (element: HTMLVideoElement) => {
546 this.playerElement = element
547 },
546 548
547 videoDuration: videoInfo.duration, 549 videoDuration: videoInfo.duration,
548 enableHotkeys: true, 550 enableHotkeys: true,
@@ -577,10 +579,13 @@ export class PeerTubeEmbed {
577 }) 579 })
578 } 580 }
579 581
580 this.player = await PeertubePlayerManager.initialize(this.mode, options, (player: videojs.Player) => this.player = player) 582 this.player = await PeertubePlayerManager.initialize(this.mode, options, (player: videojs.Player) => {
583 this.player = player
584 })
585
581 this.player.on('customError', (event: any, data: any) => this.handleError(data.err, serverTranslations)) 586 this.player.on('customError', (event: any, data: any) => this.handleError(data.err, serverTranslations))
582 587
583 window[ 'videojsPlayer' ] = this.player 588 window['videojsPlayer'] = this.player
584 589
585 this.buildCSS() 590 this.buildCSS()
586 591
@@ -656,7 +661,7 @@ export class PeerTubeEmbed {
656 this.player.dispose() 661 this.player.dispose()
657 this.playerElement = null 662 this.playerElement = null
658 this.displayError('This video is not available because the remote instance is not responding.', translations) 663 this.displayError('This video is not available because the remote instance is not responding.', translations)
659 return 664
660 } 665 }
661 } 666 }
662 667
@@ -694,9 +699,9 @@ export class PeerTubeEmbed {
694 699
695 private async buildCaptions (serverTranslations: any, captionsResponse: Response): Promise<VideoJSCaption[]> { 700 private async buildCaptions (serverTranslations: any, captionsResponse: Response): Promise<VideoJSCaption[]> {
696 if (captionsResponse.ok) { 701 if (captionsResponse.ok) {
697 const { data } = (await captionsResponse.json()) as ResultList<VideoCaption> 702 const { data } = await captionsResponse.json()
698 703
699 return data.map(c => ({ 704 return data.map((c: VideoCaption) => ({
700 label: peertubeTranslate(c.language.label, serverTranslations), 705 label: peertubeTranslate(c.language.label, serverTranslations),
701 language: c.language.id, 706 language: c.language.id,
702 src: window.location.origin + c.captionPath 707 src: window.location.origin + c.captionPath
@@ -733,7 +738,7 @@ export class PeerTubeEmbed {
733 738
734 private getResourceId () { 739 private getResourceId () {
735 const urlParts = window.location.pathname.split('/') 740 const urlParts = window.location.pathname.split('/')
736 return urlParts[ urlParts.length - 1 ] 741 return urlParts[urlParts.length - 1]
737 } 742 }
738 743
739 private isPlaylistEmbed () { 744 private isPlaylistEmbed () {
@@ -751,7 +756,7 @@ export class PeerTubeEmbed {
751 } 756 }
752 757
753 private buildPeerTubeHelpers (translations?: { [ id: string ]: string }): RegisterClientHelpers { 758 private buildPeerTubeHelpers (translations?: { [ id: string ]: string }): RegisterClientHelpers {
754 function unimplemented (): any { 759 const unimplemented = () => {
755 throw new Error('This helper is not implemented in embed.') 760 throw new Error('This helper is not implemented in embed.')
756 } 761 }
757 762
@@ -780,9 +785,7 @@ export class PeerTubeEmbed {
780 enhancedMarkdownToHTML: unimplemented 785 enhancedMarkdownToHTML: unimplemented
781 }, 786 },
782 787
783 translate: (value: string) => { 788 translate: (value: string) => Promise.resolve(peertubeTranslate(value, translations))
784 return Promise.resolve(peertubeTranslate(value, translations))
785 }
786 } 789 }
787 } 790 }
788} 791}
diff --git a/client/src/standalone/videos/test-embed.ts b/client/src/standalone/videos/test-embed.ts
index 6e035c0c9..066b3e024 100644
--- a/client/src/standalone/videos/test-embed.ts
+++ b/client/src/standalone/videos/test-embed.ts
@@ -4,11 +4,11 @@ import { PeerTubePlayer } from '../player/player'
4 4
5window.addEventListener('load', async () => { 5window.addEventListener('load', async () => {
6 const urlParts = window.location.href.split('/') 6 const urlParts = window.location.href.split('/')
7 const lastPart = urlParts[ urlParts.length - 1 ] 7 const lastPart = urlParts[urlParts.length - 1]
8 8
9 const isPlaylist = window.location.pathname.startsWith('/video-playlists/') 9 const isPlaylist = window.location.pathname.startsWith('/video-playlists/')
10 10
11 const elementId = lastPart.indexOf('?') === -1 ? lastPart : lastPart.split('?')[ 0 ] 11 const elementId = lastPart.indexOf('?') === -1 ? lastPart : lastPart.split('?')[0]
12 12
13 const iframe = document.createElement('iframe') 13 const iframe = document.createElement('iframe')
14 iframe.src = isPlaylist 14 iframe.src = isPlaylist
@@ -18,14 +18,14 @@ window.addEventListener('load', async () => {
18 const mainElement = document.querySelector('#host') 18 const mainElement = document.querySelector('#host')
19 mainElement.appendChild(iframe) 19 mainElement.appendChild(iframe)
20 20
21 console.log(`Document finished loading.`) 21 console.log('Document finished loading.')
22 const player = new PeerTubePlayer(document.querySelector('iframe')) 22 const player = new PeerTubePlayer(document.querySelector('iframe'))
23 23
24 window[ 'player' ] = player 24 window['player'] = player
25 25
26 console.log(`Awaiting player ready...`) 26 console.log('Awaiting player ready...')
27 await player.ready 27 await player.ready
28 console.log(`Player is ready.`) 28 console.log('Player is ready.')
29 29
30 const monitoredEvents = [ 30 const monitoredEvents = [
31 'pause', 31 'pause',
@@ -39,7 +39,9 @@ window.addEventListener('load', async () => {
39 console.log(`PLAYER: now listening for event '${e}'`) 39 console.log(`PLAYER: now listening for event '${e}'`)
40 40
41 player.getCurrentPosition() 41 player.getCurrentPosition()
42 .then(position => document.getElementById('playlist-position').innerHTML = position + '') 42 .then(position => {
43 document.getElementById('playlist-position').innerHTML = position + ''
44 })
43 }) 45 })
44 46
45 let playbackRates: number[] = [] 47 let playbackRates: number[] = []
@@ -105,7 +107,7 @@ window.addEventListener('load', async () => {
105 107
106 updateCaptions() 108 updateCaptions()
107 109
108 const updateResolutions = ((resolutions: PeerTubeResolution[]) => { 110 const updateResolutions = (resolutions: PeerTubeResolution[]) => {
109 const resolutionListEl = document.querySelector('#resolution-list') 111 const resolutionListEl = document.querySelector('#resolution-list')
110 resolutionListEl.innerHTML = '' 112 resolutionListEl.innerHTML = ''
111 113
@@ -126,7 +128,7 @@ window.addEventListener('load', async () => {
126 resolutionListEl.appendChild(itemEl) 128 resolutionListEl.appendChild(itemEl)
127 } 129 }
128 }) 130 })
129 }) 131 }
130 132
131 player.getResolutions().then( 133 player.getResolutions().then(
132 resolutions => updateResolutions(resolutions)) 134 resolutions => updateResolutions(resolutions))