aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/src
diff options
context:
space:
mode:
Diffstat (limited to 'client/src')
-rw-r--r--client/src/standalone/player/definitions.ts24
-rw-r--r--client/src/standalone/player/events.ts56
-rw-r--r--client/src/standalone/player/player.ts104
-rw-r--r--client/src/standalone/videos/embed.ts120
-rw-r--r--client/src/standalone/videos/test-embed.ts32
5 files changed, 165 insertions, 171 deletions
diff --git a/client/src/standalone/player/definitions.ts b/client/src/standalone/player/definitions.ts
index 6920672a7..7f9ef9b6f 100644
--- a/client/src/standalone/player/definitions.ts
+++ b/client/src/standalone/player/definitions.ts
@@ -1,18 +1,16 @@
1
2export interface EventHandler<T> { 1export interface EventHandler<T> {
3 (ev : T) : void 2 (ev: T): void
4} 3}
5 4
6export type PlayerEventType = 5export type PlayerEventType =
7 'pause' | 'play' | 6 'pause' | 'play' |
8 'playbackStatusUpdate' | 7 'playbackStatusUpdate' |
9 'playbackStatusChange' | 8 'playbackStatusChange' |
10 'resolutionUpdate' 9 'resolutionUpdate'
11;
12 10
13export interface PeerTubeResolution { 11export interface PeerTubeResolution {
14 id : any 12 id: any
15 label : string 13 label: string
16 src : string 14 src: string
17 active : boolean 15 active: boolean
18} \ No newline at end of file 16}
diff --git a/client/src/standalone/player/events.ts b/client/src/standalone/player/events.ts
index c01328352..f1639ef19 100644
--- a/client/src/standalone/player/events.ts
+++ b/client/src/standalone/player/events.ts
@@ -1,48 +1,48 @@
1import { EventHandler } from "./definitions" 1import { EventHandler } from './definitions'
2 2
3interface PlayerEventRegistrar { 3interface PlayerEventRegistrar {
4 registrations : Function[] 4 registrations: Function[]
5} 5}
6 6
7interface PlayerEventRegistrationMap { 7interface PlayerEventRegistrationMap {
8 [name : string] : PlayerEventRegistrar 8 [ name: string ]: PlayerEventRegistrar
9} 9}
10 10
11export class EventRegistrar { 11export class EventRegistrar {
12 12
13 private eventRegistrations : PlayerEventRegistrationMap = {} 13 private eventRegistrations: PlayerEventRegistrationMap = {}
14 14
15 public bindToChannel(channel : Channel.MessagingChannel) { 15 public bindToChannel (channel: Channel.MessagingChannel) {
16 for (let name of Object.keys(this.eventRegistrations)) 16 for (let name of Object.keys(this.eventRegistrations)) {
17 channel.bind(name, (txn, params) => this.fire(name, params)) 17 channel.bind(name, (txn, params) => this.fire(name, params))
18 } 18 }
19 }
19 20
20 public registerTypes(names : string[]) { 21 public registerTypes (names: string[]) {
21 for (let name of names) 22 for (let name of names) {
22 this.eventRegistrations[name] = { registrations: [] } 23 this.eventRegistrations[ name ] = { registrations: [] }
23 } 24 }
25 }
24 26
25 public fire<T>(name : string, event : T) { 27 public fire<T> (name: string, event: T) {
26 this.eventRegistrations[name].registrations.forEach(x => x(event)) 28 this.eventRegistrations[ name ].registrations.forEach(x => x(event))
29 }
30
31 public addListener<T> (name: string, handler: EventHandler<T>) {
32 if (!this.eventRegistrations[ name ]) {
33 console.warn(`PeerTube: addEventListener(): The event '${name}' is not supported`)
34 return false
27 } 35 }
28 36
29 public addListener<T>(name : string, handler : EventHandler<T>) { 37 this.eventRegistrations[ name ].registrations.push(handler)
30 if (!this.eventRegistrations[name]) { 38 return true
31 console.warn(`PeerTube: addEventListener(): The event '${name}' is not supported`) 39 }
32 return false
33 }
34 40
35 this.eventRegistrations[name].registrations.push(handler) 41 public removeListener<T> (name: string, handler: EventHandler<T>) {
36 return true 42 if (!this.eventRegistrations[ name ]) return false
37 }
38 43
39 public removeListener<T>(name : string, handler : EventHandler<T>) { 44 this.eventRegistrations[ name ].registrations = this.eventRegistrations[ name ].registrations.filter(x => x === handler)
40 if (!this.eventRegistrations[name])
41 return false
42 45
43 this.eventRegistrations[name].registrations = 46 return true
44 this.eventRegistrations[name].registrations.filter(x => x === handler) 47 }
45
46 return true
47 }
48} 48}
diff --git a/client/src/standalone/player/player.ts b/client/src/standalone/player/player.ts
index 9fc648d25..91a5e73f3 100644
--- a/client/src/standalone/player/player.ts
+++ b/client/src/standalone/player/player.ts
@@ -3,29 +3,35 @@ import { EventRegistrar } from './events'
3import { EventHandler, PlayerEventType, PeerTubeResolution } from './definitions' 3import { EventHandler, PlayerEventType, PeerTubeResolution } from './definitions'
4 4
5const PASSTHROUGH_EVENTS = [ 5const PASSTHROUGH_EVENTS = [
6 'pause', 'play', 6 'pause',
7 'play',
7 'playbackStatusUpdate', 8 'playbackStatusUpdate',
8 'playbackStatusChange', 9 'playbackStatusChange',
9 'resolutionUpdate' 10 'resolutionUpdate'
10] 11]
11 12
12/** 13/**
13 * Allows for programmatic control of a PeerTube embed running in an <iframe> 14 * Allows for programmatic control of a PeerTube embed running in an <iframe>
14 * within a web page. 15 * within a web page.
15 */ 16 */
16export class PeerTubePlayer { 17export class PeerTubePlayer {
18
19 private eventRegistrar: EventRegistrar = new EventRegistrar()
20 private channel: Channel.MessagingChannel
21 private readyPromise: Promise<void>
22
17 /** 23 /**
18 * Construct a new PeerTubePlayer for the given PeerTube embed iframe. 24 * Construct a new PeerTubePlayer for the given PeerTube embed iframe.
19 * Optionally provide a `scope` to ensure that messages are not crossed 25 * Optionally provide a `scope` to ensure that messages are not crossed
20 * between multiple PeerTube embeds. The string passed here must match the 26 * between multiple PeerTube embeds. The string passed here must match the
21 * `scope=` query parameter on the embed URL. 27 * `scope=` query parameter on the embed URL.
22 * 28 *
23 * @param embedElement 29 * @param embedElement
24 * @param scope 30 * @param scope
25 */ 31 */
26 constructor( 32 constructor (
27 private embedElement : HTMLIFrameElement, 33 private embedElement: HTMLIFrameElement,
28 private scope? : string 34 private scope?: string
29 ) { 35 ) {
30 this.eventRegistrar.registerTypes(PASSTHROUGH_EVENTS) 36 this.eventRegistrar.registerTypes(PASSTHROUGH_EVENTS)
31 37
@@ -33,55 +39,51 @@ export class PeerTubePlayer {
33 this.prepareToBeReady() 39 this.prepareToBeReady()
34 } 40 }
35 41
36 private eventRegistrar : EventRegistrar = new EventRegistrar()
37 private channel : Channel.MessagingChannel
38 private readyPromise : Promise<void>
39
40 /** 42 /**
41 * Destroy the player object and remove the associated player from the DOM. 43 * Destroy the player object and remove the associated player from the DOM.
42 */ 44 */
43 destroy() { 45 destroy () {
44 this.embedElement.remove() 46 this.embedElement.remove()
45 } 47 }
46 48
47 /** 49 /**
48 * Listen to an event emitted by this player. 50 * Listen to an event emitted by this player.
49 * 51 *
50 * @param event One of the supported event types 52 * @param event One of the supported event types
51 * @param handler A handler which will be passed an event object (or undefined if no event object is included) 53 * @param handler A handler which will be passed an event object (or undefined if no event object is included)
52 */ 54 */
53 addEventListener(event : PlayerEventType, handler : EventHandler<any>): boolean { 55 addEventListener (event: PlayerEventType, handler: EventHandler<any>): boolean {
54 return this.eventRegistrar.addListener(event, handler) 56 return this.eventRegistrar.addListener(event, handler)
55 } 57 }
56 58
57 /** 59 /**
58 * Remove an event listener previously added with addEventListener(). 60 * Remove an event listener previously added with addEventListener().
59 * 61 *
60 * @param event The name of the event previously listened to 62 * @param event The name of the event previously listened to
61 * @param handler 63 * @param handler
62 */ 64 */
63 removeEventListener(event : PlayerEventType, handler : EventHandler<any>): boolean { 65 removeEventListener (event: PlayerEventType, handler: EventHandler<any>): boolean {
64 return this.eventRegistrar.removeListener(event, handler) 66 return this.eventRegistrar.removeListener(event, handler)
65 } 67 }
66 68
67 /** 69 /**
68 * Promise resolves when the player is ready. 70 * Promise resolves when the player is ready.
69 */ 71 */
70 get ready(): Promise<void> { 72 get ready (): Promise<void> {
71 return this.readyPromise 73 return this.readyPromise
72 } 74 }
73 75
74 /** 76 /**
75 * Tell the embed to start/resume playback 77 * Tell the embed to start/resume playback
76 */ 78 */
77 async play() { 79 async play () {
78 await this.sendMessage('play') 80 await this.sendMessage('play')
79 } 81 }
80 82
81 /** 83 /**
82 * Tell the embed to pause playback. 84 * Tell the embed to pause playback.
83 */ 85 */
84 async pause() { 86 async pause () {
85 await this.sendMessage('pause') 87 await this.sendMessage('pause')
86 } 88 }
87 89
@@ -89,7 +91,7 @@ export class PeerTubePlayer {
89 * Tell the embed to change the audio volume 91 * Tell the embed to change the audio volume
90 * @param value A number from 0 to 1 92 * @param value A number from 0 to 1
91 */ 93 */
92 async setVolume(value : number) { 94 async setVolume (value: number) {
93 await this.sendMessage('setVolume', value) 95 await this.sendMessage('setVolume', value)
94 } 96 }
95 97
@@ -97,62 +99,62 @@ export class PeerTubePlayer {
97 * Get the current volume level in the embed. 99 * Get the current volume level in the embed.
98 * @param value A number from 0 to 1 100 * @param value A number from 0 to 1
99 */ 101 */
100 async getVolume(): Promise<number> { 102 async getVolume (): Promise<number> {
101 return await this.sendMessage<void, number>('setVolume') 103 return this.sendMessage<void, number>('setVolume')
102 } 104 }
103 105
104 /** 106 /**
105 * Tell the embed to seek to a specific position (in seconds) 107 * Tell the embed to seek to a specific position (in seconds)
106 * @param seconds 108 * @param seconds
107 */ 109 */
108 async seek(seconds : number) { 110 async seek (seconds: number) {
109 await this.sendMessage('seek', seconds) 111 await this.sendMessage('seek', seconds)
110 } 112 }
111 113
112 /** 114 /**
113 * Tell the embed to switch resolutions to the resolution identified 115 * Tell the embed to switch resolutions to the resolution identified
114 * by the given ID. 116 * by the given ID.
115 * 117 *
116 * @param resolutionId The ID of the resolution as found with getResolutions() 118 * @param resolutionId The ID of the resolution as found with getResolutions()
117 */ 119 */
118 async setResolution(resolutionId : any) { 120 async setResolution (resolutionId: any) {
119 await this.sendMessage('setResolution', resolutionId) 121 await this.sendMessage('setResolution', resolutionId)
120 } 122 }
121 123
122 /** 124 /**
123 * Retrieve a list of the available resolutions. This may change later, listen to the 125 * Retrieve a list of the available resolutions. This may change later, listen to the
124 * `resolutionUpdate` event with `addEventListener` in order to be updated as the available 126 * `resolutionUpdate` event with `addEventListener` in order to be updated as the available
125 * resolutions change. 127 * resolutions change.
126 */ 128 */
127 async getResolutions(): Promise<PeerTubeResolution[]> { 129 async getResolutions (): Promise<PeerTubeResolution[]> {
128 return await this.sendMessage<void, PeerTubeResolution[]>('getResolutions') 130 return this.sendMessage<void, PeerTubeResolution[]>('getResolutions')
129 } 131 }
130 132
131 /** 133 /**
132 * Retrieve a list of available playback rates. 134 * Retrieve a list of available playback rates.
133 */ 135 */
134 async getPlaybackRates() : Promise<number[]> { 136 async getPlaybackRates (): Promise<number[]> {
135 return await this.sendMessage<void, number[]>('getPlaybackRates') 137 return this.sendMessage<void, number[]>('getPlaybackRates')
136 } 138 }
137 139
138 /** 140 /**
139 * Get the current playback rate. Defaults to 1 (1x playback rate). 141 * Get the current playback rate. Defaults to 1 (1x playback rate).
140 */ 142 */
141 async getPlaybackRate() : Promise<number> { 143 async getPlaybackRate (): Promise<number> {
142 return await this.sendMessage<void, number>('getPlaybackRate') 144 return this.sendMessage<void, number>('getPlaybackRate')
143 } 145 }
144 146
145 /** 147 /**
146 * Set the playback rate. Should be one of the options returned by getPlaybackRates(). 148 * Set the playback rate. Should be one of the options returned by getPlaybackRates().
147 * Passing 0.5 means half speed, 1 means normal, 2 means 2x speed, etc. 149 * Passing 0.5 means half speed, 1 means normal, 2 means 2x speed, etc.
148 * 150 *
149 * @param rate 151 * @param rate
150 */ 152 */
151 async setPlaybackRate(rate : number) { 153 async setPlaybackRate (rate: number) {
152 await this.sendMessage('setPlaybackRate', rate) 154 await this.sendMessage('setPlaybackRate', rate)
153 } 155 }
154 156
155 private constructChannel() { 157 private constructChannel () {
156 this.channel = Channel.build({ 158 this.channel = Channel.build({
157 window: this.embedElement.contentWindow, 159 window: this.embedElement.contentWindow,
158 origin: '*', 160 origin: '*',
@@ -160,14 +162,16 @@ export class PeerTubePlayer {
160 }) 162 })
161 this.eventRegistrar.bindToChannel(this.channel) 163 this.eventRegistrar.bindToChannel(this.channel)
162 } 164 }
163 165
164 private prepareToBeReady() { 166 private prepareToBeReady () {
165 let readyResolve, readyReject 167 let readyResolve: Function
168 let readyReject: Function
169
166 this.readyPromise = new Promise<void>((res, rej) => { 170 this.readyPromise = new Promise<void>((res, rej) => {
167 readyResolve = res 171 readyResolve = res
168 readyReject = rej 172 readyReject = rej
169 }) 173 })
170 174
171 this.channel.bind('ready', success => success ? readyResolve() : readyReject()) 175 this.channel.bind('ready', success => success ? readyResolve() : readyReject())
172 this.channel.call({ 176 this.channel.call({
173 method: 'isReady', 177 method: 'isReady',
@@ -175,7 +179,7 @@ export class PeerTubePlayer {
175 }) 179 })
176 } 180 }
177 181
178 private sendMessage<TIn, TOut>(method : string, params? : TIn): Promise<TOut> { 182 private sendMessage<TIn, TOut> (method: string, params?: TIn): Promise<TOut> {
179 return new Promise<TOut>((resolve, reject) => { 183 return new Promise<TOut>((resolve, reject) => {
180 this.channel.call({ 184 this.channel.call({
181 method, params, 185 method, params,
@@ -187,4 +191,4 @@ export class PeerTubePlayer {
187} 191}
188 192
189// put it on the window as well as the export 193// put it on the window as well as the export
190window['PeerTubePlayer'] = PeerTubePlayer \ No newline at end of file 194window[ 'PeerTubePlayer' ] = PeerTubePlayer
diff --git a/client/src/standalone/videos/embed.ts b/client/src/standalone/videos/embed.ts
index e9baf64d0..a4196600a 100644
--- a/client/src/standalone/videos/embed.ts
+++ b/client/src/standalone/videos/embed.ts
@@ -22,23 +22,21 @@ import * as Channel from 'jschannel'
22 22
23import { VideoDetails } from '../../../../shared' 23import { VideoDetails } from '../../../../shared'
24import { addContextMenu, getVideojsOptions, loadLocale } from '../../assets/player/peertube-player' 24import { addContextMenu, getVideojsOptions, loadLocale } from '../../assets/player/peertube-player'
25import { PeerTubeResolution } from '../player/definitions'; 25import { PeerTubeResolution } from '../player/definitions'
26 26
27/** 27/**
28 * Embed API exposes control of the embed player to the outside world via 28 * Embed API exposes control of the embed player to the outside world via
29 * JSChannels and window.postMessage 29 * JSChannels and window.postMessage
30 */ 30 */
31class PeerTubeEmbedApi { 31class PeerTubeEmbedApi {
32 constructor( 32 private channel: Channel.MessagingChannel
33 private embed : PeerTubeEmbed
34 ) {
35 }
36
37 private channel : Channel.MessagingChannel
38 private isReady = false 33 private isReady = false
39 private resolutions : PeerTubeResolution[] = null 34 private resolutions: PeerTubeResolution[] = null
35
36 constructor (private embed: PeerTubeEmbed) {
37 }
40 38
41 initialize() { 39 initialize () {
42 this.constructChannel() 40 this.constructChannel()
43 this.setupStateTracking() 41 this.setupStateTracking()
44 42
@@ -46,14 +44,14 @@ class PeerTubeEmbedApi {
46 44
47 this.notifyReady() 45 this.notifyReady()
48 } 46 }
49 47
50 private get element() { 48 private get element () {
51 return this.embed.videoElement 49 return this.embed.videoElement
52 } 50 }
53 51
54 private constructChannel() { 52 private constructChannel () {
55 let channel = Channel.build({ window: window.parent, origin: '*', scope: this.embed.scope }) 53 let channel = Channel.build({ window: window.parent, origin: '*', scope: this.embed.scope })
56 54
57 channel.bind('play', (txn, params) => this.embed.player.play()) 55 channel.bind('play', (txn, params) => this.embed.player.play())
58 channel.bind('pause', (txn, params) => this.embed.player.pause()) 56 channel.bind('pause', (txn, params) => this.embed.player.pause())
59 channel.bind('seek', (txn, time) => this.embed.player.currentTime(time)) 57 channel.bind('seek', (txn, time) => this.embed.player.currentTime(time))
@@ -69,9 +67,8 @@ class PeerTubeEmbedApi {
69 this.channel = channel 67 this.channel = channel
70 } 68 }
71 69
72 private setResolution(resolutionId : number) { 70 private setResolution (resolutionId: number) {
73 if (resolutionId === -1 && this.embed.player.peertube().isAutoResolutionForbidden()) 71 if (resolutionId === -1 && this.embed.player.peertube().isAutoResolutionForbidden()) return
74 return
75 72
76 // Auto resolution 73 // Auto resolution
77 if (resolutionId === -1) { 74 if (resolutionId === -1) {
@@ -86,14 +83,13 @@ class PeerTubeEmbedApi {
86 /** 83 /**
87 * Let the host know that we're ready to go! 84 * Let the host know that we're ready to go!
88 */ 85 */
89 private notifyReady() { 86 private notifyReady () {
90 this.isReady = true 87 this.isReady = true
91 this.channel.notify({ method: 'ready', params: true }) 88 this.channel.notify({ method: 'ready', params: true })
92 } 89 }
93 90
94 private setupStateTracking() { 91 private setupStateTracking () {
95 92 let currentState: 'playing' | 'paused' | 'unstarted' = 'unstarted'
96 let currentState : 'playing' | 'paused' | 'unstarted' = 'unstarted'
97 93
98 setInterval(() => { 94 setInterval(() => {
99 let position = this.element.currentTime 95 let position = this.element.currentTime
@@ -104,7 +100,7 @@ class PeerTubeEmbedApi {
104 params: { 100 params: {
105 position, 101 position,
106 volume, 102 volume,
107 playbackState: currentState, 103 playbackState: currentState
108 } 104 }
109 }) 105 })
110 }, 500) 106 }, 500)
@@ -125,7 +121,7 @@ class PeerTubeEmbedApi {
125 this.embed.player.peertube().on('videoFileUpdate', () => this.loadResolutions()) 121 this.embed.player.peertube().on('videoFileUpdate', () => this.loadResolutions())
126 } 122 }
127 123
128 private loadResolutions() { 124 private loadResolutions () {
129 let resolutions = [] 125 let resolutions = []
130 let currentResolutionId = this.embed.player.peertube().getCurrentResolutionId() 126 let currentResolutionId = this.embed.player.peertube().getCurrentResolutionId()
131 127
@@ -152,30 +148,28 @@ class PeerTubeEmbedApi {
152} 148}
153 149
154class PeerTubeEmbed { 150class PeerTubeEmbed {
155 constructor( 151 videoElement: HTMLVideoElement
156 private videoContainerId : string 152 player: any
157 ) { 153 playerOptions: any
158 this.videoElement = document.getElementById(videoContainerId) as HTMLVideoElement 154 api: PeerTubeEmbedApi = null
159 } 155 autoplay = false
160 156 controls = true
161 videoElement : HTMLVideoElement 157 muted = false
162 player : any 158 loop = false
163 playerOptions : any 159 enableApi = false
164 api : PeerTubeEmbedApi = null 160 startTime = 0
165 autoplay : boolean = false 161 scope = 'peertube'
166 controls : boolean = true 162
167 muted : boolean = false 163 static async main () {
168 loop : boolean = false
169 enableApi : boolean = false
170 startTime : number = 0
171 scope : string = 'peertube'
172
173 static async main() {
174 const videoContainerId = 'video-container' 164 const videoContainerId = 'video-container'
175 const embed = new PeerTubeEmbed(videoContainerId) 165 const embed = new PeerTubeEmbed(videoContainerId)
176 await embed.init() 166 await embed.init()
177 } 167 }
178 168
169 constructor (private videoContainerId: string) {
170 this.videoElement = document.getElementById(videoContainerId) as HTMLVideoElement
171 }
172
179 getVideoUrl (id: string) { 173 getVideoUrl (id: string) {
180 return window.location.origin + '/api/v1/videos/' + id 174 return window.location.origin + '/api/v1/videos/' + id
181 } 175 }
@@ -219,15 +213,7 @@ class PeerTubeEmbed {
219 return params.has(name) ? params.get(name) : defaultValue 213 return params.has(name) ? params.get(name) : defaultValue
220 } 214 }
221 215
222 private initializeApi() { 216 async init () {
223 if (!this.enableApi)
224 return
225
226 this.api = new PeerTubeEmbedApi(this)
227 this.api.initialize()
228 }
229
230 async init() {
231 try { 217 try {
232 await this.initCore() 218 await this.initCore()
233 } catch (e) { 219 } catch (e) {
@@ -235,7 +221,14 @@ class PeerTubeEmbed {
235 } 221 }
236 } 222 }
237 223
238 private loadParams() { 224 private initializeApi () {
225 if (!this.enableApi) return
226
227 this.api = new PeerTubeEmbedApi(this)
228 this.api.initialize()
229 }
230
231 private loadParams () {
239 try { 232 try {
240 let params = new URL(window.location.toString()).searchParams 233 let params = new URL(window.location.toString()).searchParams
241 234
@@ -248,24 +241,23 @@ class PeerTubeEmbed {
248 241
249 const startTimeParamString = params.get('start') 242 const startTimeParamString = params.get('start')
250 const startTimeParamNumber = parseInt(startTimeParamString, 10) 243 const startTimeParamNumber = parseInt(startTimeParamString, 10)
251 if (isNaN(startTimeParamNumber) === false) 244
252 this.startTime = startTimeParamNumber 245 if (isNaN(startTimeParamNumber) === false) this.startTime = startTimeParamNumber
253 } catch (err) { 246 } catch (err) {
254 console.error('Cannot get params from URL.', err) 247 console.error('Cannot get params from URL.', err)
255 } 248 }
256 } 249 }
257 250
258 private async initCore() { 251 private async initCore () {
259 const urlParts = window.location.href.split('/') 252 const urlParts = window.location.href.split('/')
260 const lastPart = urlParts[urlParts.length - 1] 253 const lastPart = urlParts[ urlParts.length - 1 ]
261 const videoId = lastPart.indexOf('?') === -1 ? lastPart : lastPart.split('?')[0] 254 const videoId = lastPart.indexOf('?') === -1 ? lastPart : lastPart.split('?')[ 0 ]
262 255
263 await loadLocale(window.location.origin, vjs, navigator.language) 256 await loadLocale(window.location.origin, vjs, navigator.language)
264 let response = await this.loadVideoInfo(videoId) 257 let response = await this.loadVideoInfo(videoId)
265 258
266 if (!response.ok) { 259 if (!response.ok) {
267 if (response.status === 404) 260 if (response.status === 404) return this.videoNotFound(this.videoElement)
268 return this.videoNotFound(this.videoElement)
269 261
270 return this.videoFetchError(this.videoElement) 262 return this.videoFetchError(this.videoElement)
271 } 263 }
@@ -279,7 +271,7 @@ class PeerTubeEmbed {
279 controls: this.controls, 271 controls: this.controls,
280 muted: this.muted, 272 muted: this.muted,
281 loop: this.loop, 273 loop: this.loop,
282 startTime : this.startTime, 274 startTime: this.startTime,
283 275
284 inactivityTimeout: 1500, 276 inactivityTimeout: 1500,
285 videoViewUrl: this.getVideoUrl(videoId) + '/views', 277 videoViewUrl: this.getVideoUrl(videoId) + '/views',
@@ -295,14 +287,15 @@ class PeerTubeEmbed {
295 this.playerOptions = videojsOptions 287 this.playerOptions = videojsOptions
296 this.player = vjs(this.videoContainerId, videojsOptions, () => { 288 this.player = vjs(this.videoContainerId, videojsOptions, () => {
297 289
298 window['videojsPlayer'] = this.player 290 window[ 'videojsPlayer' ] = this.player
299 291
300 if (this.controls) { 292 if (this.controls) {
301 (this.player as any).dock({ 293 this.player.dock({
302 title: videoInfo.name, 294 title: videoInfo.name,
303 description: this.player.localize('Uses P2P, others may know your IP is downloading this video.') 295 description: this.player.localize('Uses P2P, others may know your IP is downloading this video.')
304 }) 296 })
305 } 297 }
298
306 addContextMenu(this.player, window.location.origin + videoInfo.embedPath) 299 addContextMenu(this.player, window.location.origin + videoInfo.embedPath)
307 this.initializeApi() 300 this.initializeApi()
308 }) 301 })
@@ -310,3 +303,4 @@ class PeerTubeEmbed {
310} 303}
311 304
312PeerTubeEmbed.main() 305PeerTubeEmbed.main()
306 .catch(err => console.error('Cannot init embed.', err))
diff --git a/client/src/standalone/videos/test-embed.ts b/client/src/standalone/videos/test-embed.ts
index 721514488..c0181ed28 100644
--- a/client/src/standalone/videos/test-embed.ts
+++ b/client/src/standalone/videos/test-embed.ts
@@ -1,49 +1,47 @@
1import './test-embed.scss' 1import './test-embed.scss'
2import { PeerTubePlayer } from '../player/player'; 2import { PeerTubePlayer } from '../player/player'
3import { PlayerEventType } from '../player/definitions'; 3import { PlayerEventType } from '../player/definitions'
4 4
5window.addEventListener('load', async () => { 5window.addEventListener('load', async () => {
6
7 const urlParts = window.location.href.split('/') 6 const urlParts = window.location.href.split('/')
8 const lastPart = urlParts[urlParts.length - 1] 7 const lastPart = urlParts[ urlParts.length - 1 ]
9 const videoId = lastPart.indexOf('?') === -1 ? lastPart : lastPart.split('?')[0] 8 const videoId = lastPart.indexOf('?') === -1 ? lastPart : lastPart.split('?')[ 0 ]
10 9
11 let iframe = document.createElement('iframe') 10 let iframe = document.createElement('iframe')
12 iframe.src = `/videos/embed/${videoId}?autoplay=1&controls=0&api=1` 11 iframe.src = `/videos/embed/${videoId}?autoplay=1&controls=0&api=1`
13 let mainElement = document.querySelector('#host') 12 let mainElement = document.querySelector('#host')
14 mainElement.appendChild(iframe); 13 mainElement.appendChild(iframe)
15 14
16 console.log(`Document finished loading.`) 15 console.log(`Document finished loading.`)
17 let player = new PeerTubePlayer(document.querySelector('iframe')) 16 let player = new PeerTubePlayer(document.querySelector('iframe'))
18 17
19 window['player'] = player 18 window[ 'player' ] = player
20 19
21 console.log(`Awaiting player ready...`) 20 console.log(`Awaiting player ready...`)
22 await player.ready 21 await player.ready
23 console.log(`Player is ready.`) 22 console.log(`Player is ready.`)
24 23
25 let monitoredEvents = [ 24 let monitoredEvents = [
26 'pause', 'play', 25 'pause',
27 'playbackStatusUpdate', 26 'play',
27 'playbackStatusUpdate',
28 'playbackStatusChange' 28 'playbackStatusChange'
29 ] 29 ]
30 30
31 monitoredEvents.forEach(e => { 31 monitoredEvents.forEach(e => {
32 player.addEventListener(<PlayerEventType>e, () => console.log(`PLAYER: event '${e}' received`)) 32 player.addEventListener(e as PlayerEventType, () => console.log(`PLAYER: event '${e}' received`))
33 console.log(`PLAYER: now listening for event '${e}'`) 33 console.log(`PLAYER: now listening for event '${e}'`)
34 }) 34 })
35 35
36 let playbackRates = [] 36 let playbackRates: number[] = []
37 let activeRate = 1
38 let currentRate = await player.getPlaybackRate() 37 let currentRate = await player.getPlaybackRate()
39 38
40 let updateRates = async () => { 39 let updateRates = async () => {
41
42 let rateListEl = document.querySelector('#rate-list') 40 let rateListEl = document.querySelector('#rate-list')
43 rateListEl.innerHTML = '' 41 rateListEl.innerHTML = ''
44 42
45 playbackRates.forEach(rate => { 43 playbackRates.forEach(rate => {
46 if (currentRate == rate) { 44 if (currentRate === rate) {
47 let itemEl = document.createElement('strong') 45 let itemEl = document.createElement('strong')
48 itemEl.innerText = `${rate} (active)` 46 itemEl.innerText = `${rate} (active)`
49 itemEl.style.display = 'block' 47 itemEl.style.display = 'block'
@@ -93,6 +91,6 @@ window.addEventListener('load', async () => {
93 91
94 player.getResolutions().then( 92 player.getResolutions().then(
95 resolutions => updateResolutions(resolutions)) 93 resolutions => updateResolutions(resolutions))
96 player.addEventListener('resolutionUpdate', 94 player.addEventListener('resolutionUpdate',
97 resolutions => updateResolutions(resolutions)) 95 resolutions => updateResolutions(resolutions))
98}) \ No newline at end of file 96})