aboutsummaryrefslogtreecommitdiff
path: root/packages
diff options
context:
space:
mode:
authorDhravya <[email protected]>2024-06-30 20:50:24 -0500
committerDhravya <[email protected]>2024-06-30 20:50:24 -0500
commitffd141ade4e6074ee486da7f74f31e3905807cb9 (patch)
tree505d73b0a7c04cdec93d7f5be88c635642716c15 /packages
parentshow updates in the extension (diff)
parentMerge pull request #93 from Dhravya/editor (diff)
downloadsupermemory-ffd141ade4e6074ee486da7f74f31e3905807cb9.tar.xz
supermemory-ffd141ade4e6074ee486da7f74f31e3905807cb9.zip
merge conflicts
Diffstat (limited to 'packages')
-rw-r--r--packages/ui/components/canvas/components/canvas.tsx94
-rw-r--r--packages/ui/components/canvas/components/draggableComponent.tsx71
-rw-r--r--packages/ui/components/canvas/components/dropComponent.tsx203
-rw-r--r--packages/ui/components/canvas/components/enabledComp copy.tsx22
-rw-r--r--packages/ui/components/canvas/components/enabledComp.tsx22
-rw-r--r--packages/ui/components/canvas/components/savesnap.tsx43
-rw-r--r--packages/ui/components/canvas/components/textCard.tsx45
-rw-r--r--packages/ui/components/canvas/components/twitterCard.tsx84
-rw-r--r--packages/ui/components/canvas/lib/context.ts18
-rw-r--r--packages/ui/components/canvas/lib/createAssetUrl.ts94
-rw-r--r--packages/ui/components/canvas/lib/createEmbeds.ts236
-rw-r--r--packages/ui/components/canvas/lib/loadSnap.ts14
12 files changed, 0 insertions, 946 deletions
diff --git a/packages/ui/components/canvas/components/canvas.tsx b/packages/ui/components/canvas/components/canvas.tsx
deleted file mode 100644
index f3e4c090..00000000
--- a/packages/ui/components/canvas/components/canvas.tsx
+++ /dev/null
@@ -1,94 +0,0 @@
-import { useCallback, useEffect, useRef, useState } from "react";
-import { Editor, Tldraw, setUserPreferences, TLStoreWithStatus } from "tldraw";
-import { createAssetFromUrl } from "../lib/createAssetUrl";
-import "tldraw/tldraw.css";
-import { components } from "./enabledComp";
-import { twitterCardUtil } from "./twitterCard";
-import { textCardUtil } from "./textCard";
-import createEmbedsFromUrl from "../lib/createEmbeds";
-import { loadRemoteSnapshot } from "../lib/loadSnap";
-import { SaveStatus } from "./savesnap";
-import { getAssetUrls } from "@tldraw/assets/selfHosted";
-import { memo } from "react";
-import DragContext from "../lib/context";
-import DropZone from "./dropComponent";
-// import "./canvas.css";
-
-export const Canvas = memo(() => {
- const [isDraggingOver, setIsDraggingOver] = useState<boolean>(false);
- const Dragref = useRef<HTMLDivElement | null>(null);
-
- const handleDragOver = (event: any) => {
- event.preventDefault();
- setIsDraggingOver(true);
- console.log("entere");
- };
-
- useEffect(() => {
- const divElement = Dragref.current;
- if (divElement) {
- divElement.addEventListener("dragover", handleDragOver);
- }
- return () => {
- if (divElement) {
- divElement.removeEventListener("dragover", handleDragOver);
- }
- };
- }, []);
-
- return (
- <DragContext.Provider value={{ isDraggingOver, setIsDraggingOver }}>
- <div ref={Dragref} className="w-full h-full">
- <TldrawComponent />
- </div>
- </DragContext.Provider>
- );
-});
-
-const TldrawComponent = memo(() => {
- const [storeWithStatus, setStoreWithStatus] = useState<TLStoreWithStatus>({
- status: "loading",
- });
- useEffect(() => {
- const fetchStore = async () => {
- const store = await loadRemoteSnapshot();
-
- setStoreWithStatus({
- store: store,
- status: "not-synced",
- });
- };
-
- fetchStore();
- }, []);
-
- const handleMount = useCallback((editor: Editor) => {
- (window as any).app = editor;
- (window as any).editor = editor;
- editor.registerExternalAssetHandler("url", createAssetFromUrl);
- editor.registerExternalContentHandler("url", ({ url, point, sources }) => {
- createEmbedsFromUrl({ url, point, sources, editor });
- });
- }, []);
-
- setUserPreferences({ id: "supermemory" });
-
- const assetUrls = getAssetUrls();
- return (
- <div className="w-full h-full">
- <Tldraw
- className="relative"
- assetUrls={assetUrls}
- components={components}
- store={storeWithStatus}
- shapeUtils={[twitterCardUtil, textCardUtil]}
- onMount={handleMount}
- >
- <div className="absolute left-1/2 top-0 z-[1000000] flex -translate-x-1/2 gap-2 bg-[#2C3439] text-[#B3BCC5]">
- <SaveStatus />
- </div>
- <DropZone />
- </Tldraw>
- </div>
- );
-});
diff --git a/packages/ui/components/canvas/components/draggableComponent.tsx b/packages/ui/components/canvas/components/draggableComponent.tsx
deleted file mode 100644
index d0832e81..00000000
--- a/packages/ui/components/canvas/components/draggableComponent.tsx
+++ /dev/null
@@ -1,71 +0,0 @@
-import Image from "next/image";
-import { useRef, useState } from "react";
-
-interface DraggableComponentsProps {
- content: string;
- extraInfo?: string;
- icon: string;
- iconAlt: string;
-}
-
-export default function DraggableComponentsContainer({
- content,
-}: {
- content: DraggableComponentsProps[];
-}) {
- return (
- <div className="flex flex-col gap-10">
- {content.map((i) => {
- return (
- <DraggableComponents
- content={i.content}
- icon={i.icon}
- iconAlt={i.iconAlt}
- extraInfo={i.extraInfo}
- />
- );
- })}
- </div>
- );
-}
-
-function DraggableComponents({
- content,
- extraInfo,
- icon,
- iconAlt,
-}: DraggableComponentsProps) {
- const [isDragging, setIsDragging] = useState(false);
- const containerRef = useRef<HTMLDivElement>(null);
-
- const handleDragStart = (event: React.DragEvent<HTMLDivElement>) => {
- setIsDragging(true);
- if (containerRef.current) {
- // Serialize the children as a string for dataTransfer
- const childrenHtml = containerRef.current.innerHTML;
- event.dataTransfer.setData("text/html", childrenHtml);
- }
- };
-
- const handleDragEnd = () => {
- setIsDragging(false);
- };
-
- return (
- <div
- ref={containerRef}
- onDragEnd={handleDragEnd}
- onDragStart={handleDragStart}
- draggable
- className={`flex gap-4 px-1 rounded-md text-[#989EA4] border-2 transition ${isDragging ? "border-blue-600" : "border-[#1F2428]"}`}
- >
- <Image className="select-none" src={icon} alt={iconAlt} />
- <div className="flex flex-col gap-2">
- <div>
- <h1 className="line-clamp-3">{content}</h1>
- </div>
- <p className="line-clamp-1 text-[#369DFD]">{extraInfo}</p>
- </div>
- </div>
- );
-}
diff --git a/packages/ui/components/canvas/components/dropComponent.tsx b/packages/ui/components/canvas/components/dropComponent.tsx
deleted file mode 100644
index 0374f367..00000000
--- a/packages/ui/components/canvas/components/dropComponent.tsx
+++ /dev/null
@@ -1,203 +0,0 @@
-import React, { useRef, useCallback, useEffect, useContext } from "react";
-import { useEditor } from "tldraw";
-import DragContext, { DragContextType, useDragContext } from "../lib/context";
-import { handleExternalDroppedContent } from "../lib/createEmbeds";
-
-const stripHtmlTags = (html: string): string => {
- const div = document.createElement("div");
- div.innerHTML = html;
- return div.textContent || div.innerText || "";
-};
-
-function formatTextToRatio(text: string) {
- const totalWidth = text.length;
- const maxLineWidth = Math.floor(totalWidth / 4);
-
- const words = text.split(" ");
- let lines = [];
- let currentLine = "";
-
- words.forEach((word) => {
- // Check if adding the next word exceeds the maximum line width
- if ((currentLine + word).length <= maxLineWidth) {
- currentLine += (currentLine ? " " : "") + word;
- } else {
- // If the current line is full, push it to new line
- lines.push(currentLine);
- currentLine = word;
- }
- });
- if (currentLine) {
- lines.push(currentLine);
- }
- return lines.join("\n");
-}
-
-function DropZone() {
- const dropRef = useRef<HTMLDivElement | null>(null);
- const { isDraggingOver, setIsDraggingOver } = useDragContext();
-
- const editor = useEditor();
-
- const handleDragLeave = () => {
- setIsDraggingOver(false);
- console.log("leaver");
- };
-
- useEffect(() => {
- setInterval(() => {
- editor.selectAll();
- const shapes = editor.getSelectedShapes();
- const text = shapes.filter((s) => s.type === "text");
- console.log("hrhh", text);
- }, 5000);
- }, []);
-
- const handleDrop = useCallback((event: DragEvent) => {
- event.preventDefault();
- setIsDraggingOver(false);
- const dt = event.dataTransfer;
- if (!dt) {
- return;
- }
- const items = dt.items;
-
- for (let i = 0; i < items.length; i++) {
- if (items[i]!.kind === "file" && items[i]!.type.startsWith("image/")) {
- const file = items[i]!.getAsFile();
- if (file) {
- const reader = new FileReader();
- reader.onload = (e) => {
- if (e.target) {
- // setDroppedImage(e.target.result as string);
- }
- };
- reader.readAsDataURL(file);
- }
- } else if (items[i]!.kind === "string") {
- items[i]!.getAsString((data) => {
- const cleanText = stripHtmlTags(data);
- const onethree = formatTextToRatio(cleanText);
- handleExternalDroppedContent({ editor, text: onethree });
- });
- }
- }
- }, []);
-
- useEffect(() => {
- const divElement = dropRef.current;
- if (divElement) {
- divElement.addEventListener("drop", handleDrop);
- divElement.addEventListener("dragleave", handleDragLeave);
- }
- return () => {
- if (divElement) {
- divElement.removeEventListener("drop", handleDrop);
- divElement.addEventListener("dragleave", handleDragLeave);
- }
- };
- }, []);
-
- return (
- <div
- className={`h-full flex justify-center items-center w-full absolute top-0 left-0 z-[100000] pointer-events-none ${isDraggingOver && "bg-[#2c3439ad] pointer-events-auto"}`}
- ref={dropRef}
- >
- {isDraggingOver && (
- <>
- <div className="absolute top-4 left-8">
- <TopRight />
- </div>
- <div className="absolute top-4 right-8">
- <TopLeft />
- </div>
- <div className="absolute bottom-4 left-8">
- <BottomLeft />
- </div>
- <div className="absolute bottom-4 right-8">
- <BottomRight />
- </div>
- <h2 className="text-2xl">Drop here to add Content on Canvas</h2>
- </>
- )}
- </div>
- );
-}
-
-function TopRight() {
- return (
- <svg
- width="48"
- height="48"
- viewBox="0 0 48 48"
- fill="none"
- xmlns="http://www.w3.org/2000/svg"
- >
- <path
- d="M44 4H12C7.58172 4 4 7.58172 4 12V44"
- stroke="white"
- stroke-width="8"
- stroke-linecap="round"
- />
- </svg>
- );
-}
-
-function TopLeft() {
- return (
- <svg
- width="48"
- height="48"
- viewBox="0 0 48 48"
- fill="none"
- xmlns="http://www.w3.org/2000/svg"
- >
- <path
- d="M4 4H36C40.4183 4 44 7.58172 44 12V44"
- stroke="white"
- stroke-width="8"
- stroke-linecap="round"
- />
- </svg>
- );
-}
-
-function BottomLeft() {
- return (
- <svg
- width="48"
- height="48"
- viewBox="0 0 48 48"
- fill="none"
- xmlns="http://www.w3.org/2000/svg"
- >
- <path
- d="M44 44H12C7.58172 44 4 40.4183 4 36V4"
- stroke="white"
- stroke-width="8"
- stroke-linecap="round"
- />
- </svg>
- );
-}
-
-function BottomRight() {
- return (
- <svg
- width="48"
- height="48"
- viewBox="0 0 48 48"
- fill="none"
- xmlns="http://www.w3.org/2000/svg"
- >
- <path
- d="M4 44H36C40.4183 44 44 40.4183 44 36V4"
- stroke="white"
- stroke-width="8"
- stroke-linecap="round"
- />
- </svg>
- );
-}
-
-export default DropZone;
diff --git a/packages/ui/components/canvas/components/enabledComp copy.tsx b/packages/ui/components/canvas/components/enabledComp copy.tsx
deleted file mode 100644
index 85811b82..00000000
--- a/packages/ui/components/canvas/components/enabledComp copy.tsx
+++ /dev/null
@@ -1,22 +0,0 @@
-import { TLUiComponents } from "tldraw";
-
-export const components: Partial<TLUiComponents> = {
- ActionsMenu: null,
- MainMenu: null,
- QuickActions: null,
- TopPanel: null,
- DebugPanel: null,
- DebugMenu: null,
- PageMenu: null,
- // Minimap: null,
- // ContextMenu: null,
- // HelpMenu: null,
- // ZoomMenu: null,
- // StylePanel: null,
- // NavigationPanel: null,
- // Toolbar: null,
- // KeyboardShortcutsDialog: null,
- // HelperButtons: null,
- // SharePanel: null,
- // MenuPanel: null,
-}; \ No newline at end of file
diff --git a/packages/ui/components/canvas/components/enabledComp.tsx b/packages/ui/components/canvas/components/enabledComp.tsx
deleted file mode 100644
index 85811b82..00000000
--- a/packages/ui/components/canvas/components/enabledComp.tsx
+++ /dev/null
@@ -1,22 +0,0 @@
-import { TLUiComponents } from "tldraw";
-
-export const components: Partial<TLUiComponents> = {
- ActionsMenu: null,
- MainMenu: null,
- QuickActions: null,
- TopPanel: null,
- DebugPanel: null,
- DebugMenu: null,
- PageMenu: null,
- // Minimap: null,
- // ContextMenu: null,
- // HelpMenu: null,
- // ZoomMenu: null,
- // StylePanel: null,
- // NavigationPanel: null,
- // Toolbar: null,
- // KeyboardShortcutsDialog: null,
- // HelperButtons: null,
- // SharePanel: null,
- // MenuPanel: null,
-}; \ No newline at end of file
diff --git a/packages/ui/components/canvas/components/savesnap.tsx b/packages/ui/components/canvas/components/savesnap.tsx
deleted file mode 100644
index f82e97e3..00000000
--- a/packages/ui/components/canvas/components/savesnap.tsx
+++ /dev/null
@@ -1,43 +0,0 @@
-import { useCallback, useEffect, useState } from "react";
-import { debounce, useEditor } from "tldraw";
-
-export function SaveStatus() {
- const [save, setSave] = useState("saved!");
- const editor = useEditor();
-
- const debouncedSave = useCallback(
- debounce(async () => {
- const snapshot = editor.store.getSnapshot();
- localStorage.setItem("saved", JSON.stringify(snapshot));
-
- const res = await fetch(
- "https://learning-cf.pruthvirajthinks.workers.dev/post/page3",
- {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify({
- data: snapshot,
- }),
- },
- );
-
- console.log(await res.json());
- setSave("saved!");
- }, 3000),
- [editor], // Dependency array ensures the function is not recreated on every render
- );
-
- useEffect(() => {
- const unsubscribe = editor.store.listen(
- () => {
- setSave("saving...");
- debouncedSave();
- },
- { scope: "document", source: "user" },
- );
-
- return () => unsubscribe(); // Cleanup on unmount
- }, [editor, debouncedSave]);
-
- return <button>{save}</button>;
-} \ No newline at end of file
diff --git a/packages/ui/components/canvas/components/textCard.tsx b/packages/ui/components/canvas/components/textCard.tsx
deleted file mode 100644
index b24dae52..00000000
--- a/packages/ui/components/canvas/components/textCard.tsx
+++ /dev/null
@@ -1,45 +0,0 @@
-import { BaseBoxShapeUtil, HTMLContainer, TLBaseShape } from "tldraw";
-
-type ITextCardShape = TLBaseShape<
- "Textcard",
- { w: number; h: number; content: string; extrainfo: string }
->;
-
-export class textCardUtil extends BaseBoxShapeUtil<ITextCardShape> {
- static override type = "Textcard" as const;
-
- getDefaultProps(): ITextCardShape["props"] {
- return {
- w: 100,
- h: 50,
- content: "",
- extrainfo: "",
- };
- }
-
- component(s: ITextCardShape) {
- return (
- <HTMLContainer className="flex h-full w-full items-center justify-center">
- <div
- style={{
- height: s.props.h,
- width: s.props.w,
- pointerEvents: "all",
- background: "#2C3439",
- borderRadius: "16px",
- padding: "8px 14px",
- }}
- >
- <h1 style={{ fontSize: "15px" }}>{s.props.content}</h1>
- <p style={{ fontSize: "14px", color: "#369DFD" }}>
- {s.props.extrainfo}
- </p>
- </div>
- </HTMLContainer>
- );
- }
-
- indicator(shape: ITextCardShape) {
- return <rect width={shape.props.w} height={shape.props.h} />;
- }
-}
diff --git a/packages/ui/components/canvas/components/twitterCard.tsx b/packages/ui/components/canvas/components/twitterCard.tsx
deleted file mode 100644
index c5582a98..00000000
--- a/packages/ui/components/canvas/components/twitterCard.tsx
+++ /dev/null
@@ -1,84 +0,0 @@
-import { BaseBoxShapeUtil, HTMLContainer, TLBaseShape, toDomPrecision } from "tldraw";
-
-type ITwitterCardShape = TLBaseShape<
- "Twittercard",
- { w: number; h: number; url: string }
->;
-
-export class twitterCardUtil extends BaseBoxShapeUtil<ITwitterCardShape> {
- static override type = "Twittercard" as const;
-
- getDefaultProps(): ITwitterCardShape["props"] {
- return {
- w: 500,
- h: 550,
- url: "",
- };
- }
-
- component(s: ITwitterCardShape) {
- return (
- <HTMLContainer className="flex h-full w-full items-center justify-center">
- <TwitterPost
- url={s.props.url}
- width={s.props.w}
- isInteractive={false}
- height={s.props.h}
- />
- </HTMLContainer>
- );
- }
-
- indicator(shape: ITwitterCardShape) {
- return <rect width={shape.props.w} height={shape.props.h} />;
- }
-}
-
-function TwitterPost({
- isInteractive,
- width,
- height,
- url,
-}: {
- isInteractive: boolean;
- width: number;
- height: number;
- url: string;
-}) {
- const link = (() => {
- try {
- const urlObj = new URL(url);
- const path = urlObj.pathname;
- return path;
- } catch (error) {
- console.error("Invalid URL", error);
- return null;
- }
- })();
-
- return (
- <iframe
- className="tl-embed"
- draggable={false}
- width={toDomPrecision(width)}
- height={toDomPrecision(height)}
- seamless
- referrerPolicy="no-referrer-when-downgrade"
- style={{
- pointerEvents: isInteractive ? "all" : "none",
- zIndex: isInteractive ? "" : "-1",
- }}
- srcDoc={`
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
- </head>
- <body>
- <blockquote data-theme="dark" class="twitter-tweet"><p lang="en" dir="ltr"><a href="https://twitter.com${link}"></a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
- </body>
- </html>`}
- />
- );
-}
diff --git a/packages/ui/components/canvas/lib/context.ts b/packages/ui/components/canvas/lib/context.ts
deleted file mode 100644
index 4e6ecd1c..00000000
--- a/packages/ui/components/canvas/lib/context.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import { createContext, useContext } from 'react';
-
-export interface DragContextType {
- isDraggingOver: boolean;
- setIsDraggingOver: React.Dispatch<React.SetStateAction<boolean>>;
-}
-
-const DragContext = createContext<DragContextType | undefined>(undefined);
-
-export const useDragContext = () => {
- const context = useContext(DragContext);
- if (context === undefined) {
- throw new Error('useAppContext must be used within an AppProvider');
- }
- return context;
-};
-
-export default DragContext; \ No newline at end of file
diff --git a/packages/ui/components/canvas/lib/createAssetUrl.ts b/packages/ui/components/canvas/lib/createAssetUrl.ts
deleted file mode 100644
index 05c2baea..00000000
--- a/packages/ui/components/canvas/lib/createAssetUrl.ts
+++ /dev/null
@@ -1,94 +0,0 @@
-import {
- AssetRecordType,
- TLAsset,
- getHashForString,
- truncateStringWithEllipsis,
-} from "tldraw";
-// import { BOOKMARK_ENDPOINT } from './config'
-
-interface ResponseBody {
- title?: string;
- description?: string;
- image?: string;
-}
-
-export async function createAssetFromUrl({
- url,
-}: {
- type: "url";
- url: string;
-}): Promise<TLAsset> {
- // try {
- // // First, try to get the meta data from our endpoint
- // const meta = (await (
- // await fetch(BOOKMARK_ENDPOINT, {
- // method: 'POST',
- // headers: {
- // 'Content-Type': 'application/json',
- // },
- // body: JSON.stringify({
- // url,
- // }),
- // })
- // ).json()) as ResponseBody
-
- // return {
- // id: AssetRecordType.createId(getHashForString(url)),
- // typeName: 'asset',
- // type: 'bookmark',
- // props: {
- // src: url,
- // description: meta.description ?? '',
- // image: meta.image ?? '',
- // title: meta.title ?? truncateStringWithEllipsis(url, 32),
- // },
- // meta: {},
- // }
- // } catch (error) {
- // Otherwise, fallback to fetching data from the url
-
- let meta: { image: string; title: string; description: string };
-
- try {
- const resp = await fetch(url, { method: "GET", mode: "no-cors" });
- const html = await resp.text();
- const doc = new DOMParser().parseFromString(html, "text/html");
- meta = {
- image:
- doc.head
- .querySelector('meta[property="og:image"]')
- ?.getAttribute("content") ?? "",
- title:
- doc.head
- .querySelector('meta[property="og:title"]')
- ?.getAttribute("content") ?? truncateStringWithEllipsis(url, 32),
- description:
- doc.head
- .querySelector('meta[property="og:description"]')
- ?.getAttribute("content") ?? "",
- };
- } catch (error) {
- console.error(error);
- meta = {
- image: "",
- title: truncateStringWithEllipsis(url, 32),
- description: "",
- };
- }
-
- // Create the bookmark asset from the meta
- return {
- id: AssetRecordType.createId(getHashForString(url)),
- typeName: "asset",
- type: "bookmark",
- props: {
- src: url,
- image: meta.image,
- title: meta.title,
- description: meta.description,
- favicon: meta.image,
- },
- meta: {},
- };
- // }
-}
diff --git a/packages/ui/components/canvas/lib/createEmbeds.ts b/packages/ui/components/canvas/lib/createEmbeds.ts
deleted file mode 100644
index b3a7fb52..00000000
--- a/packages/ui/components/canvas/lib/createEmbeds.ts
+++ /dev/null
@@ -1,236 +0,0 @@
-// @ts-nocheck TODO: A LOT OF TS ERRORS HERE
-
-import {
- AssetRecordType,
- Editor,
- TLAsset,
- TLAssetId,
- TLBookmarkShape,
- TLExternalContentSource,
- TLShapePartial,
- Vec,
- VecLike,
- createShapeId,
- getEmbedInfo,
- getHashForString,
-} from "tldraw";
-
-export default async function createEmbedsFromUrl({
- url,
- point,
- sources,
- editor,
-}: {
- url: string;
- point?: VecLike | undefined;
- sources?: TLExternalContentSource[] | undefined;
- editor: Editor;
-}) {
- const position =
- point ??
- (editor.inputs.shiftKey
- ? editor.inputs.currentPagePoint
- : editor.getViewportPageBounds().center);
-
- if (url?.includes("x.com") || url?.includes("twitter.com")) {
- return editor.createShape({
- type: "Twittercard",
- x: position.x - 250,
- y: position.y - 150,
- props: { url: url },
- });
- }
-
- // try to paste as an embed first
- const embedInfo = getEmbedInfo(url);
-
- if (embedInfo) {
- return editor.putExternalContent({
- type: "embed",
- url: embedInfo.url,
- point,
- embed: embedInfo.definition,
- });
- }
-
- const assetId: TLAssetId = AssetRecordType.createId(getHashForString(url));
- const shape = createEmptyBookmarkShape(editor, url, position);
-
- // Use an existing asset if we have one, or else else create a new one
- let asset = editor.getAsset(assetId) as TLAsset;
- let shouldAlsoCreateAsset = false;
- if (!asset) {
- shouldAlsoCreateAsset = true;
- try {
- const bookmarkAsset = await editor.getAssetForExternalContent({
- type: "url",
- url,
- });
- const fetchWebsite: {
- title?: string;
- image?: string;
- description?: string;
- } = await (
- await fetch(`/api/unfirlsite?website=${url}`, {
- method: "POST",
- })
- ).json();
- if (bookmarkAsset) {
- if (fetchWebsite.title) bookmarkAsset.props.title = fetchWebsite.title;
- if (fetchWebsite.image) bookmarkAsset.props.image = fetchWebsite.image;
- if (fetchWebsite.description)
- bookmarkAsset.props.description = fetchWebsite.description;
- }
- if (!bookmarkAsset) throw Error("Could not create an asset");
- asset = bookmarkAsset;
- } catch (e) {
- console.log(e);
- return;
- }
- }
-
- editor.batch(() => {
- if (shouldAlsoCreateAsset) {
- editor.createAssets([asset]);
- }
-
- editor.updateShapes([
- {
- id: shape.id,
- type: shape.type,
- props: {
- assetId: asset.id,
- },
- },
- ]);
- });
-}
-
-function isURL(str: string) {
- try {
- new URL(str);
- return true;
- } catch {
- return false;
- }
-}
-
-function formatTextToRatio(text: string) {
- const totalWidth = text.length;
- const maxLineWidth = Math.floor(totalWidth / 10);
-
- const words = text.split(" ");
- let lines = [];
- let currentLine = "";
-
- words.forEach((word) => {
- if ((currentLine + word).length <= maxLineWidth) {
- currentLine += (currentLine ? " " : "") + word;
- } else {
- lines.push(currentLine);
- currentLine = word;
- }
- });
- if (currentLine) {
- lines.push(currentLine);
- }
- return { height: (lines.length + 1) * 18, width: maxLineWidth * 10 };
-}
-
-export function handleExternalDroppedContent({
- text,
- editor,
-}: {
- text: string;
- editor: Editor;
-}) {
- const position = editor.inputs.shiftKey
- ? editor.inputs.currentPagePoint
- : editor.getViewportPageBounds().center;
-
- if (isURL(text)) {
- createEmbedsFromUrl({ editor, url: text });
- } else {
- // editor.createShape({
- // type: "text",
- // x: position.x - 75,
- // y: position.y - 75,
- // props: {
- // text: text,
- // size: "s",
- // textAlign: "start",
- // },
- // });
- const { height, width } = formatTextToRatio(text);
- editor.createShape({
- type: "Textcard",
- x: position.x - width / 2,
- y: position.y - height / 2,
- props: {
- content: text,
- extrainfo: "https://chatgpt.com/c/762cd44e-1752-495b-967a-aa3c23c6024a",
- w: width,
- h: height,
- },
- });
- }
-}
-
-function centerSelectionAroundPoint(editor: Editor, position: VecLike) {
- // Re-position shapes so that the center of the group is at the provided point
- const viewportPageBounds = editor.getViewportPageBounds();
- let selectionPageBounds = editor.getSelectionPageBounds();
-
- if (selectionPageBounds) {
- const offset = selectionPageBounds!.center.sub(position);
-
- editor.updateShapes(
- editor.getSelectedShapes().map((shape) => {
- const localRotation = editor
- .getShapeParentTransform(shape)
- .decompose().rotation;
- const localDelta = Vec.Rot(offset, -localRotation);
- return {
- id: shape.id,
- type: shape.type,
- x: shape.x! - localDelta.x,
- y: shape.y! - localDelta.y,
- };
- }),
- );
- }
-
- // Zoom out to fit the shapes, if necessary
- selectionPageBounds = editor.getSelectionPageBounds();
- if (
- selectionPageBounds &&
- !viewportPageBounds.contains(selectionPageBounds)
- ) {
- editor.zoomToSelection();
- }
-}
-
-export function createEmptyBookmarkShape(
- editor: Editor,
- url: string,
- position: VecLike,
-): TLBookmarkShape {
- const partial: TLShapePartial = {
- id: createShapeId(),
- type: "bookmark",
- x: position.x - 150,
- y: position.y - 160,
- opacity: 1,
- props: {
- assetId: null,
- url,
- },
- };
-
- editor.batch(() => {
- editor.createShapes([partial]).select(partial.id);
- centerSelectionAroundPoint(editor, position);
- });
-
- return editor.getShape(partial.id) as TLBookmarkShape;
-}
diff --git a/packages/ui/components/canvas/lib/loadSnap.ts b/packages/ui/components/canvas/lib/loadSnap.ts
deleted file mode 100644
index 846b1967..00000000
--- a/packages/ui/components/canvas/lib/loadSnap.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import { createTLStore, defaultShapeUtils, loadSnapshot } from "tldraw";
-import { twitterCardUtil } from "../components/twitterCard";
-import { textCardUtil } from "../components/textCard";
-export async function loadRemoteSnapshot() {
- const res = await fetch(
- "https://learning-cf.pruthvirajthinks.workers.dev/get/page3",
- );
- const snapshot = JSON.parse(await res.json());
- const newStore = createTLStore({
- shapeUtils: [...defaultShapeUtils, twitterCardUtil, textCardUtil],
- });
- loadSnapshot(newStore, snapshot);
- return newStore;
-}