Browse Source

feat: create new portal shape when left-clicking block/page refs inside of portal shape

Peng Xiao 3 years ago
parent
commit
52b81c809c

+ 1 - 5
deps/graph-parser/src/logseq/graph_parser/extract.cljc

@@ -250,11 +250,7 @@
         page-block (first pages)
         page-name (or (:block/name page-block)
                       (filepath->page-name file))
-        page-original-name (-> (:block/original-name page-block)
-                               (#(cond (some? %) %
-                                       (= (gp-util/page-name-sanity-lc %)
-                                          (gp-util/page-name-sanity-lc page-name)) page-name
-                                       :else page-name)))
+        page-original-name (:block/original-name page-block)
         page-name (gp-util/page-name-sanity-lc page-name)
         page {:block/name page-name
               :block/type "whiteboard"

+ 17 - 4
src/main/frontend/components/block.cljs

@@ -5,6 +5,7 @@
             [cljs-bean.core :as bean]
             [cljs.core.match :refer [match]]
             [cljs.reader :as reader]
+            [clojure.set :as set]
             [clojure.string :as string]
             [clojure.walk :as walk]
             [datascript.core :as d]
@@ -39,11 +40,13 @@
             [frontend.handler.common :as common-handler]
             [frontend.handler.dnd :as dnd]
             [frontend.handler.editor :as editor-handler]
+            [frontend.handler.file-sync :as file-sync]
             [frontend.handler.plugin :as plugin-handler]
             [frontend.handler.query :as query-handler]
             [frontend.handler.repeated :as repeated]
             [frontend.handler.route :as route-handler]
             [frontend.handler.ui :as ui-handler]
+            [frontend.handler.whiteboard :as whiteboard-handler]
             [frontend.mobile.util :as mobile-util]
             [frontend.modules.outliner.tree :as tree]
             [frontend.search :as search]
@@ -62,8 +65,8 @@
             [logseq.graph-parser.block :as gp-block]
             [logseq.graph-parser.config :as gp-config]
             [logseq.graph-parser.mldoc :as gp-mldoc]
-            [logseq.graph-parser.text :as text]
             [logseq.graph-parser.property :as gp-property]
+            [logseq.graph-parser.text :as text]
             [logseq.graph-parser.util :as gp-util]
             [logseq.graph-parser.util.block-ref :as block-ref]
             [logseq.graph-parser.util.page-ref :as page-ref]
@@ -71,8 +74,6 @@
             [promesa.core :as p]
             [reitit.frontend.easy :as rfe]
             [rum.core :as rum]
-            [frontend.handler.file-sync :as file-sync]
-            [clojure.set :as set]
             [shadow.loader :as loader]))
 
 (defn safe-read-string
@@ -535,6 +536,11 @@
        (:db/id page-entity)
        :page))
 
+    (whiteboard-handler/inside-whiteboard-portal-container (.-target e))
+    (whiteboard-handler/add-new-block-portal-shape!
+     page-name
+     (whiteboard-handler/closest-whiteboard-shape-id (.-target e)))
+
     whiteboard-page?
     (route-handler/redirect-to-whiteboard! page-name)
 
@@ -885,12 +891,19 @@
                        (not (util/right-click? e)))
                   (util/stop e)
 
-                  (if (gobj/get e "shiftKey")
+                  (cond
+                    (gobj/get e "shiftKey")
                     (state/sidebar-add-block!
                      (state/get-current-repo)
                      (:db/id block)
                      :block-ref)
 
+                    (whiteboard-handler/inside-whiteboard-portal-container (.-target e))
+                    (whiteboard-handler/add-new-block-portal-shape!
+                     (:block/uuid block)
+                     (whiteboard-handler/closest-whiteboard-shape-id (.-target e)))
+
+                    :else
                     (match [block-type (util/electron?)]
                       ;; pdf annotation
                       [:annotation true] (pdf-assets/open-block-ref! block)

+ 36 - 0
src/main/frontend/handler/whiteboard.cljs

@@ -1,6 +1,7 @@
 (ns frontend.handler.whiteboard
   "Whiteboard related handlers"
   (:require [datascript.core :as d]
+            [dommy.core :as dom]
             [frontend.db.model :as model]
             [frontend.db.utils :as db-utils]
             [frontend.handler.route :as route-handler]
@@ -127,6 +128,32 @@
    (create-new-whiteboard-page! name)
    (route-handler/redirect-to-whiteboard! name)))
 
+(defn ->logseq-portal-shape
+  [block-id point]
+  {:blockType (if (parse-uuid (str block-id)) "B" "P")
+   :id (str (d/squuid))
+   :compact false
+   :pageId (str block-id)
+   :point point
+   :size [400, 0]
+   :type "logseq-portal"})
+
+(defn add-new-block-portal-shape!
+  "Given the block uuid, add a new shape to the referenced block.
+   By default it will be placed next to the given shape id"
+  [block-uuid source-shape & {:keys [link? bottom?]}]
+  (let [app (state/active-tldraw-app)
+        api (.-api app)
+        point (-> (.getShapeById app source-shape)
+                  (.-bounds)
+                  ((fn [bounds] (if bottom? 
+                                  [(.-minX bounds) (+ 64 (.-maxY bounds))]
+                                  [(+ 64 (.-maxX bounds)) (.-minY bounds)]))))
+        shape (->logseq-portal-shape block-uuid point)]
+    (.createShapes api (clj->js shape))
+    (when link?
+      (.createNewLineBinding api source-shape (:id shape)))))
+
 (defn page-name->tldr!
   ([page-name]
    (page-name->tldr! page-name nil))
@@ -169,3 +196,12 @@
             :block/parent {:block/name page-name}}]
     (db-utils/transact! [tx])
     uuid))
