diff --git a/apps/roam/src/components/canvas/ConvertToDialog.tsx b/apps/roam/src/components/canvas/ConvertToDialog.tsx index 93298b983..f4f91e1d4 100644 --- a/apps/roam/src/components/canvas/ConvertToDialog.tsx +++ b/apps/roam/src/components/canvas/ConvertToDialog.tsx @@ -3,6 +3,7 @@ import { OnloadArgs } from "roamjs-components/types"; import { Editor } from "tldraw"; import { DiscourseNode } from "~/utils/getDiscourseNodes"; import { getOnSelectForShape } from "./uiOverrides"; +import { getConvertibleShapeText } from "./convertShapeToDiscourseNode"; import { Dialog, Button, Classes } from "@blueprintjs/core"; import posthog from "posthog-js"; @@ -21,13 +22,12 @@ const ConvertToDialog = ({ }) => { if (!editor) return null; const selectedShapes = editor.getSelectedShapes(); - const isTextSelected = selectedShapes[0]?.type === "text"; const isImageSelected = selectedShapes[0]?.type === "image"; const oneShapeSelected = selectedShapes.length === 1; const isNodeSelected = - (isTextSelected || isImageSelected) && oneShapeSelected; + oneShapeSelected && getConvertibleShapeText(selectedShapes[0]) !== null; - let errorMessage = "Please select a text or image shape"; + let errorMessage = "Please select an image, or a shape with text in it"; if (!oneShapeSelected) errorMessage = "Please select only one shape"; return ( diff --git a/apps/roam/src/components/canvas/convertShapeToDiscourseNode.ts b/apps/roam/src/components/canvas/convertShapeToDiscourseNode.ts index 13bd704ba..7083267f7 100644 --- a/apps/roam/src/components/canvas/convertShapeToDiscourseNode.ts +++ b/apps/roam/src/components/canvas/convertShapeToDiscourseNode.ts @@ -3,6 +3,20 @@ import type { OnloadArgs } from "roamjs-components/types"; import calcCanvasNodeSizeAndImg from "~/utils/calcCanvasNodeSizeAndImg"; import { DISCOURSE_NODE_SHAPE_TYPE } from "./DiscourseNodeUtil"; +const TEXT_SHAPE_TYPES = ["text", "geo", "note"]; + +export const getConvertibleShapeText = ( + shape?: TLShape | null, +): string | null => { + if (!shape || shape.isLocked) return null; + if (shape.type === "image") return ""; + if (!TEXT_SHAPE_TYPES.includes(shape.type)) return null; + if (!("text" in shape.props)) return null; + const text = shape.props.text.trim(); + // Geo and note shapes convert only when they carry text. + return shape.type === "text" || text ? text : null; +}; + export const uploadImageShapeToRoam = async ({ editor, shape, diff --git a/apps/roam/src/components/canvas/uiOverrides.tsx b/apps/roam/src/components/canvas/uiOverrides.tsx index e009160d3..957c31eb4 100644 --- a/apps/roam/src/components/canvas/uiOverrides.tsx +++ b/apps/roam/src/components/canvas/uiOverrides.tsx @@ -5,7 +5,6 @@ import { TLImageShape, TLShape, TLShapeId, - TLTextShape, TLUiDialogProps, TLUiOverrides, TLUiTranslationKey, @@ -57,6 +56,7 @@ import { import { replaceShapeWithDiscourseNode, uploadImageShapeToRoam, + getConvertibleShapeText, } from "./convertShapeToDiscourseNode"; import { AddReferencedNodeType } from "./DiscourseRelationShape/DiscourseRelationTool"; import { @@ -201,6 +201,9 @@ export const getOnSelectForShape = ({ }); }; + const shapeText = getConvertibleShapeText(shape); + if (shapeText === null) return () => {}; + if (shape.type === "image") { return async () => { const src = await uploadImageShapeToRoam({ @@ -212,13 +215,8 @@ export const getOnSelectForShape = ({ openDialogAndCreateShape({ initialText, imageUrl: src }); }; - } else if (shape.type === "text") { - return () => { - const { text } = (shape as TLTextShape).props; - openDialogAndCreateShape({ initialText: text }); - }; } - return () => {}; + return () => openDialogAndCreateShape({ initialText: shapeText }); }; type ArrowBoundNodeInfo = { @@ -407,7 +405,7 @@ export const CustomContextMenu = ({ const shareableResults = getShareableCanvasSelectionResults({ shapes: selectedShapes, }); - const isTextSelected = selectedShape?.type === "text"; + const convertibleText = getConvertibleShapeText(selectedShape); const isImageSelected = selectedShape?.type === "image"; const arrowRelationOptions = useValue( "arrowRelationOptions", @@ -454,7 +452,7 @@ export const CustomContextMenu = ({ /> )} - {(isTextSelected || isImageSelected) && ( + {selectedShape && convertibleText !== null && ( {allNodes