diff options
Diffstat (limited to 'client/src')
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 | ||
229 | videojs.registerPlugin('peerTubeHotkeysPlugin', PeerTubeHotkeysPlugin) | 254 | videojs.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' | |||
3 | function buildVideoOrPlaylistEmbed (options: { | 3 | function 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 | ||