diff --git a/deps/graph-parser/src/logseq/graph_parser/property.cljs b/deps/graph-parser/src/logseq/graph_parser/property.cljs index b08865e224..f0885bbd76 100644 --- a/deps/graph-parser/src/logseq/graph_parser/property.cljs +++ b/deps/graph-parser/src/logseq/graph_parser/property.cljs @@ -64,7 +64,7 @@ :created-at :updated-at :last-modified-at :created_at :last_modified_at :query-table :query-properties :query-sort-by :query-sort-desc :ls-type :hl-type :hl-page :hl-stamp :hl-color :logseq.macro-name :logseq.macro-arguments - :logseq.tldraw.page :logseq.tldraw.shape + :logseq.order-list-type :logseq.tldraw.page :logseq.tldraw.shape ; task markers :todo :doing :now :later :done} @built-in-extended-properties)) diff --git a/src/main/frontend/commands.cljs b/src/main/frontend/commands.cljs index e659dff9a0..8a9aa3580c 100644 --- a/src/main/frontend/commands.cljs +++ b/src/main/frontend/commands.cljs @@ -147,6 +147,7 @@ "Tomorrow" "TIME & DATE" "LATER" "TASK" "A" "PRIORITY" + "Number list" "LIST TYPE" "Query" "ADVANCED" "Quote" "ORG-MODE"}) @@ -250,9 +251,12 @@ ["Current time" #(date/get-current-time) "Insert current time"] ["Date picker" [[:editor/show-date-picker]] "Pick a date and insert here"]] + ;; order list + [["Number list" [[:editor/clear-current-slash] + [:editor/toggle-own-number-list]] "Number list"]] + ;; task management (get-preferred-workflow) - [["DONE" (->marker "DONE")] ["WAITING" (->marker "WAITING")] ["CANCELED" (->marker "CANCELED")] @@ -654,6 +658,18 @@ macro (youtube/gen-youtube-ts-macro)] (insert! input-id macro {}))) +(defmethod handle-step :editor/toggle-children-number-list [[_]] + (when-let [block (state/get-edit-block)] + (state/pub-event! [:editor/toggle-children-number-list block]))) + +(defmethod handle-step :editor/toggle-own-number-list [[_]] + (when-let [block (state/get-edit-block)] + (state/pub-event! [:editor/toggle-own-number-list block]))) + +(defmethod handle-step :editor/remove-own-number-list [[_]] + (when-let [block (state/get-edit-block)] + (state/pub-event! [:editor/remove-own-number-list block]))) + (defmethod handle-step :editor/show-date-picker [[_ type]] (if (and (contains? #{:scheduled :deadline} type) diff --git a/src/main/frontend/components/block.cljs b/src/main/frontend/components/block.cljs index 3cdd912272..7a74a6c4b4 100644 --- a/src/main/frontend/components/block.cljs +++ b/src/main/frontend/components/block.cljs @@ -1691,10 +1691,10 @@ (rum/defc block-children < rum/reactive [config block children collapsed?] - (let [ref? (:ref? config) - query? (:custom-query? config) - children (when (coll? children) - (remove nil? children))] + (let [ref? (:ref? config) + query? (:custom-query? config) + children (when (coll? children) + (remove nil? children))] (when (and (coll? children) (seq children) (not collapsed?)) @@ -1728,12 +1728,17 @@ (rum/defcs block-control < rum/reactive [state config block uuid block-id collapsed? *control-show? edit? has-child?] - (let [doc-mode? (state/sub :document/mode?) - control-show? (util/react *control-show?) - ref? (:ref? config) - empty-content? (block-content-empty? block) - fold-button-right? (state/enable-fold-button-right?)] + (let [doc-mode? (state/sub :document/mode?) + control-show? (util/react *control-show?) + ref? (:ref? config) + empty-content? (block-content-empty? block) + fold-button-right? (state/enable-fold-button-right?) + own-number-list? (:own-order-number-list? config) + order-list? (boolean own-number-list?) + order-list-idx (:own-order-list-index config)] [:div.block-control-wrap.mr-1.flex.flex-row.items-center.sm:mr-2 + {:class (util/classnames [{:is-order-list order-list? + :bullet-closed collapsed?}])} (when (or (not fold-button-right?) has-child?) [:a.block-control {:id (str "control-" uuid) @@ -1745,13 +1750,15 @@ (if collapsed? (editor-handler/expand-block! uuid) (editor-handler/collapse-block! uuid))))} - [:span {:class (if (and control-show? - (or collapsed? - (editor-handler/collapsable? uuid {:semantic? true}))) "control-show cursor-pointer" "control-hide")} + [:span {:class (if (or (and control-show? + (or collapsed? + (editor-handler/collapsable? uuid {:semantic? true}))) + (and collapsed? order-list?)) + "control-show cursor-pointer" + "control-hide")} (ui/rotating-arrow collapsed?)]]) - (let [bullet [:a {:on-click (fn [event] - (bullet-on-click event block uuid))} + (let [bullet [:a.bullet-link-wrap {:on-click #(bullet-on-click % block uuid)} [:span.bullet-container.cursor {:id (str "dot-" uuid) :draggable true @@ -1759,11 +1766,14 @@ (bullet-drag-start event block uuid block-id)) :blockid (str uuid) :class (str (when collapsed? "bullet-closed") - " " (when (and (:document/mode? config) (not collapsed?)) - "hide-inner-bullet"))} - [:span.bullet {:blockid (str uuid)}]]]] + " hide-inner-bullet") + (when order-list? " as-order-list typed-list"))} + + [:span.bullet {:blockid (str uuid)} + (when order-list? + [:label (str order-list-idx ".")])]]]] (cond (and (or (mobile-util/native-platform?) (:ui/show-empty-bullets? (state/get-config))) @@ -1771,14 +1781,14 @@ bullet (or - (and empty-content? - (not edit?) - (not (:block/top? block)) - (not (:block/bottom? block)) - (not (util/react *control-show?))) - (and doc-mode? - (not collapsed?) - (not (util/react *control-show?)))) + (and empty-content? + (not edit?) + (not (:block/top? block)) + (not (:block/bottom? block)) + (not (util/react *control-show?))) + (and doc-mode? + (not collapsed?) + (not (util/react *control-show?)))) ;; hidden [:span.bullet-container] @@ -2765,6 +2775,7 @@ config (if (nil? (:query-result config)) (assoc config :query-result (atom nil)) config) + config (if ref? (block-handler/attach-order-list-state config block) config) heading? (:heading properties) *control-show? (get state ::control-show?) db-collapsed? (util/collapsed? block) @@ -2865,6 +2876,12 @@ (dnd-separator-wrapper block block-id slide? false false)])) +(defn- attach-order-list-state! + [cp-state] + (let [args (:rum/args cp-state)] + (assoc cp-state + :rum/args (assoc (vec args) 0 (block-handler/attach-order-list-state (first args) (second args)))))) + (rum/defcs block-container < rum/reactive (rum/local false ::show-block-left-menu?) (rum/local false ::show-block-right-menu?) @@ -2881,20 +2898,26 @@ :else nil) - (assoc state - ::control-show? (atom false) - ::navigating-block (atom (:block/uuid block))))) + (-> (assoc state + ::control-show? (atom false) + ::navigating-block (atom (:block/uuid block))) + (attach-order-list-state!)))) + + :will-remount (fn [_old-state new-state] + (-> new-state + (attach-order-list-state!))) + :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?] - config-compare-keys [:show-cloze?] - b1 (second (:rum/args old-state)) - b2 (second (:rum/args new-state)) - result (or - (not= (select-keys b1 compare-keys) - (select-keys b2 compare-keys)) - (not= (select-keys (first (:rum/args old-state)) config-compare-keys) - (select-keys (first (:rum/args new-state)) config-compare-keys)))] + (let [compare-keys [:block/uuid :block/content :block/parent :block/collapsed? + :block/properties :block/left :block/children :block/_refs :block/bottom? :block/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)) + result (or + (not= (select-keys b1 compare-keys) + (select-keys b2 compare-keys)) + (not= (select-keys (first (:rum/args old-state)) config-compare-keys) + (select-keys (first (:rum/args new-state)) config-compare-keys)))] (boolean result))) :will-unmount (fn [state] ;; restore root block's collapsed state @@ -2904,8 +2927,8 @@ (state/set-collapsed-block! block-id nil))) state)} [state config block] - (let [repo (state/get-current-repo) - ref? (:ref? config) + (let [repo (state/get-current-repo) + ref? (:ref? config) custom-query? (boolean (:custom-query? config))] (if (and (or ref? custom-query?) (not (:ref-query-child? config))) (ui/lazy-visible @@ -2915,11 +2938,11 @@ (defn divide-lists [[f & l]] - (loop [l l + (loop [l l ordered? (:ordered f) - result [[f]]] + result [[f]]] (if (seq l) - (let [cur (first l) + (let [cur (first l) cur-ordered? (:ordered cur)] (if (= ordered? cur-ordered?) (recur diff --git a/src/main/frontend/components/block.css b/src/main/frontend/components/block.css index 2cb26333a0..4f00376fed 100644 --- a/src/main/frontend/components/block.css +++ b/src/main/frontend/components/block.css @@ -116,6 +116,7 @@ position: relative; top: 4px; } + a { color: var(--ls-primary-text-color); @@ -202,6 +203,10 @@ .block-control-wrap { height: 24px; margin-top: 0; + + &.is-order-list { + @apply relative right-0; + } } .block-control, .block-control:hover { @@ -525,6 +530,13 @@ background-color: var(--ls-block-bullet-color, #8fbc8f); } + &.as-order-list { + min-width: 16px; + width: auto; + white-space: nowrap; + justify-content: end; + } + .bullet { border-radius: 50%; width: 6px; @@ -533,17 +545,32 @@ transition: transform 0.2s; } - &.bullet-closed { - background-color: var(--ls-block-bullet-border-color, #ced9e0); + &:not(.typed-list) { + &.bullet-closed { + background-color: var(--ls-block-bullet-border-color, #ced9e0); + } + } + + &.typed-list:not(:focus-within) { + .bullet { + background-color: unset; + height: unset; + width: unset; + box-shadow: none; + } } } -a:hover > .bullet-container .bullet { - transform: scale(1.4); -} +.bullet-link-wrap { + color: var(--ls-primary-text-color); -a:hover > .bullet-container { - background-color: var(--ls-block-bullet-border-color, #ced9e0); + &:hover > .bullet-container .bullet { + transform: scale(1.4); + } + + &:hover > .bullet-container:not(.typed-list) { + background-color: var(--ls-block-bullet-border-color, #ced9e0); + } } .content.doc-mode { diff --git a/src/main/frontend/components/content.cljs b/src/main/frontend/components/content.cljs index 87f64a09eb..e791732079 100644 --- a/src/main/frontend/components/content.cljs +++ b/src/main/frontend/components/content.cljs @@ -353,7 +353,8 @@ (mixins/listen state js/window "contextmenu" (fn [e] (let [target (gobj/get e "target") - block-id (d/attr target "blockid") + block-el (.closest target ".bullet-container[blockid]") + block-id (some-> block-el (.getAttribute "blockid")) {:keys [block block-ref]} (state/sub :block-ref/context) {:keys [page]} (state/sub :page-title/context)] (cond diff --git a/src/main/frontend/handler/block.cljs b/src/main/frontend/handler/block.cljs index f7a898a557..cb369d070f 100644 --- a/src/main/frontend/handler/block.cljs +++ b/src/main/frontend/handler/block.cljs @@ -291,3 +291,32 @@ (recur parent (conj result parent)) result))))] (distinct (mapcat get-parents filtered-ref-blocks))))) + +(defn get-idx-of-order-list-block + [block order-list-type] + (let [order-block-fn? #(some-> % :block/properties :logseq.order-list-type (= order-list-type)) + prev-block-fn #(some->> (:db/id %) (db-model/get-prev-sibling (state/get-current-repo))) + prev-block (prev-block-fn block)] + (letfn [(page-fn? [b] (some-> b :block/name some?)) + (order-sibling-list [b] + (lazy-seq + (when (and (not (page-fn? b)) (order-block-fn? b)) + (cons b (order-sibling-list (prev-block-fn b)))))) + (order-parent-list [b] + (lazy-seq + (when (and (not (page-fn? b)) (order-block-fn? b)) + (cons b (order-parent-list (db-model/get-block-parent (:block/uuid b)))))))] + (let [idx (if prev-block + (count (order-sibling-list block)) 1) + order-parents-count (count (order-parent-list block))] + (if (or (zero? order-parents-count) + (odd? order-parents-count)) + idx (nth (seq "abcdefghijklmnopqrstuvwxyz") (mod (dec idx) 26))))))) + +(defn attach-order-list-state + [config block] + (let [own-order-list-type (some-> block :block/properties :logseq.order-list-type str string/lower-case) + own-order-list-index (some->> own-order-list-type (get-idx-of-order-list-block block))] + (assoc config :own-order-list-type own-order-list-type + :own-order-list-index own-order-list-index + :own-order-number-list? (= own-order-list-type "number")))) \ No newline at end of file diff --git a/src/main/frontend/handler/editor.cljs b/src/main/frontend/handler/editor.cljs index fa5347eb09..5e50e23e4c 100644 --- a/src/main/frontend/handler/editor.cljs +++ b/src/main/frontend/handler/editor.cljs @@ -62,6 +62,35 @@ (defonce *asset-uploading? (atom false)) (defonce *asset-uploading-process (atom 0)) +(declare set-block-property!) +(declare remove-block-property!) + +(defn get-block-own-order-list-type + [block] + (some-> block :block/properties :logseq.order-list-type)) + +(defn set-block-own-order-list-type! + [block type] + (when-let [uuid (:block/uuid block)] + (set-block-property! uuid :logseq.order-list-type (name type)))) + +(defn remove-block-own-order-list-type! + [block] + (when-let [uuid (:block/uuid block)] + (remove-block-property! uuid :logseq.order-list-type))) + +(defn own-order-list? + [block] + (not (string/blank? (get-block-own-order-list-type block)))) + +(defn own-order-number-list? + [block] + (= (get-block-own-order-list-type block) "number")) + +(defn make-block-as-own-order-list! + [block] + (some-> block (set-block-own-order-list-type! "number"))) + (defn get-selection-and-format [] (when-let [block (state/get-edit-block)] @@ -558,7 +587,9 @@ {:ok-handler (fn [last-block] (clear-when-saved!) - (edit-block! last-block 0 id))})))) + (edit-block! last-block 0 id) + (when-let [order-list-type (and (own-order-list? block) (get-block-own-order-list-type block))] + (set-block-own-order-list-type! last-block order-list-type)))})))) (state/set-editor-op! nil))) (defn api-insert-new-block! @@ -2450,6 +2481,7 @@ (let [{:keys [block config]} (get-state)] (when block (let [input (state/get-input) + config (assoc config :keydown-new-block true) content (gobj/get input "value") pos (cursor/pos input) current-node (outliner-core/block block) @@ -2492,6 +2524,12 @@ "list-item" (dwim-in-list) "properties-drawer" (dwim-in-properties state)) + (and (string/blank? content) + (own-order-number-list? block) + (not (some-> (db-model/get-block-parent (:block/uuid block)) + (own-order-number-list?)))) + (remove-block-own-order-list-type! block) + (and (string/blank? content) (not has-right?) @@ -2739,7 +2777,9 @@ (not root-block?) (not single-block?) (not custom-query?)) - (delete-block! repo false))) + (if (own-order-number-list? block) + (remove-block-own-order-list-type! block) + (delete-block! repo false)))) (and (> current-pos 1) (= (util/nth-safe value (dec current-pos)) (state/get-editor-command-trigger))) diff --git a/src/main/frontend/handler/events.cljs b/src/main/frontend/handler/events.cljs index 98a5700f27..4a66b41117 100644 --- a/src/main/frontend/handler/events.cljs +++ b/src/main/frontend/handler/events.cljs @@ -948,6 +948,16 @@ (defmethod handle :editor/quick-capture [[_ args]] (quick-capture/quick-capture args)) +(defmethod handle :editor/toggle-own-number-list [[_ block]] + (when block + (if (editor-handler/own-order-number-list? block) + (editor-handler/remove-block-own-order-list-type! block) + (editor-handler/make-block-as-own-order-list! block)))) + +(defmethod handle :editor/remove-own-number-list [[_ block]] + (when (some-> block (editor-handler/own-order-number-list?)) + (editor-handler/remove-block-own-order-list-type! block))) + (defn run! [] (let [chan (state/get-events-chan)]