diff --git a/client/src/App.scss b/client/src/App.scss
index b0640c2..8eaedf4 100644
--- a/client/src/App.scss
+++ b/client/src/App.scss
@@ -28,7 +28,7 @@ a {
$border-radius: 9px;
$padding: 9px;
$height: 40px;
-$left: 50px;
+$left: 110px;
.container {
z-index: 2;
diff --git a/client/src/components/Editor.tsx b/client/src/components/Editor.tsx
index 764aef2..b795b3e 100644
--- a/client/src/components/Editor.tsx
+++ b/client/src/components/Editor.tsx
@@ -1,18 +1,12 @@
-import { FormEvent, useState } from "react";
-import { Tldraw, useFileSystem } from "@tldraw/tldraw";
+import { FormEvent, useCallback, useState } from "react";
+import { Tldraw, TldrawApp, useFileSystem } from "@tldraw/tldraw";
import { CustomCursor } from "./Cursor";
import { useAssets } from "../hooks/useAssets";
import { useMultiplayer } from "../hooks/useMultiplayer";
-import { useSingleplayer } from "../hooks/useSingleplayer";
-import { cloneDoc, initPersistence, initProvider, newDoc } from "../utils/yjs";
+import { cloneDoc, initProvider, newDoc } from "../utils/yjs";
import { v4 as uuidv4, validate as uuidValidate } from "uuid";
import PropTypes from "prop-types";
-import {
- Multiplayer,
- MultiplayerReadOnly,
- Settings,
- Singleplayer,
-} from "../types/types";
+import { Multiplayer, Settings, Singleplayer } from "../types/types";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
faArrowRightFromBracket,
@@ -57,10 +51,11 @@ function Editor({
const [useLocalDoc, setUseLocalDoc] = useState(false);
language = language || "en";
- initPersistence(idbName, localDoc);
+ readOnly = readOnly || false;
let editor = (
- ) : (
+ editor = (
);
}
@@ -185,22 +174,32 @@ function Editor({
);
}
-function SingleplayerEditor({ apiUrl, doc, language, readOnly }: Singleplayer) {
+function SingleplayerEditor({
+ apiUrl,
+ idbName,
+ doc,
+ language,
+ readOnly,
+}: Singleplayer) {
const fileSystemEvents = useFileSystem();
const { onAssetCreate, onAssetDelete, onAssetUpload } = useAssets(apiUrl);
- const { ...events } = useSingleplayer(doc, language);
+
+ const onMount = useCallback((app: TldrawApp) => {
+ app.setSetting("language", language);
+ app.setSetting("keepStyleMenuOpen", true);
+ }, []);
return (
);
}
@@ -211,6 +210,7 @@ function MultiplayerEditor({
provider,
roomId,
language,
+ readOnly,
}: Multiplayer) {
const { onSaveProjectAs, onSaveProject } = useFileSystem();
const { onAssetCreate, onAssetDelete, onAssetUpload } = useAssets(apiUrl);
@@ -222,34 +222,12 @@ function MultiplayerEditor({
components={components}
showPages={false}
showMultiplayerMenu={false}
- onAssetCreate={onAssetCreate}
+ onAssetCreate={readOnly ? undefined : onAssetCreate}
onAssetDelete={onAssetDelete}
onAssetUpload={onAssetUpload}
onSaveProjectAs={onSaveProjectAs}
onSaveProject={onSaveProject}
- {...events}
- />
- );
-}
-
-function MultiplayerReadOnlyEditor({
- doc,
- provider,
- roomId,
- language,
-}: MultiplayerReadOnly) {
- const { onSaveProjectAs, onSaveProject } = useFileSystem();
- const { ...events } = useMultiplayer(doc, provider, roomId, language);
-
- return (
-
);
diff --git a/client/src/hooks/useSingleplayer.ts b/client/src/hooks/useSingleplayer.ts
deleted file mode 100644
index eef37df..0000000
--- a/client/src/hooks/useSingleplayer.ts
+++ /dev/null
@@ -1,136 +0,0 @@
-import type { TDAsset, TDBinding, TDShape, TldrawApp } from "@tldraw/tldraw";
-import { useCallback, useEffect, useState } from "react";
-import { useHotkeys } from "react-hotkeys-hook";
-import * as Y from "yjs";
-import { getDocData } from "../utils/yjs";
-
-export function useSingleplayer(doc: Y.Doc, language: string) {
- const [app, setApp] = useState();
- const [loading, setLoading] = useState(true);
-
- const { yShapes, yBindings, yAssets, undoManager } = getDocData(doc);
-
- const onUndo = useCallback(() => {
- undoManager.undo();
- }, []);
- const onRedo = useCallback(() => {
- undoManager.redo();
- }, []);
-
- // Callbacks --------------
-
- // Put the state into the window, for debugging.
- const onMount = useCallback((app: TldrawApp) => {
- app.setSetting("language", language);
- app.setSetting("keepStyleMenuOpen", true);
- app.pause(); // Turn off the app's own undo / redo stack
- setApp(app);
- }, []);
-
- // Update the live shapes when the app's shapes change.
- const onChangePage = useCallback(
- (
- app: TldrawApp,
- shapes: Record,
- bindings: Record,
- assets: Record
- ) => {
- doc.transact(() => {
- if (!(yShapes && yBindings && yAssets)) return;
-
- Object.entries(shapes).forEach(([id, shape]) => {
- if (!shape) {
- yShapes.delete(id);
- } else {
- yShapes.set(shape.id, shape);
- }
- });
-
- Object.entries(bindings).forEach(([id, binding]) => {
- if (!binding) {
- yBindings.delete(id);
- } else {
- yBindings.set(binding.id, binding);
- }
- });
-
- Object.entries(assets).forEach(([id, asset]) => {
- if (!asset) {
- yAssets.delete(id);
- } else {
- yAssets.set(asset.id, asset);
- }
- });
- });
- },
- []
- );
-
- // Document Changes --------
-
- useEffect(() => {
- if (!app) return;
-
- // Subscribe to changes
- function handleChanges() {
- if (!app) return;
-
- app.replacePageContent(
- Object.fromEntries(yShapes.entries()),
- Object.fromEntries(yBindings.entries()),
- Object.fromEntries(yAssets.entries())
- );
- }
-
- async function setup() {
- yShapes.observe(handleChanges);
- handleChanges();
- setLoading(false);
- }
-
- setup();
-
- return () => {
- yShapes.unobserveDeep(handleChanges);
- };
- }, [app]);
-
- const onSessionStart = useCallback(() => {}, []);
-
- const onSessionEnd = useCallback(() => {}, []);
-
- useHotkeys(
- "ctrl+shift+l;,⌘+shift+l",
- () => {
- if (window.confirm("Reset the document?")) {
- undoManager.stopCapturing();
- doc.transact(() => {
- if (!(yShapes && yBindings && yAssets)) return;
-
- yShapes.forEach((shape) => {
- yShapes.delete(shape.id);
- });
-
- yBindings.forEach((shape) => {
- yBindings.delete(shape.id);
- });
-
- yAssets.forEach((shape) => {
- yAssets.delete(shape.id);
- });
- });
- }
- },
- []
- );
-
- return {
- onMount,
- onUndo,
- onRedo,
- onChangePage,
- onSessionStart,
- onSessionEnd,
- loading,
- };
-}
diff --git a/client/src/types/types.ts b/client/src/types/types.ts
index cddc522..cdcdc99 100644
--- a/client/src/types/types.ts
+++ b/client/src/types/types.ts
@@ -15,6 +15,7 @@ export type Settings = {
export type Singleplayer = {
apiUrl: string;
+ idbName: string;
doc: Y.Doc;
language: string;
readOnly: boolean;
@@ -26,11 +27,5 @@ export type Multiplayer = {
provider: WebsocketProvider;
roomId: string;
language: string;
-};
-
-export type MultiplayerReadOnly = {
- doc: Y.Doc;
- provider: WebsocketProvider;
- roomId: string;
- language: string;
+ readOnly: boolean;
};