embeds work!

This commit is contained in:
Jeff Emmett 2024-10-19 00:42:23 -04:00
parent 375f69b365
commit 895d02a19c
5 changed files with 92 additions and 4 deletions

View File

@ -12,6 +12,8 @@ import { VideoChatTool } from '@/tools/VideoChatTool'
import { VideoChatShape } from '@/shapes/VideoChatShapeUtil' import { VideoChatShape } from '@/shapes/VideoChatShapeUtil'
import { multiplayerAssetStore } from '../client/multiplayerAssetStore' import { multiplayerAssetStore } from '../client/multiplayerAssetStore'
import { customSchema } from '../../worker/TldrawDurableObject' import { customSchema } from '../../worker/TldrawDurableObject'
import { EmbedShape } from '@/shapes/EmbedShapeUtil'
import { EmbedTool } from '@/tools/EmbedTool'
import React, { useState } from 'react'; import React, { useState } from 'react';
import { ChatBox } from '@/shapes/ChatBoxShapeUtil'; import { ChatBox } from '@/shapes/ChatBoxShapeUtil';
@ -19,8 +21,8 @@ import { components, uiOverrides } from '@/ui-overrides'
const WORKER_URL = `https://jeffemmett-canvas.jeffemmett.workers.dev` const WORKER_URL = `https://jeffemmett-canvas.jeffemmett.workers.dev`
const shapeUtils = [ChatBoxShape, VideoChatShape] const shapeUtils = [ChatBoxShape, VideoChatShape, EmbedShape]
const tools = [ChatBoxTool, VideoChatTool]; // Array of tools const tools = [ChatBoxTool, VideoChatTool, EmbedTool]; // Array of tools
export function Board() { export function Board() {
const { slug } = useParams<{ slug: string }>(); // Ensure this is inside the Board component const { slug } = useParams<{ slug: string }>(); // Ensure this is inside the Board component
@ -107,4 +109,4 @@ async function unfurlBookmarkUrl({ url }: { url: string }): Promise<TLBookmarkAs
} }
return asset return asset
} }

View File

@ -0,0 +1,59 @@
import { BaseBoxShapeUtil, TLBaseShape } from "tldraw";
import { useCallback, useState } from "react";
export type IEmbedShape = TLBaseShape<
'Embed',
{
w: number;
h: number;
url: string | null;
}
>;
export class EmbedShape extends BaseBoxShapeUtil<IEmbedShape> {
static override type = 'Embed';
getDefaultProps(): IEmbedShape['props'] {
return {
url: null,
w: 640,
h: 480,
};
}
indicator(shape: IEmbedShape) {
return <rect x={0} y={0} width={shape.props.w} height={shape.props.h} />;
}
component(shape: IEmbedShape) {
const [inputUrl, setInputUrl] = useState(shape.props.url || '');
const handleSubmit = useCallback((e: React.FormEvent) => {
e.preventDefault();
this.editor.updateShape<IEmbedShape>({ id: shape.id, type: 'Embed', props: { ...shape.props, url: inputUrl } });
}, [inputUrl]);
if (!shape.props.url) {
return (
<div style={{ pointerEvents: 'all' }}>
<form onSubmit={handleSubmit}>
<input
type="text"
value={inputUrl}
onChange={(e) => setInputUrl(e.target.value)}
placeholder="Enter URL"
style={{ width: shape.props.w, height: shape.props.h }}
/>
<button type="submit">Load</button>
</form>
</div>
);
}
return (
<div style={{ pointerEvents: 'all' }}>
<iframe src={shape.props.url} width={shape.props.w} height={shape.props.h} />
</div>
);
}
}

9
src/tools/EmbedTool.ts Normal file
View File

@ -0,0 +1,9 @@
import { BaseBoxShapeTool } from "tldraw";
export class EmbedTool extends BaseBoxShapeTool {
static override id = 'Embed'
shapeType = 'Embed';
override initial = 'idle';
// Additional methods for handling video chat functionality can be added here
}

View File

@ -8,6 +8,7 @@ import {
useTools, useTools,
} from 'tldraw' } from 'tldraw'
import { CustomMainMenu } from './components/CustomMainMenu' import { CustomMainMenu } from './components/CustomMainMenu'
import { EmbedShape } from './shapes/EmbedShapeUtil'
export const uiOverrides: TLUiOverrides = { export const uiOverrides: TLUiOverrides = {
tools(editor, tools) { tools(editor, tools) {
@ -29,6 +30,15 @@ export const uiOverrides: TLUiOverrides = {
editor.setCurrentTool('ChatBox') editor.setCurrentTool('ChatBox')
}, },
} }
tools.Embed = {
id: 'Embed',
icon: 'embed',
label: 'Embed',
kbd: 'e',
onSelect: () => {
editor.setCurrentTool('Embed')
},
}
return tools return tools
}, },
} }
@ -38,10 +48,12 @@ export const components: TLComponents = {
const tools = useTools() const tools = useTools()
const isChatBoxSelected = useIsToolSelected(tools['ChatBox']) const isChatBoxSelected = useIsToolSelected(tools['ChatBox'])
const isVideoSelected = useIsToolSelected(tools['VideoChat']) const isVideoSelected = useIsToolSelected(tools['VideoChat'])
const isEmbedSelected = useIsToolSelected(tools['Embed'])
return ( return (
<DefaultToolbar {...props}> <DefaultToolbar {...props}>
<TldrawUiMenuItem {...tools['VideoChat']} isSelected={isVideoSelected} /> <TldrawUiMenuItem {...tools['VideoChat']} isSelected={isVideoSelected} />
<TldrawUiMenuItem {...tools['ChatBox']} isSelected={isChatBoxSelected} /> <TldrawUiMenuItem {...tools['ChatBox']} isSelected={isChatBoxSelected} />
<TldrawUiMenuItem {...tools['Embed']} isSelected={isEmbedSelected} />
<DefaultToolbarContent /> <DefaultToolbarContent />
</DefaultToolbar> </DefaultToolbar>
) )

View File

@ -13,10 +13,16 @@ import throttle from 'lodash.throttle'
import { Environment } from './types' import { Environment } from './types'
import { ChatBoxShape } from '@/shapes/ChatBoxShapeUtil' import { ChatBoxShape } from '@/shapes/ChatBoxShapeUtil'
import { VideoChatShape } from '@/shapes/VideoChatShapeUtil' import { VideoChatShape } from '@/shapes/VideoChatShapeUtil'
import { EmbedShape } from '@/shapes/EmbedShapeUtil'
// add custom shapes and bindings here if needed: // add custom shapes and bindings here if needed:
export const customSchema = createTLSchema({ export const customSchema = createTLSchema({
shapes: { ...defaultShapeSchemas, ChatBox: ChatBoxShape, VideoChat: VideoChatShape }, shapes: {
...defaultShapeSchemas,
ChatBox: ChatBoxShape,
VideoChat: VideoChatShape,
Embed: EmbedShape
},
// bindings: { ...defaultBindingSchemas }, // bindings: { ...defaultBindingSchemas },
}) })