mirror of
https://github.com/penpot/penpot.git
synced 2025-06-11 03:51:37 +02:00
🐛 Fix critical inconsistencies on group handling.
This commit is contained in:
parent
93a967ed8f
commit
b68a076e57
16 changed files with 323 additions and 236 deletions
|
@ -16,6 +16,7 @@
|
|||
[uxbox.common.data :as d]
|
||||
[uxbox.common.exceptions :as ex]
|
||||
[uxbox.common.pages :as cp]
|
||||
[uxbox.common.pages-helpers :as cph]
|
||||
[uxbox.common.spec :as us]
|
||||
[uxbox.common.uuid :as uuid]
|
||||
[uxbox.config :as cfg]
|
||||
|
@ -212,7 +213,7 @@
|
|||
(initialize [state local]
|
||||
(let [page-id (get-in state [:workspace-page :id])
|
||||
objects (get-in state [:workspace-data page-id :objects])
|
||||
shapes (cp/select-toplevel-shapes objects {:include-frames? true})
|
||||
shapes (cph/select-toplevel-shapes objects {:include-frames? true})
|
||||
srect (geom/selection-rect shapes)
|
||||
local (assoc local :vport size)]
|
||||
(cond
|
||||
|
@ -286,7 +287,7 @@
|
|||
(let [page-id (:current-page-id state)
|
||||
objects (get-in state [:workspace-data page-id :objects])
|
||||
groups-to-adjust (->> ids
|
||||
(mapcat #(reverse (cp/get-all-parents % objects)))
|
||||
(mapcat #(cph/get-parents % objects))
|
||||
(map #(get objects %))
|
||||
(filter #(= (:type %) :group))
|
||||
(map #(:id %))
|
||||
|
@ -405,7 +406,7 @@
|
|||
(update [_ state]
|
||||
(let [page-id (get-in state [:workspace-page :id])
|
||||
objects (get-in state [:workspace-data page-id :objects])
|
||||
shapes (cp/select-toplevel-shapes objects {:include-frames? true})
|
||||
shapes (cph/select-toplevel-shapes objects {:include-frames? true})
|
||||
srect (geom/selection-rect shapes)]
|
||||
|
||||
(if (or (mth/nan? (:width srect))
|
||||
|
@ -481,7 +482,7 @@
|
|||
unames (retrieve-used-names objects)
|
||||
name (generate-unique-name unames (:name shape))
|
||||
|
||||
frames (cp/select-frames objects)
|
||||
frames (cph/select-frames objects)
|
||||
|
||||
frame-id (if (= :frame (:type shape))
|
||||
uuid/zero
|
||||
|
@ -578,7 +579,7 @@
|
|||
grouped #{:frame :group}]
|
||||
(update-in state [:workspace-data page-id :objects]
|
||||
(fn [objects]
|
||||
(->> (d/concat [id] (cp/get-children id objects))
|
||||
(->> (d/concat [id] (cph/get-children id objects))
|
||||
(map #(get objects %))
|
||||
(remove #(grouped (:type %)))
|
||||
(reduce #(update %1 (:id %2) update-shape) objects)))))))))
|
||||
|
@ -647,6 +648,7 @@
|
|||
:right (gpt/point 1 0)))
|
||||
|
||||
;; --- Delete Selected
|
||||
|
||||
(defn- delete-shapes
|
||||
[ids]
|
||||
(us/assert (s/coll-of ::us/uuid) ids)
|
||||
|
@ -655,38 +657,57 @@
|
|||
(watch [_ state stream]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (get-in state [:workspace-data page-id :objects])
|
||||
cpindex (cp/calculate-child-parent-map objects)
|
||||
|
||||
del-change #(array-map :type :del-obj :id %)
|
||||
reg-change #(array-map :type :reg-obj :id %)
|
||||
|
||||
get-empty-parents
|
||||
(fn get-empty-parents [id]
|
||||
(let [parent (get objects (get cpindex id))]
|
||||
(if (and (= :group (:type parent))
|
||||
(= 1 (count (:shapes parent))))
|
||||
(lazy-seq (cons (:id parent)
|
||||
(get-empty-parents (:id parent))))
|
||||
nil)))
|
||||
(fn get-empty-parents [parents]
|
||||
(->> parents
|
||||
(map (fn [id]
|
||||
(let [obj (get objects id)]
|
||||
(when (and (= :group (:type obj))
|
||||
(= 1 (count (:shapes obj))))
|
||||
obj))))
|
||||
(take-while (complement nil?))
|
||||
(map :id)))
|
||||
|
||||
rchanges
|
||||
(reduce (fn [res id]
|
||||
(let [chd (cp/get-children id objects)]
|
||||
(into res (d/concat
|
||||
(mapv del-change (reverse chd))
|
||||
[(del-change id)]
|
||||
(map del-change (get-empty-parents id))))))
|
||||
(let [children (cph/get-children id objects)
|
||||
parents (cph/get-parents id objects)]
|
||||
(d/concat res
|
||||
(map del-change (reverse children))
|
||||
[(del-change id)]
|
||||
(map del-change (get-empty-parents parents))
|
||||
[{:type :reg-obj :ids parents}])))
|
||||
[]
|
||||
ids)
|
||||
|
||||
uchanges
|
||||
(mapv (fn [id]
|
||||
(let [obj (get objects id)]
|
||||
{:type :add-obj
|
||||
:id id
|
||||
:frame-id (:frame-id obj)
|
||||
:parent-id (get cpindex id)
|
||||
:obj obj}))
|
||||
(reverse (map :id rchanges)))]
|
||||
(reduce (fn [res id]
|
||||
(let [children (cph/get-children id objects)
|
||||
parents (cph/get-parents id objects)
|
||||
add-chg (fn [id]
|
||||
(let [item (get objects id)]
|
||||
{:type :add-obj
|
||||
:id (:id item)
|
||||
:frame-id (:frame-id item)
|
||||
:parent-id (:parent-id item)
|
||||
:obj item}))]
|
||||
(d/concat res
|
||||
(map add-chg (reverse (get-empty-parents parents)))
|
||||
[(add-chg id)]
|
||||
(map add-chg children)
|
||||
[{:type :reg-obj :ids parents}])))
|
||||
[]
|
||||
ids)
|
||||
]
|
||||
|
||||
;; (println "================ rchanges")
|
||||
;; (cljs.pprint/pprint rchanges)
|
||||
;; (println "================ uchanges")
|
||||
;; (cljs.pprint/pprint uchanges)
|
||||
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true}))))))
|
||||
|
||||
(def delete-selected
|
||||
|
@ -764,7 +785,7 @@
|
|||
(watch [_ state stream]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (get-in state [:workspace-data page-id :objects])
|
||||
parent (get objects (cp/get-parent id objects))
|
||||
parent (get objects (cph/get-parent id objects))
|
||||
current-index (d/index-of (:shapes parent) id)
|
||||
selected (get-in state [:workspace-local :selected])]
|
||||
(rx/of (dwc/commit-changes [{:type :mov-objects
|
||||
|
@ -992,7 +1013,7 @@
|
|||
(update [_ state]
|
||||
(let [page-id (get-in state [:workspace-page :id])
|
||||
objects (get-in state [:workspace-data page-id :objects])
|
||||
childs (cp/get-children id objects)]
|
||||
childs (cph/get-children id objects)]
|
||||
(update-in state [:workspace-data page-id :objects]
|
||||
(fn [objects]
|
||||
(reduce (fn [objects id]
|
||||
|
@ -1215,7 +1236,6 @@
|
|||
(when (not-empty selected)
|
||||
(let [page-id (get-in state [:workspace-page :id])
|
||||
objects (get-in state [:workspace-data page-id :objects])
|
||||
|
||||
selected-objects (map (partial get objects) selected)
|
||||
selrect (geom/selection-rect selected-objects)
|
||||
frame-id (-> selected-objects first :frame-id)
|
||||
|
@ -1226,7 +1246,6 @@
|
|||
(map-indexed vector)
|
||||
(filter #(selected (second %)))
|
||||
(ffirst))
|
||||
|
||||
rchanges [{:type :add-obj
|
||||
:id id
|
||||
:frame-id frame-id
|
||||
|
@ -1255,7 +1274,7 @@
|
|||
(when (and (= 1 (count selected))
|
||||
(= (:type group) :group))
|
||||
(let [shapes (:shapes group)
|
||||
parent-id (cp/get-parent group-id objects)
|
||||
parent-id (cph/get-parent group-id objects)
|
||||
parent (get objects parent-id)
|
||||
index-in-parent (->> (:shapes parent)
|
||||
(map-indexed vector)
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
[potok.core :as ptk]
|
||||
[uxbox.common.data :as d]
|
||||
[uxbox.common.pages :as cp]
|
||||
[uxbox.common.pages-helpers :as cph]
|
||||
[uxbox.common.spec :as us]
|
||||
[uxbox.common.uuid :as uuid]
|
||||
[uxbox.main.worker :as uw]
|
||||
|
@ -202,8 +203,8 @@
|
|||
(let [page-id (get-in state [:workspace-page :id])
|
||||
objects (get-in state [:workspace-data page-id :objects])
|
||||
|
||||
shapes (cp/select-toplevel-shapes objects)
|
||||
frames (cp/select-frames objects)
|
||||
shapes (cph/select-toplevel-shapes objects)
|
||||
frames (cph/select-frames objects)
|
||||
|
||||
[rch uch] (calculate-shape-to-frame-relationship-changes frames shapes)]
|
||||
(when-not (empty? rch)
|
||||
|
@ -212,7 +213,7 @@
|
|||
|
||||
(defn get-frame-at-point
|
||||
[objects point]
|
||||
(let [frames (cp/select-frames objects)]
|
||||
(let [frames (cph/select-frames objects)]
|
||||
(loop [frame (first frames)
|
||||
rest (rest frames)]
|
||||
(d/seek #(geom/has-point? % point) frames))))
|
||||
|
@ -306,7 +307,7 @@
|
|||
(let [expand-fn (fn [expanded]
|
||||
(merge expanded
|
||||
(->> ids
|
||||
(map #(cp/get-all-parents % objects))
|
||||
(map #(cph/get-parents % objects))
|
||||
flatten
|
||||
(filter #(not= % uuid/zero))
|
||||
(map (fn [id] {id true}))
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
[uxbox.common.geom.shapes :as geom]
|
||||
[uxbox.common.geom.point :as gpt]
|
||||
[uxbox.common.pages :as cp]
|
||||
[uxbox.common.pages-helpers :as cph]
|
||||
[uxbox.util.geom.path :as path]
|
||||
[uxbox.main.snap :as snap]
|
||||
[uxbox.main.streams :as ms]
|
||||
|
@ -95,7 +96,7 @@
|
|||
objects (get-in state [:workspace-data page-id :objects])
|
||||
layout (get state :workspace-layout)
|
||||
|
||||
frames (cp/select-frames objects)
|
||||
frames (cph/select-frames objects)
|
||||
fid (or (->> frames
|
||||
(filter #(geom/has-point? % initial))
|
||||
first
|
||||
|
|
|
@ -12,16 +12,17 @@
|
|||
[beicon.core :as rx]
|
||||
[cljs.spec.alpha :as s]
|
||||
[potok.core :as ptk]
|
||||
[uxbox.main.data.workspace.common :as dwc]
|
||||
[uxbox.main.worker :as uw]
|
||||
[uxbox.main.streams :as ms]
|
||||
[uxbox.common.data :as d]
|
||||
[uxbox.common.geom.point :as gpt]
|
||||
[uxbox.common.geom.shapes :as geom]
|
||||
[uxbox.common.math :as mth]
|
||||
[uxbox.common.pages :as cp]
|
||||
[uxbox.common.pages-helpers :as cph]
|
||||
[uxbox.common.spec :as us]
|
||||
[uxbox.common.uuid :as uuid]
|
||||
[uxbox.common.data :as d]
|
||||
[uxbox.common.geom.shapes :as geom]
|
||||
[uxbox.common.geom.point :as gpt]
|
||||
[uxbox.common.math :as mth]))
|
||||
[uxbox.main.data.workspace.common :as dwc]
|
||||
[uxbox.main.streams :as ms]
|
||||
[uxbox.main.worker :as uw]))
|
||||
|
||||
(s/def ::set-of-uuid
|
||||
(s/every uuid? :kind set?))
|
||||
|
@ -220,7 +221,7 @@
|
|||
name (generate-unique-name names (:name obj))
|
||||
renamed-obj (assoc obj :id id :name name)
|
||||
moved-obj (geom/move renamed-obj delta)
|
||||
frames (cp/select-frames objects)
|
||||
frames (cph/select-frames objects)
|
||||
frame-id (if frame-id
|
||||
frame-id
|
||||
(dwc/calculate-frame-overlap frames moved-obj))
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
[uxbox.common.data :as d]
|
||||
[uxbox.common.spec :as us]
|
||||
[uxbox.common.pages :as cp]
|
||||
[uxbox.common.pages-helpers :as cph]
|
||||
[uxbox.main.data.workspace.common :as dwc]
|
||||
[uxbox.main.data.workspace.selection :as dws]
|
||||
[uxbox.main.refs :as refs]
|
||||
|
@ -346,7 +347,7 @@
|
|||
(or recurse-frames? (not (= :frame (:type shape))))))
|
||||
|
||||
;; ID's + Children but remove frame children if the flag is set to false
|
||||
ids-with-children (concat ids (mapcat #(cp/get-children % objects)
|
||||
ids-with-children (concat ids (mapcat #(cph/get-children % objects)
|
||||
(filter not-frame-id? ids)))
|
||||
|
||||
;; For each shape updates the modifiers given as arguments
|
||||
|
@ -391,7 +392,7 @@
|
|||
|
||||
(let [objects (get-in state [:workspace-data page-id :objects])
|
||||
id->obj #(get objects %)
|
||||
get-children (fn [shape] (map id->obj (cp/get-children (:id shape) objects)))
|
||||
get-children (fn [shape] (map id->obj (cph/get-children (:id shape) objects)))
|
||||
shapes (concat shapes (mapcat get-children shapes))]
|
||||
(rotate-around-center state delta-rotation center shapes))))))))
|
||||
|
||||
|
@ -408,7 +409,7 @@
|
|||
objects (get-in state [:workspace-data page-id :objects])
|
||||
|
||||
;; ID's + Children
|
||||
ids-with-children (concat ids (mapcat #(cp/get-children % objects) ids))
|
||||
ids-with-children (concat ids (mapcat #(cph/get-children % objects) ids))
|
||||
|
||||
;; For each shape applies the modifiers by transforming the objects
|
||||
update-shape
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
[rumext.alpha :as mf]
|
||||
[uxbox.common.uuid :as uuid]
|
||||
[uxbox.common.pages :as cp]
|
||||
[uxbox.common.pages-helpers :as cph]
|
||||
[uxbox.common.math :as mth]
|
||||
[uxbox.common.geom.shapes :as geom]
|
||||
[uxbox.common.geom.point :as gpt]
|
||||
|
@ -39,7 +40,7 @@
|
|||
|
||||
(defn- calculate-dimensions
|
||||
[{:keys [objects] :as data} vport]
|
||||
(let [shapes (cp/select-toplevel-shapes objects {:include-frames? true})]
|
||||
(let [shapes (cph/select-toplevel-shapes objects {:include-frames? true})]
|
||||
(->> (geom/selection-rect shapes)
|
||||
(geom/adjust-to-viewport vport)
|
||||
(geom/fix-invalid-rect-values))))
|
||||
|
@ -132,7 +133,7 @@
|
|||
|
||||
frame-id (:id frame)
|
||||
|
||||
modifier-ids (concat [frame-id] (cp/get-children frame-id objects))
|
||||
modifier-ids (concat [frame-id] (cph/get-children frame-id objects))
|
||||
update-fn #(assoc-in %1 [%2 :modifiers :displacement] modifier)
|
||||
objects (reduce update-fn objects modifier-ids)
|
||||
frame (assoc-in frame [:modifiers :displacement] modifier)
|
||||
|
|
|
@ -10,12 +10,13 @@
|
|||
(ns uxbox.main.refs
|
||||
"A collection of derived refs."
|
||||
(:require
|
||||
[okulary.core :as l]
|
||||
[beicon.core :as rx]
|
||||
[okulary.core :as l]
|
||||
[uxbox.common.pages :as cp]
|
||||
[uxbox.common.pages-helpers :as cph]
|
||||
[uxbox.common.uuid :as uuid]
|
||||
[uxbox.main.constants :as c]
|
||||
[uxbox.main.store :as st]
|
||||
[uxbox.common.uuid :as uuid]))
|
||||
[uxbox.main.store :as st]))
|
||||
|
||||
;; ---- Global refs
|
||||
|
||||
|
@ -78,7 +79,7 @@
|
|||
(l/derived :objects workspace-data))
|
||||
|
||||
(def workspace-frames
|
||||
(l/derived cp/select-frames workspace-objects))
|
||||
(l/derived cph/select-frames workspace-objects))
|
||||
|
||||
(defn object-by-id
|
||||
[id]
|
||||
|
@ -106,7 +107,7 @@
|
|||
objects (get-in state [:workspace-data page-id :objects])
|
||||
selected (get-in state [:workspace-local :selected])
|
||||
shape (get objects id)
|
||||
children (cp/get-children id objects)]
|
||||
children (cph/get-children id objects)]
|
||||
(some selected children)))]
|
||||
(l/derived selector st/state)))
|
||||
|
||||
|
@ -118,7 +119,7 @@
|
|||
(let [selected (get-in state [:workspace-local :selected])
|
||||
page-id (get-in state [:workspace-page :id])
|
||||
objects (get-in state [:workspace-data page-id :objects])
|
||||
children (mapcat #(cp/get-children % objects) selected)]
|
||||
children (mapcat #(cph/get-children % objects) selected)]
|
||||
(into selected children)))]
|
||||
(l/derived selector st/state)))
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
[rumext.alpha :as mf]
|
||||
[uxbox.common.data :as d]
|
||||
[uxbox.common.pages :as cp]
|
||||
[uxbox.common.pages-helpers :as cph]
|
||||
[uxbox.main.data.viewer :as dv]
|
||||
[uxbox.main.refs :as refs]
|
||||
[uxbox.main.store :as st]
|
||||
|
@ -174,7 +175,7 @@
|
|||
update-fn #(assoc-in %1 [%2 :modifiers :displacement] modifier)
|
||||
|
||||
frame-id (:id frame)
|
||||
modifier-ids (d/concat [frame-id] (cp/get-children frame-id objects))
|
||||
modifier-ids (d/concat [frame-id] (cph/get-children frame-id objects))
|
||||
objects (reduce update-fn objects modifier-ids)
|
||||
frame (assoc-in frame [:modifiers :displacement] modifier)
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
[uxbox.common.data :as d]
|
||||
[uxbox.common.uuid :as uuid]
|
||||
[uxbox.common.pages :as cp]
|
||||
[uxbox.common.pages-helpers :as cph]
|
||||
[uxbox.main.data.workspace :as dw]
|
||||
[uxbox.main.refs :as refs]
|
||||
[uxbox.main.store :as st]
|
||||
|
@ -154,7 +155,7 @@
|
|||
(if (= side :center)
|
||||
(st/emit! (dw/relocate-shape id (:id item) 0))
|
||||
(let [to-index (if (= side :top) (inc index) index)
|
||||
parent-id (cp/get-parent (:id item) objects)]
|
||||
parent-id (cph/get-parent (:id item) objects)]
|
||||
(st/emit! (dw/relocate-shape id parent-id to-index)))))
|
||||
|
||||
on-hold
|
||||
|
@ -223,7 +224,7 @@
|
|||
old-obs (unchecked-get oprops "objects")]
|
||||
(and (= new-itm old-itm)
|
||||
(identical? new-idx old-idx)
|
||||
(let [childs (cp/get-children (:id new-itm) new-obs)
|
||||
(let [childs (cph/get-children (:id new-itm) new-obs)
|
||||
childs' (conj childs (:id new-itm))]
|
||||
(and (or (= new-sel old-sel)
|
||||
(not (or (boolean (some new-sel childs'))
|
||||
|
@ -273,7 +274,7 @@
|
|||
|
||||
(defn- strip-objects
|
||||
[objects]
|
||||
(let [strip-data #(select-keys % [:id :name :blocked :hidden :shapes :type :content :metadata])]
|
||||
(let [strip-data #(select-keys % [:id :name :blocked :hidden :shapes :type :content :parent-id :metadata])]
|
||||
(persistent!
|
||||
(reduce-kv (fn [res id obj]
|
||||
(assoc! res id (strip-data obj)))
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
(:require
|
||||
[rumext.alpha :as mf]
|
||||
[uxbox.main.ui.icons :as i]
|
||||
[uxbox.common.pages :as cp]
|
||||
[uxbox.common.pages-helpers :as cph]
|
||||
[uxbox.main.data.workspace :as dw]
|
||||
[uxbox.main.refs :as refs]
|
||||
[uxbox.main.store :as st]
|
||||
|
@ -31,7 +31,7 @@
|
|||
|
||||
destination (get objects (:destination interaction))
|
||||
frames (mf/use-memo (mf/deps objects)
|
||||
#(cp/select-frames objects))
|
||||
#(cph/select-frames objects))
|
||||
|
||||
show-frames-dropdown? (mf/use-state false)
|
||||
|
||||
|
|
|
@ -12,12 +12,13 @@
|
|||
[cljs.spec.alpha :as s]
|
||||
[okulary.core :as l]
|
||||
[uxbox.common.exceptions :as ex]
|
||||
[uxbox.common.spec :as us]
|
||||
[uxbox.common.pages :as cp]
|
||||
[uxbox.common.uuid :as uuid]
|
||||
[uxbox.worker.impl :as impl]
|
||||
[uxbox.common.geom.shapes :as geom]
|
||||
[uxbox.util.quadtree :as qdt]))
|
||||
[uxbox.common.pages :as cp]
|
||||
[uxbox.common.pages-helpers :as cph]
|
||||
[uxbox.common.spec :as us]
|
||||
[uxbox.common.uuid :as uuid]
|
||||
[uxbox.util.quadtree :as qdt]
|
||||
[uxbox.worker.impl :as impl]))
|
||||
|
||||
(defonce state (l/atom {}))
|
||||
|
||||
|
@ -63,7 +64,7 @@
|
|||
|
||||
(defn- create-index
|
||||
[objects]
|
||||
(let [shapes (->> (cp/select-toplevel-shapes objects {:include-frames? true})
|
||||
(let [shapes (->> (cph/select-toplevel-shapes objects {:include-frames? true})
|
||||
(map #(merge % (select-keys % [:x :y :width :height]))))
|
||||
bounds (geom/selection-rect shapes)
|
||||
bounds #js {:x (:x bounds)
|
||||
|
|
|
@ -12,7 +12,8 @@
|
|||
[okulary.core :as l]
|
||||
[uxbox.common.uuid :as uuid]
|
||||
[uxbox.common.pages :as cp]
|
||||
[uxbox.common.data :as d]
|
||||
[uxbox.common.pages-helpers :as cph]
|
||||
[uxbox.common.data :as d]
|
||||
[uxbox.worker.impl :as impl]
|
||||
[uxbox.util.range-tree :as rt]
|
||||
[uxbox.util.geom.snap-points :as snap]
|
||||
|
@ -45,7 +46,7 @@
|
|||
(let [frame-shapes (->> (vals objects)
|
||||
(filter :frame-id)
|
||||
(group-by :frame-id))
|
||||
frame-shapes (->> (cp/select-frames objects)
|
||||
frame-shapes (->> (cph/select-frames objects)
|
||||
(reduce #(update %1 (:id %2) conj %2) frame-shapes))]
|
||||
(d/mapm (fn [frame-id shapes] {:x (create-coord-data frame-id shapes :x)
|
||||
:y (create-coord-data frame-id shapes :y)})
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue