diff --git a/backend/src/app/rpc/commands/search.clj b/backend/src/app/rpc/commands/search.clj index 1c4026d6db..5710156458 100644 --- a/backend/src/app/rpc/commands/search.clj +++ b/backend/src/app/rpc/commands/search.clj @@ -9,6 +9,7 @@ [app.common.spec :as us] [app.db :as db] [app.rpc :as-alias rpc] + [app.rpc.commands.files :refer [resolve-public-uri]] [app.rpc.doc :as-alias doc] [app.util.services :as sv] [clojure.spec.alpha :as s])) @@ -37,12 +38,15 @@ ) select distinct f.id, + f.revn, f.project_id, f.created_at, f.modified_at, f.name, - f.is_shared + f.is_shared, + ft.media_id from file as f + left join file_thumbnail as ft on (ft.file_id = f.id and ft.revn = f.revn) inner join projects as pr on (f.project_id = pr.id) where f.name ilike ('%' || ? || '%') and (f.deleted_at is null or f.deleted_at > now()) @@ -50,10 +54,16 @@ (defn search-files [conn profile-id team-id search-term] - (db/exec! conn [sql:search-files - profile-id team-id - profile-id team-id - search-term])) + (->> (db/exec! conn [sql:search-files + profile-id team-id + profile-id team-id + search-term]) + (mapv (fn [row] + (if-let [media-id (:media-id row)] + (-> row + (dissoc :media-id) + (assoc :thumbnail-uri (resolve-public-uri media-id))) + (dissoc row :media-id)))))) (s/def ::team-id ::us/uuid) (s/def ::search-files ::us/string) diff --git a/common/src/app/common/geom/rect.cljc b/common/src/app/common/geom/rect.cljc index 62222b707f..5fa77b8d3d 100644 --- a/common/src/app/common/geom/rect.cljc +++ b/common/src/app/common/geom/rect.cljc @@ -353,3 +353,19 @@ (mth/max by1 y1) (mth/min bx2 x2) (mth/min by2 y2))))) +(defn fix-aspect-ratio + [bounds aspect-ratio] + (if aspect-ratio + (let [width (dm/get-prop bounds :width) + height (dm/get-prop bounds :height) + target-height (* width aspect-ratio) + target-width (* height (/ 1 aspect-ratio))] + (cond-> bounds + (> target-height height) + (-> (assoc :height target-height) + (update :y - (/ (- target-height height ) 2))) + + (< target-height height) + (-> (assoc :width target-width) + (update :x - (/ (- target-width width ) 2))))) + bounds)) diff --git a/frontend/src/app/main/data/dashboard.cljs b/frontend/src/app/main/data/dashboard.cljs index 9e723ca20b..b9dec712e6 100644 --- a/frontend/src/app/main/data/dashboard.cljs +++ b/frontend/src/app/main/data/dashboard.cljs @@ -831,9 +831,15 @@ (ptk/reify ::set-file-thumbnail ptk/UpdateEvent (update [_ state] - (-> state - (d/update-in-when [:dashboard-files file-id] assoc :thumbnail-uri thumbnail-uri) - (d/update-in-when [:dashboard-recent-files file-id] assoc :thumbnail-uri thumbnail-uri))))) + (letfn [(update-search-files [files] + (->> files + (mapv #(cond-> % + (= file-id (:id %)) + (assoc :thumbnail-uri thumbnail-uri)))))] + (-> state + (d/update-in-when [:dashboard-files file-id] assoc :thumbnail-uri thumbnail-uri) + (d/update-in-when [:dashboard-recent-files file-id] assoc :thumbnail-uri thumbnail-uri) + (d/update-when :dashboard-search-result update-search-files)))))) ;; --- EVENT: create-file diff --git a/frontend/src/app/main/render.cljs b/frontend/src/app/main/render.cljs index 3ea0e1d341..2066ad30cf 100644 --- a/frontend/src/app/main/render.cljs +++ b/frontend/src/app/main/render.cljs @@ -66,16 +66,18 @@ :fill color}]) (defn- calculate-dimensions - [objects] - (let [bounds (->> (ctst/get-root-objects objects) - (map (partial gsb/get-object-bounds objects)) - (grc/join-rects))] + [objects aspect-ratio] + (let [bounds + (->> (ctst/get-root-objects objects) + (map (partial gsb/get-object-bounds objects)) + (grc/join-rects))] (-> bounds (update :x mth/finite 0) (update :y mth/finite 0) (update :width mth/finite 100000) (update :height mth/finite 100000) - (grc/update-rect :position)))) + (grc/update-rect :position) + (grc/fix-aspect-ratio aspect-ratio)))) (declare shape-wrapper-factory) @@ -194,11 +196,11 @@ (mf/defc page-svg {::mf/wrap [mf/memo]} - [{:keys [data use-thumbnails embed include-metadata] :as props + [{:keys [data use-thumbnails embed include-metadata aspect-ratio] :as props :or {embed false include-metadata false}}] (let [objects (:objects data) shapes (cfh/get-immediate-children objects) - dim (calculate-dimensions objects) + dim (calculate-dimensions objects aspect-ratio) vbox (format-viewbox dim) bgcolor (dm/get-in data [:options :background] default-color) @@ -253,11 +255,14 @@ ;; the viewer and inspector (mf/defc frame-svg {::mf/wrap [mf/memo]} - [{:keys [objects frame zoom use-thumbnails] :or {zoom 1} :as props}] + [{:keys [objects frame zoom use-thumbnails aspect-ratio background-color] :or {zoom 1} :as props}] (let [frame-id (:id frame) + + bgcolor (d/nilv background-color default-color) include-metadata (mf/use-ctx export/include-metadata-ctx) - bounds (gsb/get-object-bounds objects frame) + bounds (-> (gsb/get-object-bounds objects frame) + (grc/fix-aspect-ratio aspect-ratio)) ;; Bounds without shadows/blur will be the bounds of the thumbnail bounds2 (gsb/get-object-bounds objects (dissoc frame :shadow :blur)) @@ -305,6 +310,7 @@ :xmlns "http://www.w3.org/2000/svg" :xmlnsXlink "http://www.w3.org/1999/xlink" :xmlns:penpot (when include-metadata "https://penpot.app/xmlns") + :style {:background bgcolor} :fill "none"} [:& shape-wrapper {:shape frame}]]])) diff --git a/frontend/src/app/main/ui/dashboard/grid.cljs b/frontend/src/app/main/ui/dashboard/grid.cljs index 66a3f98601..663e26710a 100644 --- a/frontend/src/app/main/ui/dashboard/grid.cljs +++ b/frontend/src/app/main/ui/dashboard/grid.cljs @@ -61,7 +61,7 @@ (rx/map (fn [styles] (assoc result :styles styles - :width 250)))))) + :width 252)))))) (rx/mapcat thr/render) (rx/mapcat (partial persist-thumbnail file-id revn)))) diff --git a/frontend/src/app/main/ui/dashboard/grid.scss b/frontend/src/app/main/ui/dashboard/grid.scss index 55d63faee8..818b7fdce6 100644 --- a/frontend/src/app/main/ui/dashboard/grid.scss +++ b/frontend/src/app/main/ui/dashboard/grid.scss @@ -7,7 +7,7 @@ @import "refactor/common-refactor.scss"; $thumbnail-default-width: $s-252; // Default width -$thumbnail-aspect-ration: #{2 / 3}; // Ratio 2:3 +$thumbnail-default-height: $s-168; // Default width .dashboard-grid { font-size: $fs-14; @@ -44,10 +44,12 @@ $thumbnail-aspect-ration: #{2 / 3}; // Ratio 2:3 } .grid-item-th { - border-radius: $br-4; + border-radius: $br-8; text-align: initial; width: var(--th-width, #{$thumbnail-default-width}); - height: calc(var(--th-width, #{$thumbnail-default-width}) * #{$thumbnail-aspect-ration}); + height: var(--th-height, #{$thumbnail-default-height}); + background-size: cover; + overflow: hidden; img { object-fit: contain; @@ -59,7 +61,7 @@ $thumbnail-aspect-ration: #{2 / 3}; // Ratio 2:3 outline: $br-4 solid $da-primary; text-align: initial; width: calc(var(--th-width) + $s-12); - height: calc(var(--th-width, #{$thumbnail-default-width}) * #{$thumbnail-aspect-ration}); + height: var(--th-height, #{$thumbnail-default-height}); } &.overlay { @@ -131,10 +133,10 @@ $thumbnail-aspect-ration: #{2 / 3}; // Ratio 2:3 .item-badge { background-color: $da-primary; border: none; - border-radius: $br-4; + border-radius: $br-6; position: absolute; - top: $s-8; - right: $s-8; + top: $s-12; + right: $s-12; height: $s-32; width: $s-32; display: flex; @@ -258,17 +260,10 @@ $thumbnail-aspect-ration: #{2 / 3}; // Ratio 2:3 .grid-item-th { border-radius: $br-4; cursor: pointer; - - background-position: center; - background-size: auto 80%; - background-repeat: no-repeat; - height: 100%; overflow: hidden; position: relative; width: 100%; - - background-color: var(--canvas-color); display: flex; justify-content: center; flex-direction: row; @@ -283,8 +278,9 @@ $thumbnail-aspect-ration: #{2 / 3}; // Ratio 2:3 width: 100%; } - svg#loader-pencil { - fill: $db-cuaternary; + :global(svg#loader-pencil) { + stroke: $db-cuaternary; + width: calc(var(--th-width, #{$thumbnail-default-width}) * 0.25); } } diff --git a/frontend/src/app/main/ui/dashboard/placeholder.scss b/frontend/src/app/main/ui/dashboard/placeholder.scss index 9b10a5a091..829ad1d530 100644 --- a/frontend/src/app/main/ui/dashboard/placeholder.scss +++ b/frontend/src/app/main/ui/dashboard/placeholder.scss @@ -65,7 +65,7 @@ text-transform: uppercase; border: $s-2 solid transparent; width: var(--th-width, #{g.$thumbnail-default-width}); - height: calc(var(--th-width, #{g.$thumbnail-default-width}) * #{g.$thumbnail-aspect-ration}); + height: var(--th-height, #{g.$thumbnail-default-height}); svg { width: $s-32; diff --git a/frontend/src/app/main/ui/hooks.cljs b/frontend/src/app/main/ui/hooks.cljs index d15a87185c..ec41de80f8 100644 --- a/frontend/src/app/main/ui/hooks.cljs +++ b/frontend/src/app/main/ui/hooks.cljs @@ -367,13 +367,17 @@ limit (mth/max 1 limit) th-size (when width - (- (/ (- width 32 (* (dec limit) 24)) limit) 12))] + (mth/floor (- (/ (- width 32 (* (dec limit) 24)) limit) 12))) + + ;; Need an even value + th-size (if (odd? (int th-size)) (- th-size 1) th-size)] (mf/with-effect [th-size] (when th-size (let [node (mf/ref-val rowref)] - (.setProperty (.-style node) "--th-width" (str th-size "px"))))) + (.setProperty (.-style node) "--th-width" (str th-size "px")) + (.setProperty (.-style node) "--th-height" (str (mth/ceil (* th-size (/ 2 3))) "px"))))) (mf/with-effect [] (let [node (mf/ref-val rowref) diff --git a/frontend/src/app/worker/thumbnails.cljs b/frontend/src/app/worker/thumbnails.cljs index 3e3cbbfef8..93f9688526 100644 --- a/frontend/src/app/worker/thumbnails.cljs +++ b/frontend/src/app/worker/thumbnails.cljs @@ -7,6 +7,7 @@ (ns app.worker.thumbnails (:require ["react-dom/server" :as rds] + [app.common.data.macros :as dm] [app.common.logging :as log] [app.common.uri :as u] [app.config :as cf] @@ -62,16 +63,27 @@ (binding [fonts/loaded-hints (l/atom #{})] (let [objects (:objects page) frame (some->> page :thumbnail-frame-id (get objects)) + background-color (dm/get-in page [:options :background]) element (if frame - (mf/element render/frame-svg #js {:objects objects :frame frame :use-thumbnails true}) - (mf/element render/page-svg #js {:data page :use-thumbnails true :embed true})) + (mf/element render/frame-svg #js + {:objects objects + :frame frame + :use-thumbnails true + :background-color background-color + :aspect-ratio (/ 2 3)}) + + (mf/element render/page-svg #js + {:data page + :use-thumbnails true + :embed true + :aspect-ratio (/ 2 3)})) data (rds/renderToStaticMarkup element)] {:data data :fonts @fonts/loaded-hints :file-id file-id :revn revn})) (catch :default cause - (js/console.error "unexpected erorr on rendering thumbnail" cause) + (js/console.error "unexpected error on rendering thumbnail" cause) nil))) (defmethod impl/handler :thumbnails/generate-for-file