From 9917fc316952eb247e7009d6ae5a810e6b71b6a8 Mon Sep 17 00:00:00 2001 From: Thibault Junin Date: Wed, 29 Oct 2025 14:20:11 +0000 Subject: [PATCH] feat(player): always show camera names + add UI config toggle (#20705) * feat(player): always show camera names + add UI config toggle * feat(settings): add toggle for displaying camera names in multi-camera views * update label and description for camera name setting --- web/public/locales/en/views/settings.json | 4 ++++ web/src/components/player/LivePlayer.tsx | 20 ++++++++++++-------- web/src/views/live/DraggableGridLayout.tsx | 2 ++ web/src/views/live/LiveCameraView.tsx | 1 + web/src/views/live/LiveDashboardView.tsx | 2 ++ web/src/views/settings/UiSettingsView.tsx | 19 +++++++++++++++++++ 6 files changed, 40 insertions(+), 8 deletions(-) diff --git a/web/public/locales/en/views/settings.json b/web/public/locales/en/views/settings.json index 3600529f0..f50272596 100644 --- a/web/public/locales/en/views/settings.json +++ b/web/public/locales/en/views/settings.json @@ -47,6 +47,10 @@ "playAlertVideos": { "label": "Play Alert Videos", "desc": "By default, recent alerts on the Live dashboard play as small looping videos. Disable this option to only show a static image of recent alerts on this device/browser." + }, + "displayCameraNames": { + "label": "Always Show Camera Names", + "desc": "Always show the camera names in a chip in the multi-camera live view dashboard." } }, "storedLayouts": { diff --git a/web/src/components/player/LivePlayer.tsx b/web/src/components/player/LivePlayer.tsx index 1f5ca703a..3e7dcde00 100644 --- a/web/src/components/player/LivePlayer.tsx +++ b/web/src/components/player/LivePlayer.tsx @@ -35,6 +35,7 @@ type LivePlayerProps = { streamName: string; preferredLiveMode: LivePlayerMode; showStillWithoutActivity?: boolean; + alwaysShowCameraName?: boolean; useWebGL: boolean; windowVisible?: boolean; playAudio?: boolean; @@ -59,6 +60,7 @@ export default function LivePlayer({ streamName, preferredLiveMode, showStillWithoutActivity = true, + alwaysShowCameraName = false, useWebGL = false, windowVisible = true, playAudio = false, @@ -433,20 +435,22 @@ export default function LivePlayer({ )} -
- {autoLive && - !offline && - activeMotion && - ((showStillWithoutActivity && !liveReady) || liveReady) && ( - - )} - {((offline && showStillWithoutActivity) || !cameraEnabled) && ( +
+ {(alwaysShowCameraName || + (offline && showStillWithoutActivity) || + !cameraEnabled) && ( {cameraName} )} + {autoLive && + !offline && + activeMotion && + ((showStillWithoutActivity && !liveReady) || liveReady) && ( + + )}
{showStats && ( diff --git a/web/src/views/live/DraggableGridLayout.tsx b/web/src/views/live/DraggableGridLayout.tsx index ccd1b373b..5239fe388 100644 --- a/web/src/views/live/DraggableGridLayout.tsx +++ b/web/src/views/live/DraggableGridLayout.tsx @@ -95,6 +95,7 @@ export default function DraggableGridLayout({ } = useCameraLiveMode(cameras, windowVisible); const [globalAutoLive] = usePersistence("autoLiveView", true); + const [displayCameraNames] = usePersistence("displayCameraNames", false); const { allGroupsStreamingSettings, setAllGroupsStreamingSettings } = useStreamingSettings(); @@ -610,6 +611,7 @@ export default function DraggableGridLayout({ streamName={streamName} autoLive={autoLive ?? globalAutoLive} showStillWithoutActivity={showStillWithoutActivity ?? true} + alwaysShowCameraName={displayCameraNames} useWebGL={useWebGL} cameraRef={cameraRef} className={cn( diff --git a/web/src/views/live/LiveCameraView.tsx b/web/src/views/live/LiveCameraView.tsx index 2253385ac..2d61d40f5 100644 --- a/web/src/views/live/LiveCameraView.tsx +++ b/web/src/views/live/LiveCameraView.tsx @@ -654,6 +654,7 @@ export default function LiveCameraView({ className={`${fullscreen ? "*:rounded-none" : ""}`} windowVisible showStillWithoutActivity={false} + alwaysShowCameraName={false} cameraConfig={camera} playAudio={audio} playInBackground={playInBackground ?? false} diff --git a/web/src/views/live/LiveDashboardView.tsx b/web/src/views/live/LiveDashboardView.tsx index 0aaca18a1..8b7dd1336 100644 --- a/web/src/views/live/LiveDashboardView.tsx +++ b/web/src/views/live/LiveDashboardView.tsx @@ -211,6 +211,7 @@ export default function LiveDashboardView({ } = useCameraLiveMode(cameras, windowVisible); const [globalAutoLive] = usePersistence("autoLiveView", true); + const [displayCameraNames] = usePersistence("displayCameraNames", false); const { allGroupsStreamingSettings, setAllGroupsStreamingSettings } = useStreamingSettings(); @@ -549,6 +550,7 @@ export default function LiveDashboardView({ preferredLiveMode={preferredLiveModes[camera.name] ?? "mse"} autoLive={autoLive ?? globalAutoLive} showStillWithoutActivity={showStillWithoutActivity ?? true} + alwaysShowCameraName={displayCameraNames} useWebGL={useWebGL} playInBackground={false} showStats={statsStates[camera.name]} diff --git a/web/src/views/settings/UiSettingsView.tsx b/web/src/views/settings/UiSettingsView.tsx index 432a989a7..092e3713d 100644 --- a/web/src/views/settings/UiSettingsView.tsx +++ b/web/src/views/settings/UiSettingsView.tsx @@ -92,6 +92,10 @@ export default function UiSettingsView() { // settings const [autoLive, setAutoLive] = usePersistence("autoLiveView", true); + const [cameraNames, setCameraName] = usePersistence( + "displayCameraNames", + false, + ); const [playbackRate, setPlaybackRate] = usePersistence("playbackRate", 1); const [weekStartsOn, setWeekStartsOn] = usePersistence("weekStartsOn", 0); const [alertVideos, setAlertVideos] = usePersistence("alertVideos", true); @@ -142,6 +146,21 @@ export default function UiSettingsView() {

{t("general.liveDashboard.playAlertVideos.desc")}

+
+
+ + +
+
+

{t("general.liveDashboard.displayCameraNames.desc")}

+
+