mirror of
https://github.com/penpot/penpot.git
synced 2025-02-13 10:38:13 -05:00
✨ Improved dashboard thumbnails
This commit is contained in:
parent
5522430afe
commit
030ff398ed
9 changed files with 90 additions and 40 deletions
|
@ -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)
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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}]]]))
|
||||
|
||||
|
|
|
@ -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))))
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue