Ensure all streaming settings are saved correctly on mobile (#16511)

* Ensure streaming settings are saved correctly on mobile

* remove extra check
This commit is contained in:
Josh Hawkins 2025-02-11 17:49:22 -06:00 committed by GitHub
parent 73fee6372b
commit 11baf237bc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 104 additions and 12 deletions

View File

@ -82,7 +82,7 @@ export default function LiveContextMenu({
); );
useEffect(() => { useEffect(() => {
if (cameraGroup) { if (cameraGroup && cameraGroup != "default") {
setGroupStreamingSettings(allGroupsStreamingSettings[cameraGroup]); setGroupStreamingSettings(allGroupsStreamingSettings[cameraGroup]);
} }
// set individual group when all groups changes // set individual group when all groups changes
@ -91,7 +91,12 @@ export default function LiveContextMenu({
const onSave = useCallback( const onSave = useCallback(
(settings: GroupStreamingSettings) => { (settings: GroupStreamingSettings) => {
if (!cameraGroup || !allGroupsStreamingSettings) { if (
!cameraGroup ||
!allGroupsStreamingSettings ||
cameraGroup == "default" ||
!settings
) {
return; return;
} }

View File

@ -14,7 +14,11 @@ import {
TooltipTrigger, TooltipTrigger,
} from "@/components/ui/tooltip"; } from "@/components/ui/tooltip";
import { usePersistence } from "@/hooks/use-persistence"; import { usePersistence } from "@/hooks/use-persistence";
import { CameraConfig, FrigateConfig } from "@/types/frigateConfig"; import {
AllGroupsStreamingSettings,
CameraConfig,
FrigateConfig,
} from "@/types/frigateConfig";
import { ReviewSegment } from "@/types/review"; import { ReviewSegment } from "@/types/review";
import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { import {
@ -38,6 +42,7 @@ import { FaCompress, FaExpand } from "react-icons/fa";
import useCameraLiveMode from "@/hooks/use-camera-live-mode"; import useCameraLiveMode from "@/hooks/use-camera-live-mode";
import { useResizeObserver } from "@/hooks/resize-observer"; import { useResizeObserver } from "@/hooks/resize-observer";
import LiveContextMenu from "@/components/menu/LiveContextMenu"; import LiveContextMenu from "@/components/menu/LiveContextMenu";
import { useStreamingSettings } from "@/context/streaming-settings-provider";
type LiveDashboardViewProps = { type LiveDashboardViewProps = {
cameras: CameraConfig[]; cameras: CameraConfig[];
@ -135,8 +140,6 @@ export default function LiveDashboardView({
// camera live views // camera live views
const [autoLiveView] = usePersistence("autoLiveView", true);
const [{ height: containerHeight }] = useResizeObserver(containerRef); const [{ height: containerHeight }] = useResizeObserver(containerRef);
const hasScrollbar = useMemo(() => { const hasScrollbar = useMemo(() => {
@ -198,6 +201,17 @@ export default function LiveDashboardView({
supportsAudioOutputStates, supportsAudioOutputStates,
} = useCameraLiveMode(cameras, windowVisible); } = useCameraLiveMode(cameras, windowVisible);
const [globalAutoLive] = usePersistence("autoLiveView", true);
const { allGroupsStreamingSettings, setAllGroupsStreamingSettings } =
useStreamingSettings();
const currentGroupStreamingSettings = useMemo(() => {
if (cameraGroup && cameraGroup != "default" && allGroupsStreamingSettings) {
return allGroupsStreamingSettings[cameraGroup];
}
}, [allGroupsStreamingSettings, cameraGroup]);
const cameraRef = useCallback( const cameraRef = useCallback(
(node: HTMLElement | null) => { (node: HTMLElement | null) => {
if (!visibleCameraObserver.current) { if (!visibleCameraObserver.current) {
@ -245,6 +259,25 @@ export default function LiveDashboardView({
})); }));
}; };
useEffect(() => {
if (!allGroupsStreamingSettings) {
return;
}
const initialAudioStates: AudioState = {};
const initialVolumeStates: VolumeState = {};
Object.entries(allGroupsStreamingSettings).forEach(([_, groupSettings]) => {
Object.entries(groupSettings).forEach(([camera, cameraSettings]) => {
initialAudioStates[camera] = cameraSettings.playAudio ?? false;
initialVolumeStates[camera] = cameraSettings.volume ?? 1;
});
});
setAudioStates(initialAudioStates);
setVolumeStates(initialVolumeStates);
}, [allGroupsStreamingSettings]);
const toggleAudio = (cameraName: string): void => { const toggleAudio = (cameraName: string): void => {
setAudioStates((prev) => ({ setAudioStates((prev) => ({
...prev, ...prev,
@ -252,12 +285,53 @@ export default function LiveDashboardView({
})); }));
}; };
const onSaveMuting = useCallback(
(playAudio: boolean) => {
if (
!cameraGroup ||
!allGroupsStreamingSettings ||
cameraGroup == "default"
) {
return;
}
const existingGroupSettings =
allGroupsStreamingSettings[cameraGroup] || {};
const updatedSettings: AllGroupsStreamingSettings = {
...Object.fromEntries(
Object.entries(allGroupsStreamingSettings || {}).filter(
([key]) => key !== cameraGroup,
),
),
[cameraGroup]: {
...existingGroupSettings,
...Object.fromEntries(
Object.entries(existingGroupSettings).map(
([cameraName, settings]) => [
cameraName,
{
...settings,
playAudio: playAudio,
},
],
),
),
},
};
setAllGroupsStreamingSettings?.(updatedSettings);
},
[cameraGroup, allGroupsStreamingSettings, setAllGroupsStreamingSettings],
);
const muteAll = (): void => { const muteAll = (): void => {
const updatedStates: Record<string, boolean> = {}; const updatedStates: Record<string, boolean> = {};
visibleCameras.forEach((cameraName) => { visibleCameras.forEach((cameraName) => {
updatedStates[cameraName] = false; updatedStates[cameraName] = false;
}); });
setAudioStates(updatedStates); setAudioStates(updatedStates);
onSaveMuting(false);
}; };
const unmuteAll = (): void => { const unmuteAll = (): void => {
@ -266,6 +340,7 @@ export default function LiveDashboardView({
updatedStates[cameraName] = true; updatedStates[cameraName] = true;
}); });
setAudioStates(updatedStates); setAudioStates(updatedStates);
onSaveMuting(true);
}; };
return ( return (
@ -392,19 +467,30 @@ export default function LiveDashboardView({
} else { } else {
grow = "aspect-video"; grow = "aspect-video";
} }
const streamName =
currentGroupStreamingSettings?.[camera.name]?.streamName ||
Object.values(camera.live.streams)?.[0];
const autoLive =
currentGroupStreamingSettings?.[camera.name]?.streamType !==
"no-streaming";
const showStillWithoutActivity =
currentGroupStreamingSettings?.[camera.name]?.streamType !==
"continuous";
const useWebGL =
currentGroupStreamingSettings?.[camera.name]
?.compatibilityMode || false;
return ( return (
<LiveContextMenu <LiveContextMenu
className={grow} className={grow}
key={camera.name} key={camera.name}
camera={camera.name} camera={camera.name}
cameraGroup={cameraGroup} cameraGroup={cameraGroup}
streamName={Object.values(camera.live.streams)?.[0]} streamName={streamName}
preferredLiveMode={preferredLiveModes[camera.name] ?? "mse"} preferredLiveMode={preferredLiveModes[camera.name] ?? "mse"}
isRestreamed={isRestreamedStates[camera.name]} isRestreamed={isRestreamedStates[camera.name]}
supportsAudio={ supportsAudio={
supportsAudioOutputStates[ supportsAudioOutputStates[streamName]?.supportsAudio ??
Object.values(camera.live.streams)?.[0] false
]?.supportsAudio ?? false
} }
audioState={audioStates[camera.name]} audioState={audioStates[camera.name]}
toggleAudio={() => toggleAudio(camera.name)} toggleAudio={() => toggleAudio(camera.name)}
@ -431,11 +517,12 @@ export default function LiveDashboardView({
} }
cameraConfig={camera} cameraConfig={camera}
preferredLiveMode={preferredLiveModes[camera.name] ?? "mse"} preferredLiveMode={preferredLiveModes[camera.name] ?? "mse"}
autoLive={autoLiveView} autoLive={autoLive ?? globalAutoLive}
useWebGL={false} showStillWithoutActivity={showStillWithoutActivity ?? true}
useWebGL={useWebGL}
playInBackground={false} playInBackground={false}
showStats={statsStates[camera.name]} showStats={statsStates[camera.name]}
streamName={Object.values(camera.live.streams)[0]} streamName={streamName}
onClick={() => onSelectCamera(camera.name)} onClick={() => onSelectCamera(camera.name)}
onError={(e) => handleError(camera.name, e)} onError={(e) => handleError(camera.name, e)}
onResetLiveMode={() => resetPreferredLiveMode(camera.name)} onResetLiveMode={() => resetPreferredLiveMode(camera.name)}