Skip to content

Commit

Permalink
add assets support
Browse files Browse the repository at this point in the history
  • Loading branch information
davwas committed Nov 10, 2023
1 parent d9e098a commit 345385e
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 8 deletions.
6 changes: 5 additions & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,18 @@ import { useMultiplayerState } from './hooks/useMultiplayerState';

function Editor({ id, roomId }: { id: string; roomId: string }) {
const fileSystemEvents = useFileSystem();
const { onMount, ...events } = useMultiplayerState(roomId);
const { onMount, onAssetCreate, onAssetDelete, ...events } =
useMultiplayerState(roomId);

return (
<Tldraw
id={id}
autofocus
showPages={false}
onMount={onMount}
disableAssets={false}
onAssetCreate={onAssetCreate}
onAssetDelete={onAssetDelete}
{...fileSystemEvents}
{...events}
/>
Expand Down
31 changes: 29 additions & 2 deletions src/hooks/useMultiplayerState.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { TDBinding, TDShape, TDUser, TldrawApp } from '@tldraw/tldraw';
import { TDAsset, TDBinding, TDShape, TDUser, TldrawApp } from '@tldraw/tldraw';
import { useCallback, useEffect, useState } from 'react';
import { Room } from '@y-presence/client';
import {
Expand All @@ -8,6 +8,7 @@ import {
undoManager,
yBindings,
yShapes,
yAssets,
} from '../store/store';
import { TldrawPresence } from '../types';

Expand Down Expand Up @@ -35,6 +36,7 @@ export function useMultiplayerState(roomId: string) {
app: TldrawApp,
shapes: Record<string, TDShape | undefined>,
bindings: Record<string, TDBinding | undefined>,
assets: Record<string, TDAsset | undefined>,
) => {
undoManager.stopCapturing();
doc.transact(() => {
Expand All @@ -52,6 +54,13 @@ export function useMultiplayerState(roomId: string) {
yBindings.set(binding.id, binding);
}
});
Object.entries(assets).forEach(([id, asset]) => {
if (!asset) {
yAssets.delete(id);
} else {
yAssets.set(asset.id, asset);
}
});
});
},
[],
Expand All @@ -70,6 +79,22 @@ export function useMultiplayerState(roomId: string) {
room.setPresence({ id: app.room.userId, tdUser: user });
}, []);

const onAssetCreate = useCallback(
async (app: TldrawApp, file: File, assetId: string) => {
// const url = await uploadToStorage(file, id);
// return url;
console.log(file);
return 'test';
},
[],
);

const onAssetDelete = useCallback(async (app: TldrawApp, assetId: string) => {
// await deleteFromStorage(id);
console.log(assetId);
return;
}, []);

/**
* Update app users whenever there is a change in the room users
*/
Expand Down Expand Up @@ -120,7 +145,7 @@ export function useMultiplayerState(roomId: string) {
appInstance?.replacePageContent(
Object.fromEntries(yShapes.entries()),
Object.fromEntries(yBindings.entries()),
{},
Object.fromEntries(yAssets.entries()),
);
}

Expand All @@ -145,5 +170,7 @@ export function useMultiplayerState(roomId: string) {
onRedo,
loading,
onChangePresence,
onAssetCreate,
onAssetDelete,
};
}
3 changes: 2 additions & 1 deletion src/store/store.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Doc, Map, UndoManager } from 'yjs';
import { WebsocketProvider } from 'y-websocket';
import { TDBinding, TDShape } from '@tldraw/tldraw';
import { TDAsset, TDBinding, TDShape } from '@tldraw/tldraw';

const defaultOptions = {
roomName: 'GLOBAL',
Expand Down Expand Up @@ -38,6 +38,7 @@ export let provider = new WebsocketProvider(
export const awareness = provider.awareness;
export const yShapes: Map<TDShape> = doc.getMap('shapes');
export const yBindings: Map<TDBinding> = doc.getMap('bindings');
export const yAssets: Map<TDAsset> = doc.getMap('assets');
export const undoManager = new UndoManager([yShapes, yBindings]);

export function configure(options: any) {
Expand Down
16 changes: 12 additions & 4 deletions src/tests/hooks/useMultiplayerState.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ShapeStyles, TDShape, TDUser } from '@tldraw/tldraw';
import { ShapeStyles, TDAsset, TDShape, TDUser } from '@tldraw/tldraw';
import { TldrawApp } from '@tldraw/tldraw';
import { room, useMultiplayerState } from '../../hooks/useMultiplayerState';
import { undoManager, yBindings, yShapes } from '../../store/store';
Expand Down Expand Up @@ -89,13 +89,15 @@ describe('useMultiplayerState', () => {
const bindings = {
binding1: undefined,
};

const assets = {
asset1: undefined,
};
const deleteShapeSpy = jest.spyOn(yShapes, 'delete');
const deleteBindingSpy = jest.spyOn(yBindings, 'delete');

const { onChangePage } = useMultiplayerState('1');

onChangePage(tldrawApp, shapes, bindings);
onChangePage(tldrawApp, shapes, bindings, assets);

expect(deleteShapeSpy).toHaveBeenCalledWith('shape1');

Expand All @@ -118,13 +120,19 @@ describe('useMultiplayerState', () => {
style: {} as ShapeStyles,
} as TDShape,
};
const assets: Record<string, TDShape | undefined> = {
test: {
id: 'test',
style: {} as ShapeStyles,
} as TDShape,
};

const setShapeSpy = jest.spyOn(yShapes, 'set');
const setBindingSpy = jest.spyOn(yBindings, 'set');

const { onChangePage } = useMultiplayerState('1');

onChangePage(tldrawApp, shapes, bindings as any);
onChangePage(tldrawApp, shapes, bindings as any, assets as any);
expect(setShapeSpy).toHaveBeenCalledWith('test', shapes.test);
expect(setBindingSpy).toHaveBeenCalledWith('test', bindings.test);
});
Expand Down

0 comments on commit 345385e

Please sign in to comment.