mirror of
https://github.com/wgh136/nysoure.git
synced 2025-09-27 04:17:23 +00:00
Refactor image display in activities, resource, and user pages to use ImageGrid component
This commit is contained in:
@@ -51,3 +51,156 @@ export function SquareImage({ image }: { image: Image }) {
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function VerticalImage({ image }: { image: Image }) {
|
||||||
|
let cover = false;
|
||||||
|
const imgAspectRatio = image.width / image.height;
|
||||||
|
if (imgAspectRatio < 0.8 && imgAspectRatio > 0.5) {
|
||||||
|
cover = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div
|
||||||
|
className="w-full bg-base-200 rounded-lg cursor-pointer aspect-[9/16]"
|
||||||
|
onClick={() => {
|
||||||
|
const dialog = document.getElementById(
|
||||||
|
`image-dialog-${image.id}`,
|
||||||
|
) as HTMLDialogElement;
|
||||||
|
dialog.showModal();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src={network.getImageUrl(image.id)}
|
||||||
|
alt={"image"}
|
||||||
|
className={`w-full h-full rounded-lg ${cover ? "object-cover" : "object-contain"}`}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<dialog id={`image-dialog-${image.id}`} className="modal">
|
||||||
|
<div
|
||||||
|
className={"w-screen h-screen flex items-center justify-center"}
|
||||||
|
onClick={() => {
|
||||||
|
const dialog = document.getElementById(
|
||||||
|
`image-dialog-${image.id}`,
|
||||||
|
) as HTMLDialogElement;
|
||||||
|
dialog.close();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src={network.getImageUrl(image.id)}
|
||||||
|
alt={"image"}
|
||||||
|
className={`object-contain max-w-screen max-h-screen modal-box`}
|
||||||
|
style={{
|
||||||
|
padding: 0,
|
||||||
|
margin: 0,
|
||||||
|
backgroundColor: "transparent",
|
||||||
|
boxShadow: "none",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</dialog>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function HorizontalImage({ image }: { image: Image }) {
|
||||||
|
let cover = false;
|
||||||
|
const imgAspectRatio = image.width / image.height;
|
||||||
|
if (imgAspectRatio > 1.2 && imgAspectRatio < 2) {
|
||||||
|
cover = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div
|
||||||
|
className="w-full aspect-video bg-base-200 rounded-lg cursor-pointer"
|
||||||
|
onClick={() => {
|
||||||
|
const dialog = document.getElementById(
|
||||||
|
`image-dialog-${image.id}`,
|
||||||
|
) as HTMLDialogElement;
|
||||||
|
dialog.showModal();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src={network.getImageUrl(image.id)}
|
||||||
|
alt={"image"}
|
||||||
|
className={`w-full h-full rounded-lg ${cover ? "object-cover" : "object-contain"}`}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<dialog id={`image-dialog-${image.id}`} className="modal">
|
||||||
|
<div
|
||||||
|
className={"w-screen h-screen flex items-center justify-center"}
|
||||||
|
onClick={() => {
|
||||||
|
const dialog = document.getElementById(
|
||||||
|
`image-dialog-${image.id}`,
|
||||||
|
) as HTMLDialogElement;
|
||||||
|
dialog.close();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src={network.getImageUrl(image.id)}
|
||||||
|
alt={"image"}
|
||||||
|
className={`object-contain max-w-screen max-h-screen modal-box`}
|
||||||
|
style={{
|
||||||
|
padding: 0,
|
||||||
|
margin: 0,
|
||||||
|
backgroundColor: "transparent",
|
||||||
|
boxShadow: "none",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</dialog>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ImageGrid({ images }: { images: Image[] }) {
|
||||||
|
let verticalCount = 0;
|
||||||
|
let horizontalCount = 0;
|
||||||
|
for (const image of images) {
|
||||||
|
const imgAspectRatio = image.width / image.height;
|
||||||
|
if (imgAspectRatio < 0.8) {
|
||||||
|
verticalCount++;
|
||||||
|
} else if (imgAspectRatio > 1.2) {
|
||||||
|
horizontalCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (verticalCount / images.length > 0.5) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={
|
||||||
|
"grid grid-cols-4 sm:grid-cols-6 md:grid-cols-7 lg:grid-cols-8 gap-2 px-1 py-2"
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{images.map((image) => (
|
||||||
|
<VerticalImage key={image.id} image={image} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
} else if (horizontalCount / images.length > 0.5) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={
|
||||||
|
"grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-2 px-1 py-2"
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{images.map((image) => (
|
||||||
|
<HorizontalImage key={image.id} image={image} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={
|
||||||
|
"grid grid-cols-3 sm:grid-cols-5 md:grid-cols-6 lg:grid-cols-8 gap-2 px-1 py-2"
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{images.map((image) => (
|
||||||
|
<SquareImage key={image.id} image={image} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -6,7 +6,7 @@ import { useTranslation } from "react-i18next";
|
|||||||
import { MdArrowRight } from "react-icons/md";
|
import { MdArrowRight } from "react-icons/md";
|
||||||
import { useNavigate } from "react-router";
|
import { useNavigate } from "react-router";
|
||||||
import Loading from "../components/loading.tsx";
|
import Loading from "../components/loading.tsx";
|
||||||
import {SquareImage} from "../components/image.tsx";
|
import { ImageGrid } from "../components/image.tsx";
|
||||||
|
|
||||||
export default function ActivitiesPage() {
|
export default function ActivitiesPage() {
|
||||||
const [activities, setActivities] = useState<Activity[]>([]);
|
const [activities, setActivities] = useState<Activity[]>([]);
|
||||||
@@ -98,15 +98,7 @@ function ActivityCard({ activity }: { activity: Activity }) {
|
|||||||
<div className={"text-sm mx-1 whitespace-pre-wrap"}>
|
<div className={"text-sm mx-1 whitespace-pre-wrap"}>
|
||||||
{activity.comment?.content}
|
{activity.comment?.content}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<ImageGrid images={activity.comment?.images ?? []} />
|
||||||
className={
|
|
||||||
"grid grid-cols-3 sm:grid-cols-5 md:grid-cols-6 lg:grid-cols-8 gap-2 px-1 py-2"
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{(activity.comment?.images ?? []).map((image) => (
|
|
||||||
<SquareImage key={image.id} image={image} />
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
<div className={"flex items-center mt-1"}>
|
<div className={"flex items-center mt-1"}>
|
||||||
<MdArrowRight />
|
<MdArrowRight />
|
||||||
<span className={"text-sm text-base-content/80"}>
|
<span className={"text-sm text-base-content/80"}>
|
||||||
|
@@ -47,7 +47,7 @@ import Button from "../components/button.tsx";
|
|||||||
import Badge, { BadgeAccent } from "../components/badge.tsx";
|
import Badge, { BadgeAccent } from "../components/badge.tsx";
|
||||||
import Input, { TextArea } from "../components/input.tsx";
|
import Input, { TextArea } from "../components/input.tsx";
|
||||||
import { useAppContext } from "../components/AppContext.tsx";
|
import { useAppContext } from "../components/AppContext.tsx";
|
||||||
import { SquareImage } from "../components/image.tsx";
|
import { ImageGrid, SquareImage } from "../components/image.tsx";
|
||||||
|
|
||||||
export default function ResourcePage() {
|
export default function ResourcePage() {
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
@@ -1398,15 +1398,7 @@ function CommentTile({ comment }: { comment: Comment }) {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<ImageGrid images={comment.images} />
|
||||||
className={
|
|
||||||
"grid grid-cols-3 sm:grid-cols-5 md:grid-cols-6 lg:grid-cols-8 gap-2 p-2"
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{comment.images.map((image) => (
|
|
||||||
<SquareImage key={image.id} image={image} />
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
{app.user?.id === comment.user.id && (
|
{app.user?.id === comment.user.id && (
|
||||||
<div className={"flex flex-row-reverse"}>
|
<div className={"flex flex-row-reverse"}>
|
||||||
<DeleteCommentDialog commentId={comment.id} />
|
<DeleteCommentDialog commentId={comment.id} />
|
||||||
|
@@ -7,7 +7,7 @@ import ResourcesView from "../components/resources_view";
|
|||||||
import Loading from "../components/loading";
|
import Loading from "../components/loading";
|
||||||
import Pagination from "../components/pagination";
|
import Pagination from "../components/pagination";
|
||||||
import { MdOutlineArrowRight } from "react-icons/md";
|
import { MdOutlineArrowRight } from "react-icons/md";
|
||||||
import {SquareImage} from "../components/image.tsx";
|
import { ImageGrid } from "../components/image.tsx";
|
||||||
|
|
||||||
export default function UserPage() {
|
export default function UserPage() {
|
||||||
const [user, setUser] = useState<User | null>(null);
|
const [user, setUser] = useState<User | null>(null);
|
||||||
@@ -208,15 +208,7 @@ function CommentTile({ comment }: { comment: CommentWithResource }) {
|
|||||||
<div className={"p-2 whitespace-pre-wrap text-sm"}>
|
<div className={"p-2 whitespace-pre-wrap text-sm"}>
|
||||||
{limitArticleLength(comment.content, 200)}
|
{limitArticleLength(comment.content, 200)}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<ImageGrid images={comment.images} />
|
||||||
className={
|
|
||||||
"grid grid-cols-3 sm:grid-cols-5 md:grid-cols-6 lg:grid-cols-8 gap-2 p-2"
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{comment.images.map((image) => (
|
|
||||||
<SquareImage key={image.id} image={image} />
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
<a
|
<a
|
||||||
className="text-sm text-base-content/80 p-1 hover:text-primary cursor-pointer transition-all"
|
className="text-sm text-base-content/80 p-1 hover:text-primary cursor-pointer transition-all"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
Reference in New Issue
Block a user