Skip to content

Commit

Permalink
implement preview
Browse files Browse the repository at this point in the history
  • Loading branch information
paoloose committed Nov 29, 2024
1 parent 9acf5f1 commit 6a1fef4
Show file tree
Hide file tree
Showing 5 changed files with 171 additions and 27 deletions.
4 changes: 4 additions & 0 deletions app/src/hooks/useApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,24 +14,28 @@ const mockedUserMedia = [
{
id: 1,
title: 'Aiko Tanaka',
ext: '.png',
description: 'Lorem punpuns',
url: 'https://www.grupoeducar.cl/wp-content/uploads/2023/06/Arte-Revista-Educar-Julio-2023-edicion-274.png',
},
{
id: 2,
title: 'Grace en 3d',
ext: '.png',
description: 'Modelo 3d no implementado',
url: 'https://diario.global/wp-content/uploads/2022/02/C2015014-TOTS-SOM-EUROPA-UNIDA.jpg',
},
{
id: 3,
title: 'Xiao Pang',
ext: '.png',
description: 'Le gusta mirar fijamente a cosas cotidianas',
url: 'https://unidadlatina.org/wp-content/uploads/2024/04/arte-contemporaneo-latinoamerica.jpg',
},
{
id: 4,
title: 'Xiao Pang',
ext: '.glb',
description: 'Le gusta mirar fijamente a cosas cotidianas',
url: 'http://localhost:5173/assets/3d/chihiro.glb',
},
Expand Down
72 changes: 66 additions & 6 deletions app/src/pages/Editor/components/ContentSidebarElement.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,53 @@
import FileEditor from "@/components/FileEditor";
import { DRAG_PORTAL_ID, smallIconProps } from "@/constants";
import { DynamicSculpture } from "@/pages/Gallery3D/components/gallery/DynamicSculpture";
import { useMetagalleryStore } from "@/providers/MetagalleryProvider";
import { useEditorStore } from "@/stores/editorAction";
import { UserContentFileElement } from "@/types";
import { Button, Card, Image, Menu, Portal, rem, Text } from "@mantine/core";
import { Button, Card, Image, MantineStyleProp, Menu, Portal, rem, Text } from "@mantine/core";
import { useHover, useMouse } from "@mantine/hooks";
import { Canvas } from "@react-three/fiber";
import { IconDots, IconDownload, IconEdit, IconTrash } from "@tabler/icons-react";
import { useRef, useState } from "react";
import { RefObject, useRef, useState } from "react";

type UserContentPreviewProps = {
ref: RefObject<any>;
contentId: number;
title: string;
url: string;
ext: string;
style: MantineStyleProp;
}

const UserContentPreview = ({ ref, title, contentId, url, ext, style }: UserContentPreviewProps) => {
if (ext.includes('glb')) {
return (
<Canvas
gl={{ preserveDrawingBuffer: true }}
id={`sidebar_canvas_${contentId}`}
ref={ref}
style={{ pointerEvents: 'none' }}
>
<DynamicSculpture
position={[0, -1.5, 0]}
glbUrl={url}
rotation={[0, Math.PI / 4, 0]}
scale={[2, 2, 2] as any}
rotate={true}
/>
</Canvas>
);
}

return (
<Image
ref={ref}
src={url}
alt={title}
style={style}
/>
);
}

const ContentSidebarElement = ({ element }: { element: UserContentFileElement }) => {
const { hovered, ref } = useHover();
Expand All @@ -28,12 +69,20 @@ const ContentSidebarElement = ({ element }: { element: UserContentFileElement })
top: y - 20,
left: x - 40,
zIndex: 6969,
border: '1px solid black',
opacity: 0.8,
width: imageRef.current?.width,
height: imageRef.current?.height,
width: imageRef.current?.width ?? 100,
height: imageRef.current?.height ?? 100,
}}
>
<Image m={0} src={element.url} alt={element.title} radius={5} />
<UserContentPreview
ref={imageRef}
title={element.title}
url={element.url}
contentId={element.id}
ext={element.ext}
style={{ borderRadius: 5 }}
/>
</div>
</Portal>
)
Expand All @@ -50,14 +99,25 @@ const ContentSidebarElement = ({ element }: { element: UserContentFileElement })
}}
>
<Card.Section>
<Image
{/* <Image
ref={imageRef}
src={element.url}
alt={element.title}
style={{
height: '100%',
display: 'block'
}}
/> */}
<UserContentPreview
ref={imageRef}
url={element.url}
title={element.title}
contentId={element.id}
ext={element.ext}
style={{
height: '100%',
display: 'block'
}}
/>
</Card.Section>
<Text size="xs" fw={700} mt={8}>{element.title || 'Sin título'}</Text>
Expand Down
4 changes: 1 addition & 3 deletions app/src/pages/Editor/components/GalleryCanvas2D.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,6 @@ export const GalleryCanvas2D = ({ gallery, triggerReRender }: GalleryCanvas2DPro
}
}, [response]);

console.log(response?.data.slots.slots)

