mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-02-06 19:25:22 +03:00
add ability to playback exports on exports screen
This commit is contained in:
parent
6aedc39a9a
commit
7d0733c3e7
35
web/src/components/DialogLarge.jsx
Normal file
35
web/src/components/DialogLarge.jsx
Normal file
@ -0,0 +1,35 @@
|
||||
import { h, Fragment } from 'preact';
|
||||
import { createPortal } from 'preact/compat';
|
||||
import { useState, useEffect } from 'preact/hooks';
|
||||
|
||||
export default function LargeDialog({ children, portalRootID = 'dialogs' }) {
|
||||
const portalRoot = portalRootID && document.getElementById(portalRootID);
|
||||
const [show, setShow] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
window.requestAnimationFrame(() => {
|
||||
setShow(true);
|
||||
});
|
||||
}, []);
|
||||
|
||||
const dialog = (
|
||||
<Fragment>
|
||||
<div
|
||||
data-testid="scrim"
|
||||
key="scrim"
|
||||
className="fixed bg-fixed inset-0 z-10 flex justify-center items-center bg-black bg-opacity-40"
|
||||
>
|
||||
<div
|
||||
role="modal"
|
||||
className={`absolute rounded shadow-2xl bg-white dark:bg-gray-700 w-4/5 text-gray-900 dark:text-white transition-transform transition-opacity duration-75 transform scale-90 opacity-0 ${
|
||||
show ? 'scale-100 opacity-100' : ''
|
||||
}`}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
</Fragment>
|
||||
);
|
||||
|
||||
return portalRoot ? createPortal(dialog, portalRoot) : dialog;
|
||||
}
|
||||
@ -6,11 +6,15 @@ import axios from 'axios';
|
||||
import { baseUrl } from '../api/baseUrl';
|
||||
import { Fragment } from 'preact';
|
||||
import ActivityIndicator from '../components/ActivityIndicator';
|
||||
import { Play } from '../icons/Play';
|
||||
import LargeDialog from '../components/DialogLarge';
|
||||
import VideoPlayer from '../components/VideoPlayer';
|
||||
|
||||
export default function Export() {
|
||||
const { data: config } = useSWR('config');
|
||||
const { data: exports } = useSWR('exports/', (url) => axios({ baseURL: baseUrl, url }).then((res) => res.data));
|
||||
|
||||
// Export States
|
||||
const [camera, setCamera] = useState('select');
|
||||
const [playback, setPlayback] = useState('select');
|
||||
const [message, setMessage] = useState({ text: '', error: false });
|
||||
@ -26,6 +30,10 @@ export default function Export() {
|
||||
const [endDate, setEndDate] = useState(localISODate);
|
||||
const [endTime, setEndTime] = useState('23:59');
|
||||
|
||||
// Playback States
|
||||
|
||||
const [selectedClip, setSelectedClip] = useState();
|
||||
|
||||
const onHandleExport = () => {
|
||||
if (camera == 'select') {
|
||||
setMessage({ text: 'A camera needs to be selected.', error: true });
|
||||
@ -74,6 +82,38 @@ export default function Export() {
|
||||
<div className={`max-h-20 ${message.error ? 'text-red-500' : 'text-green-500'}`}>{message.text}</div>
|
||||
)}
|
||||
|
||||
{selectedClip && (
|
||||
<LargeDialog>
|
||||
<div className="min-w-[720px] max-w-7xl">
|
||||
<Heading className="p-2">Playback</Heading>
|
||||
<VideoPlayer
|
||||
options={{
|
||||
preload: 'auto',
|
||||
autoplay: true,
|
||||
sources: [
|
||||
{
|
||||
src: `${baseUrl}exports/${selectedClip}`,
|
||||
type: 'video/mp4',
|
||||
},
|
||||
],
|
||||
}}
|
||||
seekOptions={{ forward: 10, backward: 5 }}
|
||||
onReady={(player) => {
|
||||
this.player = player;
|
||||
}}
|
||||
onDispose={() => {
|
||||
this.player = null;
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="p-2 flex justify-start flex-row-reverse space-x-2">
|
||||
<Button className="ml-2" onClick={() => setSelectedClip('')} type="text">
|
||||
Close
|
||||
</Button>
|
||||
</div>
|
||||
</LargeDialog>
|
||||
)}
|
||||
|
||||
<div className="xl:flex justify-between">
|
||||
<div>
|
||||
<div>
|
||||
@ -144,7 +184,7 @@ export default function Export() {
|
||||
{exports && (
|
||||
<div className="p-4 bg-gray-800 xl:w-1/2">
|
||||
<Heading size="md">Exports</Heading>
|
||||
<Exports exports={exports} />
|
||||
<Exports exports={exports} onSetClip={(clip) => setSelectedClip(clip)} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@ -152,7 +192,7 @@ export default function Export() {
|
||||
);
|
||||
}
|
||||
|
||||
function Exports({ exports }) {
|
||||
function Exports({ exports, onSetClip }) {
|
||||
return (
|
||||
<Fragment>
|
||||
{exports.map((item) => (
|
||||
@ -166,6 +206,9 @@ function Exports({ exports }) {
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex justify-start items-center">
|
||||
<Button type="iconOnly" onClick={() => onSetClip(item.name)}>
|
||||
<Play className="h-6 w-6 text-green-600" />
|
||||
</Button>
|
||||
<a className="text-blue-500 hover:underline" href={`${baseUrl}exports/${item.name}`} download>
|
||||
{item.name.substring(0, item.name.length - 4)}
|
||||
</a>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user