Jelajahi Sumber

enhance(ui): use dots menu for the asset actions

charlie 6 bulan lalu
induk
melakukan
71cdd4a55f

+ 99 - 91
src/main/frontend/components/block.cljs

@@ -303,83 +303,91 @@
 (defonce *resizing-image? (atom false))
 (rum/defc asset-container
   [asset-block src title metadata {:keys [breadcrumb? positioned? local? full-text]}]
-  [:div.asset-container
-   {:key "resize-asset-container"}
-   [:img.rounded-sm.relative
-    (merge
-     {:loading "lazy"
-      :referrerPolicy "no-referrer"
-      :src src
-      :title title}
-     metadata)]
-   (when (and (not breadcrumb?)
-              (not positioned?))
-     [:<>
-      (let [image-src (fs/asset-path-normalize src)]
-        [:.asset-action-bar {:aria-hidden "true"}
-         [:.flex
-          (when-not config/publishing?
-            [:button.asset-action-btn
-             {:title (t :asset/delete)
-              :tabIndex "-1"
-              :on-pointer-down util/stop
-              :on-click
-              (fn [e]
-                (util/stop e)
-                (when-let [block-id (some-> (.-target e) (.closest "[blockid]") (.getAttribute "blockid") (uuid))]
+  (let [*el-ref (rum/use-ref nil)]
+    [:div.asset-container
+     {:key "resize-asset-container"
+      :ref *el-ref}
+     [:img.rounded-sm.relative
+      (merge
+        {:loading "lazy"
+         :referrerPolicy "no-referrer"
+         :src src
+         :title title}
+        metadata)]
+     (when (and (not breadcrumb?)
+             (not positioned?))
+       [:<>
+        (let [image-src (fs/asset-path-normalize src)
+              handle-copy!
+              (fn [_e]
+                (-> (util/copy-image-to-clipboard image-src)
+                  (p/then #(notification/show! "Copied!" :success))))
+              handle-delete!
+              (fn [_e]
+                (when-let [block-id (some-> (rum/deref *el-ref) (.closest "[blockid]") (.getAttribute "blockid") (uuid))]
                   (let [*local-selected? (atom local?)]
                     (-> (shui/dialog-confirm!
-                         [:div.text-xs.opacity-60.-my-2
-                          (when (and local? (not= (:block/uuid asset-block) block-id))
-                            [:label.flex.gap-1.items-center
-                             (shui/checkbox
-                              {:default-checked @*local-selected?
-                               :on-checked-change #(reset! *local-selected? %)})
-                             (t :asset/physical-delete)])]
-                         {:title (t :asset/confirm-delete (.toLocaleLowerCase (t :text/image)))
-                          :outside-cancel? true})
-                        (p/then (fn []
-                                  (shui/dialog-close!)
-                                  (editor-handler/delete-asset-of-block!
-                                   {:block-id block-id
-                                    :asset-block asset-block
-                                    :local? local?
-                                    :delete-local? @*local-selected?
-                                    :repo (state/get-current-repo)
-                                    :href src
-                                    :title title
-                                    :full-text full-text})))))))}
-             (ui/icon "trash")])
-
-          [:button.asset-action-btn
-           {:title (t :asset/copy)
-            :tabIndex "-1"
-            :on-pointer-down util/stop
-            :on-click (fn [e]
-                        (util/stop e)
-                        (-> (util/copy-image-to-clipboard image-src)
-                            (p/then #(notification/show! "Copied!" :success))))}
-           (ui/icon "copy")]
-
-          [:button.asset-action-btn
-           {:title (t :asset/maximize)
-            :tabIndex "-1"
-            :on-pointer-down util/stop
-            :on-click open-lightbox}
-
-           (ui/icon "maximize")]
-
-          (when (util/electron?)
-            [:button.asset-action-btn
-             {:title (t (if local? :asset/show-in-folder :asset/open-in-browser))
-              :tabIndex "-1"
-              :on-pointer-down util/stop
-              :on-click (fn [e]
-                          (util/stop e)
-                          (if local?
-                            (ipc/ipc "openFileInFolder" image-src)
-                            (js/window.apis.openExternal image-src)))}
-             (shui/tabler-icon "folder-pin")])]])])])
+                          [:div.text-xs.opacity-60.-my-2
+                           (when (and local? (not= (:block/uuid asset-block) block-id))
+                             [:label.flex.gap-1.items-center
+                              (shui/checkbox
+                                {:default-checked @*local-selected?
+                                 :on-checked-change #(reset! *local-selected? %)})
+                              (t :asset/physical-delete)])]
+                          {:title (t :asset/confirm-delete (.toLocaleLowerCase (t :text/image)))
+                           :outside-cancel? true})
+                      (p/then (fn []
+                                (shui/dialog-close!)
+                                (editor-handler/delete-asset-of-block!
+                                  {:block-id block-id
+                                   :asset-block asset-block
+                                   :local? local?
+                                   :delete-local? @*local-selected?
+                                   :repo (state/get-current-repo)
+                                   :href src
+                                   :title title
+                                   :full-text full-text})))))))]
+          [:.asset-action-bar {:aria-hidden "true"}
+           (shui/button-group
+             (shui/button
+               {:variant :outline
+                :size :icon
+                :class "h-7 w-7"
+                :on-pointer-down util/stop
+                :on-click (fn [e]
+                            (shui/popup-show! (.closest (.-target e) ".asset-action-bar")
+                              (fn []
+                                [:div
+                                 {:on-click #(shui/popup-hide!)}
+                                 (shui/dropdown-menu-item
+                                   {:on-click handle-copy!}
+                                   [:span.flex.items-center.gap-1
+                                    (ui/icon "copy") (t :asset/copy)])
+                                 (shui/dropdown-menu-item
+                                   {:on-click open-lightbox}
+                                   [:span.flex.items-center.gap-1
+                                    (ui/icon "maximize") (t :asset/maximize)])
+
+                                 (when (util/electron?)
+                                   (shui/dropdown-menu-item
+                                     {:on-click (fn [e]
+                                                  (util/stop e)
+                                                  (if local?
+                                                    (ipc/ipc "openFileInFolder" image-src)
+                                                    (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)
+                                    (shui/dropdown-menu-item
+                                      {:on-click handle-delete!}
+                                      [:span.flex.items-center.gap-1.text-red-700
+                                       (ui/icon "trash") (t :asset/delete)])])
+                                 ])
+                              {:align :start}))}
+               (shui/tabler-icon "dots-vertical")))])])]))
 
 ;; TODO: store image height and width for better ux
 (rum/defcs ^:large-vars/cleanup-todo resizable-image <
@@ -392,32 +400,32 @@
         positioned? (:property-position config)
         asset-block (:asset-block config)
         width (or (get-in asset-block [:logseq.property.asset/resize-metadata :width])
-                  (:width metadata))
+                (:width metadata))
         *width (get state ::size)
         width (or @*width width 250)
         metadata' (merge
-                   (cond->
-                    {:height 125}
-                     width
-                     (assoc :width width))
-                   metadata)
+                    (cond->
+                      {:height 125}
+                      width
+                      (assoc :width width))
+                    metadata)
         resizable? (and (not (mobile-util/native-platform?))
-                        (not breadcrumb?)
-                        (not positioned?))
+                     (not breadcrumb?)
+                     (not positioned?))
         asset-container-cp (asset-container asset-block src title metadata'
-                                            {:breadcrumb? breadcrumb?
-                                             :positioned? positioned?
-                                             :local? local?
-                                             :full-text full-text})]
+                             {:breadcrumb? breadcrumb?
+                              :positioned? positioned?
+                              :local? local?
+                              :full-text full-text})]
     (if (or (:disable-resize? config)
-            (not resizable?))
+          (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)]
+         (fn [k ^js event]
+           (let [dx (.-dx event)
+                 ^js target (.-target event)]
 
             (case k
               :start

+ 6 - 3
src/main/frontend/components/block.css

@@ -29,8 +29,11 @@
     @apply relative inline-block mt-2 w-full;
 
     .asset-action-bar {
-      @apply top-0.5 right-0.5 absolute flex items-center
-      border bg-gray-02 rounded opacity-0 transition-opacity;
+      @apply top-1 right-1 absolute flex items-center opacity-0 transition-opacity;
+
+      &[data-popup-active] {
+        @apply opacity-100;
+      }
     }
 
     .asset-action-btn {
@@ -1119,7 +1122,7 @@ html.is-mac {
 }
 
 .ls-resize-image {
-  @apply flex relative;
+  @apply flex relative w-fit;
 
   .handle-left, .handle-right {
     @apply absolute w-[6px] h-[15%] min-h-[30px] bg-black/30 hover:bg-black/70