return (
<Box
id="canvas"
Expand Down Expand Up @@ -127,7 +125,7 @@ export const GalleryCanvas2D = ({ gallery, triggerReRender }: GalleryCanvas2DPro
return (
<Model3DSlot
key={i}
id={i} // TODO: replace
idRef={block.ref} // TODO: replace
v={block.v[0] as any}
props={block.props}
res={res} // TODO: make reactive
Expand Down
117 changes: 99 additions & 18 deletions app/src/pages/Editor/components/blocks/Model3DBlock.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,84 @@
import useImage from 'use-image';
import { useState } from 'react';
import { Image, Rect } from 'react-konva';
import { useEffect, useState } from 'react';
import { Image as KonvaImage, Rect } from 'react-konva';
import { setCursor } from '@/utils';
import { useEditorStore } from '@/stores/editorAction';
import { FRAME_STROKE_WIDTH, noImageSrc } from '@/constants';
import { JSONValue, SlotVertex } from '@/types';
import { FRAME_STROKE_WIDTH } from '@/constants';
import { JSONValue, SlotVertex, UserContentFileElement } from '@/types';
import { v3tov2 } from '../../utils';
import { useMetagalleryStore } from '@/providers/MetagalleryProvider';
import { Text } from '@mantine/core';
import { useUser } from '@/stores/useUser';
import { mutate } from 'swr';
import { useQuery } from '@tanstack/react-query';
import { useForceUpdate } from '@mantine/hooks';

type Model3DBlockProps = {
id: number,
idRef: string,
v: SlotVertex,
res: string | null;
props: Record<string, JSONValue>;
};

export const Model3DSlot = ({ id, v, res, props }: Model3DBlockProps) => {
export const Model3DSlot = ({ idRef, v, res, props }: Model3DBlockProps) => {
const [hovering, setHovering] = useState(false);
const draggingElem = useEditorStore((state) => state.draggingFile);
const dragging = draggingElem !== null;
const gallery = useEditorStore((s) => s.gallery);

const forceUpdate = useForceUpdate();

useEffect(() => {
const i = setInterval(forceUpdate, 500);
return () => {
clearInterval(i);
}
}, []);

const userMediaQuery = useQuery({
queryKey: ['user/media'],
queryFn: async () => {
const res = await fetch('https://pandadiestro.xyz/services/stiller/file', {
method: 'GET',
headers: {
'token': useUser.getState().token,
} as any,
});
const data: UserContentFileElement[] = await res.json();

for (let e of data) {
e.url = `https://pandadiestro.xyz/services/stiller/${e.url}`;
}

return data;
}
});


let src = res;
if (hovering && dragging) {
// Preview when user hover this slot while drawing
src = draggingElem.url;
if (!draggingElem.ext.includes('glb')) {
src = draggingElem.url;
}
useEditorStore.getState().setDraggingFileVisible(false);
} else {
useEditorStore.getState().setDraggingFileVisible(true);
}

const [image] = useImage(src ?? '');
let image: HTMLImageElement | undefined = undefined;

if (userMediaQuery.data && res) {
image = new Image();
// parse from www.url.com/dl/number to number
const id = parseInt(res.split('/').pop() ?? '0');
const canvas = document.getElementById(`sidebar_canvas_${id}`)?.querySelector('canvas');

if (canvas) {
const img = new Image();
img.src = canvas.toDataURL();
image = img;
}
}

const pos = v3tov2(v);
const size = 2 * (props.scale as number | null ?? 1);
Expand All @@ -44,13 +94,51 @@ export const Model3DSlot = ({ id, v, res, props }: Model3DBlockProps) => {
height={size}
fill={dragging ? '#fcf3de' : (hovering ? '#e1e3e5' : '#f1f3f5')}
cornerRadius={1.2}
onMouseEnter={() => {
setHovering(true);
setCursor('pointer');
}}
onMouseLeave={() => {
setHovering(false);
setCursor(null);
}}
onClick={() => {
useMetagalleryStore.getState().openModal({
id: 'picture-slot-modal',
child: <Text>Hawk tuah!</Text>
});
}}
onMouseUp={async () => {
const dropped = hovering && dragging;

if (dropped) {
// setOptimisticImgSrc(draggingElem.url);
const response = await fetch('https://pandadiestro.xyz/services/stiller/gallery/slot', {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
'token': useUser.getState().token ?? 'invalid-token',
},
body: JSON.stringify({
gallery: gallery,
ref: idRef,
title: draggingElem.title,
description: draggingElem.description,
res: draggingElem.id,
}),
});
console.log('UPDATING TO', draggingElem.id, 'MUTATING', `/gallery/${gallery}`)
mutate(`/gallery/${gallery}`);
}
}}
/>
<Image
<KonvaImage
x={x}
y={y}
image={image}
width={size}
height={size}
listening={false}
/>
{/* Border stroke */}
<Rect
Expand All @@ -61,14 +149,7 @@ export const Model3DSlot = ({ id, v, res, props }: Model3DBlockProps) => {
stroke={hovering ? (dragging ? '#e8bb74' : '#b0b0b0') : '#c0c0c0'}
strokeWidth={FRAME_STROKE_WIDTH / 2}
cornerRadius={1.2}
onMouseEnter={() => {
setHovering(true);
setCursor('pointer');
}}
onMouseLeave={() => {
setHovering(false);
setCursor(null);
}}
listening={false}
/>
</>
);
Expand Down
1 change: 1 addition & 0 deletions app/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
export interface UserContentFileElement {
id: number,
url: string,
ext: string,
title: string,
description?: string,
}
Expand Down

0 comments on commit 6a1fef4

Please sign in to comment.