diff --git a/packages/social-media-app/frontend/src/canvas/Canvas.tsx b/packages/social-media-app/frontend/src/canvas/Canvas.tsx index 22b0ffd7..6949cad6 100644 --- a/packages/social-media-app/frontend/src/canvas/Canvas.tsx +++ b/packages/social-media-app/frontend/src/canvas/Canvas.tsx @@ -36,16 +36,6 @@ export const Canvas = ( canvas, } = useCanvas(); - // Inside your Canvas component: - const filteredTextRectsCount = useMemo(() => { - const filtered = [...rects, ...pendingRects].filter( - (rect, i) => - rect.content instanceof StaticContent && - rect.content.content instanceof StaticMarkdownText - ); - return filtered.length; - }, [rects, pendingRects]); - // rects and pendingRects purpose filtered for properties.appearance const filteredRects = useMemo(() => { return [...rects, ...pendingRects].filter((rect, i) => @@ -145,6 +135,11 @@ export const Canvas = ( coverParent={ properties.appearance === "chat-view-images" } + fit={ + properties.appearance === "chat-view-images" + ? "cover" + : undefined + } /> ); @@ -160,7 +155,7 @@ export const Canvas = ( ? "flex gap-4 p-4" : "" } ${properties.fitHeight ? "h-full" : ""} ${ - properties.fitWidth ? "w-full" : "min-w-fit" + properties.fitWidth ? "w-full" : "" }`} > {renderRects(filteredRects)} diff --git a/packages/social-media-app/frontend/src/canvas/CanvasAndReplies.tsx b/packages/social-media-app/frontend/src/canvas/CanvasAndReplies.tsx index 1446fbc8..fa551f6e 100644 --- a/packages/social-media-app/frontend/src/canvas/CanvasAndReplies.tsx +++ b/packages/social-media-app/frontend/src/canvas/CanvasAndReplies.tsx @@ -39,7 +39,7 @@ const CanvasWithReplies = (props: { canvas?: CanvasDB }) => { return (
-
+
@@ -123,7 +123,7 @@ export const CanvasAndReplies = () => { return (
-
+
{ return ( ); }; diff --git a/packages/social-media-app/frontend/src/content/Frame.tsx b/packages/social-media-app/frontend/src/content/Frame.tsx index 490a04e3..5f551252 100644 --- a/packages/social-media-app/frontend/src/content/Frame.tsx +++ b/packages/social-media-app/frontend/src/content/Frame.tsx @@ -31,6 +31,7 @@ export const Frame = (properties: { key?: number; delete(): void; coverParent?: boolean; + fit?: "cover" | "contain"; }) => { const navigate = useNavigate(); @@ -78,6 +79,7 @@ export const Frame = (properties: { } }} coverParent={coverParent} + fit={properties.fit} /> ); } diff --git a/packages/social-media-app/frontend/src/content/native/NativeContent.tsx b/packages/social-media-app/frontend/src/content/native/NativeContent.tsx index d700f5e9..dcf52930 100644 --- a/packages/social-media-app/frontend/src/content/native/NativeContent.tsx +++ b/packages/social-media-app/frontend/src/content/native/NativeContent.tsx @@ -13,6 +13,7 @@ export type EditableStaticContentProps = { onChange?: (newContent: StaticContent["content"]) => void; thumbnail?: boolean; coverParent?: boolean; + fit?: "cover" | "contain"; }; export const EditableStaticContent = ({ @@ -22,6 +23,7 @@ export const EditableStaticContent = ({ onChange, thumbnail, coverParent, + fit, }: EditableStaticContentProps) => { if (staticContent instanceof StaticMarkdownText) { return ( @@ -43,6 +45,7 @@ export const EditableStaticContent = ({ onChange={onChange} thumbnail={thumbnail} coverParent={coverParent} + fit={fit} /> ); } diff --git a/packages/social-media-app/frontend/src/content/native/image/Image.tsx b/packages/social-media-app/frontend/src/content/native/image/Image.tsx index b2d6e1d5..e2d3f2ee 100644 --- a/packages/social-media-app/frontend/src/content/native/image/Image.tsx +++ b/packages/social-media-app/frontend/src/content/native/image/Image.tsx @@ -1,7 +1,22 @@ +/** + * @fileoverview React component for displaying and editing images with drag-and-drop functionality. + */ + import React, { useRef, useEffect, useState, useCallback } from "react"; import { StaticImage } from "@dao-xyz/social"; import { readFileAsImage } from "./utils"; +/** + * Props interface for the ImageContent component + * ImageContentProps + * content - The image data to display + * onResize - Callback when image dimensions change + * [editable] - Whether the image can be edited/replaced + * [onChange] - Callback when image content changes + * [thumbnail] - Display as thumbnail + * [coverParent] - Cover parent container + * [fit] - How image should fit container. If not given, scales to parent on width and height + */ export type ImageContentProps = { content: StaticImage; onResize: (dims: { width: number; height: number }) => void; @@ -9,21 +24,31 @@ export type ImageContentProps = { onChange?: (newContent: StaticImage) => void; thumbnail?: boolean; coverParent?: boolean; + fit?: "cover" | "contain"; }; +/** + * Component for displaying and editing image content + * Supports drag-and-drop uploads and dimension monitoring + */ export const ImageContent = ({ content, onResize, editable = false, onChange, coverParent, + fit, }: ImageContentProps) => { + // References for container element and dimension tracking const containerRef = useRef(null); const lastDims = useRef<{ width: number; height: number } | null>(null); const threshold = 1; const [isDragOver, setIsDragOver] = useState(false); - // ResizeObserver to trigger onResize callback + /** + * ResizeObserver setup to monitor container dimensions + * Triggers onResize callback when dimensions change beyond threshold + */ useEffect(() => { if (!containerRef.current) return; const observer = new ResizeObserver((entries) => { @@ -47,15 +72,22 @@ export const ImageContent = ({ return () => observer.disconnect(); }, [onResize, threshold]); - // Common file handling logic. + /** + * Handles processing of uploaded image files + */ const handleFile = useCallback(readFileAsImage(onChange), [onChange]); + /** + * Handles file input change events + */ const handleFileChange = (e: React.ChangeEvent) => { const file = e.target.files && e.target.files[0]; handleFile(file); }; - // Drag and drop handlers + /** + * Drag and drop event handlers + */ const handleDragOver = (e: React.DragEvent) => { e.preventDefault(); setIsDragOver(true); @@ -80,7 +112,11 @@ export const ImageContent = ({ onDragLeave={editable ? handleDragLeave : undefined} onDrop={editable ? handleDrop : undefined} className={`relative w-full h-full ${ - coverParent ? "object-cover" : "min-w-max" + { + cover: "object-cover", + contain: "object-contain", + default: "", + }[fit ?? "default"] } ${ editable ? "cursor-pointer border-2 border-dashed p-4 transition-colors duration-150 bg-gray-50 dark:bg-gray-800" @@ -94,7 +130,13 @@ export const ImageContent = ({ {content.alt} {editable && ( diff --git a/packages/social-media-app/frontend/src/context/TagInput.tsx b/packages/social-media-app/frontend/src/context/TagInput.tsx index 9013e1e3..0d683e74 100644 --- a/packages/social-media-app/frontend/src/context/TagInput.tsx +++ b/packages/social-media-app/frontend/src/context/TagInput.tsx @@ -62,11 +62,11 @@ const TagInput = ({ tags, onTagsChange, renderTag }) => { className="flex items-center gap-1 px-2 py-1 border border-gray-300 rounded h-full cursor-text" onClick={() => inputRef.current.focus()} > -
+
{tags.map((tag, index) => ( {index > 0 ? ( - / + / ) : null} <>{renderTagContent(tag, index)}