From edbaf690866a8ba39027eb459bbf4f7f857b1b49 Mon Sep 17 00:00:00 2001 From: reloxx13 Date: Wed, 26 Nov 2025 16:17:56 +0100 Subject: [PATCH 1/9] Revert "Migrate preview.url field in config" This reverts commit 11987cacf9f026f6e07cad3580ca6f754dc2fbe8. --- src/Service/ConfigurationService.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Service/ConfigurationService.php b/src/Service/ConfigurationService.php index a9a3dcaf9..007ad5ff8 100644 --- a/src/Service/ConfigurationService.php +++ b/src/Service/ConfigurationService.php @@ -213,11 +213,6 @@ protected function processMigration(array $config): array $config['preview']['mode'] = 'device_cam'; } - // Migrate Preview URL - if (isset($config['preview']['url']) && substr($config['preview']['url'], 0, 4) === 'url(' && substr($config['preview']['url'], -1) === ')') { - $config['preview']['url'] = trim(substr($config['preview']['url'], 4, -1), '"\''); - } - // Migrate Background URLs if (isset($config['background']) && is_array($config['background'])) { $baseUrl = PathUtility::getBaseUrl(); From 18d8d5d75c716915e399416f5e9d6e17a55720f1 Mon Sep 17 00:00:00 2001 From: reloxx13 Date: Wed, 26 Nov 2025 16:17:56 +0100 Subject: [PATCH 2/9] Revert "Ensure live preview is not cached" This reverts commit 80faa473070ece4c27ffce2f559d36d48394aec6. --- admin/captureconfig.php | 2 +- admin/wgetcaptureconfig.php | 2 +- assets/js/preview.js | 23 +++-------------------- assets/js/test-preview.js | 2 +- assets/sass/components/_preview.scss | 6 ++++++ docs/faq/index.md | 4 ++-- lib/configsetup.inc.php | 2 +- template/components/preview.php | 2 +- 8 files changed, 16 insertions(+), 27 deletions(-) diff --git a/admin/captureconfig.php b/admin/captureconfig.php index 5acde7ef8..e4af93df2 100644 --- a/admin/captureconfig.php +++ b/admin/captureconfig.php @@ -34,7 +34,7 @@ $config['picture']['cheese_time'] = '0'; $config['preview']['mode'] = 'url'; -$config['preview']['url'] = 'http://' . Environment::getIp() . ':1984/api/stream.mjpeg?src=photobooth'; +$config['preview']['url'] = 'url("http://' . Environment::getIp() . ':1984/api/stream.mjpeg?src=photobooth")'; $config['preview']['camTakesPic'] = false; try { diff --git a/admin/wgetcaptureconfig.php b/admin/wgetcaptureconfig.php index 4c2ad75fe..18edb01b6 100644 --- a/admin/wgetcaptureconfig.php +++ b/admin/wgetcaptureconfig.php @@ -34,7 +34,7 @@ $config['picture']['cheese_time'] = '0'; $config['preview']['mode'] = 'url'; -$config['preview']['url'] = 'http://' . Environment::getIp() . ':1984/api/stream.mjpeg?src=photobooth'; +$config['preview']['url'] = 'url("http://' . Environment::getIp() . ':1984/api/stream.mjpeg?src=photobooth")'; $config['preview']['camTakesPic'] = false; try { diff --git a/assets/js/preview.js b/assets/js/preview.js index a72fc692f..2cb3e5bbd 100644 --- a/assets/js/preview.js +++ b/assets/js/preview.js @@ -1,22 +1,5 @@ /* eslint n/no-unsupported-features/node-builtins: "off" */ /* globals photoBooth photoboothTools */ - -function addCacheBustingParam(url) { - const timestamp = new Date().getTime(); - - if (url.includes('?')) { - return `${url}&t=${timestamp}`; - } - - return `${url}?t=${timestamp}`; -} - -function getRootProperty(property) { - const root = document.documentElement; - const style = getComputedStyle(root); - return style.getPropertyValue(property).trim(); -} - const photoboothPreview = (function () { // vars const CameraDisplayMode = { @@ -196,8 +179,8 @@ const photoboothPreview = (function () { } else if (config.preview.mode === PreviewMode.URL.valueOf()) { photoboothTools.console.logDev('Preview: Preview at countdown from URL.'); setTimeout(function () { - url.attr('src', addCacheBustingParam(getRootProperty('--background-preview'))); url.show(); + url.addClass('streaming'); }, config.preview.url_delay); } break; @@ -208,8 +191,8 @@ const photoboothPreview = (function () { } else if (config.preview.mode === PreviewMode.URL.valueOf()) { photoboothTools.console.logDev('Preview: Preview from URL.'); setTimeout(function () { - url.attr('src', addCacheBustingParam(getRootProperty('--background-preview'))); url.show(); + url.addClass('streaming'); }, config.preview.url_delay); } break; @@ -235,8 +218,8 @@ const photoboothPreview = (function () { tracks.forEach((track) => track.stop()); api.stream = null; } + url.removeClass('streaming'); url.hide(); - url.attr('src', ''); video.hide(); pictureFrame.hide(); collageFrame.hide(); diff --git a/assets/js/test-preview.js b/assets/js/test-preview.js index b32b57728..4a3a8b9eb 100644 --- a/assets/js/test-preview.js +++ b/assets/js/test-preview.js @@ -96,7 +96,7 @@ const photoboothPreviewTest = (function () { if (config.preview.mode === PreviewMode.DEVICE.valueOf()) { photoboothPreview.stopVideo(); } else if (config.preview.mode === PreviewMode.URL.valueOf()) { - previewIpcam.attr('src', ''); + previewIpcam.removeClass('streaming'); previewIpcam.hide(); } diff --git a/assets/sass/components/_preview.scss b/assets/sass/components/_preview.scss index 1b39e2b44..48eda7ea9 100644 --- a/assets/sass/components/_preview.scss +++ b/assets/sass/components/_preview.scss @@ -92,3 +92,9 @@ scale: 1 -1; } } + +#preview--ipcam { + &.streaming { + background-image: var(--background-preview); + } +} diff --git a/docs/faq/index.md b/docs/faq/index.md index 1daac3063..ef6aedc9f 100644 --- a/docs/faq/index.md +++ b/docs/faq/index.md @@ -476,7 +476,7 @@ If you like to have the same preview independent of the device you access Photob Make sure to have a stream available you can use (e.g. from your Webcam, Smartphone Camera or Raspberry Pi Camera) - Admin panel config _"Preview mode"_: `from URL` -- Admin panel config _"Preview-URL"_ example (add needed IP address instead): `http://192.168.0.2:8081` +- Admin panel config _"Preview-URL"_ example (add needed IP address instead): `url(http://192.168.0.2:8081)` **Note** @@ -488,7 +488,7 @@ Make sure to have a stream available you can use (e.g. from your Webcam, Smartph If you want to use a stream from your DSLR or Pi Camera, install go2rtc and setup needed service to use. -go2rtc can be accessed at `http://localhost:1984`. Use `http://localhost:1984/api/stream.mjpeg?src=photobooth` as _"Preview-URL"_ (replace `localhost` with Photobooths IP for remote access). +go2rtc can be accessed at `http://localhost:1984`. Use `url("http://localhost:1984/api/stream.mjpeg?src=photobooth")` as _"Preview-URL"_ (replace `localhost` with Photobooths IP for remote access). To be able to also capture images you need to adjust the capture command. _"Commands"_: _"Take picture command"_: `capture %s` diff --git a/lib/configsetup.inc.php b/lib/configsetup.inc.php index c643b2fc8..6003c3ea9 100644 --- a/lib/configsetup.inc.php +++ b/lib/configsetup.inc.php @@ -1513,7 +1513,7 @@ 'preview_url' => [ 'type' => 'input', 'name' => 'preview[url]', - 'placeholder' => 'http://localhost:8081', + 'placeholder' => 'url(http://localhost:8081)', 'value' => htmlentities($config['preview']['url'] ?? ''), ], 'preview_url_delay' => [ diff --git a/template/components/preview.php b/template/components/preview.php index e84dd9376..30c943f4a 100644 --- a/template/components/preview.php +++ b/template/components/preview.php @@ -45,7 +45,7 @@ echo '
'; echo '
'; echo ''; -echo ''; +echo '
'; echo '
' . $languageService->translate('no_preview') . '
'; echo '
'; From 7881f93174ecf84be2fa3b7d986a2760e63aeec5 Mon Sep 17 00:00:00 2001 From: reloxx13 Date: Wed, 26 Nov 2025 14:44:29 +0100 Subject: [PATCH 3/9] fix ios cache busting on preview fix --- assets/js/preview.js | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/assets/js/preview.js b/assets/js/preview.js index 2cb3e5bbd..713ee1ba0 100644 --- a/assets/js/preview.js +++ b/assets/js/preview.js @@ -1,5 +1,28 @@ /* eslint n/no-unsupported-features/node-builtins: "off" */ /* globals photoBooth photoboothTools */ + +function addCacheBustingParam() { + const url = getBasePreviewUrl(); + const timestamp = new Date().getTime(); + + if (url.includes('?')) { + return `${url}&t=${timestamp}`; + } + + return `${url}?t=${timestamp}`; +} + +function getBasePreviewUrl() { + if (!config.preview || !config.preview.url) { + return ''; + } + + const raw = config.preview.url; + const match = raw.match(/^url\((['"]?)(.+?)\1\)$/); + + return match ? match[2] : raw; +} + const photoboothPreview = (function () { // vars const CameraDisplayMode = { @@ -179,6 +202,7 @@ const photoboothPreview = (function () { } else if (config.preview.mode === PreviewMode.URL.valueOf()) { photoboothTools.console.logDev('Preview: Preview at countdown from URL.'); setTimeout(function () { + url.css('background-image', 'url("' + addCacheBustingParam() + '")'); url.show(); url.addClass('streaming'); }, config.preview.url_delay); @@ -191,6 +215,7 @@ const photoboothPreview = (function () { } else if (config.preview.mode === PreviewMode.URL.valueOf()) { photoboothTools.console.logDev('Preview: Preview from URL.'); setTimeout(function () { + url.css('background-image', 'url("' + addCacheBustingParam() + '")'); url.show(); url.addClass('streaming'); }, config.preview.url_delay); @@ -220,6 +245,7 @@ const photoboothPreview = (function () { } url.removeClass('streaming'); url.hide(); + url.css('background-image', 'none'); video.hide(); pictureFrame.hide(); collageFrame.hide(); From aa01b921363029ce1f8bbbf30218809aeab983a0 Mon Sep 17 00:00:00 2001 From: reloxx13 Date: Wed, 10 Dec 2025 19:27:18 +0100 Subject: [PATCH 4/9] =?UTF-8?q?rename=20cache=20busting=20function,=20remo?= =?UTF-8?q?ve=20leftover=20url()=C2=B4s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- admin/captureconfig.php | 2 +- admin/wgetcaptureconfig.php | 2 +- assets/js/preview.js | 9 ++++++--- lib/configsetup.inc.php | 2 +- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/admin/captureconfig.php b/admin/captureconfig.php index e4af93df2..5acde7ef8 100644 --- a/admin/captureconfig.php +++ b/admin/captureconfig.php @@ -34,7 +34,7 @@ $config['picture']['cheese_time'] = '0'; $config['preview']['mode'] = 'url'; -$config['preview']['url'] = 'url("http://' . Environment::getIp() . ':1984/api/stream.mjpeg?src=photobooth")'; +$config['preview']['url'] = 'http://' . Environment::getIp() . ':1984/api/stream.mjpeg?src=photobooth'; $config['preview']['camTakesPic'] = false; try { diff --git a/admin/wgetcaptureconfig.php b/admin/wgetcaptureconfig.php index 18edb01b6..4c2ad75fe 100644 --- a/admin/wgetcaptureconfig.php +++ b/admin/wgetcaptureconfig.php @@ -34,7 +34,7 @@ $config['picture']['cheese_time'] = '0'; $config['preview']['mode'] = 'url'; -$config['preview']['url'] = 'url("http://' . Environment::getIp() . ':1984/api/stream.mjpeg?src=photobooth")'; +$config['preview']['url'] = 'http://' . Environment::getIp() . ':1984/api/stream.mjpeg?src=photobooth'; $config['preview']['camTakesPic'] = false; try { diff --git a/assets/js/preview.js b/assets/js/preview.js index 713ee1ba0..7410682df 100644 --- a/assets/js/preview.js +++ b/assets/js/preview.js @@ -1,7 +1,7 @@ /* eslint n/no-unsupported-features/node-builtins: "off" */ /* globals photoBooth photoboothTools */ -function addCacheBustingParam() { +function getPreviewUrlWithCacheBusting() { const url = getBasePreviewUrl(); const timestamp = new Date().getTime(); @@ -18,6 +18,7 @@ function getBasePreviewUrl() { } const raw = config.preview.url; + //remove url("") if present const match = raw.match(/^url\((['"]?)(.+?)\1\)$/); return match ? match[2] : raw; @@ -202,7 +203,8 @@ const photoboothPreview = (function () { } else if (config.preview.mode === PreviewMode.URL.valueOf()) { photoboothTools.console.logDev('Preview: Preview at countdown from URL.'); setTimeout(function () { - url.css('background-image', 'url("' + addCacheBustingParam() + '")'); + url.css('background-image', + 'url("' + getPreviewUrlWithCacheBusting() + '")'); url.show(); url.addClass('streaming'); }, config.preview.url_delay); @@ -215,7 +217,8 @@ const photoboothPreview = (function () { } else if (config.preview.mode === PreviewMode.URL.valueOf()) { photoboothTools.console.logDev('Preview: Preview from URL.'); setTimeout(function () { - url.css('background-image', 'url("' + addCacheBustingParam() + '")'); + url.css('background-image', + 'url("' + getPreviewUrlWithCacheBusting() + '")'); url.show(); url.addClass('streaming'); }, config.preview.url_delay); diff --git a/lib/configsetup.inc.php b/lib/configsetup.inc.php index 6003c3ea9..c643b2fc8 100644 --- a/lib/configsetup.inc.php +++ b/lib/configsetup.inc.php @@ -1513,7 +1513,7 @@ 'preview_url' => [ 'type' => 'input', 'name' => 'preview[url]', - 'placeholder' => 'url(http://localhost:8081)', + 'placeholder' => 'http://localhost:8081', 'value' => htmlentities($config['preview']['url'] ?? ''), ], 'preview_url_delay' => [ From 42561eda737d50a090f345ffe1c3732da71cf1cd Mon Sep 17 00:00:00 2001 From: reloxx13 Date: Wed, 10 Dec 2025 19:31:11 +0100 Subject: [PATCH 5/9] fix for manual page sidebar Undefined variable $appVersion --- manual/index.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/manual/index.php b/manual/index.php index 92ca37415..2af298d44 100644 --- a/manual/index.php +++ b/manual/index.php @@ -19,7 +19,12 @@ $configsetup = require PathUtility::getAbsolutePath('lib/configsetup.inc.php'); $languageService = LanguageService::getInstance(); -$pageTitle = 'Manual - ' . ApplicationService::getInstance()->getTitle(); + +$appName = ApplicationService::getInstance()->getTitle(); +$appVersion = ApplicationService::getInstance()->getVersion(); +$page = 'Manual'; +$pageTitle = $page . ' - ' . $appName . ' (' . $appVersion . ')'; + include PathUtility::getAbsolutePath('admin/components/head.admin.php'); include PathUtility::getAbsolutePath('admin/helper/index.php'); @@ -31,7 +36,7 @@
From a5817134a71276115995bd2ad32595143c8dedfb Mon Sep 17 00:00:00 2001 From: reloxx13 Date: Wed, 10 Dec 2025 19:40:58 +0100 Subject: [PATCH 6/9] fix ci --- assets/js/preview.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/assets/js/preview.js b/assets/js/preview.js index 7410682df..6aa22ea7d 100644 --- a/assets/js/preview.js +++ b/assets/js/preview.js @@ -1,4 +1,5 @@ /* eslint n/no-unsupported-features/node-builtins: "off" */ + /* globals photoBooth photoboothTools */ function getPreviewUrlWithCacheBusting() { @@ -203,8 +204,7 @@ const photoboothPreview = (function () { } else if (config.preview.mode === PreviewMode.URL.valueOf()) { photoboothTools.console.logDev('Preview: Preview at countdown from URL.'); setTimeout(function () { - url.css('background-image', - 'url("' + getPreviewUrlWithCacheBusting() + '")'); + url.css('background-image', 'url("' + getPreviewUrlWithCacheBusting() + '")'); url.show(); url.addClass('streaming'); }, config.preview.url_delay); @@ -217,8 +217,7 @@ const photoboothPreview = (function () { } else if (config.preview.mode === PreviewMode.URL.valueOf()) { photoboothTools.console.logDev('Preview: Preview from URL.'); setTimeout(function () { - url.css('background-image', - 'url("' + getPreviewUrlWithCacheBusting() + '")'); + url.css('background-image', 'url("' + getPreviewUrlWithCacheBusting() + '")'); url.show(); url.addClass('streaming'); }, config.preview.url_delay); From 36aaa363183afc9a102fe80b97b13fcab05c9e78 Mon Sep 17 00:00:00 2001 From: Andreas Skomski Date: Thu, 18 Dec 2025 17:15:20 +0100 Subject: [PATCH 7/9] docs: fix go2rtc config instructions --- docs/faq/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/faq/index.md b/docs/faq/index.md index ef6aedc9f..6d82cc67d 100644 --- a/docs/faq/index.md +++ b/docs/faq/index.md @@ -488,7 +488,7 @@ Make sure to have a stream available you can use (e.g. from your Webcam, Smartph If you want to use a stream from your DSLR or Pi Camera, install go2rtc and setup needed service to use. -go2rtc can be accessed at `http://localhost:1984`. Use `url("http://localhost:1984/api/stream.mjpeg?src=photobooth")` as _"Preview-URL"_ (replace `localhost` with Photobooths IP for remote access). +go2rtc can be accessed at `http://localhost:1984`. Use `http://localhost:1984/api/stream.mjpeg?src=photobooth` as _"Preview-URL"_ (replace `localhost` with Photobooths IP for remote access). To be able to also capture images you need to adjust the capture command. _"Commands"_: _"Take picture command"_: `capture %s` From 2afab13761240f7bb59c3831baf87a9468d8f195 Mon Sep 17 00:00:00 2001 From: Andreas Skomski Date: Thu, 18 Dec 2025 17:16:34 +0100 Subject: [PATCH 8/9] docs: fix url --- docs/faq/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/faq/index.md b/docs/faq/index.md index 6d82cc67d..1daac3063 100644 --- a/docs/faq/index.md +++ b/docs/faq/index.md @@ -476,7 +476,7 @@ If you like to have the same preview independent of the device you access Photob Make sure to have a stream available you can use (e.g. from your Webcam, Smartphone Camera or Raspberry Pi Camera) - Admin panel config _"Preview mode"_: `from URL` -- Admin panel config _"Preview-URL"_ example (add needed IP address instead): `url(http://192.168.0.2:8081)` +- Admin panel config _"Preview-URL"_ example (add needed IP address instead): `http://192.168.0.2:8081` **Note** From 0dd39951a6cf330280531b896b7f214299285292 Mon Sep 17 00:00:00 2001 From: reloxx13 Date: Fri, 19 Dec 2025 14:23:32 +0100 Subject: [PATCH 9/9] add Migrate Preview URL, remove surrounding url("...") --- src/Service/ConfigurationService.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Service/ConfigurationService.php b/src/Service/ConfigurationService.php index 007ad5ff8..e90b94ee0 100644 --- a/src/Service/ConfigurationService.php +++ b/src/Service/ConfigurationService.php @@ -213,6 +213,11 @@ protected function processMigration(array $config): array $config['preview']['mode'] = 'device_cam'; } + // Migrate Preview URL, remove surrounding url("...") + if (isset($config['preview']['url']) && substr($config['preview']['url'], 0, 4) === 'url(' && substr($config['preview']['url'], -1) === ')') { + $config['preview']['url'] = trim(substr($config['preview']['url'], 4, -1), '"\''); + } + // Migrate Background URLs if (isset($config['background']) && is_array($config['background'])) { $baseUrl = PathUtility::getBaseUrl();