diff --git a/client-src/routeTree.gen.ts b/client-src/routeTree.gen.ts index 2aab3e0..d204c26 100644 --- a/client-src/routeTree.gen.ts +++ b/client-src/routeTree.gen.ts @@ -9,14 +9,8 @@ // Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified. import { Route as rootRouteImport } from './routes/__root' -import { Route as DrawRouteImport } from './routes/draw' import { Route as IndexRouteImport } from './routes/index' -const DrawRoute = DrawRouteImport.update({ - id: '/draw', - path: '/draw', - getParentRoute: () => rootRouteImport, -} as any) const IndexRoute = IndexRouteImport.update({ id: '/', path: '/', @@ -25,39 +19,28 @@ const IndexRoute = IndexRouteImport.update({ export interface FileRoutesByFullPath { '/': typeof IndexRoute - '/draw': typeof DrawRoute } export interface FileRoutesByTo { '/': typeof IndexRoute - '/draw': typeof DrawRoute } export interface FileRoutesById { __root__: typeof rootRouteImport '/': typeof IndexRoute - '/draw': typeof DrawRoute } export interface FileRouteTypes { fileRoutesByFullPath: FileRoutesByFullPath - fullPaths: '/' | '/draw' + fullPaths: '/' fileRoutesByTo: FileRoutesByTo - to: '/' | '/draw' - id: '__root__' | '/' | '/draw' + to: '/' + id: '__root__' | '/' fileRoutesById: FileRoutesById } export interface RootRouteChildren { IndexRoute: typeof IndexRoute - DrawRoute: typeof DrawRoute } declare module '@tanstack/react-router' { interface FileRoutesByPath { - '/draw': { - id: '/draw' - path: '/draw' - fullPath: '/draw' - preLoaderRoute: typeof DrawRouteImport - parentRoute: typeof rootRouteImport - } '/': { id: '/' path: '/' @@ -70,7 +53,6 @@ declare module '@tanstack/react-router' { const rootRouteChildren: RootRouteChildren = { IndexRoute: IndexRoute, - DrawRoute: DrawRoute, } export const routeTree = rootRouteImport ._addFileChildren(rootRouteChildren) diff --git a/client-src/routes/draw.tsx b/client-src/routes/draw.tsx deleted file mode 100644 index dff346e..0000000 --- a/client-src/routes/draw.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import { createFileRoute } from "@tanstack/react-router"; -import { DrawPage } from "../views/draw/draw-page"; - -export const Route = createFileRoute("/draw")({ - component: Index, -}); - -function Index() { - return ; -} diff --git a/client-src/routes/index.tsx b/client-src/routes/index.tsx index bf53c9d..2179db0 100644 --- a/client-src/routes/index.tsx +++ b/client-src/routes/index.tsx @@ -1,14 +1,40 @@ import { createFileRoute } from "@tanstack/react-router"; import UserToolbar from "../views/room/UserToolbar"; +import usePartySocket from "partysocket/react"; +import { useState } from "react"; +import { FromServerSocketMessage } from "../../isomophic-src/isomorphic"; export const Route = createFileRoute("/")({ component: Index, }); function Index() { + const [images, setImages] = useState([]); + + usePartySocket({ + host: window.location.host, + room: "room-1", + party: "chat", + onMessage(event) { + const data: FromServerSocketMessage = JSON.parse(event.data); + switch (data.type) { + case "svg_uploaded": + setImages((prev) => [...prev, data.svgPath]); + break; + } + }, + }); + return (

Welcome Home!

