feat: enhance asset browser panel with improved asset selection and loading states
- Added state management for asset selection to prevent multiple simultaneous selections. - Implemented request sequence tracking to ensure accurate loading state handling during asset searches. - Enhanced error handling and user feedback for asset loading failures. - Updated UI elements to improve accessibility and user experience during asset browsing.
This commit is contained in:
@@ -4,7 +4,6 @@ import {
|
||||
useState,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useLayoutEffect,
|
||||
useRef,
|
||||
type ChangeEvent,
|
||||
type DragEvent,
|
||||
@@ -77,11 +76,9 @@ export default function ImageNode({
|
||||
const updateData = useMutation(api.nodes.updateData);
|
||||
const resizeNode = useMutation(api.nodes.resize);
|
||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||
const contentRef = useRef<HTMLDivElement | null>(null);
|
||||
const mediaRef = useRef<HTMLDivElement | null>(null);
|
||||
const [isUploading, setIsUploading] = useState(false);
|
||||
const [isDragOver, setIsDragOver] = useState(false);
|
||||
const [handleTop, setHandleTop] = useState<number | undefined>(undefined);
|
||||
const hasAutoSizedRef = useRef(false);
|
||||
|
||||
const aspectRatio = resolveMediaAspectRatio(data.width, data.height);
|
||||
|
||||
@@ -90,6 +87,9 @@ export default function ImageNode({
|
||||
return;
|
||||
}
|
||||
|
||||
if (hasAutoSizedRef.current) return;
|
||||
hasAutoSizedRef.current = true;
|
||||
|
||||
const targetSize = computeMediaNodeSize("image", {
|
||||
intrinsicWidth: data.width,
|
||||
intrinsicHeight: data.height,
|
||||
@@ -106,39 +106,6 @@ export default function ImageNode({
|
||||
});
|
||||
}, [data.height, data.width, height, id, resizeNode, width]);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
if (!contentRef.current || !mediaRef.current) return;
|
||||
|
||||
const contentEl = contentRef.current;
|
||||
const mediaEl = mediaRef.current;
|
||||
let frameId: number | undefined;
|
||||
|
||||
const updateHandleTop = () => {
|
||||
if (frameId !== undefined) {
|
||||
cancelAnimationFrame(frameId);
|
||||
}
|
||||
frameId = requestAnimationFrame(() => {
|
||||
const contentRect = contentEl.getBoundingClientRect();
|
||||
const mediaRect = mediaEl.getBoundingClientRect();
|
||||
const nextTop = mediaRect.top - contentRect.top + mediaRect.height / 2;
|
||||
setHandleTop(nextTop);
|
||||
});
|
||||
};
|
||||
|
||||
updateHandleTop();
|
||||
|
||||
const observer = new ResizeObserver(updateHandleTop);
|
||||
observer.observe(contentEl);
|
||||
observer.observe(mediaEl);
|
||||
|
||||
return () => {
|
||||
observer.disconnect();
|
||||
if (frameId !== undefined) {
|
||||
cancelAnimationFrame(frameId);
|
||||
}
|
||||
};
|
||||
}, [aspectRatio, data.filename, data.url, isDragOver, isUploading]);
|
||||
|
||||
const uploadFile = useCallback(
|
||||
async (file: File) => {
|
||||
if (!ALLOWED_IMAGE_TYPES.has(file.type)) {
|
||||
@@ -274,10 +241,9 @@ export default function ImageNode({
|
||||
type="target"
|
||||
position={Position.Left}
|
||||
className="h-3! w-3! bg-primary! border-2! border-background!"
|
||||
style={{ top: handleTop ? `${handleTop}px` : "50%" }}
|
||||
/>
|
||||
|
||||
<div ref={contentRef} className="p-2">
|
||||
<div className="p-2">
|
||||
<div className="mb-1 flex items-center justify-between">
|
||||
<div className="text-xs font-medium text-muted-foreground">🖼️ Bild</div>
|
||||
{data.url && (
|
||||
@@ -290,7 +256,7 @@ export default function ImageNode({
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div ref={mediaRef} className="relative w-full overflow-hidden rounded-lg" style={{ aspectRatio }}>
|
||||
<div className="relative w-full overflow-hidden rounded-lg" style={{ aspectRatio }}>
|
||||
{isUploading ? (
|
||||
<div className="flex h-full w-full items-center justify-center bg-muted">
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
@@ -349,7 +315,6 @@ export default function ImageNode({
|
||||
type="source"
|
||||
position={Position.Right}
|
||||
className="h-3! w-3! bg-primary! border-2! border-background!"
|
||||
style={{ top: handleTop ? `${handleTop}px` : "50%" }}
|
||||
/>
|
||||
</BaseNodeWrapper>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user