mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-08-01 16:42:18 +03:00
Feature: Share Timestamped URL for Camera Footage History (#22537)
* Initial copy timestamp url implementation
* revise url format
* Implement share timestamp dialog
* Use translations
* Add comments
* Add validations to shared link
* Switch to searchEffect implementation
* Add missing accessibility related dialog description
* Change URL format to unix timestamps
* Remove unnecessary useEffect
* Remove duplicated dialog title
* Fixes/improvements based off PR review comments
* Add missing cancel button & separators to dialog
* Make share description clearer
* Bugfix: guard against showing toasts twice
Because this effect ends up running multiple times
* Clamp future timestamps to now
* Revert "Bugfix: guard against showing toasts twice"
This reverts commit 99fa5e1dee.
* Use normal separator
Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com>
* Fixes based off PR review comments
* Bugfix: Share dialog was not receiving the player timestamp after removing key that triggered remounts
* Defer `setRecording` and return true from hook for cleanup
* Remove timeout defer hack in favor of refactored hook
* Attempt to replay video muted on NotAllowedError
* Use separate persistent mute and temporary forced mute states
* Align cancel button with other dialogs
* Prevent wrapping on dialog title
* Remove extra "back" button on mobile drawer
* Fix back navigation when coming from direct shared timestamp links
* Use new timeformat hook
* Simplify dialog radio buttons
* Apply suggestions from code review
Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com>
---------
Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com>
This commit is contained in:
@@ -216,7 +216,11 @@ export default function HlsVideoPlayer({
|
||||
|
||||
const [tallCamera, setTallCamera] = useState(false);
|
||||
const [isPlaying, setIsPlaying] = useState(true);
|
||||
const [muted, setMuted] = useUserPersistence("hlsPlayerMuted", true);
|
||||
const [persistedMuted, setPersistedMuted] = useUserPersistence(
|
||||
"hlsPlayerMuted",
|
||||
true,
|
||||
);
|
||||
const [temporaryMuted, setTemporaryMuted] = useState(false);
|
||||
const [volume, setVolume] = useOverlayState("playerVolume", 1.0);
|
||||
const [defaultPlaybackRate] = useUserPersistence("playbackRate", 1);
|
||||
const [playbackRate, setPlaybackRate] = useOverlayState(
|
||||
@@ -232,6 +236,16 @@ export default function HlsVideoPlayer({
|
||||
height: number;
|
||||
}>({ width: 0, height: 0 });
|
||||
|
||||
const muted = persistedMuted || temporaryMuted;
|
||||
|
||||
const onSetMuted = useCallback(
|
||||
(muted: boolean) => {
|
||||
setTemporaryMuted(false);
|
||||
setPersistedMuted(muted);
|
||||
},
|
||||
[setPersistedMuted],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isDesktop) {
|
||||
return;
|
||||
@@ -297,7 +311,7 @@ export default function HlsVideoPlayer({
|
||||
fullscreen: supportsFullscreen,
|
||||
}}
|
||||
setControlsOpen={setControlsOpen}
|
||||
setMuted={(muted) => setMuted(muted)}
|
||||
setMuted={onSetMuted}
|
||||
playbackRate={playbackRate ?? 1}
|
||||
hotKeys={hotKeys}
|
||||
onPlayPause={onPlayPause}
|
||||
@@ -404,9 +418,20 @@ export default function HlsVideoPlayer({
|
||||
: undefined
|
||||
}
|
||||
onVolumeChange={() => {
|
||||
setVolume(videoRef.current?.volume ?? 1.0, true);
|
||||
if (!frigateControls) {
|
||||
setMuted(videoRef.current?.muted);
|
||||
if (!videoRef.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
setVolume(videoRef.current.volume ?? 1.0, true);
|
||||
|
||||
if (frigateControls) {
|
||||
if (videoRef.current.muted && !persistedMuted) {
|
||||
setTemporaryMuted(true);
|
||||
} else if (!videoRef.current.muted && temporaryMuted) {
|
||||
setTemporaryMuted(false);
|
||||
}
|
||||
} else {
|
||||
setPersistedMuted(videoRef.current.muted);
|
||||
}
|
||||
}}
|
||||
onPlay={() => {
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
calculateInpointOffset,
|
||||
calculateSeekPosition,
|
||||
} from "@/utils/videoUtil";
|
||||
import { playWithTemporaryMuteFallback } from "@/utils/videoUtil.ts";
|
||||
|
||||
type PlayerMode = "playback" | "scrubbing";
|
||||
|
||||
@@ -107,7 +108,7 @@ export class DynamicVideoController {
|
||||
return new Promise((resolve) => {
|
||||
const onSeekedHandler = () => {
|
||||
this.playerController.removeEventListener("seeked", onSeekedHandler);
|
||||
this.playerController.play();
|
||||
playWithTemporaryMuteFallback(this.playerController);
|
||||
resolve(undefined);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user