+
+(defn inside-whiteboard-portal-container
+  [target]
+  (dom/closest target ".tl-logseq-cp-container"))
+
+(defn closest-whiteboard-shape-id
+  [target]
+  (when-let [shape-el (dom/closest target "[data-shape-id]")]
+    (.getAttribute shape-el "data-shape-id")))

+ 1 - 0
tldraw/apps/tldraw-logseq/src/lib/shapes/LogseqPortalShape.tsx

@@ -835,6 +835,7 @@ export class LogseqPortalShape extends TLBoxShape<LogseqPortalShapeProps> {
                 data-collapsed={this.collapsed}
                 data-page-id={pageId}
                 data-portal-selected={portalSelected}
+                data-editing={isEditing}
                 style={{
                   background: this.props.compact ? 'transparent' : fill,
                   color: stroke,

+ 4 - 0
tldraw/apps/tldraw-logseq/src/styles.css

@@ -625,6 +625,10 @@ button.tl-select-input-trigger {
   user-select: text;
   transform-origin: top left;
 
+  &[data-collapsed='true'][data-editing='false'] {
+    @apply overflow-hidden;
+  }
+
   &[data-portal-selected='true'] {
     filter: brightness(0.9) contrast(0.5);
   }

+ 1 - 1
tldraw/packages/core/src/lib/TLApi/TLApi.ts

@@ -192,7 +192,7 @@ export class TLApi<S extends TLShape = TLShape, K extends TLEventMap = TLEventMa
     return this
   }
 
-  createNewLineBinding = (source: TLShape, target: TLShape) => {
+  createNewLineBinding = (source: S | string, target: S | string) => {
     return this.app.createNewLineBinding(source, target)
   }
 }

+ 8 - 4
tldraw/packages/core/src/lib/TLApp/TLApp.ts

@@ -425,7 +425,9 @@ export class TLApp<
   distribute = (type: DistributeType, shapes: S[] = this.selectedShapesArray): this => {
     if (shapes.length < 2) return this
 
-    const deltaMap = Object.fromEntries(BoundsUtils.getDistributions(shapes, type).map(d => [d.id, d]))
+    const deltaMap = Object.fromEntries(
+      BoundsUtils.getDistributions(shapes, type).map(d => [d.id, d])
+    )
 
     shapes.forEach(shape => {
       if (deltaMap[shape.id]) shape.update({ point: deltaMap[shape.id].next })
@@ -662,9 +664,11 @@ export class TLApp<
     return this.setBindingShapes()
   }
 
-  @action createNewLineBinding = (source: TLShape, target: TLShape) => {
-    if (source.canBind && target.canBind) {
-      const result = createNewLineBinding(source, target)
+  @action createNewLineBinding = (source: S | string, target: S | string) => {
+    const src = typeof source === 'string' ? this.getShapeById(source) : source
+    const tgt = typeof target === 'string' ? this.getShapeById(target) : target
+    if (src?.canBind && tgt?.canBind) {
+      const result = createNewLineBinding(src, tgt)
       if (result) {
         const [newLine, newBindings] = result
         this.createShapes([newLine])

+ 8 - 1
tldraw/packages/react/src/components/Shape/Shape.tsx

@@ -37,7 +37,14 @@ export const Shape = observer(function Shape({
   } = shape
   const events = useShapeEvents(shape)
   return (
-    <Container zIndex={zIndex} data-type="Shape" bounds={bounds} rotation={rotation} scale={scale}>
+    <Container
+      data-shape-id={shape.id}
+      zIndex={zIndex}
+      data-type="Shape"
+      bounds={bounds}
+      rotation={rotation}
+      scale={scale}
+    >
       <ReactComponent
         meta={meta}
         isEditing={isEditing}