Skip to content

Commit

Permalink
fix and optimize rendering
Browse files Browse the repository at this point in the history
  • Loading branch information
paoloose committed Dec 1, 2024
1 parent f38aabd commit b403e86
Show file tree
Hide file tree
Showing 12 changed files with 206 additions and 132 deletions.
4 changes: 2 additions & 2 deletions app/src/hooks/useApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useUser } from '@/stores/useUser';

type ArgsType<T> = T extends (...args: infer U) => any ? U : never;

type ApiResponse<T> = {
export type ApiResponse<T> = {
data: T;
code: number;
headers?: Headers;
Expand Down Expand Up @@ -256,7 +256,7 @@ export function useApi<T, E = any>(path: string, options: RequestInit = {}) {
}
const url = `https://pandadiestro.xyz/services/stiller${key.startsWith('/') ? key : `/${key}`}`;
return fetcher<T>(url, options);
}, { revalidateOnFocus: false, refreshInterval: 3000 },
}, { revalidateOnFocus: false },
);

return {
Expand Down
3 changes: 3 additions & 0 deletions app/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ import { theme } from '@/theme/theme';
import App from './App';

import '@mantine/core/styles.css';
import '@mantine/notifications/styles.css';
import './main.css';
import { MetagalleryProvider } from './providers/MetagalleryProvider';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { Notifications } from '@mantine/notifications';

const queryClient = new QueryClient();

Expand All @@ -19,6 +21,7 @@ ReactDOM.createRoot(document.getElementById('root')!).render(
>
<MetagalleryProvider>
<App />
<Notifications />
</MetagalleryProvider>
</MantineProvider>
</QueryClientProvider>
Expand Down
2 changes: 2 additions & 0 deletions app/src/pages/Editor/components/GalleryCanvas2D.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ export const GalleryCanvas2D = memo(({ gallery, triggerReRender }: GalleryCanvas
if (bounds) setViewport({ x: bounds.width, y: bounds.height });
};

console.log('CANVAS SHIT')

useEffect(() => {
handleViewportResize();
window.addEventListener('resize', handleViewportResize);
Expand Down
4 changes: 2 additions & 2 deletions app/src/pages/Editor/components/MainButtons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import { primaryIconProps } from '@/constants';
import { DeployModal } from './modals/DeployModal';
import { IconShare, IconPlayerPlay, IconPlayerStop } from '@tabler/icons-react';

type Props = { onPreviewButton: () => void; closePreviewButton: () => void; isPreviewing: boolean };
type Props = { onPreviewButton: () => void; onClosePreviewButton: () => void; isPreviewing: boolean };

export const MainButtons = ({ onPreviewButton, closePreviewButton, isPreviewing }: Props) => {
export const MainButtons = ({ onPreviewButton, onClosePreviewButton: closePreviewButton, isPreviewing }: Props) => {
const [isModalOpen, setModalOpen] = useState(false);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
Expand Down
123 changes: 75 additions & 48 deletions app/src/pages/Editor/components/blocks/Model3DBlock.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import { useEffect, useState } from 'react';
import { memo, useEffect, useMemo, useState } from 'react';
import { Image as KonvaImage, Rect } from 'react-konva';
import { setCursor } from '@/utils';
import { useEditorStore } from '@/stores/editorAction';
import { FRAME_STROKE_WIDTH } from '@/constants';
import { JSONValue, SlotVertex, UserContentFileElement } from '@/types';
import { JSONValue, SlotVertex } 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 { useQueryClient } from '@tanstack/react-query';
import { useForceUpdate } from '@mantine/hooks';
import { notifications } from '@mantine/notifications';

type Model3DBlockProps = {
idRef: string,
Expand All @@ -19,50 +20,59 @@ type Model3DBlockProps = {
props: Record<string, JSONValue>;
};

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

const forceUpdate = useForceUpdate();
const [forced, forceUpdate] = useState(false);
const [optimisticResId, setOptimisticResId] = useState<number | null>(null);
const isPreviewingGallery = useEditorStore((s) => s.isPreviewingGallery);

useEffect(() => {
const i = setInterval(forceUpdate, 500);
const i = setInterval(() => {
if (!isPreviewingGallery) {
forceUpdate(s => !s); // too heavy to use while previewing
}
}, 100);
return () => {
clearInterval(i);
}
}, []);
}, [isPreviewingGallery]);

const queryClient = useQueryClient();
const data = queryClient.getQueryData(['user/media']);
const data = queryClient.getQueryData(['user/media']); // Data loaded in the sidebar

if (hovering && dragging && draggingElem.ext.includes('glb')) {
if (hovering && dragging) {
useEditorStore.getState().setDraggingFileVisible(false);
} else {
useEditorStore.getState().setDraggingFileVisible(true);
}

let image: HTMLImageElement | undefined = undefined;
let image: HTMLImageElement | undefined = useMemo(() => {
if (data && res) {
// We convert the canvas rendered in the sidebar to an image
const img = new Image();

if (data && res) {
image = new Image();
// parse from www.url.com/dl/number to number
let id: number | null = null;
// parse from www.url.com/dl/number to number
let id: number | null = null;

if (hovering && dragging) {
id = draggingElem.id;
} else {
id = parseInt(res.split('/').at(-2) ?? '0'); // extract id from url
}
const canvas = document.getElementById(`sidebar_canvas_${id}`)?.querySelector('canvas');
if (hovering && dragging) {
id = draggingElem.id;
} else {
id = optimisticResId ?? parseInt(res.split('/').at(-2) ?? '0'); // extract id from url
}
const canvas = document.getElementById(`sidebar_canvas_${id}`)?.querySelector('canvas');

if (canvas) {
const img = new Image();
img.src = canvas.toDataURL();
image = img;
if (canvas) {
img.src = canvas.toDataURL();
return img;
}
return undefined;
}
}
return undefined;
}, [data, res, optimisticResId, hovering, dragging, forced]);

// console.log({ forced })

const pos = v3tov2(v);
const size = 2 * (props.scale as number | null ?? 1);
Expand All @@ -79,12 +89,17 @@ export const Model3DSlot = ({ idRef, v, res, props }: Model3DBlockProps) => {
fill={dragging ? '#fcf3de' : (hovering ? '#e1e3e5' : '#f1f3f5')}
cornerRadius={1.2}
onMouseEnter={() => {
setHovering(true);
setCursor('pointer');
if (!graggingInvalid) {
setHovering(true);
setCursor('pointer');
} else {
setCursor('not-allowed');
}
}}
onMouseLeave={() => {
setHovering(false);
setCursor(null);
useEditorStore.getState().setDraggingFileVisible(true);
}}
onClick={() => {
useMetagalleryStore.getState().openModal({
Expand All @@ -96,23 +111,32 @@ export const Model3DSlot = ({ idRef, v, res, props }: Model3DBlockProps) => {
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}`);
setOptimisticResId(parseInt(draggingElem.url.split('/').at(-2) ?? '0'));
try {
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}`)
} catch {
notifications.show({
color: 'red',
title: 'Error',
message: 'Failed to update slot',
});
} finally {
mutate(`/gallery/${gallery}`);
}
}
}}
/>
Expand All @@ -137,4 +161,7 @@ export const Model3DSlot = ({ idRef, v, res, props }: Model3DBlockProps) => {
/>
</>
);
};
}, (prev, next) => {
return prev.res === next.res;
});

80 changes: 49 additions & 31 deletions app/src/pages/Editor/components/blocks/PictureSlot.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import useImage from 'use-image';
import { useState } from 'react';
import { memo, useState } from 'react';
import { Text } from '@mantine/core';
import { Image, Rect, Group, Text as Text3D } from 'react-konva';
import { setCursor } from '@/utils';
import { copyGalleryWithSlotResId, setCursor } from '@/utils';
import { useEditorStore } from '@/stores/editorAction';
import { useMetagalleryStore } from '@/providers/MetagalleryProvider';
import { CORNER_RADIUS, FRAME_STROKE_WIDTH, noImageSrc } from '@/constants';
import { JSONValue, SlotVertices } from '@/types';
import { JSONValue, SlotVertices, StillerGallery } from '@/types';
import { cosine, getFrameAngle, getFrameHeight, getFrameWidth, sine, v3tov2 } from '@/pages/Editor/utils';
import { mutate } from 'swr';
import { useUser } from '@/stores/useUser';
import { ApiResponse, useApi } from '@/hooks/useApi';
import { mutate, useSWRConfig } from 'swr';
import { notifications } from '@mantine/notifications';

type PictureSlotProps = {
idRef: string,
Expand All @@ -18,24 +20,25 @@ type PictureSlotProps = {
props: Record<string, JSONValue>;
};

export const PictureSlot = ({ idRef, v, res, props }: PictureSlotProps) => {
export const PictureSlot = memo(({ idRef, v, res, props }: PictureSlotProps) => {
const [hovering, setHovering] = useState(false);
const draggingElem = useEditorStore((s) => s.draggingFile);
const gallery = useEditorStore((s) => s.gallery);
const dragging = draggingElem !== null;
const dragging = draggingElem !== null && !draggingElem.ext.includes('glb');
const graggingInvalid = draggingElem !== null && draggingElem.ext.includes('glb');
const [optimisticImgSrc, setOptimisticImgSrc] = useState<string | null>(null);

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

const [optimisticImgSrc, setOptimisticImgSrc] = useState<string | null>(null);

const [image] = useImage(src ?? optimisticImgSrc ?? noImageSrc);
const [image] = useImage(src ?? noImageSrc);

const pos = v3tov2(v[2]);
const rotation = getFrameAngle(v);
Expand Down Expand Up @@ -87,29 +90,42 @@ export const PictureSlot = ({ idRef, v, res, props }: PictureSlotProps) => {

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}`);
try {
const r = 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,
}),
});
} catch {
notifications.show({
color: 'red',
title: 'Error',
message: 'Failed to update slot',
});
} finally {
mutate(`/gallery/${gallery}`);
}
}
}}
onMouseEnter={() => {
setHovering(true);
setCursor('pointer');
if (!graggingInvalid) {
setHovering(true);
setCursor('pointer');
} else {
setCursor('not-allowed');
}
}}
onMouseLeave={() => {
useEditorStore.getState().setDraggingFileVisible(true);
setHovering(false);
setCursor(null);
}}
Expand Down Expand Up @@ -137,4 +153,6 @@ export const PictureSlot = ({ idRef, v, res, props }: PictureSlotProps) => {
/> */}
</Group>
);
};
}, (prev, next) => {
return prev.res === next.res;
});
Loading

0 comments on commit b403e86

Please sign in to comment.