0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-02-13 10:38:13 -05:00

🎉 Synchronize page with a library

This commit is contained in:
Andrés Moya 2020-09-08 13:11:18 +02:00
parent 5e585201d3
commit 917643489f
3 changed files with 131 additions and 11 deletions

View file

@ -362,6 +362,9 @@
(defmethod change-spec :del-component [_]
(s/keys :req-un [::id]))
(defmethod change-spec :sync-library [_]
(s/keys :req-un [::id]))
(s/def ::change (s/multi-spec change-spec :type))
(s/def ::changes (s/coll-of ::change))
@ -774,6 +777,81 @@
[data {:keys [id]}]
(d/dissoc-in data [:components id]))
(declare sync-page)
(declare sync-shape-and-children)
(declare sync-shape)
(defmethod process-change :sync-library
[data id]
(cph/walk-pages (sync-page (:components data)) data))
(defn- sync-page
[components]
(fn [page-id page]
(let [linked-shapes
(cph/select-objects #(some? (:component-id %)) page)
updated-shapes
(reduce
(fn [updated-shapes linked-shape]
(let [component-id (:component-id linked-shape)
component (get components component-id)]
(into updated-shapes
(sync-shape-and-children linked-shape
component
(:objects page)))))
[]
linked-shapes)]
(cph/update-object-list page updated-shapes))))
(defn- sync-shape-and-children
[linked-shape component objects]
(let [children (cph/get-children-objects (:id linked-shape) objects)
all-shapes (conj children linked-shape)]
(if (nil? component)
(map #(dissoc % :component-id :shape-ref) all-shapes)
(map #(sync-shape % (:objects component)) all-shapes))))
(defn- sync-shape
[shape component-objs]
(let [component-shape (get component-objs (:shape-ref shape))]
(if (nil? component-shape)
(assoc shape :shape-ref nil)
(-> shape
(d/update-when :content :content component-shape)
(d/update-when :fill-color :fill-color component-shape)
(d/update-when :fill-color-ref-file :fill-color-ref-file component-shape)
(d/update-when :fill-color-ref-id :fill-color-ref-id component-shape)
(d/update-when :fill-opacity :fill-opacity component-shape)
(d/update-when :font-family :font-family component-shape)
(d/update-when :font-size :font-size component-shape)
(d/update-when :font-style :font-style component-shape)
(d/update-when :font-weight :font-weight component-shape)
(d/update-when :letter-spacing :letter-spacing component-shape)
(d/update-when :line-height :line-height component-shape)
(d/update-when :proportion :proportion component-shape)
(d/update-when :rx :rx component-shape)
(d/update-when :ry :ry component-shape)
(d/update-when :cx :cx component-shape)
(d/update-when :cy :cy component-shape)
(d/update-when :x :x component-shape)
(d/update-when :y :y component-shape)
(d/update-when :exports :exports component-shape)
(d/update-when :stroke-color :stroke-color component-shape)
(d/update-when :stroke-color-ref-file :stroke-color-ref-file component-shape)
(d/update-when :stroke-color-ref-id :stroke-color-ref-id component-shape)
(d/update-when :stroke-opacity :stroke-opacity component-shape)
(d/update-when :stroke-style :stroke-style component-shape)
(d/update-when :stroke-width :stroke-width component-shape)
(d/update-when :stroke-alignment :stroke-alignment component-shape)
(d/update-when :text-align :text-align component-shape)
(d/update-when :width :width component-shape)
(d/update-when :height :height component-shape)
(d/update-when :interactions :interactions component-shape)
(d/update-when :selrect :selrect component-shape)
(d/update-when :points :points component-shape)))))
(defmethod process-operation :set
[shape op]
(let [attr (:attr op)

View file

@ -12,6 +12,24 @@
[app.common.data :as d]
[app.common.uuid :as uuid]))
(defn walk-pages
"Go through all pages of a file and apply a function to each one"
;; The function receives two parameters (page-id and page), and
;; returns the updated page.
[f data]
(update data :pages-index #(d/mapm f %)))
(defn select-objects
"Get a list of all objects in a page that satisfy a condition"
[f page]
(filter f (vals (get page :objects))))
(defn update-object-list
"Update multiple objects in a page at once"
[page objects-list]
(update page :objects
#(into % (d/index-by :id objects-list))))
(defn get-children
"Retrieve all children ids recursively for a given object"
[id objects]
@ -20,6 +38,11 @@
(d/concat shapes (mapcat #(get-children % objects) shapes))
[])))
(defn get-children-objects
"Retrieve all children objects recursively for a given object"
[id objects]
(map #(get objects %) (get-children id objects)))
(defn is-shape-grouped
"Checks if a shape is inside a group"
[shape-id objects]

View file

@ -142,7 +142,10 @@
:id (:id updated-shape)
:operations [{:type :set
:attr :component-id
:val (:component-id updated-shape)}]})
:val (:component-id updated-shape)}
{:type :set
:attr :shape-ref
:val (:shape-ref updated-shape)}]})
updated-shapes))
uchanges (conj uchanges
@ -156,6 +159,9 @@
:id (:id updated-shape)
:operations [{:type :set
:attr :component-id
:val nil}
{:type :set
:attr :shape-ref
:val nil}]})
updated-shapes))]
@ -174,10 +180,15 @@
(let [new-shape (assoc shape
:id new-id
:parent-id parent-id
:frame-id nil)]
[new-shape
[new-shape]
[(assoc shape :component-id (:id new-shape))]])
:frame-id nil)
new-shapes [new-shape]
updated-shapes [(cond-> shape
true (assoc :shape-ref (:id new-shape))
(nil? parent-id) (assoc :component-id (:id new-shape)))]]
[new-shape new-shapes updated-shapes])
(loop [child-ids (seq (:shapes shape))
new-children []
@ -188,11 +199,17 @@
:id new-id
:parent-id parent-id
:frame-id nil
:shapes (map :id new-children))]
[new-shape
(conj new-children new-shape)
(conj updated-children
(assoc shape :component-id (:id new-shape)))])
:shapes (map :id new-children))
new-shapes (conj new-children new-shape)
updated-shapes
(conj updated-children
(cond-> shape
true (assoc :shape-ref (:id new-shape))
(nil? parent-id) (assoc :component-id (:id new-shape))))]
[new-shape new-shapes updated-shapes])
(let [child-id (first child-ids)
child (get objects child-id)
@ -213,7 +230,9 @@
(let [component (get-in state [:workspace-data :components id])
rchanges [{:type :del-component
:id id}]
:id id}
{:type :sync-library
:id (get-in state [:workspace-file :id])}]
uchanges [{:type :add-component
:id id