mirror of
https://github.com/penpot/penpot.git
synced 2025-05-25 20:26:11 +02:00
✨ Set an artboard as the file thumbnail
This commit is contained in:
parent
a588267fc2
commit
0a04a856da
11 changed files with 150 additions and 26 deletions
|
@ -1061,6 +1061,36 @@
|
|||
(let [selected (wsh/lookup-selected state)]
|
||||
(rx/of (dch/update-shapes selected #(update % :blocked not)))))))
|
||||
|
||||
(defn extract-file-thumbnails-from-page
|
||||
[state selected page]
|
||||
(let [extract-frames (fn [page-id]
|
||||
(let [objects (wsh/lookup-page-objects state page-id)]
|
||||
(cph/get-frames objects)))
|
||||
page-id (key page)
|
||||
frames-with-thumbnail (->> (extract-frames page-id)
|
||||
(filter (comp true? :file-thumbnail))
|
||||
(map :id)
|
||||
(remove #(some #{%} selected))
|
||||
(map #(into {} {:id % :page-id page-id})))]
|
||||
(when frames-with-thumbnail frames-with-thumbnail)))
|
||||
|
||||
|
||||
(defn toggle-file-thumbnail-selected
|
||||
[]
|
||||
(ptk/reify ::toggle-file-thumbnail-selected
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [selected (wsh/lookup-selected state)
|
||||
pages (get-in state [:workspace-data
|
||||
:pages-index])
|
||||
file-thumbnails (->> pages
|
||||
(mapcat #(extract-file-thumbnails-from-page state selected %)))]
|
||||
(rx/concat
|
||||
(rx/from
|
||||
(for [ft file-thumbnails]
|
||||
(dch/update-shapes [(:id ft)] #(update % :file-thumbnail not) (:page-id ft) nil)))
|
||||
(rx/of (dch/update-shapes selected #(update % :file-thumbnail not))))))))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Navigation
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
|
|
@ -71,9 +71,10 @@
|
|||
(update :undo-changes conj (assoc change :operations uops)))))
|
||||
|
||||
(defn update-shapes
|
||||
([ids f] (update-shapes ids f nil))
|
||||
([ids f {:keys [reg-objects? save-undo? attrs ignore-tree]
|
||||
:or {reg-objects? false save-undo? true attrs nil}}]
|
||||
([ids f] (update-shapes ids f nil nil))
|
||||
([ids f keys] (update-shapes ids f nil keys))
|
||||
([ids f page-id {:keys [reg-objects? save-undo? attrs ignore-tree]
|
||||
:or {reg-objects? false save-undo? true attrs nil}}]
|
||||
|
||||
(us/assert ::coll-of-uuid ids)
|
||||
(us/assert fn? f)
|
||||
|
@ -81,8 +82,8 @@
|
|||
(ptk/reify ::update-shapes
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state)
|
||||
(let [page-id (or page-id (:current-page-id state))
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
changes {:redo-changes []
|
||||
:undo-changes []
|
||||
:origin it
|
||||
|
@ -91,8 +92,8 @@
|
|||
ids (into [] (filter some?) ids)
|
||||
|
||||
changes (reduce
|
||||
#(update-shape-changes %1 page-id objects f attrs %2 (get ignore-tree %2))
|
||||
changes ids)]
|
||||
#(update-shape-changes %1 page-id objects f attrs %2 (get ignore-tree %2))
|
||||
changes ids)]
|
||||
|
||||
(when-not (empty? (:redo-changes changes))
|
||||
(let [reg-objs {:type :reg-objects
|
||||
|
|
|
@ -358,7 +358,12 @@
|
|||
|
||||
:toggle-focus-mode {:command "f"
|
||||
:tooltip "F"
|
||||
:fn #(st/emit! (dw/toggle-focus-mode))}})
|
||||
:fn #(st/emit! (dw/toggle-focus-mode))}
|
||||
|
||||
:thumbnail-set {:tooltip (ds/shift "T")
|
||||
:command "shift+t"
|
||||
:fn #(st/emit! (dw/toggle-file-thumbnail-selected))}})
|
||||
|
||||
|
||||
(def opacity-shortcuts
|
||||
(into {} (->>
|
||||
|
|
|
@ -215,6 +215,31 @@
|
|||
[:& shape-wrapper {:shape item
|
||||
:key (:id item)}])))]]]))
|
||||
|
||||
(mf/defc file-thumbnail-svg
|
||||
{::mf/wrap [mf/memo]}
|
||||
[{:keys [data embed? include-metadata?] :as props
|
||||
:or {embed? false include-metadata? false}}]
|
||||
(let [data (assoc data :x 0 :y 0)
|
||||
vbox (format-viewbox {:width (:width data 0) :height (:height data 0)})
|
||||
background-color (get-in data [:options :background] default-color)]
|
||||
|
||||
[:& (mf/provider embed/context) {:value embed?}
|
||||
[:& (mf/provider export/include-metadata-ctx) {:value include-metadata?}
|
||||
[:svg {:view-box vbox
|
||||
:version "1.1"
|
||||
:xmlns "http://www.w3.org/2000/svg"
|
||||
:xmlnsXlink "http://www.w3.org/1999/xlink"
|
||||
:xmlns:penpot (when include-metadata? "https://penpot.app/xmlns")
|
||||
:style {:width "100%"
|
||||
:height "100%"
|
||||
:background background-color}}
|
||||
|
||||
(when include-metadata?
|
||||
[:& export/export-page {:options (:options data)}])
|
||||
|
||||
[:> shape-container {:shape data}
|
||||
[:& frame/frame-thumbnail {:shape data}]]]]]))
|
||||
|
||||
(mf/defc frame-svg
|
||||
{::mf/wrap [mf/memo]}
|
||||
[{:keys [objects frame zoom] :or {zoom 1} :as props}]
|
||||
|
|
|
@ -38,12 +38,12 @@
|
|||
(def ^:const CACHE-NAME "penpot")
|
||||
(def ^:const CACHE-URL "https://penpot.app/cache/")
|
||||
|
||||
|
||||
(defn use-thumbnail-cache
|
||||
"Creates some hooks to handle the files thumbnails cache"
|
||||
[file]
|
||||
|
||||
(let [cache-url (str CACHE-URL (:id file) "/" (:revn file) ".svg")
|
||||
|
||||
get-thumbnail
|
||||
(mf/use-callback
|
||||
(mf/deps cache-url)
|
||||
|
@ -83,14 +83,12 @@
|
|||
(if (some? thumb-data)
|
||||
(rx/of thumb-data)
|
||||
(->> (wrk/ask! {:cmd :thumbnails/generate
|
||||
:file-id (:id file)
|
||||
:page-id (get-in file [:data :pages 0])})
|
||||
:file-id (:id file)})
|
||||
(rx/tap cache-thumbnail)))))
|
||||
|
||||
;; If we have a problem we delegate to the thumbnail generation
|
||||
(rx/catch #(wrk/ask! {:cmd :thumbnails/generate
|
||||
:file-id (:id file)
|
||||
:page-id (get-in file [:data :pages 0])})))))))
|
||||
:file-id (:id file)})))))))
|
||||
|
||||
(mf/defc grid-item-thumbnail
|
||||
{::mf/wrap [mf/memo]}
|
||||
|
|
|
@ -164,6 +164,22 @@
|
|||
:on-click do-flip-horizontal}]
|
||||
[:& menu-separator]]))
|
||||
|
||||
(mf/defc context-menu-thumbnail
|
||||
[{:keys [shapes]}]
|
||||
(let [single? (= (count shapes) 1)
|
||||
has-frame? (->> shapes (d/seek #(= :frame (:type %))))
|
||||
is-frame? (and single? has-frame?)
|
||||
do-toggle-thumbnail (st/emitf (dw/toggle-file-thumbnail-selected))]
|
||||
(when is-frame?
|
||||
[:*
|
||||
(if (every? :file-thumbnail shapes)
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.thumbnail-remove")
|
||||
:on-click do-toggle-thumbnail}]
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.thumbnail-set")
|
||||
:shortcut (sc/get-tooltip :thumbnail-set)
|
||||
:on-click do-toggle-thumbnail}])
|
||||
[:& menu-separator]])))
|
||||
|
||||
(mf/defc context-menu-group
|
||||
[{:keys [shapes]}]
|
||||
|
||||
|
@ -436,6 +452,7 @@
|
|||
[:> context-menu-edit props]
|
||||
[:> context-menu-layer-position props]
|
||||
[:> context-menu-flip props]
|
||||
[:> context-menu-thumbnail props]
|
||||
[:> context-menu-group props]
|
||||
[:> context-focus-mode-menu props]
|
||||
[:> context-menu-path props]
|
||||
|
|
|
@ -29,11 +29,10 @@
|
|||
(rx/throw {:type :unexpected
|
||||
:code (:error response)})))
|
||||
|
||||
(defn- request-page
|
||||
[file-id page-id]
|
||||
(let [uri (u/join (cfg/get-public-uri) "api/rpc/query/page")
|
||||
(defn- request-thumbnail
|
||||
[file-id]
|
||||
(let [uri (u/join (cfg/get-public-uri) "api/rpc/query/file-data-for-thumbnail")
|
||||
params {:file-id file-id
|
||||
:id page-id
|
||||
:strip-frames-with-thumbnails true}]
|
||||
(->> (http/send!
|
||||
{:method :get
|
||||
|
@ -45,20 +44,23 @@
|
|||
|
||||
(defonce cache (atom {}))
|
||||
|
||||
(defn render-page
|
||||
(defn render-frame
|
||||
[data ckey]
|
||||
(let [prev (get @cache ckey)]
|
||||
(if (= (:data prev) data)
|
||||
(:result prev)
|
||||
(let [elem (mf/element render/page-svg #js {:data data :width "290" :height "150" :thumbnails? true})
|
||||
(let [file-thumbnail (:file-thumbnail data)
|
||||
elem (if file-thumbnail
|
||||
(mf/element render/file-thumbnail-svg #js {:data file-thumbnail :width "290" :height "150"})
|
||||
(mf/element render/page-svg #js {:data data :width "290" :height "150" :thumbnails? true}))
|
||||
result (rds/renderToStaticMarkup elem)]
|
||||
(swap! cache assoc ckey {:data data :result result})
|
||||
result))))
|
||||
|
||||
(defmethod impl/handler :thumbnails/generate
|
||||
[{:keys [file-id page-id] :as message}]
|
||||
(->> (request-page file-id page-id)
|
||||
[{:keys [file-id] :as message}]
|
||||
(->> (request-thumbnail file-id)
|
||||
(rx/map
|
||||
(fn [data]
|
||||
{:svg (render-page data #{file-id page-id})
|
||||
{:svg (render-frame data #{file-id})
|
||||
:fonts @fonts/loaded}))))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue