aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/src
diff options
context:
space:
mode:
Diffstat (limited to 'client/src')
-rw-r--r--client/src/app/shared/shared-share-modal/video-share.component.html29
-rw-r--r--client/src/app/shared/shared-share-modal/video-share.component.ts20
-rw-r--r--client/src/assets/player/shared/hotkeys/peertube-hotkeys-plugin.ts27
-rw-r--r--client/src/root-helpers/video.ts21
4 files changed, 78 insertions, 19 deletions
diff --git a/client/src/app/shared/shared-share-modal/video-share.component.html b/client/src/app/shared/shared-share-modal/video-share.component.html
index f4d249b41..01d351783 100644
--- a/client/src/app/shared/shared-share-modal/video-share.component.html
+++ b/client/src/app/shared/shared-share-modal/video-share.component.html
@@ -72,13 +72,21 @@
72 ></my-peertube-checkbox> 72 ></my-peertube-checkbox>
73 </div> 73 </div>
74 74
75 <div class="form-group"> 75 <ng-container *ngIf="isInPlaylistEmbedTab()">
76 <my-peertube-checkbox 76 <div class="form-group">
77 *ngIf="isInPlaylistEmbedTab()" 77 <my-peertube-checkbox
78 inputName="onlyEmbedUrl" [(ngModel)]="customizations.onlyEmbedUrl" 78 inputName="onlyEmbedUrl" [(ngModel)]="customizations.onlyEmbedUrl"
79 i18n-labelText labelText="Only display embed URL" 79 i18n-labelText labelText="Only display embed URL"
80 ></my-peertube-checkbox> 80 ></my-peertube-checkbox>
81 </div> 81 </div>
82
83 <div class="form-group">
84 <my-peertube-checkbox
85 inputName="responsive" [(ngModel)]="customizations.responsive"
86 i18n-labelText labelText="Responsive embed"
87 ></my-peertube-checkbox>
88 </div>
89 </ng-container>
82 90
83 <my-plugin-placeholder pluginId="share-modal-playlist-settings"></my-plugin-placeholder> 91 <my-plugin-placeholder pluginId="share-modal-playlist-settings"></my-plugin-placeholder>
84 </div> 92 </div>
@@ -230,6 +238,13 @@
230 <ng-container *ngIf="isInVideoEmbedTab()"> 238 <ng-container *ngIf="isInVideoEmbedTab()">
231 <div class="form-group"> 239 <div class="form-group">
232 <my-peertube-checkbox 240 <my-peertube-checkbox
241 inputName="responsive" [(ngModel)]="customizations.responsive"
242 i18n-labelText labelText="Responsive embed"
243 ></my-peertube-checkbox>
244 </div>
245
246 <div class="form-group">
247 <my-peertube-checkbox
233 inputName="title" [(ngModel)]="customizations.title" 248 inputName="title" [(ngModel)]="customizations.title"
234 i18n-labelText labelText="Display video title" 249 i18n-labelText labelText="Display video title"
235 ></my-peertube-checkbox> 250 ></my-peertube-checkbox>
diff --git a/client/src/app/shared/shared-share-modal/video-share.component.ts b/client/src/app/shared/shared-share-modal/video-share.component.ts
index e1db4a3b8..43229c330 100644
--- a/client/src/app/shared/shared-share-modal/video-share.component.ts
+++ b/client/src/app/shared/shared-share-modal/video-share.component.ts
@@ -29,6 +29,7 @@ type Customizations = {
29 warningTitle: boolean 29 warningTitle: boolean
30 controlBar: boolean 30 controlBar: boolean
31 peertubeLink: boolean 31 peertubeLink: boolean
32 responsive: boolean
32 33
33 includeVideoInPlaylist: boolean 34 includeVideoInPlaylist: boolean
34} 35}
@@ -100,6 +101,7 @@ export class VideoShareComponent {
100 warningTitle: true, 101 warningTitle: true,
101 controlBar: true, 102 controlBar: true,
102 peertubeLink: true, 103 peertubeLink: true,
104 responsive: false,
103 105
104 includeVideoInPlaylist: false 106 includeVideoInPlaylist: false
105 }, { 107 }, {
@@ -152,10 +154,11 @@ export class VideoShareComponent {
152 ) 154 )
153 } 155 }
154 156
155 async getVideoIframeCode () { 157 async getVideoEmbedCode (options: { responsive: boolean }) {
158 const { responsive } = options
156 return this.hooks.wrapFun( 159 return this.hooks.wrapFun(
157 buildVideoOrPlaylistEmbed, 160 buildVideoOrPlaylistEmbed,
158 { embedUrl: await this.getVideoEmbedUrl(), embedTitle: this.video.name }, 161 { embedUrl: await this.getVideoEmbedUrl(), embedTitle: this.video.name, responsive },
159 'video-watch', 162 'video-watch',
160 'filter:share.video-embed-code.build.params', 163 'filter:share.video-embed-code.build.params',
161 'filter:share.video-embed-code.build.result' 164 'filter:share.video-embed-code.build.result'
@@ -186,10 +189,11 @@ export class VideoShareComponent {
186 ) 189 )
187 } 190 }
188 191
189 async getPlaylistEmbedCode () { 192 async getPlaylistEmbedCode (options: { responsive: boolean }) {
193 const { responsive } = options
190 return this.hooks.wrapFun( 194 return this.hooks.wrapFun(
191 buildVideoOrPlaylistEmbed, 195 buildVideoOrPlaylistEmbed,
192 { embedUrl: await this.getPlaylistEmbedUrl(), embedTitle: this.playlist.displayName }, 196 { embedUrl: await this.getPlaylistEmbedUrl(), embedTitle: this.playlist.displayName, responsive },
193 'video-watch', 197 'video-watch',
194 'filter:share.video-playlist-embed-code.build.params', 198 'filter:share.video-playlist-embed-code.build.params',
195 'filter:share.video-playlist-embed-code.build.result' 199 'filter:share.video-playlist-embed-code.build.result'
@@ -204,15 +208,15 @@ export class VideoShareComponent {
204 if (this.playlist) { 208 if (this.playlist) {
205 this.playlistUrl = await this.getPlaylistUrl() 209 this.playlistUrl = await this.getPlaylistUrl()
206 this.playlistEmbedUrl = await this.getPlaylistEmbedUrl() 210 this.playlistEmbedUrl = await this.getPlaylistEmbedUrl()
207 this.playlistEmbedHTML = await this.getPlaylistEmbedCode() 211 this.playlistEmbedHTML = await this.getPlaylistEmbedCode({ responsive: this.customizations.responsive })
208 this.playlistEmbedSafeHTML = this.sanitizer.bypassSecurityTrustHtml(this.playlistEmbedHTML) 212 this.playlistEmbedSafeHTML = this.sanitizer.bypassSecurityTrustHtml(await this.getPlaylistEmbedCode({ responsive: false }))
209 } 213 }
210 214
211 if (this.video) { 215 if (this.video) {
212 this.videoUrl = await this.getVideoUrl() 216 this.videoUrl = await this.getVideoUrl()
213 this.videoEmbedUrl = await this.getVideoEmbedUrl() 217 this.videoEmbedUrl = await this.getVideoEmbedUrl()
214 this.videoEmbedHTML = await this.getVideoIframeCode() 218 this.videoEmbedHTML = await this.getVideoEmbedCode({ responsive: this.customizations.responsive })
215 this.videoEmbedSafeHTML = this.sanitizer.bypassSecurityTrustHtml(this.videoEmbedHTML) 219 this.videoEmbedSafeHTML = this.sanitizer.bypassSecurityTrustHtml(await this.getVideoEmbedCode({ responsive: false }))
216 } 220 }
217 } 221 }
218 222
diff --git a/client/src/assets/player/shared/hotkeys/peertube-hotkeys-plugin.ts b/client/src/assets/player/shared/hotkeys/peertube-hotkeys-plugin.ts
index f5b4b3919..2742b21a1 100644
--- a/client/src/assets/player/shared/hotkeys/peertube-hotkeys-plugin.ts
+++ b/client/src/assets/player/shared/hotkeys/peertube-hotkeys-plugin.ts
@@ -218,12 +218,37 @@ class PeerTubeHotkeysPlugin extends Plugin {
218 } 218 }
219 219
220 private isNaked (event: KeyboardEvent, key: string) { 220 private isNaked (event: KeyboardEvent, key: string) {
221 return (!event.ctrlKey && !event.altKey && !event.metaKey && !event.shiftKey && event.key === key) 221 if (key.length === 1) key = key.toUpperCase()
222
223 return (!event.ctrlKey && !event.altKey && !event.metaKey && !event.shiftKey && this.getLatinKey(event.key, event.code) === key)
222 } 224 }
223 225
224 private isNakedOrShift (event: KeyboardEvent, key: string) { 226 private isNakedOrShift (event: KeyboardEvent, key: string) {
225 return (!event.ctrlKey && !event.altKey && !event.metaKey && event.key === key) 227 return (!event.ctrlKey && !event.altKey && !event.metaKey && event.key === key)
226 } 228 }
229
230 // Thanks Maciej Krawczyk
231 // https://stackoverflow.com/questions/70211837/keyboard-shortcuts-commands-on-non-latin-alphabet-keyboards-javascript?rq=1
232 private getLatinKey (key: string, code: string) {
233 if (key.length !== 1) {
234 return key
235 }
236
237 const capitalHetaCode = 880
238 const isNonLatin = key.charCodeAt(0) >= capitalHetaCode
239
240 if (isNonLatin) {
241 if (code.indexOf('Key') === 0 && code.length === 4) { // i.e. 'KeyW'
242 return code.charAt(3)
243 }
244
245 if (code.indexOf('Digit') === 0 && code.length === 6) { // i.e. 'Digit7'
246 return code.charAt(5)
247 }
248 }
249
250 return key.toUpperCase()
251 }
227} 252}
228 253
229videojs.registerPlugin('peerTubeHotkeysPlugin', PeerTubeHotkeysPlugin) 254videojs.registerPlugin('peerTubeHotkeysPlugin', PeerTubeHotkeysPlugin)
diff --git a/client/src/root-helpers/video.ts b/client/src/root-helpers/video.ts
index 107ba1eba..01feddbdc 100644
--- a/client/src/root-helpers/video.ts
+++ b/client/src/root-helpers/video.ts
@@ -3,19 +3,34 @@ import { HTMLServerConfig, Video, VideoPrivacy } from '@shared/models'
3function buildVideoOrPlaylistEmbed (options: { 3function buildVideoOrPlaylistEmbed (options: {
4 embedUrl: string 4 embedUrl: string
5 embedTitle: string 5 embedTitle: string
6 responsive?: boolean
6}) { 7}) {
7 const { embedUrl, embedTitle } = options 8 const { embedUrl, embedTitle, responsive = false } = options
8 9
9 const iframe = document.createElement('iframe') 10 const iframe = document.createElement('iframe')
10 11
11 iframe.title = embedTitle 12 iframe.title = embedTitle
12 iframe.width = '560' 13 iframe.width = responsive ? '100%' : '560'
13 iframe.height = '315' 14 iframe.height = responsive ? '100%' : '315'
14 iframe.src = embedUrl 15 iframe.src = embedUrl
15 iframe.frameBorder = '0' 16 iframe.frameBorder = '0'
16 iframe.allowFullscreen = true 17 iframe.allowFullscreen = true
17 iframe.sandbox.add('allow-same-origin', 'allow-scripts', 'allow-popups') 18 iframe.sandbox.add('allow-same-origin', 'allow-scripts', 'allow-popups')
18 19
20 if (responsive) {
21 const wrapper = document.createElement('div')
22
23 wrapper.style.position = 'relative'
24 wrapper.style['padding-top'] = '56.25%'
25
26 iframe.style.position = 'absolute'
27 iframe.style.inset = '0'
28
29 wrapper.appendChild(iframe)
30
31 return wrapper.outerHTML
32 }
33
19 return iframe.outerHTML 34 return iframe.outerHTML
20} 35}
21 36