refactor: unify heading UX for both markdown and org mode

pull/6808/head^2
Tienson Qin 2022-09-22 18:10:46 +08:00
parent 9c7b4ea201
commit 8b144269f7
14 changed files with 124 additions and 96 deletions

View File

@ -62,9 +62,6 @@
;; first block that's not a heading or unordered list
:block/pre-block? {}
;; heading's level (the block must be a heading)
:block/heading-level {}
;; scheduled day
:block/scheduled {}
@ -116,7 +113,6 @@
:block/deadline
:block/repeated?
:block/pre-block?
:block/heading-level
:block/type
:block/properties
:block/properties-order

View File

@ -541,6 +541,16 @@
blocks)]
(with-path-refs blocks)))
(defn- with-heading-property
[properties markdown-heading? size]
(let [properties (if markdown-heading?
(assoc properties :heading size)
properties)]
(if (true? (:heading properties))
;; default-level 2
(assoc properties :heading 2)
properties)))
(defn- construct-block
[block properties timestamps body encoded-content format pos-meta with-id? {:keys [block-pattern supported-formats db date-formatter]}]
(let [id (get-custom-id-or-new-id properties)
@ -551,18 +561,17 @@
markdown-heading? (and (:size block) (= :markdown format))
block (if markdown-heading?
(assoc block
:type :heading
:level (if unordered? (:level block) 1)
:heading-level (or (:size block) 6))
:level (if unordered? (:level block) 1))
block)
block (cond->
(assoc block
:uuid id
:refs ref-pages-in-properties
:format format
:meta pos-meta)
(seq (:properties properties))
(assoc :properties (:properties properties)
(-> (assoc block
:uuid id
:refs ref-pages-in-properties
:format format
:meta pos-meta)
(dissoc :size))
(or (seq (:properties properties)) markdown-heading?)
(assoc :properties (with-heading-property (:properties properties) markdown-heading? (:size block))
:properties-text-values (:properties-text-values properties)
:properties-order (vec (:properties-order properties)))

View File

@ -115,10 +115,9 @@
:block/priority 4
:block/deadline 1
:block/collapsed? 22
:block/heading-level 60
:block/repeated? 1}
(->> [:block/scheduled :block/priority :block/deadline :block/collapsed?
:block/heading-level :block/repeated?]
:block/repeated?]
(map (fn [attr]
[attr
(ffirst (d/q [:find (list 'count '?b) :where ['?b attr]]

View File

@ -132,13 +132,11 @@
[:editor/set-heading heading]
[:editor/move-cursor-to-end]])
(defn- markdown-headings
(defn- headings
[]
(let [format (state/get-preferred-format)]
(when (= (name format) "markdown")
(mapv (fn [level]
(let [heading (str "h" level)]
[heading (->heading (apply str (repeat level "#")))])) (range 1 7)))))
(mapv (fn [level]
(let [heading (str "h" level)]
[heading (->heading level)])) (range 1 7)))
(defonce *matched-commands (atom nil))
(defonce *initial-commands (atom nil))
@ -241,7 +239,7 @@
;; ["Upload an image" [[:editor/click-hidden-file-input :id]]]
)]
(markdown-headings)
(headings)
;; time & date
@ -593,19 +591,33 @@
(property/goto-properties-end format current-input)
(cursor/move-cursor-backward current-input 3)))))
(defonce markdown-heading-pattern #"^#+\s+")
(defn set-markdown-heading
[content heading]
(let [heading-str (apply str (repeat heading "#"))]
(if (util/safe-re-find markdown-heading-pattern content)
(string/replace-first content
markdown-heading-pattern
(str heading-str " "))
(str heading-str " " (string/triml content)))))
(defn clear-markdown-heading
[content]
[:pre (string? content)]
(string/replace-first content
markdown-heading-pattern
""))
(defmethod handle-step :editor/set-heading [[_ heading]]
(when-let [input-id (state/get-edit-input-id)]
(when-let [current-input (gdom/getElement input-id)]
(let [edit-content (gobj/get current-input "value")
heading-pattern #"^#+\s+"
new-value (cond
(util/safe-re-find heading-pattern edit-content)
(string/replace-first edit-content
heading-pattern
(str heading " "))
:else
(str heading " " (string/triml edit-content)))]
(state/set-edit-content! input-id new-value)))))
(let [current-block (state/get-edit-block)
format (:block/format current-block)]
(if (= format :markdown)
(let [edit-content (gobj/get current-input "value")
new-content (set-markdown-heading edit-content heading)]
(state/set-edit-content! input-id new-content))
(state/pub-event! [:editor/set-org-mode-heading current-block heading]))))))
(defmethod handle-step :editor/search-page [[_]]
(state/set-editor-action! :page-search))

View File

