Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 40 additions & 22 deletions src/views/Page.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect, useState } from "react";
import { useEffect, useState, useCallback } from "react";
import {
Tooltip,
TooltipContent,
Expand All @@ -16,8 +16,7 @@ import { ExcalidrawImperativeAPI } from "@excalidraw/excalidraw/types/types";
import { useQuery, useMutation } from "@tanstack/react-query";
import { RefreshCcw } from "lucide-react";
import { getDrawData, setDrawData } from "@/db/draw";
import { drawDataStore } from "@/stores/drawDataStore"; // Adjust the import path as needed
import { queryClient } from "@/main";
import { drawDataStore } from "@/stores/drawDataStore";

type PageProps = {
id: string;
Expand All @@ -27,6 +26,7 @@ export default function Page({ id }: PageProps) {
const [excalidrawAPI, setExcalidrawAPI] =
useState<ExcalidrawImperativeAPI | null>(null);
const [name, setName] = useState("");
const [isSaving, setIsSaving] = useState(false);
const { theme } = useTheme();

const { data, isLoading } = useQuery({
Expand All @@ -40,16 +40,18 @@ export default function Page({ id }: PageProps) {
name: string;
}) => setDrawData(id, data.elements, data.name),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["page", id] });
toast("Your page has been saved to the server!");
setIsSaving(false);
},
onError: (error: Error) => {
setIsSaving(false);
toast("An error occurred while saving to the server", {
description: error.message,
});
},
});

const { mutate } = mutation;

async function updateScene() {
if (data?.data && excalidrawAPI) {
const elements = data.data[0].page_elements.elements;
Expand All @@ -58,37 +60,49 @@ export default function Page({ id }: PageProps) {
appState: { theme: theme },
});
setName(data.data[0].name);
toast("Scene updated");
}
if (data?.error) {
toast("An error occurred", { description: data.error.message });
}
}

async function setSceneData() {
const setSceneData = useCallback(async () => {
if (excalidrawAPI) {
const scene = excalidrawAPI.getSceneElements();
const updatedAt = new Date().toISOString();

// Save locally first
drawDataStore.getState().setPageData(id, scene, updatedAt, name);
toast("Your page has been saved locally!");
const existingData = drawDataStore.getState().getPageData(id);

// Then push to API
mutation.mutate({
elements: scene as NonDeletedExcalidrawElement[],
name,
});
if (JSON.stringify(existingData?.elements) !== JSON.stringify(scene)) {
setIsSaving(true);
// Save locally first
drawDataStore.getState().setPageData(id, scene, updatedAt, name);

// Then push to API
await mutate({
elements: scene as NonDeletedExcalidrawElement[],
name,
});
setIsSaving(false);
}
}
}
}, [excalidrawAPI, id, name, mutate]);

useEffect(() => {
if (!isLoading && data?.data && excalidrawAPI) {
setTimeout(updateScene, 10);
setTimeout(updateScene, 1000);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isLoading, data, excalidrawAPI]);

useEffect(() => {
const interval = setInterval(() => {
setSceneData();
}, 5000);

return () => clearInterval(interval);
}, [setSceneData]);

useEffect(() => {
// Load data from local storage if available
const localData = drawDataStore.getState().getPageData(id);
Expand All @@ -98,7 +112,6 @@ export default function Page({ id }: PageProps) {
appState: { theme: theme },
});
setName(localData.name);
toast("Loaded data from local storage");
}
}, [id, excalidrawAPI, theme]);

Expand All @@ -118,18 +131,23 @@ export default function Page({ id }: PageProps) {
value={name}
className="w-40"
/>
<Button variant="secondary" onClick={setSceneData}>
Save
<Button
variant="secondary"
onClick={setSceneData}
disabled={isSaving}
size="sm"
>
{isSaving ? "Saving..." : "Save"}
</Button>
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<Button
variant="secondary"
size="icon"
size="sm"
onClick={updateScene}
>
<RefreshCcw className="h-5 w-5" />
<RefreshCcw className="h-4 w-4" />
</Button>
</TooltipTrigger>
<TooltipContent>
Expand Down