* fix squashed alert thumbnails in filmstrip

* add genai debug logs

* consistent themed image loading indicator background color

* improve image loading skeleton in object lifecycle pane

* less rounding when screen is smaller

* use browser back button to dismiss review pane

* initial state
This commit is contained in:
Josh Hawkins 2024-10-01 08:01:45 -05:00 committed by GitHub
parent 141cf39368
commit fafe5623d1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 39 additions and 9 deletions

View File

@ -137,6 +137,9 @@ class EmbeddingMaintainer(threading.Thread):
or set(event.zones) & set(camera_config.genai.required_zones) or set(event.zones) & set(camera_config.genai.required_zones)
) )
): ):
logger.debug(
f"Description generation for {event}, has_snapshot: {event.has_snapshot}"
)
if event.has_snapshot and camera_config.genai.use_snapshot: if event.has_snapshot and camera_config.genai.use_snapshot:
with open( with open(
os.path.join(CLIPS_DIR, f"{event.camera}-{event.id}.jpg"), os.path.join(CLIPS_DIR, f"{event.camera}-{event.id}.jpg"),
@ -276,7 +279,9 @@ class EmbeddingMaintainer(threading.Thread):
metadata = get_metadata(event) metadata = get_metadata(event)
thumbnail = base64.b64decode(event.thumbnail) thumbnail = base64.b64decode(event.thumbnail)
logger.debug(f"Using ${source} regeneration for ${event}") logger.debug(
f"Trying {source} regeneration for {event}, has_snapshot: {event.has_snapshot}"
)
if event.has_snapshot and source == "snapshot": if event.has_snapshot and source == "snapshot":
with open( with open(

View File

@ -107,7 +107,7 @@ export function AnimatedEventCard({
<Tooltip> <Tooltip>
<TooltipTrigger asChild> <TooltipTrigger asChild>
<div <div
className="relative h-24 4k:h-32" className="relative h-24 flex-shrink-0 4k:h-32"
style={{ style={{
aspectRatio: alertVideos ? aspectRatio : undefined, aspectRatio: alertVideos ? aspectRatio : undefined,
}} }}
@ -145,7 +145,7 @@ export function AnimatedEventCard({
> >
{!alertVideos ? ( {!alertVideos ? (
<img <img
className="size-full select-none" className="max-h-full select-none"
src={`${apiHost}${event.thumb_path.replace("/media/frigate/", "")}`} src={`${apiHost}${event.thumb_path.replace("/media/frigate/", "")}`}
loading={isSafari ? "eager" : "lazy"} loading={isSafari ? "eager" : "lazy"}
onLoad={() => setIsLoaded(true)} onLoad={() => setIsLoaded(true)}

View File

@ -14,7 +14,7 @@ export default function ImageLoadingIndicator({
} }
return isSafari ? ( return isSafari ? (
<div className={cn("pointer-events-none bg-gray-300", className)} /> <div className={cn("pointer-events-none bg-background_alt", className)} />
) : ( ) : (
<Skeleton className={cn("pointer-events-none", className)} /> <Skeleton className={cn("pointer-events-none", className)} />
); );

View File

@ -77,6 +77,17 @@ export default function ObjectLifecycle({
const [showControls, setShowControls] = useState(false); const [showControls, setShowControls] = useState(false);
const [showZones, setShowZones] = useState(true); const [showZones, setShowZones] = useState(true);
const aspectRatio = useMemo(() => {
if (!config) {
return 16 / 9;
}
return (
config.cameras[event.camera].detect.width /
config.cameras[event.camera].detect.height
);
}, [config, event]);
const getZoneColor = useCallback( const getZoneColor = useCallback(
(zoneName: string) => { (zoneName: string) => {
const zoneColor = const zoneColor =
@ -240,7 +251,15 @@ export default function ObjectLifecycle({
</div> </div>
)} )}
<div className="relative flex flex-row justify-center"> <div
className={cn(
"relative mx-auto flex max-h-[50dvh] flex-row justify-center",
!imgLoaded && aspectRatio < 16 / 9 && "h-full",
)}
style={{
aspectRatio: !imgLoaded ? aspectRatio : undefined,
}}
>
<ImageLoadingIndicator <ImageLoadingIndicator
className="absolute inset-0" className="absolute inset-0"
imgLoaded={imgLoaded} imgLoaded={imgLoaded}
@ -263,7 +282,7 @@ export default function ObjectLifecycle({
key={event.id} key={event.id}
ref={imgRef} ref={imgRef}
className={cn( className={cn(
"max-h-[50dvh] max-w-full select-none rounded-lg object-contain transition-opacity", "max-h-[50dvh] max-w-full select-none rounded-lg object-contain",
)} )}
loading={isSafari ? "eager" : "lazy"} loading={isSafari ? "eager" : "lazy"}
style={ style={

View File

@ -37,6 +37,7 @@ import {
MobilePageHeader, MobilePageHeader,
MobilePageTitle, MobilePageTitle,
} from "@/components/mobile/MobilePage"; } from "@/components/mobile/MobilePage";
import { useOverlayState } from "@/hooks/use-overlay-state";
type ReviewDetailDialogProps = { type ReviewDetailDialogProps = {
review?: ReviewSegment; review?: ReviewSegment;
@ -83,10 +84,15 @@ export default function ReviewDetailDialog({
// dialog and mobile page // dialog and mobile page
const [isOpen, setIsOpen] = useState(review != undefined); const [isOpen, setIsOpen] = useOverlayState(
"reviewPane",
review != undefined,
);
useEffect(() => { useEffect(() => {
setIsOpen(review != undefined); setIsOpen(review != undefined);
// we know that these deps are correct
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [review]); }, [review]);
const Overlay = isDesktop ? Sheet : MobilePage; const Overlay = isDesktop ? Sheet : MobilePage;
@ -102,7 +108,7 @@ export default function ReviewDetailDialog({
return ( return (
<> <>
<Overlay <Overlay
open={isOpen} open={isOpen ?? false}
onOpenChange={(open) => { onOpenChange={(open) => {
if (!open) { if (!open) {
setReview(undefined); setReview(undefined);

View File

@ -200,7 +200,7 @@ function ExploreThumbnailImage({
<img <img
ref={imgRef} ref={imgRef}
className={cn( className={cn(
"absolute h-full w-full cursor-pointer rounded-lg object-cover transition-all duration-300 ease-in-out md:rounded-2xl", "absolute h-full w-full cursor-pointer rounded-lg object-cover transition-all duration-300 ease-in-out lg:rounded-2xl",
)} )}
style={ style={
isIOS isIOS