@ -1839,7 +1839,7 @@
(declare block-content)
(defn build-block-title
[config {:block/keys [title marker pre-block? properties level heading-level]
[config {:block/keys [title marker pre-block? properties]
:as t}]
(let [config (assoc config :block t)
slide? (boolean (:slide? config))
@ -1856,14 +1856,9 @@
priority (priority-cp t)
tags (block-tags-cp t)
bg-color (:background-color properties)
heading-level (or (and heading-level
(<= heading-level 6)
heading-level)
(and (get properties :heading)
(<= level 6)
level))
elem (if heading-level
(keyword (str "h" heading-level
heading (:heading properties)
elem (if heading
(keyword (str "h" heading
(when block-ref? ".inline")))
:span.inline)]
(->elem
@ -2289,7 +2284,7 @@
(rum/defcs block-content-or-editor < rum/reactive
(rum/local true ::hide-block-refs?)
[state config {:block/keys [uuid format] :as block} edit-input-id block-id heading-level edit?]
[state config {:block/keys [uuid format] :as block} edit-input-id block-id edit?]
(let [*hide-block-refs? (get state ::hide-block-refs?)
hide-block-refs? @*hide-block-refs?
editor-box (get config :editor-box)
@ -2307,7 +2302,6 @@
:block-id uuid
:block-parent-id block-id
:format format
:heading-level heading-level
:on-hide (fn [value event]
(when (= event :esc)
(editor-handler/save-block! (editor-handler/get-state) value)
@ -2574,7 +2568,7 @@
block (if ref?
(merge block (db/pull-block (:db/id block)))
block)
{:block/keys [uuid children pre-block? top? refs heading-level level format content properties]} block
{:block/keys [uuid children pre-block? top? refs level format content properties]} 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)
@ -2583,7 +2577,7 @@
config (if (nil? (:query-result config))
(assoc config :query-result (atom nil))
config)
heading? (or (:heading properties) (and heading-level (<= heading-level 6)))
heading? (:heading properties)
*control-show? (get state ::control-show?)
db-collapsed? (util/collapsed? block)
collapsed? (cond
@ -2665,7 +2659,7 @@
(when @*show-left-menu?
(block-left-menu config block))
(block-content-or-editor config block edit-input-id block-id heading-level edit?)
(block-content-or-editor config block edit-input-id block-id edit?)
(when @*show-right-menu?
(block-right-menu config block edit?))]

View File

@ -84,7 +84,7 @@
:on-click editor-handler/copy-block-embeds}
"Copy block embeds"
nil)
[:hr.menu-separator]
(ui/menu-link
@ -100,8 +100,7 @@
"#787f97"
"#978626"
"#49767b"
"#264c9b"
"#793e3e"])
"#264c9b"])
(defonce *template-including-parent? (atom nil))
@ -163,22 +162,36 @@
(rum/defc ^:large-vars/cleanup-todo block-context-menu-content
[_target block-id]
(when-let [block (db/entity [:block/uuid block-id])]
(let [properties (:block/properties block)
heading? (true? (:heading properties))]
(let [format (:block/format block)]
[:.menu-links-wrapper
[:div.flex-row.flex.justify-between.pb-2.pt-1.px-2
[:div.flex-row.flex.justify-between
[:div.flex.flex-row.justify-between.pb-2.pt-1.px-2.items-center
[:div.flex.flex-row.justify-between.flex-1
(for [color block-background-colors]
[:a.m-2.shadow-sm
{:on-click (fn [_e]
(editor-handler/set-block-property! block-id "background-color" color))}
[:div.heading-bg {:style {:background-color color}}]])
[:a.m-2.shadow-sm
{:title (t :remove-background)
:on-click (fn [_e]
(editor-handler/remove-block-property! block-id "background-color"))}
[:div.heading-bg.remove "-"]]]]
[:div.heading-bg {:style {:background-color color}}]])]
[:a.m-2.shadow-sm
{:title (t :remove-background)
:on-click (fn [_e]
(editor-handler/remove-block-property! block-id "background-color"))}
[:div.heading-bg.remove "-"]]]
[:div.flex.flex-row.justify-between.pb-2.pt-1.px-2.items-center
[:div.flex.flex-row.justify-between.flex-1
(for [i (range 1 7)]
(ui/button
(str "H" i)
:on-click (fn [_e]
(editor-handler/set-heading! block-id format i))
:intent "link"
:small? true))]
[:a.m-2
{:title (t :remove-heading)
:on-click (fn [_e]
(editor-handler/remove-heading! block-id format))}
[:div.heading-bg.remove "-"]]]
[:hr.menu-separator]
(ui/menu-link
@ -232,17 +245,6 @@
[:hr.menu-separator]
(ui/menu-link
{:key "Convert heading"
:on-click (fn [_e]
(if heading?
(editor-handler/remove-block-property! block-id :heading)
(editor-handler/set-block-property! block-id :heading true)))}
(if heading?
"Convert back to a block"
"Convert to a heading")
nil)
(block-template block-id)
(if (srs/card-block? block)

View File

@ -568,7 +568,7 @@
(rum/defcs box < rum/reactive
{:init (fn [state]
(assoc state ::heading-level (:heading-level (first (:rum/args state)))
(assoc state
::id (str (random-uuid))))
:did-mount (fn [state]
(state/set-editor-args! (:rum/args state))

View File

@ -54,7 +54,6 @@
:block/created-at
:block/updated-at
:block/file
:block/heading-level
{:block/page [:db/id :block/name :block/original-name :block/journal-day]}
{:block/_parent ...}])

View File

@ -316,9 +316,10 @@
(block/parse-title-and-body uuid format pre-block? (:block/content block)))
properties (:block/properties block)
real-content (:block/content block)
content (if (and (seq properties) real-content (not= real-content content))
(property/with-built-in-properties properties content format)
content)
content (let [properties (if (= format :markdown) (dissoc properties :heading) properties)]
(if (and (seq properties) real-content (not= real-content content))
(property/with-built-in-properties properties content format)
content))
content (drawer/with-logbook block content)
content (with-timetracking block content)
first-block? (= left page)
@ -1939,6 +1940,7 @@
(property/insert-properties format content props))
ast (mldoc/->edn content* (gp-mldoc/default-config format))
blocks (block/extract-blocks ast content* format {})
_ (prn {:block (first blocks)})
fst-block (first blocks)
fst-block (if (and keep-uuid? (uuid? (:uuid block)))
(assoc fst-block :block/uuid (:uuid block))
@ -3465,3 +3467,21 @@
;; has children
(first (:block/_parent (db/entity (:db/id block)))))
(util/collapsed? block)))
(defn set-heading!
[block-id format heading]
(if (= format :markdown)
(let [repo (state/get-current-repo)
block (db/entity [:block/uuid block-id])
content' (commands/set-markdown-heading (:block/content block) heading)]
(save-block! repo block-id content'))
(set-block-property! block-id "heading" heading)))
(defn remove-heading!
[block-id format]
(remove-block-property! block-id "heading")
(when (= format :markdown)
(let [repo (state/get-current-repo)
block (db/entity [:block/uuid block-id])
content' (commands/clear-markdown-heading (:block/content block))]
(save-block! repo block-id content'))))

View File

@ -611,6 +611,10 @@
template
{:target page}))))))
(defmethod handle :editor/set-org-mode-heading [[_ block heading]]
(when-let [id (:block/uuid block)]
(editor-handler/set-heading! id :org heading)))
(defmethod handle :file-sync-graph/restore-file [[_ graph page-entity content]]
(when (db/get-db graph)
(let [file (:block/file page-entity)]

View File

@ -482,7 +482,6 @@
[:block/id
:block/page-name
:block/properties
:block/heading-level
:block/format
:block/children
:block/content]))})

View File

@ -52,13 +52,6 @@
(.scrollBy (util/app-scroll-container-node) #js {:top (- 10 delta)})))
[:div.action-bar
[:div.action-bar-commands
(when-not (= (:block/format block) :org)
(action-command "heading" "Heading"
#(let [properties (:block/properties block)
heading? (true? (:heading properties))]
(if heading?
(editor-handler/remove-block-property! uuid :heading)
(editor-handler/set-block-property! uuid :heading true)))))
(action-command "infinity" "Card" #(srs/make-block-a-card! (:block/uuid block)))
(action-command "copy" "Copy" #(editor-handler/copy-selection-blocks false))
(action-command "cut" "Cut" #(editor-handler/cut-selection-blocks true))

View File

@ -29,13 +29,14 @@
content))
(defn transform-content
[{:block/keys [collapsed? format pre-block? unordered content heading-level left page parent]} level {:keys [heading-to-list?]}]
(let [content (or content "")
[{:block/keys [collapsed? format pre-block? unordered content left page parent properties]} level {:keys [heading-to-list?]}]
(let [heading (:heading properties)
markdown? (= :markdown format)
content (or content "")
pre-block? (or pre-block?
(and (= page parent left) ; first block
(= :markdown format)
markdown?
(string/includes? (first (string/split-lines content)) ":: ")))
markdown? (= format :markdown)
content (cond
pre-block?
(let [content (string/trim content)]
@ -45,7 +46,7 @@
(let [markdown-top-heading? (and markdown?
(= parent page)
(not unordered)
heading-level)
heading)
[prefix spaces-tabs]
(cond
(= format :org)
@ -57,10 +58,10 @@
["" ""]
:else
(let [level (if (and heading-to-list? heading-level)
(if (> heading-level 1)
(dec heading-level)
heading-level)
(let [level (if (and heading-to-list? heading)
(if (> heading 1)
(dec heading)
heading)
level)
spaces-tabs (->>
(repeat (dec level) (state/get-export-bullet-indentation))

View File

@ -245,7 +245,7 @@ html.is-mobile {
.ui__button {
@apply flex items-center px-3 py-2 border border-transparent
text-sm leading-4 font-medium rounded-md text-white
focus:outline-none transition ease-in-out duration-150 mt-1;
focus:outline-none transition ease-in-out duration-150;
&:disabled {
opacity: 0.5;
@ -355,4 +355,4 @@ html.is-mobile {
.ui__icon {
display: inline-block;
}
}