quick add block shape

pull/6345/head
Peng Xiao 2022-08-05 01:58:39 +08:00
parent a2103a0d45
commit fcd158fdc8
8 changed files with 76 additions and 25 deletions

View File

@ -193,7 +193,9 @@
[shape]
{:block/content (case (:type shape)
"text" (:text shape)
"logseq-portal" (str "[[" (:pageId shape) "]]")
"logseq-portal" (if (= (:blockType shape) "P")
(str "[[" (:pageId shape) "]]")
(str "((" (:pageId shape) "))"))
"line" (str "whiteboard arrow" (when-let [label (:label shape)] (str ": " label)))
(str "whiteboard " (:type shape)))})
@ -218,7 +220,7 @@
page-entity (build-page-entity {} file page-name page-name nil options)
page-block (merge page-block page-entity (when-not (:block/uuid page-block) {:block/uuid (d/squuid)}))
blocks (->> blocks
(map #(merge % {:block/level 1
(map #(merge % {:block/level 1 ;; fixme
:block/uuid (or (:block/uuid %)
(gp-block/get-custom-id-or-new-id (:block/properties %)))}
(with-whiteboard-block-props %)))

View File

@ -62,7 +62,9 @@
:Block block-cp
:Breadcrumb breadcrumb
:PageNameLink page-name-link}
:searchHandler (comp clj->js vec search/page-search)
:handlers (clj->js {:search (comp clj->js vec search/page-search)
:addNewBlock (fn [content]
(str (whiteboard-handler/add-new-block! name content)))})
:onMount (fn [app] (set-tln ^js app))
:onPersist (fn [app]
(let [document (gobj/get app "serialized")]

View File

@ -75,10 +75,16 @@
:block/original-name original-page-name
:block/whiteboard? true
:block/properties (dissoc tldr-data :shapes)}
;; todo: use get-paginated-blocks instead?
existing-blocks (model/get-page-blocks-no-cache page-name)
shapes (:shapes tldr-data)
blocks (mapv #(shape->block % page-name) shapes)
block-ids (set (map :block/uuid blocks))
block-ids (->> shapes
(map (fn [shape] (when (= (:blockType shape) "B")
(uuid (:pageId shape)))))
(concat (map :block/uuid blocks))
(remove nil?)
(set))
delete-shapes (filter (fn [shape]
(not (block-ids (:block/uuid shape))))
existing-blocks)
@ -166,3 +172,14 @@
point (js->clj (.. (get-tldr-app) -viewport (getPagePoint #js[client-x client-y])))
shape (->logseq-portal-shape block-id point)]
(.createShapes api (clj->js shape))))
(defn add-new-block!
[page-name content]
(let [uuid (d/squuid)
tx {:block/uuid uuid
:block/content (or content "")
:block/format :markdown ; fixme
:block/page {:block/name (util/page-name-sanity-lc page-name)}
:block/parent {:block/name page-name}}]
(db-utils/transact! [tx])
uuid))

View File

@ -21,9 +21,11 @@
[]
(empty? @write-chan-batch-buf))
(def blocks-pull-keys-with-persisted-ids
(def whiteboard-blocks-pull-keys-with-persisted-ids
'[:block/properties
:block/uuid
:block/content
:block/format
{:block/page [:block/name :block/uuid]}
{:block/left [:block/name :block/uuid]}
{:block/parent [:block/name :block/uuid]}
@ -33,8 +35,11 @@
[repo page-db-id]
(let [page-block (db/pull repo '[*] page-db-id)
whiteboard? (:block/whiteboard? page-block)
blocks (model/get-page-blocks-no-cache repo (:block/name page-block)
{:pull-keys (if whiteboard? blocks-pull-keys-with-persisted-ids '[*])})]
blocks (model/get-page-blocks-no-cache
repo (:block/name page-block)
{:pull-keys (if whiteboard? whiteboard-blocks-pull-keys-with-persisted-ids '[*])})
blocks (map #(if (get-in % [:block/properties :ls-type] false)
(dissoc % :block/content :block/format) %) blocks)]
(when-not (and (= 1 (count blocks))
(string/blank? (:block/content (first blocks)))
(nil? (:block/file page-block)))

View File

@ -6,7 +6,7 @@ import {
AppProvider,
TLReactCallbacks,
TLReactComponents,
TLReactToolConstructor
TLReactToolConstructor,
} from '@tldraw/react'
import * as React from 'react'
import { AppUI } from '~components/AppUI'
@ -22,8 +22,9 @@ import {
LineTool,
LogseqPortalTool,
NuEraseTool,
PencilTool, TextTool,
YouTubeTool
PencilTool,
TextTool,
YouTubeTool,
} from '~lib/tools'
const components: TLReactComponents<Shape> = {
@ -51,13 +52,16 @@ interface LogseqTldrawProps {
Breadcrumb: React.FC
PageNameLink: React.FC
}
searchHandler: (query: string) => string[]
handlers: {
search: (query: string) => string[]
addNewBlock: (content: string) => string
}
model?: TLDocumentModel<Shape>
onMount?: TLReactCallbacks<Shape>['onMount']
onPersist?: TLReactCallbacks<Shape>['onPersist']
}
export const App = function App({ searchHandler, ...props }: LogseqTldrawProps): JSX.Element {
export const App = function App(props: LogseqTldrawProps): JSX.Element {
const onFileDrop = useFileDrop()
const onPaste = usePaste()
const onQuickAdd = useQuickAdd()
@ -71,7 +75,12 @@ export const App = function App({ searchHandler, ...props }: LogseqTldrawProps):
}, [])
return (
<LogseqContext.Provider value={{ renderers, search: searchHandler }}>
<LogseqContext.Provider
value={{
renderers,
handlers: props.handlers,
}}
>
<AppProvider
Shapes={shapes}
Tools={tools}

View File

@ -15,6 +15,9 @@ export const LogseqContext = React.createContext<
pageName: string
}>
}
search: (query: string) => string[]
handlers: {
search: (query: string) => string[]
addNewBlock: (content: string) => string // returns the new block uuid
}
}>
>({})

View File

@ -30,17 +30,23 @@ interface LogseqQuickSearchProps {
const LogseqQuickSearch = observer(({ onChange }: LogseqQuickSearchProps) => {
const [q, setQ] = React.useState('')
const rInput = React.useRef<HTMLInputElement>(null)
const { search } = React.useContext(LogseqContext)
const { handlers } = React.useContext(LogseqContext)
const commitChange = React.useCallback((id: string) => {
setQ(id)
const finishCreating = React.useCallback((id: string) => {
onChange(id)
rInput.current?.blur()
}, [])
const onAddBlock = React.useCallback((content: string) => {
const uuid = handlers?.addNewBlock(content)
if (uuid) {
finishCreating(uuid)
}
}, [])
const options = React.useMemo(() => {
return search?.(q)
}, [search, q])
return handlers?.search?.(q)
}, [handlers?.search, q])
React.useEffect(() => {
// autofocus seems not to be working
@ -62,17 +68,19 @@ const LogseqQuickSearch = observer(({ onChange }: LogseqQuickSearchProps) => {
onChange={q => setQ(q.target.value)}
onKeyDown={e => {
if (e.key === 'Enter') {
commitChange(q)
finishCreating(q)
}
}}
className="tl-quick-search-input text-input"
/>
</div>
</div>
<div className="tl-quick-search-options">
<div className="tl-quick-search-option" onClick={() => onAddBlock(q)}>
New block{q.length > 0 ? `: ${q}` : ''}
</div>
{options?.map(name => (
<div key={name} className="tl-quick-search-option" onClick={() => commitChange(name)}>
<div key={name} className="tl-quick-search-option" onClick={() => finishCreating(name)}>
{name}
</div>
))}
@ -372,10 +380,12 @@ export class LogseqPortalShape extends TLBoxShape<LogseqPortalShapeProps> {
const onPageNameChanged = React.useCallback((id: string) => {
this.initialHeightCalculated = false
const blockType = validUUID(id) ? 'B' : 'P'
this.update({
pageId: id,
size: [600, 320],
blockType: validUUID(id) ? 'B' : 'P',
size: [400, 320],
blockType: blockType,
compact: blockType === 'B',
})
app.selectTool('select')
app.history.resume()

View File

@ -146,7 +146,10 @@ export default function App() {
Breadcrumb,
PageNameLink,
}}
searchHandler={q => (q ? list : [])}
handlers={{
search: q => (q ? list : []),
addNewBlock: q => q,
}}
model={documentModel}
onPersist={onPersist}
/>