diff --git a/web/src/components/card/ExportCard.tsx b/web/src/components/card/ExportCard.tsx index 3d374b859d..3510cb39de 100644 --- a/web/src/components/card/ExportCard.tsx +++ b/web/src/components/card/ExportCard.tsx @@ -1,32 +1,87 @@ import { baseUrl } from "@/api/baseUrl"; import ActivityIndicator from "../indicators/activity-indicator"; -import { Card } from "../ui/card"; -import { LuPlay, LuTrash } from "react-icons/lu"; +import { LuTrash } from "react-icons/lu"; import { Button } from "../ui/button"; +import { useMemo, useRef, useState } from "react"; +import { isDesktop } from "react-device-detect"; +import { FaPlay } from "react-icons/fa"; +import Chip from "../indicators/Chip"; type ExportProps = { file: { name: string; }; - onSelect: (file: string) => void; onDelete: (file: string) => void; }; -export default function ExportCard({ file, onSelect, onDelete }: ExportProps) { +export default function ExportCard({ file, onDelete }: ExportProps) { + const videoRef = useRef(null); + const [hovered, setHovered] = useState(false); + const [playing, setPlaying] = useState(false); + const inProgress = useMemo( + () => file.name.startsWith("in_progress"), + [file.name], + ); + return ( - - {file.name.startsWith("in_progress") ? ( +
setHovered(true) : undefined + } + onMouseLeave={ + isDesktop && !inProgress ? () => setHovered(false) : undefined + } + onClick={isDesktop || inProgress ? undefined : () => setHovered(!hovered)} + > + {!playing && hovered && ( <> -
- -
-
- {file.name.substring(12, file.name.length - 4)} -
+
+ onDelete(file.name)} + > + + + + )} + {inProgress ? ( + ) : ( - <> -
+ ); +} + +/** + * - - )} - - ); -} + */ diff --git a/web/src/components/indicators/Chip.tsx b/web/src/components/indicators/Chip.tsx index 8d1b6555d6..16cfb9bf5b 100644 --- a/web/src/components/indicators/Chip.tsx +++ b/web/src/components/indicators/Chip.tsx @@ -3,14 +3,16 @@ import { CSSTransition } from "react-transition-group"; type ChipProps = { className?: string; - children?: ReactNode[]; + children?: ReactNode | ReactNode[]; in?: boolean; + onClick?: () => void; }; export default function Chip({ className, children, in: inProp = true, + onClick, }: ChipProps) { const nodeRef = useRef(null); @@ -30,6 +32,7 @@ export default function Chip({
{children}
diff --git a/web/src/components/player/PreviewThumbnailPlayer.tsx b/web/src/components/player/PreviewThumbnailPlayer.tsx index e526fa7775..4cf7f29b55 100644 --- a/web/src/components/player/PreviewThumbnailPlayer.tsx +++ b/web/src/components/player/PreviewThumbnailPlayer.tsx @@ -217,7 +217,7 @@ export default function PreviewThumbnailPlayer({
-
+
{formattedDate}
diff --git a/web/src/pages/Export.tsx b/web/src/pages/Export.tsx index 07abfd2689..188382b0b4 100644 --- a/web/src/pages/Export.tsx +++ b/web/src/pages/Export.tsx @@ -1,6 +1,5 @@ import { baseUrl } from "@/api/baseUrl"; import ExportCard from "@/components/card/ExportCard"; -import VideoPlayer from "@/components/player/VideoPlayer"; import { AlertDialog, AlertDialogCancel, @@ -12,13 +11,8 @@ import { } from "@/components/ui/alert-dialog"; import { Button } from "@/components/ui/button"; import { Calendar } from "@/components/ui/calendar"; -import { Card } from "@/components/ui/card"; -import { - Dialog, - DialogContent, - DialogHeader, - DialogTitle, -} from "@/components/ui/dialog"; +import { Dialog, DialogContent, DialogTrigger } from "@/components/ui/dialog"; +import { Drawer, DrawerContent, DrawerTrigger } from "@/components/ui/drawer"; import { DropdownMenuRadioGroup, DropdownMenuTrigger, @@ -28,18 +22,13 @@ import { DropdownMenuSeparator, DropdownMenuRadioItem, } from "@/components/ui/dropdown-menu"; -import Heading from "@/components/ui/heading"; -import { - Popover, - PopoverContent, - PopoverTrigger, -} from "@/components/ui/popover"; import { Toaster } from "@/components/ui/sonner"; import { FrigateConfig } from "@/types/frigateConfig"; import axios from "axios"; import { format } from "date-fns"; import { useCallback, useState } from "react"; import { DateRange } from "react-day-picker"; +import { isDesktop } from "react-device-detect"; import { toast } from "sonner"; import useSWR from "swr"; @@ -67,7 +56,6 @@ function Export() { const [startTime, setStartTime] = useState("00:00:00"); const [endTime, setEndTime] = useState("23:59:59"); - const [selectedClip, setSelectedClip] = useState(); const [deleteClip, setDeleteClip] = useState(); const onHandleExport = () => { @@ -150,8 +138,12 @@ function Export() { }); }, [deleteClip, mutate]); + const Create = isDesktop ? Dialog : Drawer; + const Trigger = isDesktop ? DialogTrigger : DrawerTrigger; + const Content = isDesktop ? DialogContent : DrawerContent; + return ( -
+
- setSelectedClip(undefined)} - > - - - Playback - - - - - -
-
-
- - - - - - Select A Camera - - - {Object.keys(config?.cameras || {}).map((item) => ( - - {item.replaceAll("_", " ")} - - ))} - - - -
+
+ + + + + +
- + + + + Select A Camera + + + + {Object.keys(config?.cameras || {}).map((item) => ( + + {item.replaceAll("_", " ")} + + ))} + + + + + + - + Select A Playback Factor @@ -252,56 +225,54 @@ function Export() {
-
- - - - - - -
- setStartTime(e.target.value)} - /> - setEndTime(e.target.value)} - /> -
-
-
-
- -
-
+ } ${endTime}`} + +
+ + +
+
{exports && ( - - Exports +
{Object.values(exports).map((item) => ( setSelectedClip(file)} onDelete={(file) => setDeleteClip(file)} /> ))} - +
)}