mirror of
https://github.com/blakeblackshear/frigate.git
synced 2025-12-16 18:16:44 +03:00
Update to use pre-defined component for image shadow
This commit is contained in:
parent
8c318699c4
commit
1c6506aa9e
@ -21,6 +21,7 @@ import { baseUrl } from "@/api/baseUrl";
|
|||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { shareOrCopy } from "@/utils/browserUtil";
|
import { shareOrCopy } from "@/utils/browserUtil";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { ImageShadowOverlay } from "../overlay/ImageShadowOverlay";
|
||||||
|
|
||||||
type ExportProps = {
|
type ExportProps = {
|
||||||
className: string;
|
className: string;
|
||||||
@ -224,7 +225,7 @@ export default function ExportCard({
|
|||||||
{loading && (
|
{loading && (
|
||||||
<Skeleton className="absolute inset-0 aspect-video rounded-lg md:rounded-2xl" />
|
<Skeleton className="absolute inset-0 aspect-video rounded-lg md:rounded-2xl" />
|
||||||
)}
|
)}
|
||||||
<div className="rounded-b-l pointer-events-none absolute inset-x-0 bottom-0 h-[50%] rounded-lg bg-gradient-to-t from-black/60 to-transparent md:rounded-2xl" />
|
<ImageShadowOverlay />
|
||||||
<div className="absolute bottom-2 left-3 flex h-full items-end justify-between text-white smart-capitalize">
|
<div className="absolute bottom-2 left-3 flex h-full items-end justify-between text-white smart-capitalize">
|
||||||
{exportedRecording.name.replaceAll("_", " ")}
|
{exportedRecording.name.replaceAll("_", " ")}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
27
web/src/components/overlay/ImageShadowOverlay.tsx
Normal file
27
web/src/components/overlay/ImageShadowOverlay.tsx
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
|
type ImageShadowOverlayProps = {
|
||||||
|
upperClassName?: string;
|
||||||
|
lowerClassName?: string;
|
||||||
|
};
|
||||||
|
export function ImageShadowOverlay({
|
||||||
|
upperClassName,
|
||||||
|
lowerClassName,
|
||||||
|
}: ImageShadowOverlayProps) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"pointer-events-none absolute inset-x-0 top-0 z-10 h-[30%] w-full rounded-lg bg-gradient-to-b to-transparent md:rounded-2xl",
|
||||||
|
upperClassName,
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"pointer-events-none absolute inset-x-0 bottom-0 z-10 h-[10%] w-full rounded-lg bg-gradient-to-t to-transparent md:rounded-2xl",
|
||||||
|
lowerClassName,
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -6,6 +6,7 @@ import MSEPlayer from "./MsePlayer";
|
|||||||
import { LivePlayerMode } from "@/types/live";
|
import { LivePlayerMode } from "@/types/live";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import { ImageShadowOverlay } from "../overlay/ImageShadowOverlay";
|
||||||
|
|
||||||
type LivePlayerProps = {
|
type LivePlayerProps = {
|
||||||
className?: string;
|
className?: string;
|
||||||
@ -76,8 +77,7 @@ export default function BirdseyeLivePlayer({
|
|||||||
)}
|
)}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
>
|
>
|
||||||
<div className="pointer-events-none absolute inset-x-0 top-0 z-10 h-[30%] w-full rounded-lg bg-gradient-to-b from-black/20 to-transparent md:rounded-2xl"></div>
|
<ImageShadowOverlay />
|
||||||
<div className="pointer-events-none absolute inset-x-0 bottom-0 z-10 h-[10%] w-full rounded-lg bg-gradient-to-t from-black/20 to-transparent md:rounded-2xl"></div>
|
|
||||||
<div className="size-full" ref={playerRef}>
|
<div className="size-full" ref={playerRef}>
|
||||||
{player}
|
{player}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -25,6 +25,7 @@ import { PlayerStats } from "./PlayerStats";
|
|||||||
import { LuVideoOff } from "react-icons/lu";
|
import { LuVideoOff } from "react-icons/lu";
|
||||||
import { Trans, useTranslation } from "react-i18next";
|
import { Trans, useTranslation } from "react-i18next";
|
||||||
import { useCameraFriendlyName } from "@/hooks/use-camera-friendly-name";
|
import { useCameraFriendlyName } from "@/hooks/use-camera-friendly-name";
|
||||||
|
import { ImageShadowOverlay } from "../overlay/ImageShadowOverlay";
|
||||||
|
|
||||||
type LivePlayerProps = {
|
type LivePlayerProps = {
|
||||||
cameraRef?: (ref: HTMLDivElement | null) => void;
|
cameraRef?: (ref: HTMLDivElement | null) => void;
|
||||||
@ -328,10 +329,7 @@ export default function LivePlayer({
|
|||||||
>
|
>
|
||||||
{cameraEnabled &&
|
{cameraEnabled &&
|
||||||
((showStillWithoutActivity && !liveReady) || liveReady) && (
|
((showStillWithoutActivity && !liveReady) || liveReady) && (
|
||||||
<>
|
<ImageShadowOverlay />
|
||||||
<div className="pointer-events-none absolute inset-x-0 top-0 z-10 h-[30%] w-full rounded-lg bg-gradient-to-b from-black/20 to-transparent md:rounded-2xl"></div>
|
|
||||||
<div className="pointer-events-none absolute inset-x-0 bottom-0 z-10 h-[10%] w-full rounded-lg bg-gradient-to-t from-black/20 to-transparent md:rounded-2xl"></div>
|
|
||||||
</>
|
|
||||||
)}
|
)}
|
||||||
{player}
|
{player}
|
||||||
{cameraEnabled &&
|
{cameraEnabled &&
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { baseUrl } from "@/api/baseUrl";
|
import { baseUrl } from "@/api/baseUrl";
|
||||||
import ClassificationModelWizardDialog from "@/components/classification/ClassificationModelWizardDialog";
|
import ClassificationModelWizardDialog from "@/components/classification/ClassificationModelWizardDialog";
|
||||||
import ActivityIndicator from "@/components/indicators/activity-indicator";
|
import ActivityIndicator from "@/components/indicators/activity-indicator";
|
||||||
|
import { ImageShadowOverlay } from "@/components/overlay/ImageShadowOverlay";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group";
|
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group";
|
||||||
import useOptimisticState from "@/hooks/use-optimistic-state";
|
import useOptimisticState from "@/hooks/use-optimistic-state";
|
||||||
@ -163,7 +164,7 @@ function ModelCard({ config, onClick }: ModelCardProps) {
|
|||||||
className={cn("size-full", isMobile && "w-full")}
|
className={cn("size-full", isMobile && "w-full")}
|
||||||
src={`${baseUrl}clips/${config.name}/dataset/${coverImage?.name}/${coverImage?.img}`}
|
src={`${baseUrl}clips/${config.name}/dataset/${coverImage?.name}/${coverImage?.img}`}
|
||||||
/>
|
/>
|
||||||
<div className="absolute bottom-0 h-[50%] w-full bg-gradient-to-t from-black/60 to-transparent" />
|
<ImageShadowOverlay />
|
||||||
<div className="absolute bottom-2 left-3 text-lg smart-capitalize">
|
<div className="absolute bottom-2 left-3 text-lg smart-capitalize">
|
||||||
{config.name}
|
{config.name}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user