+
    + {images.map((image, index) => ( +
  • + {`Uploaded +
  • + ))} +
); diff --git a/client-src/views/draw/constants/constants.ts b/client-src/views/draw/constants/constants.ts index 7699413..4db8f1a 100644 --- a/client-src/views/draw/constants/constants.ts +++ b/client-src/views/draw/constants/constants.ts @@ -3,5 +3,5 @@ import { PartySocket } from "partysocket"; export const socket = new PartySocket({ host: window.location.host, party: "chat", - room: "test" + room: "room-1" }); diff --git a/client-src/views/draw/draw-page.tsx b/client-src/views/draw/draw-page.tsx deleted file mode 100644 index b9f89d9..0000000 --- a/client-src/views/draw/draw-page.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import { Editor } from "./components/editor"; -import { Controls } from "./components/controls"; -import { useKeyboardShortcuts } from "./hooks"; -import { app } from "./state"; -import { socketSend } from "./services/socket"; - -export function DrawPage() { - useKeyboardShortcuts(); - - return ( -
-
- -
-
- -
- -
- ); -} diff --git a/client-src/views/room/UserToolbar.tsx b/client-src/views/room/UserToolbar.tsx index 8005fc3..0969973 100644 --- a/client-src/views/room/UserToolbar.tsx +++ b/client-src/views/room/UserToolbar.tsx @@ -1,6 +1,8 @@ import { useState } from "react"; import { Controls } from "../draw/components/controls"; import { Editor } from "../draw/components/editor"; +import { socketSend } from "../draw/services/socket"; +import { app } from "../draw/state"; export default function UserToolbar() { const [name, setName] = useState("frogboi"); @@ -12,14 +14,14 @@ export default function UserToolbar() { - setName(e.currentTarget.value)} - className="text-lg text-center w-fit border-2 border-green-800 bg-white font-bold rounded pl-2" + className="text-lg text-center w-fit border-2 border-green-800 bg-white font-bold rounded pl-2" /> - +
@@ -29,7 +31,11 @@ export default function UserToolbar() {
- +
diff --git a/isomophic-src/isomorphic.ts b/isomophic-src/isomorphic.ts index be3085a..7680160 100644 --- a/isomophic-src/isomorphic.ts +++ b/isomophic-src/isomorphic.ts @@ -12,10 +12,14 @@ export const FromClientSocketMessageSchema = z.union([ export type FromClientSocketMessage = z.infer; -// The type of messages sent from the server to the client via WebSocket -export const FromServerSocketMessageSchema = z.object({ - type: z.literal("acknowledge"), - message: z.string(), +const SVGUploadedSchema = z.object({ + type: z.literal("svg_uploaded"), + svgPath: z.string(), }); +// The type of messages sent from the server to the client via WebSocket +export const FromServerSocketMessageSchema = z.union([ + SVGUploadedSchema, +]); + export type FromServerSocketMessage = z.infer; \ No newline at end of file diff --git a/package.json b/package.json index 303cca5..af6c660 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,8 @@ "build": "tsc && vite build", "lint": "eslint .", "preview": "vite preview", - "format": "prettier --write ." + "format": "prettier --write .", + "gen:wrangler:types": "wrangler types" }, "dependencies": { "@modulz/radix-icons": "^4.0.0", diff --git a/server-src/server.ts b/server-src/server.ts index 035897f..13fb968 100644 --- a/server-src/server.ts +++ b/server-src/server.ts @@ -17,13 +17,19 @@ export class Chat extends Server { switch (data.type) { case "upload-svg": { - await this.ctx.storage.put("value", '123'); + const svgContent = data.svg; - const val = await this.ctx.storage.get("value"); + const svgFileName = `drawing-${crypto.randomUUID()}.svg`; + + await (this.env as Cloudflare.Env).DRAWINGS_BUCKET.put(svgFileName, svgContent, { + httpMetadata: { + contentType: "image/svg+xml", + }, + }); this.broadcast(getMessageForClient({ - type: "acknowledge", - message: `SVG received and stored with value: ${val}`, + type: "svg_uploaded", + svgPath: `https://drawings.tadpole.social/${svgFileName}`, })); break; } diff --git a/worker-configuration.d.ts b/worker-configuration.d.ts index 25ede53..910daae 100644 --- a/worker-configuration.d.ts +++ b/worker-configuration.d.ts @@ -1,5 +1,5 @@ /* eslint-disable */ -// Generated by Wrangler by running `wrangler types` (hash: 312235bc59d50703278e9ebbb16915d4) +// Generated by Wrangler by running `wrangler types` (hash: b867445971fae1bd36cd3546834ddd85) // Runtime types generated with workerd@1.20251109.0 2025-11-05 declare namespace Cloudflare { interface GlobalProps { @@ -8,6 +8,7 @@ declare namespace Cloudflare { } interface Env { Chat: DurableObjectNamespace; + DRAWINGS_BUCKET: R2Bucket; } } interface Env extends Cloudflare.Env {} diff --git a/wrangler.toml b/wrangler.toml index 973ff10..f03b351 100644 --- a/wrangler.toml +++ b/wrangler.toml @@ -13,3 +13,8 @@ class_name = "Chat" [[migrations]] tag = "v1" # Should be unique for each entry new_sqlite_classes = ["Chat"] + +[[r2_buckets]] +binding = 'DRAWINGS_BUCKET' # <~ valid JavaScript variable name +bucket_name = 'drawings' +remote = true