From f5a97d36ff8afeb6749f7cbb5914faf1bd105c2d Mon Sep 17 00:00:00 2001 From: 4gray Date: Fri, 17 Jul 2026 19:48:39 +0200 Subject: [PATCH] feat(playback): expose shared picture-in-picture action --- apps/web/src/assets/i18n/ar.json | 2 + apps/web/src/assets/i18n/ary.json | 2 + apps/web/src/assets/i18n/by.json | 2 + apps/web/src/assets/i18n/de.json | 2 + apps/web/src/assets/i18n/el.json | 2 + apps/web/src/assets/i18n/en.json | 2 + apps/web/src/assets/i18n/es.json | 2 + apps/web/src/assets/i18n/fr.json | 2 + apps/web/src/assets/i18n/it.json | 2 + apps/web/src/assets/i18n/ja.json | 2 + apps/web/src/assets/i18n/ko.json | 2 + apps/web/src/assets/i18n/nl.json | 2 + apps/web/src/assets/i18n/pl.json | 2 + apps/web/src/assets/i18n/pt.json | 2 + apps/web/src/assets/i18n/ru.json | 2 + apps/web/src/assets/i18n/tr.json | 2 + apps/web/src/assets/i18n/zh.json | 2 + apps/web/src/assets/i18n/zhtw.json | 2 + .../player-controls.component.html | 30 ++++ ...trols.component.picture-in-picture.spec.ts | 162 ++++++++++++++++++ .../player-controls.component.ts | 13 +- 21 files changed, 235 insertions(+), 6 deletions(-) create mode 100644 libs/ui/playback/src/lib/player-controls/player-controls.component.picture-in-picture.spec.ts diff --git a/apps/web/src/assets/i18n/ar.json b/apps/web/src/assets/i18n/ar.json index 81cb8bfec..d1ff0c9ba 100644 --- a/apps/web/src/assets/i18n/ar.json +++ b/apps/web/src/assets/i18n/ar.json @@ -489,6 +489,8 @@ "RECORDING_FAILED_TO_START": "فشل بدء التسجيل.", "RECORDING_FAILED_TO_STOP": "فشل إيقاف التسجيل.", "SAVED_TO": "تم الحفظ في {{path}}", + "ENTER_PICTURE_IN_PICTURE": "تشغيل صورة داخل صورة", + "EXIT_PICTURE_IN_PICTURE": "إنهاء صورة داخل صورة", "ENTER_FULLSCREEN": "ملء الشاشة", "EXIT_FULLSCREEN": "الخروج من ملء الشاشة" } diff --git a/apps/web/src/assets/i18n/ary.json b/apps/web/src/assets/i18n/ary.json index 8615f456b..ccd51471c 100644 --- a/apps/web/src/assets/i18n/ary.json +++ b/apps/web/src/assets/i18n/ary.json @@ -489,6 +489,8 @@ "RECORDING_FAILED_TO_START": "التسجيل ما قدرش يبدا.", "RECORDING_FAILED_TO_STOP": "التسجيل ما قدرش يتوقف.", "SAVED_TO": "تحفظ في {{path}}", + "ENTER_PICTURE_IN_PICTURE": "شغّل صورة داخل صورة", + "EXIT_PICTURE_IN_PICTURE": "خرج من صورة داخل صورة", "ENTER_FULLSCREEN": "دخل لملء الشاشة", "EXIT_FULLSCREEN": "خرج من ملء الشاشة" } diff --git a/apps/web/src/assets/i18n/by.json b/apps/web/src/assets/i18n/by.json index 3c3f62f7f..3c8433486 100644 --- a/apps/web/src/assets/i18n/by.json +++ b/apps/web/src/assets/i18n/by.json @@ -489,6 +489,8 @@ "RECORDING_FAILED_TO_START": "Не ўдалося пачаць запіс.", "RECORDING_FAILED_TO_STOP": "Не ўдалося спыніць запіс.", "SAVED_TO": "Захавана ў {{path}}", + "ENTER_PICTURE_IN_PICTURE": "Уключыць рэжым «выява ў выяве»", + "EXIT_PICTURE_IN_PICTURE": "Выйсці з рэжыму «выява ў выяве»", "ENTER_FULLSCREEN": "Увайсці ў поўнаэкранны рэжым", "EXIT_FULLSCREEN": "Выйсці з поўнаэкраннага рэжыму" } diff --git a/apps/web/src/assets/i18n/de.json b/apps/web/src/assets/i18n/de.json index 4b311c69f..313309af8 100644 --- a/apps/web/src/assets/i18n/de.json +++ b/apps/web/src/assets/i18n/de.json @@ -489,6 +489,8 @@ "RECORDING_FAILED_TO_START": "Aufnahme konnte nicht gestartet werden.", "RECORDING_FAILED_TO_STOP": "Aufnahme konnte nicht gestoppt werden.", "SAVED_TO": "Gespeichert unter {{path}}", + "ENTER_PICTURE_IN_PICTURE": "Bild-in-Bild starten", + "EXIT_PICTURE_IN_PICTURE": "Bild-in-Bild beenden", "ENTER_FULLSCREEN": "Vollbild aktivieren", "EXIT_FULLSCREEN": "Vollbild beenden" } diff --git a/apps/web/src/assets/i18n/el.json b/apps/web/src/assets/i18n/el.json index c65264fa3..afc38a1f4 100644 --- a/apps/web/src/assets/i18n/el.json +++ b/apps/web/src/assets/i18n/el.json @@ -489,6 +489,8 @@ "RECORDING_FAILED_TO_START": "Η έναρξη της εγγραφής απέτυχε.", "RECORDING_FAILED_TO_STOP": "Η διακοπή της εγγραφής απέτυχε.", "SAVED_TO": "Αποθηκεύτηκε στο {{path}}", + "ENTER_PICTURE_IN_PICTURE": "Έναρξη εικόνας εντός εικόνας", + "EXIT_PICTURE_IN_PICTURE": "Έξοδος από εικόνα εντός εικόνας", "ENTER_FULLSCREEN": "Μετάβαση σε πλήρη οθόνη", "EXIT_FULLSCREEN": "Έξοδος από πλήρη οθόνη" } diff --git a/apps/web/src/assets/i18n/en.json b/apps/web/src/assets/i18n/en.json index dd305961d..5f33f3935 100644 --- a/apps/web/src/assets/i18n/en.json +++ b/apps/web/src/assets/i18n/en.json @@ -489,6 +489,8 @@ "RECORDING_FAILED_TO_START": "Recording failed to start.", "RECORDING_FAILED_TO_STOP": "Recording failed to stop.", "SAVED_TO": "Saved to {{path}}", + "ENTER_PICTURE_IN_PICTURE": "Enter picture-in-picture", + "EXIT_PICTURE_IN_PICTURE": "Exit picture-in-picture", "ENTER_FULLSCREEN": "Enter fullscreen", "EXIT_FULLSCREEN": "Exit fullscreen" } diff --git a/apps/web/src/assets/i18n/es.json b/apps/web/src/assets/i18n/es.json index 12395cd45..c05d3ffb7 100644 --- a/apps/web/src/assets/i18n/es.json +++ b/apps/web/src/assets/i18n/es.json @@ -489,6 +489,8 @@ "RECORDING_FAILED_TO_START": "No se pudo iniciar la grabación.", "RECORDING_FAILED_TO_STOP": "No se pudo detener la grabación.", "SAVED_TO": "Guardada en {{path}}", + "ENTER_PICTURE_IN_PICTURE": "Activar imagen en imagen", + "EXIT_PICTURE_IN_PICTURE": "Salir de imagen en imagen", "ENTER_FULLSCREEN": "Entrar en pantalla completa", "EXIT_FULLSCREEN": "Salir de pantalla completa" } diff --git a/apps/web/src/assets/i18n/fr.json b/apps/web/src/assets/i18n/fr.json index 769382a0c..f98222115 100644 --- a/apps/web/src/assets/i18n/fr.json +++ b/apps/web/src/assets/i18n/fr.json @@ -489,6 +489,8 @@ "RECORDING_FAILED_TO_START": "L'enregistrement n'a pas pu démarrer.", "RECORDING_FAILED_TO_STOP": "L'enregistrement n'a pas pu s'arrêter.", "SAVED_TO": "Enregistré dans {{path}}", + "ENTER_PICTURE_IN_PICTURE": "Activer le mode image dans l’image", + "EXIT_PICTURE_IN_PICTURE": "Quitter le mode image dans l’image", "ENTER_FULLSCREEN": "Passer en plein écran", "EXIT_FULLSCREEN": "Quitter le plein écran" } diff --git a/apps/web/src/assets/i18n/it.json b/apps/web/src/assets/i18n/it.json index becf1856a..13f846f00 100644 --- a/apps/web/src/assets/i18n/it.json +++ b/apps/web/src/assets/i18n/it.json @@ -489,6 +489,8 @@ "RECORDING_FAILED_TO_START": "Impossibile avviare la registrazione.", "RECORDING_FAILED_TO_STOP": "Impossibile interrompere la registrazione.", "SAVED_TO": "Salvato in {{path}}", + "ENTER_PICTURE_IN_PICTURE": "Attiva Picture-in-Picture", + "EXIT_PICTURE_IN_PICTURE": "Esci da Picture-in-Picture", "ENTER_FULLSCREEN": "Attiva schermo intero", "EXIT_FULLSCREEN": "Esci dallo schermo intero" } diff --git a/apps/web/src/assets/i18n/ja.json b/apps/web/src/assets/i18n/ja.json index 30277f87f..aa8e59c32 100644 --- a/apps/web/src/assets/i18n/ja.json +++ b/apps/web/src/assets/i18n/ja.json @@ -489,6 +489,8 @@ "RECORDING_FAILED_TO_START": "録画を開始できませんでした。", "RECORDING_FAILED_TO_STOP": "録画を停止できませんでした。", "SAVED_TO": "{{path}}に保存しました", + "ENTER_PICTURE_IN_PICTURE": "ピクチャーインピクチャーを開始", + "EXIT_PICTURE_IN_PICTURE": "ピクチャーインピクチャーを終了", "ENTER_FULLSCREEN": "全画面表示", "EXIT_FULLSCREEN": "全画面表示を終了" } diff --git a/apps/web/src/assets/i18n/ko.json b/apps/web/src/assets/i18n/ko.json index 27e08f9fe..fb8a6a661 100644 --- a/apps/web/src/assets/i18n/ko.json +++ b/apps/web/src/assets/i18n/ko.json @@ -489,6 +489,8 @@ "RECORDING_FAILED_TO_START": "녹화를 시작하지 못했습니다.", "RECORDING_FAILED_TO_STOP": "녹화를 중지하지 못했습니다.", "SAVED_TO": "{{path}}에 저장되었습니다", + "ENTER_PICTURE_IN_PICTURE": "PIP 모드 시작", + "EXIT_PICTURE_IN_PICTURE": "PIP 모드 종료", "ENTER_FULLSCREEN": "전체 화면", "EXIT_FULLSCREEN": "전체 화면 종료" } diff --git a/apps/web/src/assets/i18n/nl.json b/apps/web/src/assets/i18n/nl.json index ccf3ec726..153a6e6ae 100644 --- a/apps/web/src/assets/i18n/nl.json +++ b/apps/web/src/assets/i18n/nl.json @@ -489,6 +489,8 @@ "RECORDING_FAILED_TO_START": "Opname kon niet worden gestart.", "RECORDING_FAILED_TO_STOP": "Opname kon niet worden gestopt.", "SAVED_TO": "Opgeslagen in {{path}}", + "ENTER_PICTURE_IN_PICTURE": "Beeld-in-beeld starten", + "EXIT_PICTURE_IN_PICTURE": "Beeld-in-beeld sluiten", "ENTER_FULLSCREEN": "Volledig scherm openen", "EXIT_FULLSCREEN": "Volledig scherm sluiten" } diff --git a/apps/web/src/assets/i18n/pl.json b/apps/web/src/assets/i18n/pl.json index 0be167258..32d8608d6 100644 --- a/apps/web/src/assets/i18n/pl.json +++ b/apps/web/src/assets/i18n/pl.json @@ -489,6 +489,8 @@ "RECORDING_FAILED_TO_START": "Nie udało się rozpocząć nagrywania.", "RECORDING_FAILED_TO_STOP": "Nie udało się zatrzymać nagrywania.", "SAVED_TO": "Zapisano w {{path}}", + "ENTER_PICTURE_IN_PICTURE": "Włącz obraz w obrazie", + "EXIT_PICTURE_IN_PICTURE": "Wyłącz obraz w obrazie", "ENTER_FULLSCREEN": "Włącz pełny ekran", "EXIT_FULLSCREEN": "Wyłącz pełny ekran" } diff --git a/apps/web/src/assets/i18n/pt.json b/apps/web/src/assets/i18n/pt.json index 51ecc82f8..861f772e9 100644 --- a/apps/web/src/assets/i18n/pt.json +++ b/apps/web/src/assets/i18n/pt.json @@ -489,6 +489,8 @@ "RECORDING_FAILED_TO_START": "Falha ao iniciar a gravação.", "RECORDING_FAILED_TO_STOP": "Falha ao parar a gravação.", "SAVED_TO": "Salvo em {{path}}", + "ENTER_PICTURE_IN_PICTURE": "Ativar imagem em imagem", + "EXIT_PICTURE_IN_PICTURE": "Sair de imagem em imagem", "ENTER_FULLSCREEN": "Entrar em tela cheia", "EXIT_FULLSCREEN": "Sair da tela cheia" } diff --git a/apps/web/src/assets/i18n/ru.json b/apps/web/src/assets/i18n/ru.json index 1fa420759..d84865bde 100644 --- a/apps/web/src/assets/i18n/ru.json +++ b/apps/web/src/assets/i18n/ru.json @@ -489,6 +489,8 @@ "RECORDING_FAILED_TO_START": "Не удалось начать запись.", "RECORDING_FAILED_TO_STOP": "Не удалось остановить запись.", "SAVED_TO": "Сохранено в {{path}}", + "ENTER_PICTURE_IN_PICTURE": "Включить режим «картинка в картинке»", + "EXIT_PICTURE_IN_PICTURE": "Выйти из режима «картинка в картинке»", "ENTER_FULLSCREEN": "Во весь экран", "EXIT_FULLSCREEN": "Выйти из полноэкранного режима" } diff --git a/apps/web/src/assets/i18n/tr.json b/apps/web/src/assets/i18n/tr.json index 74a629255..6f0d14338 100644 --- a/apps/web/src/assets/i18n/tr.json +++ b/apps/web/src/assets/i18n/tr.json @@ -489,6 +489,8 @@ "RECORDING_FAILED_TO_START": "Kayıt başlatılamadı.", "RECORDING_FAILED_TO_STOP": "Kayıt durdurulamadı.", "SAVED_TO": "{{path}} konumuna kaydedildi", + "ENTER_PICTURE_IN_PICTURE": "Resim içinde resim modunu aç", + "EXIT_PICTURE_IN_PICTURE": "Resim içinde resim modundan çık", "ENTER_FULLSCREEN": "Tam ekrana geç", "EXIT_FULLSCREEN": "Tam ekrandan çık" } diff --git a/apps/web/src/assets/i18n/zh.json b/apps/web/src/assets/i18n/zh.json index 03fa17ac3..06f0bda98 100644 --- a/apps/web/src/assets/i18n/zh.json +++ b/apps/web/src/assets/i18n/zh.json @@ -489,6 +489,8 @@ "RECORDING_FAILED_TO_START": "录制启动失败。", "RECORDING_FAILED_TO_STOP": "录制停止失败。", "SAVED_TO": "已保存至 {{path}}", + "ENTER_PICTURE_IN_PICTURE": "进入画中画", + "EXIT_PICTURE_IN_PICTURE": "退出画中画", "ENTER_FULLSCREEN": "进入全屏", "EXIT_FULLSCREEN": "退出全屏" } diff --git a/apps/web/src/assets/i18n/zhtw.json b/apps/web/src/assets/i18n/zhtw.json index 97c7004c9..7d7653315 100644 --- a/apps/web/src/assets/i18n/zhtw.json +++ b/apps/web/src/assets/i18n/zhtw.json @@ -489,6 +489,8 @@ "RECORDING_FAILED_TO_START": "無法開始錄製。", "RECORDING_FAILED_TO_STOP": "無法停止錄製。", "SAVED_TO": "已儲存至 {{path}}", + "ENTER_PICTURE_IN_PICTURE": "進入子母畫面", + "EXIT_PICTURE_IN_PICTURE": "退出子母畫面", "ENTER_FULLSCREEN": "進入全螢幕", "EXIT_FULLSCREEN": "離開全螢幕" } diff --git a/libs/ui/playback/src/lib/player-controls/player-controls.component.html b/libs/ui/playback/src/lib/player-controls/player-controls.component.html index 646e65058..ecf13b621 100644 --- a/libs/ui/playback/src/lib/player-controls/player-controls.component.html +++ b/libs/ui/playback/src/lib/player-controls/player-controls.component.html @@ -568,6 +568,36 @@ } + @if (capabilities().pictureInPicture) { + + } + @if (capabilities().fullscreen) {