diff --git a/deps/db/src/logseq/db/frontend/malli_schema.cljs b/deps/db/src/logseq/db/frontend/malli_schema.cljs index 16d6ee6f1f..2efcf516b1 100644 --- a/deps/db/src/logseq/db/frontend/malli_schema.cljs +++ b/deps/db/src/logseq/db/frontend/malli_schema.cljs @@ -510,7 +510,8 @@ [:logseq.property.asset/checksum :string] [:logseq.property.asset/size :int] [:logseq.property.asset/width {:optional true} :int] - [:logseq.property.asset/height {:optional true} :int]] + [:logseq.property.asset/height {:optional true} :int] + [:logseq.property.asset/align {:optional true} :keyword]] block-attrs page-or-block-attrs))) diff --git a/deps/db/src/logseq/db/frontend/property.cljs b/deps/db/src/logseq/db/frontend/property.cljs index 13ee76927a..29f285ff0d 100644 --- a/deps/db/src/logseq/db/frontend/property.cljs +++ b/deps/db/src/logseq/db/frontend/property.cljs @@ -567,6 +567,11 @@ :schema {:type :map :hide? true :public? false}} + :logseq.property.asset/align {:title "Asset alignment" + :schema {:type :keyword + :hide? true + :public? false} + :queryable? false} :logseq.property.fsrs/due {:title "Due" :schema {:type :datetime diff --git a/deps/db/src/logseq/db/frontend/schema.cljs b/deps/db/src/logseq/db/frontend/schema.cljs index 14586b399d..c6b2582114 100644 --- a/deps/db/src/logseq/db/frontend/schema.cljs +++ b/deps/db/src/logseq/db/frontend/schema.cljs @@ -30,7 +30,7 @@ (map (juxt :major :minor) [(parse-schema-version x) (parse-schema-version y)]))) -(def version (parse-schema-version "65.22")) +(def version (parse-schema-version "65.23")) (defn major-version "Return a number. diff --git a/src/main/frontend/components/block.cljs b/src/main/frontend/components/block.cljs index cb4fcf1995..a25b0f097e 100644 --- a/src/main/frontend/components/block.cljs +++ b/src/main/frontend/components/block.cljs @@ -202,11 +202,24 @@ (on-dimensions (.-naturalWidth img) (.-naturalHeight img)))) (set! (.-src img) url))) +(defn- normalize-asset-align + [asset-align] + (cond + (keyword? asset-align) asset-align + (string? asset-align) (case asset-align + "left" :left + "center" :center + "right" :right + nil) + :else nil)) + (defonce *resizing-image? (atom false)) + (rum/defc ^:large-vars/cleanup-todo asset-container [asset-block src title metadata {:keys [breadcrumb? positioned? local? full-text]}] (let [asset-width (:logseq.property.asset/width asset-block) - asset-height (:logseq.property.asset/height asset-block)] + asset-height (:logseq.property.asset/height asset-block) + asset-align (normalize-asset-align (:logseq.property.asset/align asset-block))] (hooks/use-effect! (fn [] (when (:block/uuid asset-block) @@ -275,7 +288,13 @@ :repo (state/get-current-repo) :href src :title title - :full-text full-text})))))))] + :full-text full-text}))))))) + handle-set-align! + (fn [align] + (when-let [asset-id (:block/uuid asset-block)] + (property-handler/set-block-property! asset-id + :logseq.property.asset/align + align)))] (when asset-block [:.asset-action-bar {:aria-hidden "true"} (shui/dropdown-menu @@ -288,6 +307,33 @@ :class "h-6 w-6"} (shui/tabler-icon "dots-vertical"))) (shui/dropdown-menu-content + (shui/dropdown-menu-sub + (shui/dropdown-menu-sub-trigger + [:span.flex.items-center.gap-1 + (ui/icon "layout-align-left") (t :asset/align)]) + (shui/dropdown-menu-sub-content + (shui/dropdown-menu-item + {:on-click #(handle-set-align! :left)} + [:span.flex.items-center.gap-2 + (ui/icon "layout-align-left") + (t :asset/align-left) + (when (or (nil? asset-align) (= asset-align :left)) + (ui/icon "check"))]) + (shui/dropdown-menu-item + {:on-click #(handle-set-align! :center)} + [:span.flex.items-center.gap-2 + (ui/icon "layout-align-center") + (t :asset/align-center) + (when (= asset-align :center) + (ui/icon "check"))]) + (shui/dropdown-menu-item + {:on-click #(handle-set-align! :right)} + [:span.flex.items-center.gap-2 + (ui/icon "layout-align-right") + (t :asset/align-right) + (when (= asset-align :right) + (ui/icon "check"))]))) + (shui/dropdown-menu-item {:on-click handle-copy!} [:span.flex.items-center.gap-1 @@ -301,6 +347,7 @@ (js/window.apis.openExternal image-src)))} [:span.flex.items-center.gap-1 (ui/icon "folder-pin") (t (if local? :asset/show-in-folder :asset/open-in-browser))])) + (when-not config/publishing? [:<> (shui/dropdown-menu-separator) @@ -318,6 +365,7 @@ (let [breadcrumb? (:breadcrumb? config) positioned? (:property-position config) asset-block (:asset-block config) + asset-align (normalize-asset-align (:logseq.property.asset/align asset-block)) width (:width metadata) *width (get state ::size) width (or @*width width) @@ -334,30 +382,42 @@ (:table-view? config) (not resizable?)) asset-container-cp - [:div.ls-resize-image.rounded-md - asset-container-cp - (resize-image-handles - (fn [k ^js event] - (let [dx (.-dx event) - ^js target (.-target event)] + [:div.ls-resize-inner.w-full.select-none + {:on-double-click (fn [^js e] + (let [^js target (.-target e) + ^js container (.closest target ".ls-resize-inner")] + (when (or container (= target container)) + (when-let [block-uuid (or (:block/uuid config) + (some-> config :block :block/uuid))] + (editor-handler/select-block! block-uuid)))))} + [:div.ls-resize-image.rounded-md + {:class (case asset-align + :center "align-center" + :right "align-right" + "align-left")} + asset-container-cp + (resize-image-handles + (fn [k ^js event] + (let [dx (.-dx event) + ^js target (.-target event)] - (case k - :start - (let [c (.closest target ".ls-resize-image")] - (reset! *width (.-offsetWidth c)) - (reset! *resizing-image? true)) - :move - (let [width' (+ @*width dx)] - (when (or (> width' 60) - (not (neg? dx))) - (reset! *width width'))) - :end - (let [width' @*width] - (when (and width' @*resizing-image?) - (when-let [block-id (or (:block/uuid config) - (some-> config :block (:block/uuid)))] - (editor-handler/resize-image! config block-id metadata full-text {:width width'}))) - (reset! *resizing-image? false))))))]))) + (case k + :start + (let [c (.closest target ".ls-resize-image")] + (reset! *width (.-offsetWidth c)) + (reset! *resizing-image? true)) + :move + (let [width' (+ @*width dx)] + (when (or (> width' 60) + (not (neg? dx))) + (reset! *width width'))) + :end + (let [width' @*width] + (when (and width' @*resizing-image?) + (when-let [block-id (or (:block/uuid config) + (some-> config :block (:block/uuid)))] + (editor-handler/resize-image! config block-id metadata full-text {:width width'}))) + (reset! *resizing-image? false))))))]]))) (rum/defc audio-cp ([src] (audio-cp src nil)) diff --git a/src/main/frontend/components/block.css b/src/main/frontend/components/block.css index d37edfb414..53e76622d0 100644 --- a/src/main/frontend/components/block.css +++ b/src/main/frontend/components/block.css @@ -1194,6 +1194,19 @@ html.is-mac { .ls-resize-image { @apply flex relative w-fit cursor-pointer; + &.align-left { + margin-right: auto; + } + + &.align-center { + margin-left: auto; + margin-right: auto; + } + + &.align-right { + margin-left: auto; + } + .handle-left, .handle-right { @apply absolute w-[6px] h-[15%] min-h-[30px] bg-black/30 hover:bg-black/70 top-[50%] left-[5px] rounded-full cursor-col-resize select-none diff --git a/src/main/frontend/worker/db/migrate.cljs b/src/main/frontend/worker/db/migrate.cljs index 8240a60f78..83a0233c9f 100644 --- a/src/main/frontend/worker/db/migrate.cljs +++ b/src/main/frontend/worker/db/migrate.cljs @@ -75,7 +75,8 @@ ["65.20" {:properties [:logseq.property.class/bidirectional-property-title :logseq.property.class/enable-bidirectional?]}] ["65.21" {:properties [:logseq.property.sync/large-title-object]}] ["65.22" {:properties [:logseq.property.reaction/emoji-id - :logseq.property.reaction/target]}]]) + :logseq.property.reaction/target]}] + ["65.23" {:properties [:logseq.property.asset/align]}]]) (let [[major minor] (last (sort (map (comp (juxt :major :minor) db-schema/parse-schema-version first) schema-version->updates)))] diff --git a/src/resources/dicts/en.edn b/src/resources/dicts/en.edn index 9656eb4462..07f433a4c0 100644 --- a/src/resources/dicts/en.edn +++ b/src/resources/dicts/en.edn @@ -135,6 +135,10 @@ :asset/ref-block "Asset ref block" :asset/confirm-delete "Are you sure you want to delete this {1}?" :asset/physical-delete "Remove the file too (notice it can't be restored)" + :asset/align "Align" + :asset/align-left "Align left" + :asset/align-center "Align center" + :asset/align-right "Align right" :color/gray "Gray" :color/red "Red" :color/yellow "Yellow"