mirror of
https://github.com/logseq/logseq.git
synced 2026-05-24 04:34:14 +00:00
Merge branch 'master' into enhance/keymaps-manager-x
This commit is contained in:
@@ -208,7 +208,7 @@
|
||||
pages (remove nil? pages)
|
||||
pages (map (fn [page] (assoc page :block/uuid (d/squuid))) pages)
|
||||
blocks (->> (remove nil? blocks)
|
||||
(map (fn [b] (dissoc b :block/title :block/body :block/level :block/children :block/meta :block/anchor))))]
|
||||
(map (fn [b] (dissoc b :block/title :block/body :block/level :block/children :block/meta))))]
|
||||
[pages blocks])
|
||||
(catch :default e
|
||||
(log/error :exception e))))
|
||||
|
||||
@@ -7,11 +7,11 @@
|
||||
[goog.string.format]))
|
||||
|
||||
(def colons "Property delimiter for markdown mode" "::")
|
||||
(defn colons-org
|
||||
(defn colons-org
|
||||
"Property delimiter for org mode"
|
||||
[property]
|
||||
(str ":" property ":"))
|
||||
|
||||
|
||||
(defn ->block-content
|
||||
"Creates a block content string from properties map"
|
||||
[properties]
|
||||
@@ -47,19 +47,23 @@
|
||||
"Properties used by logseq that user can edit and that can have linkable property values"
|
||||
#{:alias :aliases :tags})
|
||||
|
||||
(def editable-view-and-table-properties
|
||||
"Properties used by view and table component"
|
||||
#{;; view props
|
||||
:logseq.color
|
||||
;; table props
|
||||
:logseq.table.version :logseq.table.compact :logseq.table.headers :logseq.table.hover
|
||||
:logseq.table.borders :logseq.table.stripes :logseq.table.max-width})
|
||||
|
||||
(defn editable-built-in-properties
|
||||
"Properties used by logseq that user can edit"
|
||||
[]
|
||||
(into #{:title :icon :template :template-including-parent :public :filters :exclude-from-graph-view
|
||||
:logseq.query/nlp-date
|
||||
;; view props
|
||||
:logseq.color
|
||||
;; table props
|
||||
:logseq.table.version :logseq.table.compact :logseq.table.headers :logseq.table.hover
|
||||
:logseq.table.borders :logseq.table.stripes :logseq.table.max-width
|
||||
(set/union #{:title :icon :template :template-including-parent :public :filters :exclude-from-graph-view
|
||||
:logseq.query/nlp-date
|
||||
;; org-mode only
|
||||
:macro :filetags}
|
||||
editable-linkable-built-in-properties))
|
||||
:macro :filetags}
|
||||
editable-linkable-built-in-properties
|
||||
editable-view-and-table-properties))
|
||||
|
||||
(defn hidden-built-in-properties
|
||||
"Properties used by logseq that user can't edit or see"
|
||||
|
||||
@@ -126,6 +126,37 @@ test('clone the rectangle', async ({ page }) => {
|
||||
await expect(page.locator('.logseq-tldraw .tl-box-container')).toHaveCount(2)
|
||||
})
|
||||
|
||||
test('group the rectangles', async ({ page }) => {
|
||||
await page.keyboard.press(modKey + '+a')
|
||||
await page.keyboard.press(modKey + '+g')
|
||||
|
||||
await expect(page.locator('.logseq-tldraw .tl-group-container')).toHaveCount(1)
|
||||
})
|
||||
|
||||
test('delete the group', async ({ page }) => {
|
||||
await page.keyboard.press(modKey + '+a')
|
||||
|
||||
await page.keyboard.press('Delete')
|
||||
|
||||
await expect(page.locator('.logseq-tldraw .tl-group-container')).toHaveCount(0)
|
||||
// should also delete the grouped shapes
|
||||
await expect(page.locator('.logseq-tldraw .tl-box-container')).toHaveCount(0)
|
||||
})
|
||||
|
||||
test('undo the group deletion', async ({ page }) => {
|
||||
await page.keyboard.press(modKey + '+z')
|
||||
|
||||
await expect(page.locator('.logseq-tldraw .tl-group-container')).toHaveCount(1)
|
||||
await expect(page.locator('.logseq-tldraw .tl-box-container')).toHaveCount(2)
|
||||
})
|
||||
|
||||
test('undo the group action', async ({ page }) => {
|
||||
await page.keyboard.press(modKey + '+z')
|
||||
|
||||
await expect(page.locator('.logseq-tldraw .tl-group-container')).toHaveCount(0)
|
||||
await expect(page.locator('.logseq-tldraw .tl-box-container')).toHaveCount(2)
|
||||
})
|
||||
|
||||
test('connect rectangles with an arrow', async ({ page }) => {
|
||||
const canvas = await page.waitForSelector('.logseq-tldraw')
|
||||
const bounds = (await canvas.boundingBox())!
|
||||
|
||||
@@ -1792,8 +1792,8 @@
|
||||
(or
|
||||
(and empty-content?
|
||||
(not edit?)
|
||||
(not (:block/top? block))
|
||||
(not (:block/bottom? block))
|
||||
(not (:block.temp/top? block))
|
||||
(not (:block.temp/bottom? block))
|
||||
(not (util/react *control-show?)))
|
||||
(and doc-mode?
|
||||
(not collapsed?)
|
||||
@@ -2066,7 +2066,8 @@
|
||||
|
||||
(def hidden-editable-block-properties
|
||||
"Properties that are hidden in a block (block property)"
|
||||
#{:logseq.query/nlp-date})
|
||||
(into #{:logseq.query/nlp-date}
|
||||
gp-property/editable-view-and-table-properties))
|
||||
|
||||
(assert (set/subset? hidden-editable-block-properties (gp-property/editable-built-in-properties))
|
||||
"Hidden editable page properties must be valid editable properties")
|
||||
@@ -2779,7 +2780,8 @@
|
||||
block (if ref?
|
||||
(merge block (db/sub-block (:db/id block)))
|
||||
block)
|
||||
{:block/keys [uuid children pre-block? top? refs level format content properties]} block
|
||||
{:block/keys [uuid children pre-block? refs level format content properties]} block
|
||||
{:block.temp/keys [top?]} block
|
||||
config (if navigated? (assoc config :id (str navigating-block)) config)
|
||||
block (merge block (block/parse-title-and-body uuid format pre-block? content))
|
||||
blocks-container-id (:blocks-container-id config)
|
||||
@@ -2922,7 +2924,7 @@
|
||||
|
||||
:should-update (fn [old-state new-state]
|
||||
(let [compare-keys [:block/uuid :block/content :block/parent :block/collapsed?
|
||||
:block/properties :block/left :block/children :block/_refs :block/bottom? :block/top?]
|
||||
:block/properties :block/left :block/children :block/_refs :block.temp/bottom? :block.temp/top?]
|
||||
config-compare-keys [:show-cloze? :own-order-list-type :own-order-list-index]
|
||||
b1 (second (:rum/args old-state))
|
||||
b2 (second (:rum/args new-state))
|
||||
@@ -3316,8 +3318,8 @@
|
||||
[config blocks idx item]
|
||||
(let [item (->
|
||||
(dissoc item :block/meta)
|
||||
(assoc :block/top? (zero? idx)
|
||||
:block/bottom? (= (count blocks) (inc idx))))
|
||||
(assoc :block.temp/top? (zero? idx)
|
||||
:block.temp/bottom? (= (count blocks) (inc idx))))
|
||||
config (assoc config :block/uuid (:block/uuid item))]
|
||||
(rum/with-key (block-container config item)
|
||||
(str (:blocks-container-id config) "-" (:block/uuid item)))))
|
||||
|
||||
@@ -138,7 +138,8 @@
|
||||
(when-let [^js api (gobj/get tln "api")]
|
||||
(p/then (when populate-onboarding?
|
||||
(whiteboard-handler/populate-onboarding-whiteboard api))
|
||||
#(do (state/focus-whiteboard-shape tln block-id)
|
||||
#(do (whiteboard-handler/cleanup! (.-currentPage tln))
|
||||
(state/focus-whiteboard-shape tln block-id)
|
||||
(set-loaded-app tln))))))]
|
||||
(rum/use-effect! (fn []
|
||||
(when (and loaded-app block-id)
|
||||
|
||||
@@ -341,8 +341,8 @@
|
||||
(select-keys properties (property/hidden-properties))
|
||||
(:block/properties block))]
|
||||
(-> block
|
||||
(dissoc :block/top?
|
||||
:block/bottom?)
|
||||
(dissoc :block.temp/top?
|
||||
:block.temp/bottom?)
|
||||
(assoc :block/content content
|
||||
:block/properties new-properties)
|
||||
(merge (if level {:block/level level} {})))))
|
||||
@@ -826,7 +826,7 @@
|
||||
(let [prev-block' (if (seq (:block/_refs block-e))
|
||||
(assoc prev-block
|
||||
:block/uuid (:block/uuid block)
|
||||
:block/additional-properties (:block/properties block))
|
||||
:block.temp/additional-properties (:block/properties block))
|
||||
prev-block)]
|
||||
(delete-block-aux! block delete-children?)
|
||||
(save-block! repo prev-block' new-content {:editor/op :delete}))
|
||||
@@ -2646,7 +2646,7 @@
|
||||
edit-block' (if next-block-has-refs?
|
||||
(assoc edit-block
|
||||
:block/uuid (:block/uuid next-block)
|
||||
:block/additional-properties (dissoc (:block/properties next-block) :block/uuid))
|
||||
:block.temp/additional-properties (dissoc (:block/properties next-block) :block/uuid))
|
||||
edit-block)]
|
||||
(outliner-tx/transact! transact-opts
|
||||
(delete-block-aux! next-block false)
|
||||
@@ -2691,7 +2691,7 @@
|
||||
repo (state/get-current-repo)
|
||||
top-block? (= (:block/left block) (:block/page block))
|
||||
single-block? (inside-of-single-block (.-target e))
|
||||
root-block? (= (:block/container block) (str (:block/uuid block)))]
|
||||
root-block? (= (:block.temp/container block) (str (:block/uuid block)))]
|
||||
(mark-last-input-time! repo)
|
||||
(cond
|
||||
(not= selected-start selected-end)
|
||||
|
||||
@@ -153,13 +153,14 @@
|
||||
(compute-tx app tl-page new-id-nonces db-id-nonces page-name replace?)
|
||||
tx-data (concat delete-blocks [page-block] upserted-blocks)
|
||||
new-shapes (get-in metadata [:data :new-shapes])
|
||||
deleted-shapes (get-in metadata [:data :deleted-shapes])
|
||||
metadata' (cond
|
||||
;; group
|
||||
(some #(= "group" (:type %)) new-shapes)
|
||||
(assoc metadata :whiteboard/op :group)
|
||||
|
||||
;; ungroup
|
||||
(some #(= "group" (:type %)) (get-in metadata [:data :deleted-shapes]))
|
||||
(and (not-empty deleted-shapes) (every? #(= "group" (:type %)) deleted-shapes))
|
||||
(assoc metadata :whiteboard/op :un-group)
|
||||
|
||||
;; arrow
|
||||
@@ -361,6 +362,11 @@
|
||||
[^js api ids]
|
||||
(apply (.-selectShapes api) ids))
|
||||
|
||||
(defn cleanup!
|
||||
[^js tl-page]
|
||||
(let [shapes (.-shapes tl-page)]
|
||||
(.cleanup tl-page (map #(.-id %) shapes))))
|
||||
|
||||
(defn update-bindings!
|
||||
[^js tl-page page-name]
|
||||
(when-let [page (db/entity [:block/name page-name])]
|
||||
|
||||
@@ -140,7 +140,7 @@
|
||||
(assert (ds/outliner-txs-state? txs-state)
|
||||
"db should be satisfied outliner-tx-state?")
|
||||
(let [m (-> (:data this)
|
||||
(dissoc :block/children :block/meta :block/top? :block/bottom?
|
||||
(dissoc :block/children :block/meta :block.temp/top? :block.temp/bottom?
|
||||
:block/title :block/body :block/level)
|
||||
(gp-util/remove-nils))
|
||||
m (if (state/enable-block-timestamps?) (block-with-timestamps m) m)
|
||||
|
||||
@@ -126,9 +126,12 @@
|
||||
(let [txs (remove-nil-from-transaction txs)
|
||||
txs (map (fn [m] (if (map? m)
|
||||
(dissoc m
|
||||
:block/children :block/meta :block/top? :block/bottom? :block/anchor
|
||||
:block/title :block/body :block/level :block/container :db/other-tx
|
||||
:block/additional-properties)
|
||||
;; TODO: Move these attributes to :block.temp when the risk is lower
|
||||
:block/children :block/meta :block/title :block/body :block/level
|
||||
:db/other-tx
|
||||
;; :block.temp is for temporary block attributes that aren't transacted
|
||||
:block.temp/container :block.temp/top? :block.temp/bottom?
|
||||
:block.temp/additional-properties)
|
||||
m)) txs)
|
||||
txs (cond-> txs
|
||||
(:uuid-changed opts)
|
||||
|
||||
@@ -1808,7 +1808,7 @@ Similar to re-frame subscriptions"
|
||||
container (util/get-block-container block-element)
|
||||
block (if container
|
||||
(assoc block
|
||||
:block/container (gobj/get container "id"))
|
||||
:block.temp/container (gobj/get container "id"))
|
||||
block)
|
||||
content (string/trim (or content ""))]
|
||||
(swap! state
|
||||
|
||||
@@ -25,7 +25,7 @@ export const QuickLinks: TLQuickLinksComponent<Shape> = observer(({ shape }) =>
|
||||
link[0].toLowerCase() !== app.currentPage.name &&
|
||||
handlers.getBlockPageName(link[0]) !== app.currentPage.name
|
||||
)
|
||||
}, [shape.props.type, shape.props.parentId, shape.props.refs])
|
||||
}, [shape.props.id, shape.props.type, shape.props.parentId, shape.props.refs])
|
||||
|
||||
if (links.length === 0) return null
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ export class GroupShape extends TLGroupShape<GroupShapeProps> {
|
||||
const Indicator = this.ReactIndicator
|
||||
|
||||
return (
|
||||
<SVGContainer {...events}>
|
||||
<SVGContainer {...events} className="tl-group-container">
|
||||
<rect
|
||||
className={'tl-hitarea-fill'}
|
||||
x={strokeWidth / 2}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { deepEqual } from '@tldraw/core'
|
||||
import { intersectRayBounds, TLBounds } from '@tldraw/intersect'
|
||||
import Vec from '@tldraw/vec'
|
||||
import { action, autorun, computed, makeObservable, observable, toJS, transaction } from 'mobx'
|
||||
@@ -264,7 +265,7 @@ export class TLPage<S extends TLShape = TLShape, E extends TLEventMap = TLEventM
|
||||
...fromDelta,
|
||||
}
|
||||
shapeChanged = true
|
||||
this.getShapeById(nextShape.id)?.update(nextShape, false, true)
|
||||
this.getShapeById(nextShape.id)?.update(nextShape, false, deepEqual(fromDelta?.handles, fromShape?.props.handles))
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import { computed, makeObservable } from 'mobx'
|
||||
import { BoundsUtils } from '../../../utils'
|
||||
import { TLBoxShape, TLBoxShapeProps } from '../TLBoxShape'
|
||||
import type { TLShape } from '../TLShape'
|
||||
import { useApp } from '@tldraw/react'
|
||||
|
||||
export interface TLGroupShapeProps extends TLBoxShapeProps {
|
||||
children: string[] // shape ids
|
||||
@@ -41,6 +42,21 @@ export class TLGroupShape<
|
||||
}
|
||||
|
||||
getBounds = (): TLBounds => {
|
||||
// A group without children needs to be removed
|
||||
if (this.shapes.length === 0) {
|
||||
const app = useApp<Shape>()
|
||||
app.deleteShapes([this.id])
|
||||
|
||||
return {
|
||||
minX: 0,
|
||||
minY: 0,
|
||||
maxX: 0,
|
||||
maxY: 0,
|
||||
width: 0,
|
||||
height: 0,
|
||||
}
|
||||
}
|
||||
|
||||
return BoundsUtils.getCommonBounds(this.shapes.map(s => s.getBounds()))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user