Merge remote-tracking branch 'origin/staging' into develop

This commit is contained in:
alonso.torres 2021-05-25 14:01:42 +02:00
commit a9e8115088
24 changed files with 274 additions and 148 deletions

View file

@ -30,7 +30,12 @@
- Remove interactions when the destination artboard is deleted [Taiga #1656](https://tree.taiga.io/project/penpot/issue/1656). - Remove interactions when the destination artboard is deleted [Taiga #1656](https://tree.taiga.io/project/penpot/issue/1656).
- Fix problem with fonts that ends with numbers [#940](https://github.com/penpot/penpot/issues/940). - Fix problem with fonts that ends with numbers [#940](https://github.com/penpot/penpot/issues/940).
- Fix problem with imported SVG on editing paths [#971](https://github.com/penpot/penpot/issues/971)
- Fix problem with color picker positioning
- Fix order on color palette [#961](https://github.com/penpot/penpot/issues/961)
- Fix issue when group creation leaves an empty group [#1724](https://tree.taiga.io/project/penpot/issue/1724)
- Fix problem with :multiple for colors and typographies [#1668](https://tree.taiga.io/project/penpot/issue/1668)
- Fix problem with locked shapes when change parents [#974](https://github.com/penpot/penpot/issues/974)
### :arrow_up: Deps updates ### :arrow_up: Deps updates

View file

@ -323,7 +323,8 @@
:has-media-trimmed false} :has-media-trimmed false}
{:id (:id file)}) {:id (:id file)})
(let [params (assoc params :file file)] (let [params (-> params (assoc :file file
:changes changes))]
;; Send asynchronous notifications ;; Send asynchronous notifications
(send-notifications cfg params) (send-notifications cfg params)

View file

@ -162,7 +162,7 @@
:points points)))) :points points))))
(defn rotation-modifiers (defn rotation-modifiers
[center shape angle] [shape center angle]
(let [displacement (let [shape-center (gco/center-shape shape)] (let [displacement (let [shape-center (gco/center-shape shape)]
(-> (gmt/matrix) (-> (gmt/matrix)
(gmt/rotate angle center) (gmt/rotate angle center)

View file

@ -134,8 +134,8 @@
width: 100%; width: 100%;
display: grid; display: grid;
grid-template-rows: 20px 1fr; grid-template-rows: 20px 100%;
grid-template-columns: 20px 1fr; grid-template-columns: 20px 100%;
} }
.viewport { .viewport {
@ -145,6 +145,11 @@
overflow: hidden; overflow: hidden;
position: relative; position: relative;
svg {
widht: 100%;
height: 100%;
}
.viewport-overlays { .viewport-overlays {
position: absolute; position: absolute;
width: 100%; width: 100%;

View file

@ -991,7 +991,8 @@
[[] [] []] [[] [] []]
ids) ids)
[rchanges uchanges] (relocate-shapes-changes objects [rchanges uchanges]
(relocate-shapes-changes objects
parents parents
parent-id parent-id
page-id page-id
@ -1001,9 +1002,11 @@
groups-to-unmask groups-to-unmask
shapes-to-detach shapes-to-detach
shapes-to-reroot shapes-to-reroot
shapes-to-deroot)] shapes-to-deroot)
]
(rx/of (dch/commit-changes {:redo-changes rchanges (rx/of (dch/commit-changes {:redo-changes rchanges
:undo-chanes uchanges :undo-changes uchanges
:origin it}) :origin it})
(dwc/expand-collapse parent-id)))))) (dwc/expand-collapse parent-id))))))
@ -1058,7 +1061,7 @@
:id id :id id
:index cidx}] :index cidx}]
(rx/of (dch/commit-changes {:redo-changes [rchg] (rx/of (dch/commit-changes {:redo-changes [rchg]
:undo-chanes [uchg] :undo-changes [uchg]
:origin it})))))) :origin it}))))))
;; --- Shape / Selection Alignment and Distribution ;; --- Shape / Selection Alignment and Distribution

View file

@ -32,31 +32,97 @@
(gsh/setup selrect) (gsh/setup selrect)
(assoc :shapes (mapv :id shapes))))) (assoc :shapes (mapv :id shapes)))))
(defn get-empty-groups
"Retrieve emtpy groups after group creation"
[objects parent-id shapes]
(let [ids (cp/clean-loops objects (into #{} (map :id) shapes))
parents (->> ids
(reduce #(conj %1 (cp/get-parent %2 objects))
#{}))]
(loop [current-id (first parents)
to-check (rest parents)
removed-id? ids
result #{}]
(if-not current-id
;; Base case, no next element
result
(let [group (get objects current-id)]
(if (and (not= :frame (:type group))
(not= current-id parent-id)
(empty? (remove removed-id? (:shapes group))))
;; Adds group to the remove and check its parent
(let [to-check (d/concat [] to-check [(cp/get-parent current-id objects)]) ]
(recur (first to-check)
(rest to-check)
(conj removed-id? current-id)
(conj result current-id)))
;; otherwise recur
(recur (first to-check)
(rest to-check)
removed-id?
result)))))))
(defn prepare-create-group (defn prepare-create-group
[page-id shapes prefix keep-name] [objects page-id shapes prefix keep-name]
(let [group (make-group shapes prefix keep-name) (let [group (make-group shapes prefix keep-name)
frame-id (:frame-id (first shapes))
parent-id (:parent-id (first shapes))
rchanges [{:type :add-obj rchanges [{:type :add-obj
:id (:id group) :id (:id group)
:page-id page-id :page-id page-id
:frame-id (:frame-id (first shapes)) :frame-id frame-id
:parent-id (:parent-id (first shapes)) :parent-id parent-id
:obj group :obj group
:index (::index (first shapes))} :index (::index (first shapes))}
{:type :mov-objects {:type :mov-objects
:page-id page-id :page-id page-id
:parent-id (:id group) :parent-id (:id group)
:shapes (mapv :id shapes)}] :shapes (mapv :id shapes)}]
uchanges (conj uchanges (-> (mapv
(mapv (fn [obj] {:type :mov-objects (fn [obj]
{:type :mov-objects
:page-id page-id :page-id page-id
:parent-id (:parent-id obj) :parent-id (:parent-id obj)
:index (::index obj) :index (::index obj)
:shapes [(:id obj)]}) :shapes [(:id obj)]}) shapes)
shapes) (conj
{:type :del-obj {:type :del-obj
:id (:id group) :id (:id group)
:page-id page-id})] :page-id page-id}))
ids-to-delete (get-empty-groups objects parent-id shapes)
delete-group
(fn [changes id]
(-> changes
(conj {:type :del-obj
:id id
:page-id page-id})))
add-deleted-group
(fn [changes id]
(let [obj (-> (get objects id)
(d/without-keys [:shapes]))]
(d/concat [{:type :add-obj
:id id
:page-id page-id
:frame-id (:frame-id obj)
:parent-id (:parent-id obj)
:obj obj
:index (::index obj)}] changes)))
rchanges (->> ids-to-delete
(reduce delete-group rchanges))
uchanges (->> ids-to-delete
(reduce add-deleted-group uchanges))]
[group rchanges uchanges])) [group rchanges uchanges]))
(defn prepare-remove-group (defn prepare-remove-group
@ -107,7 +173,8 @@
selected (cp/clean-loops objects selected) selected (cp/clean-loops objects selected)
shapes (shapes-for-grouping objects selected)] shapes (shapes-for-grouping objects selected)]
(when-not (empty? shapes) (when-not (empty? shapes)
(let [[group rchanges uchanges] (prepare-create-group page-id shapes "Group-" false)] (let [[group rchanges uchanges]
(prepare-create-group objects page-id shapes "Group-" false)]
(rx/of (dch/commit-changes {:redo-changes rchanges (rx/of (dch/commit-changes {:redo-changes rchanges
:undo-changes uchanges :undo-changes uchanges
:origin it}) :origin it})
@ -146,7 +213,7 @@
(if (and (= (count shapes) 1) (if (and (= (count shapes) 1)
(= (:type (first shapes)) :group)) (= (:type (first shapes)) :group))
[(first shapes) [] []] [(first shapes) [] []]
(prepare-create-group page-id shapes "Group-" true)) (prepare-create-group objects page-id shapes "Group-" true))
rchanges (d/concat rchanges rchanges (d/concat rchanges
[{:type :mod-obj [{:type :mod-obj

View file

@ -131,7 +131,7 @@
(if (and (= (count shapes) 1) (if (and (= (count shapes) 1)
(= (:type (first shapes)) :group)) (= (:type (first shapes)) :group))
[(first shapes) [] []] [(first shapes) [] []]
(dwg/prepare-create-group page-id shapes "Component-" true)) (dwg/prepare-create-group objects page-id shapes "Component-" true))
[new-shape new-shapes updated-shapes] [new-shape new-shapes updated-shapes]
(make-component-shape group objects file-id) (make-component-shape group objects file-id)

View file

@ -562,7 +562,7 @@
(defn- extract-frame-changes (defn- extract-frame-changes
"Process a changes set in a commit to extract the frames that are channging" "Process a changes set in a commit to extract the frames that are channging"
[[event objects]] [[event [old-objects new-objects]]]
(let [changes (-> event deref :changes) (let [changes (-> event deref :changes)
extract-ids extract-ids
@ -577,8 +577,11 @@
get-frame-id get-frame-id
(fn [id] (fn [id]
(or (and (= :frame (get-in objects [id :type])) id) (let [shape (or (get new-objects id)
(get-in objects [id :frame-id]))) (get old-objects id))]
(or (and (= :frame (:type shape)) id)
(:frame-id shape))))
;; Extracts the frames and then removes nils and the root frame ;; Extracts the frames and then removes nils and the root frame
xform (comp (mapcat extract-ids) xform (comp (mapcat extract-ids)
@ -613,7 +616,12 @@
(rx/filter #(or (= :app.main.data.workspace/finalize-page (ptk/type %)) (rx/filter #(or (= :app.main.data.workspace/finalize-page (ptk/type %))
(= ::watch-state-changes (ptk/type %))))) (= ::watch-state-changes (ptk/type %)))))
objects-stream (rx/from-atom refs/workspace-page-objects {:emit-current-value? true}) objects-stream (->> (rx/concat
(rx/of nil)
(rx/from-atom refs/workspace-page-objects {:emit-current-value? true}))
;; We need to keep the old-objects so we can check the frame for the
;; deleted objects
(rx/buffer 2 1))
frame-changes (->> stream frame-changes (->> stream
(rx/filter dch/commit-changes?) (rx/filter dch/commit-changes?)

View file

@ -26,11 +26,18 @@
(get-in state [:workspace-data :components component-id :objects]))) (get-in state [:workspace-data :components component-id :objects])))
(defn lookup-selected (defn lookup-selected
[state] ([state]
(lookup-selected state nil))
([state {:keys [omit-blocked?]
:or {omit-blocked? false}}]
(let [objects (lookup-page-objects state) (let [objects (lookup-page-objects state)
selected (->> (get-in state [:workspace-local :selected]) selected (->> (get-in state [:workspace-local :selected])
(cp/clean-loops objects)) (cp/clean-loops objects))
is-present? (fn [id] (contains? objects id))] selectable? (fn [id]
(and (contains? objects id)
(or (not omit-blocked?)
(not (get-in objects [id :blocked] false)))))]
(into (d/ordered-set) (into (d/ordered-set)
(filter is-present?) (filter selectable?)
selected))) selected))))

View file

@ -242,8 +242,9 @@
ptk/WatchEvent ptk/WatchEvent
(watch [it state stream] (watch [it state stream]
(let [initial (deref ms/mouse-position) (let [initial (deref ms/mouse-position)
selected (wsh/lookup-selected state) selected (wsh/lookup-selected state {:omit-blocked? true})
stopper (rx/filter ms/mouse-up? stream)] stopper (rx/filter ms/mouse-up? stream)]
(when-not (empty? selected)
(->> ms/mouse-position (->> ms/mouse-position
(rx/take-until stopper) (rx/take-until stopper)
(rx/map #(gpt/to-vec initial %)) (rx/map #(gpt/to-vec initial %))
@ -258,7 +259,7 @@
(rx/of (start-move-duplicate initial) (rx/of (start-move-duplicate initial)
dws/duplicate-selected) dws/duplicate-selected)
;; Otherwise just plain old move ;; Otherwise just plain old move
(rx/of (start-move initial selected)))))))))) (rx/of (start-move initial selected)))))))))))
(defn start-move-duplicate [from-position] (defn start-move-duplicate [from-position]
(ptk/reify ::start-move-selected (ptk/reify ::start-move-selected
@ -319,7 +320,8 @@
(watch [it state stream] (watch [it state stream]
(let [page-id (:current-page-id state) (let [page-id (:current-page-id state)
objects (wsh/lookup-page-objects state page-id) objects (wsh/lookup-page-objects state page-id)
ids (if (nil? ids) (wsh/lookup-selected state) ids) selected (wsh/lookup-selected state {:omit-blocked? true})
ids (if (nil? ids) selected ids)
shapes (mapv #(get objects %) ids) shapes (mapv #(get objects %) ids)
stopper (rx/filter ms/mouse-up? stream) stopper (rx/filter ms/mouse-up? stream)
layout (get state :workspace-layout) layout (get state :workspace-layout)
@ -398,7 +400,7 @@
ptk/WatchEvent ptk/WatchEvent
(watch [it state stream] (watch [it state stream]
(if (= same-event (get-in state [:workspace-local :current-move-selected])) (if (= same-event (get-in state [:workspace-local :current-move-selected]))
(let [selected (wsh/lookup-selected state) (let [selected (wsh/lookup-selected state {:omit-blocked? true})
move-events (->> stream move-events (->> stream
(rx/filter (ptk/type? ::move-selected)) (rx/filter (ptk/type? ::move-selected))
(rx/filter #(= direction (deref %)))) (rx/filter #(= direction (deref %))))
@ -435,6 +437,8 @@
page-id (:current-page-id state) page-id (:current-page-id state)
objects (wsh/lookup-page-objects state page-id) objects (wsh/lookup-page-objects state page-id)
ids (->> ids (into #{} (remove #(get-in objects [% :blocked] false))))
not-frame-id? not-frame-id?
(fn [shape-id] (fn [shape-id]
(let [shape (get objects shape-id)] (let [shape (get objects shape-id)]
@ -457,27 +461,28 @@
;; shape adjusting their position. ;; shape adjusting their position.
(defn set-rotation (defn set-rotation
([delta-rotation shapes] ([angle shapes]
(set-rotation delta-rotation shapes (-> shapes gsh/selection-rect gsh/center-selrect))) (set-rotation angle shapes (-> shapes gsh/selection-rect gsh/center-selrect)))
([delta-rotation shapes center]
(letfn [(rotate-shape [objects angle shape center]
(update-in objects [(:id shape) :modifiers] merge (gsh/rotation-modifiers center shape angle)))
(rotate-around-center [objects angle center shapes]
(reduce #(rotate-shape %1 angle %2 center) objects shapes))
(set-rotation [objects]
(let [id->obj #(get objects %)
get-children (fn [shape] (map id->obj (cp/get-children (:id shape) objects)))
shapes (concat shapes (mapcat get-children shapes))]
(rotate-around-center objects delta-rotation center shapes)))]
([angle shapes center]
(ptk/reify ::set-rotation (ptk/reify ::set-rotation
ptk/UpdateEvent ptk/UpdateEvent
(update [_ state] (update [_ state]
(let [page-id (:current-page-id state)] (let [objects (wsh/lookup-page-objects state)
(d/update-in-when state [:workspace-data :pages-index page-id :objects] set-rotation))))))) id->obj #(get objects %)
get-children (fn [shape] (map id->obj (cp/get-children (:id shape) objects)))
shapes (->> shapes (into [] (remove #(get % :blocked false))))
shapes (->> shapes (mapcat get-children) (concat shapes))
update-shape
(fn [modifiers shape]
(let [rotate-modifiers (gsh/rotation-modifiers shape center angle)]
(assoc-in modifiers [(:id shape) :modifiers] rotate-modifiers)))]
(-> state
(update :workspace-modifiers
#(reduce update-shape % shapes))))))))
(defn increase-rotation [ids rotation] (defn increase-rotation [ids rotation]
(ptk/reify ::increase-rotation (ptk/reify ::increase-rotation
@ -583,7 +588,7 @@
ptk/WatchEvent ptk/WatchEvent
(watch [it state stream] (watch [it state stream]
(let [objects (wsh/lookup-page-objects state) (let [objects (wsh/lookup-page-objects state)
selected (wsh/lookup-selected state) selected (wsh/lookup-selected state {:omit-blocked? true})
shapes (map #(get objects %) selected) shapes (map #(get objects %) selected)
selrect (gsh/selection-rect (->> shapes (map gsh/transform-shape))) selrect (gsh/selection-rect (->> shapes (map gsh/transform-shape)))
origin (gpt/point (:x selrect) (+ (:y selrect) (/ (:height selrect) 2)))] origin (gpt/point (:x selrect) (+ (:y selrect) (/ (:height selrect) 2)))]
@ -600,7 +605,7 @@
ptk/WatchEvent ptk/WatchEvent
(watch [it state stream] (watch [it state stream]
(let [objects (wsh/lookup-page-objects state) (let [objects (wsh/lookup-page-objects state)
selected (wsh/lookup-selected state) selected (wsh/lookup-selected state {:omit-blocked? true})
shapes (map #(get objects %) selected) shapes (map #(get objects %) selected)
selrect (gsh/selection-rect (->> shapes (map gsh/transform-shape))) selrect (gsh/selection-rect (->> shapes (map gsh/transform-shape)))
origin (gpt/point (+ (:x selrect) (/ (:width selrect) 2)) (:y selrect))] origin (gpt/point (+ (:x selrect) (/ (:width selrect) 2)) (:y selrect))]
@ -633,5 +638,5 @@
(ptk/reify ::selected-to-path (ptk/reify ::selected-to-path
ptk/WatchEvent ptk/WatchEvent
(watch [_ state stream] (watch [_ state stream]
(let [ids (wsh/lookup-selected state)] (let [ids (wsh/lookup-selected state {:omit-blocked? true})]
(rx/of (dch/update-shapes ids ups/convert-to-path)))))) (rx/of (dch/update-shapes ids ups/convert-to-path))))))

View file

@ -22,18 +22,22 @@
(hooks/use-effect-ssr (hooks/use-effect-ssr
(mf/deps embed? urls) (mf/deps embed? urls)
(fn [] (fn []
(let [sub (when embed? (let [;; When not active the embedding we return the URI
(->> (rx/from urls) url-mapping (fn [obs]
(rx/merge-map http/fetch-data-uri) (if embed?
(rx/merge-map http/fetch-data-uri obs)
(rx/map identity obs)))
sub (->> (rx/from urls)
(url-mapping)
(rx/reduce conj {}) (rx/reduce conj {})
(rx/subs (fn [data] (rx/subs (fn [data]
(when-not (= data (mf/ref-val uri-data)) (when-not (= data (mf/ref-val uri-data))
(mf/set-ref-val! uri-data data) (mf/set-ref-val! uri-data data)
(reset! state inc))))))] (reset! state inc)))))]
#(when sub #(when sub
(rx/dispose! sub))))) (rx/dispose! sub)))))
;; Use ref so if the urls are cached will return inmediately instead of the ;; Use ref so if the urls are cached will return inmediately instead of the
;; next render ;; next render
(when embed? (mf/ref-val uri-data)))
(mf/ref-val uri-data))))

View file

@ -31,7 +31,8 @@
:y y :y y
:height height :height height
:width width :width width
:patternTransform transform} :patternTransform transform
:data-loading (str (not (contains? embed uri)))}
[:image {:xlinkHref (get embed uri uri) [:image {:xlinkHref (get embed uri uri)
:width width :width width
:height height}]])))) :height height}]]))))

View file

@ -32,7 +32,9 @@
:transform transform :transform transform
:width width :width width
:height height :height height
:preserveAspectRatio "none"})) :preserveAspectRatio "none"
:data-loading (str (not (contains? embed uri)))}))
on-drag-start (fn [event] on-drag-start (fn [event]
;; Prevent browser dragging of the image ;; Prevent browser dragging of the image
(dom/prevent-default event))] (dom/prevent-default event))]

View file

@ -75,7 +75,8 @@
;; (uc/hex->rgba fill-color fill-opacity)) ;; (uc/hex->rgba fill-color fill-opacity))
[r g b a] (uc/hex->rgba fill-color fill-opacity) [r g b a] (uc/hex->rgba fill-color fill-opacity)
text-color (str/format "rgba(%s, %s, %s, %s)" r g b a) text-color (when (and (some? fill-color) (some? fill-opacity))
(str/format "rgba(%s, %s, %s, %s)" r g b a))
fontsdb (deref fonts/fontsdb) fontsdb (deref fonts/fontsdb)
base #js {:textDecoration text-decoration base #js {:textDecoration text-decoration

View file

@ -209,7 +209,7 @@
(into [] (into []
(cond (cond
(= selected :recent) (reverse recent-colors) (= selected :recent) (reverse recent-colors)
(= selected :file) (vals file-colors) (= selected :file) (->> (vals file-colors) (sort-by :name))
:else (library->colors shared-libs selected)))))) :else (library->colors shared-libs selected))))))
(mf/use-effect (mf/use-effect
@ -222,7 +222,8 @@
(mf/deps file-colors) (mf/deps file-colors)
(fn [] (fn []
(when (= selected :file) (when (= selected :file)
(reset! current-library-colors (into [] (vals file-colors)))))) (reset! current-library-colors (into [] (->> (vals file-colors)
(sort-by :name)))))))
[:& palette {:left-sidebar? left-sidebar? [:& palette {:left-sidebar? left-sidebar?
:current-colors @current-library-colors :current-colors @current-library-colors

View file

@ -150,10 +150,6 @@
(dom/prevent-default event) (dom/prevent-default event)
(let [id (:id item)] (let [id (:id item)]
(cond (cond
(or (:blocked item)
(:hidden item))
nil
(kbd/shift? event) (kbd/shift? event)
(st/emit! (dw/shift-select-shapes id)) (st/emit! (dw/shift-select-shapes id))

View file

@ -288,6 +288,8 @@
(fn [changes] (fn [changes]
(st/emit! (dwl/update-typography (merge typography changes) file-id)))) (st/emit! (dwl/update-typography (merge typography changes) file-id))))
multiple? (->> values vals (d/seek #(= % :multiple)))
opts #js {:ids ids opts #js {:ids ids
:values values :values values
:on-change on-change}] :on-change on-change}]
@ -295,7 +297,7 @@
[:div.element-set [:div.element-set
[:div.element-set-title [:div.element-set-title
[:span label] [:span label]
(when (not typography) (when (and (not typography) (not multiple?))
[:div.add-page {:on-click on-convert-to-typography} i/close])] [:div.add-page {:on-click on-convert-to-typography} i/close])]
(cond (cond

View file

@ -27,7 +27,19 @@
(defn color-picker-callback (defn color-picker-callback
[color disable-gradient disable-opacity handle-change-color handle-open handle-close] [color disable-gradient disable-opacity handle-change-color handle-open handle-close]
(fn [event] (fn [event]
(let [x (.-clientX event) (let [color
(cond
(uc/multiple? color)
{:color cp/default-color
:opacity 1}
(= :multiple (:opacity color))
(assoc color :opacity 1)
:else
color)
x (.-clientX event)
y (.-clientY event) y (.-clientY event)
props {:x x props {:x x
:y y :y y
@ -98,16 +110,12 @@
handle-click-color (mf/use-callback handle-click-color (mf/use-callback
(mf/deps color) (mf/deps color)
(let [;; If multiple, we change to default color
color (if (uc/multiple? color)
{:color cp/default-color :opacity 1}
color)]
(color-picker-callback color (color-picker-callback color
disable-gradient disable-gradient
disable-opacity disable-opacity
handle-pick-color handle-pick-color
handle-open handle-open
handle-close))) handle-close))
prev-color (h/use-previous color)] prev-color (h/use-previous color)]

View file

@ -148,8 +148,8 @@
extract-attrs extract-attrs
(fn [[ids values] {:keys [id type shapes content] :as shape}] (fn [[ids values] {:keys [id type shapes content] :as shape}]
(let [props (get-in type->props [type attr-type]) (let [props (get-in type->props [type attr-type])]
result (case props (case props
:ignore [ids values] :ignore [ids values]
:shape [(conj ids id) :shape [(conj ids id)
(merge-attrs values (merge (merge-attrs values (merge
@ -158,12 +158,13 @@
:text [(conj ids id) :text [(conj ids id)
(-> values (-> values
(merge-attrs (select-keys shape attrs)) (merge-attrs (select-keys shape attrs))
(merge-attrs (attrs/get-attrs-multi (txt/node-seq content) attrs)))] (merge-attrs (merge
(select-keys txt/default-text-attrs attrs)
(attrs/get-attrs-multi (txt/node-seq content) attrs))))]
:children (let [children (->> (:shapes shape []) (map #(get objects %))) :children (let [children (->> (:shapes shape []) (map #(get objects %)))
[new-ids new-values] (get-attrs children objects attr-type)] [new-ids new-values] (get-attrs children objects attr-type)]
[(d/concat ids new-ids) (merge-attrs values new-values)]) [(d/concat ids new-ids) (merge-attrs values new-values)])
[])] [])))]
result))]
(reduce extract-attrs [[] []] shapes))) (reduce extract-attrs [[] []] shapes)))
(mf/defc options (mf/defc options

View file

@ -131,7 +131,7 @@
#(rx/dispose! sub)))) #(rx/dispose! sub))))
(mf/use-effect (mf/use-effect
(mf/deps shapes modifiers) (mf/deps shapes filter-shapes modifiers)
(fn [] (fn []
(rx/push! subject props))) (rx/push! subject props)))
@ -161,7 +161,8 @@
(map #(get objects %)) (map #(get objects %))
(filterv (comp not nil?))) (filterv (comp not nil?)))
filter-shapes (into #{} filter-shapes (into #{}
(mapcat #(cp/get-object-with-children % objects)) (comp (mapcat #(cp/get-object-with-children % objects))
(map :id))
selected) selected)
filter-shapes (fn [id] filter-shapes (fn [id]

View file

@ -29,7 +29,10 @@
(when node (when node
(let [img-node (mf/ref-val thumbnail-img)] (let [img-node (mf/ref-val thumbnail-img)]
(timers/schedule-on-idle (timers/schedule-on-idle
#(if-let [frame-node (dom/get-element (str "shape-" (:id shape)))] #(let [frame-node (dom/get-element (str "shape-" (:id shape)))
loading-node (when frame-node
(dom/query frame-node "[data-loading=\"true\"]"))]
(if (and (some? frame-node) (not (some? loading-node)))
(let [xml (-> (js/XMLSerializer.) (let [xml (-> (js/XMLSerializer.)
(.serializeToString frame-node) (.serializeToString frame-node)
js/encodeURIComponent js/encodeURIComponent
@ -38,7 +41,7 @@
img-src (str "data:image/svg+xml;base64," xml)] img-src (str "data:image/svg+xml;base64," xml)]
(obj/set! img-node "src" img-src)) (obj/set! img-node "src" img-src))
(on-frame-not-found (:id shape)))))))) (on-frame-not-found (:id shape)))))))))
on-image-load on-image-load
(mf/use-callback (mf/use-callback
@ -108,8 +111,9 @@
(fn [frame-id] (fn [frame-id]
;; If we couldn't find the frame maybe is still rendering. We push the event again ;; If we couldn't find the frame maybe is still rendering. We push the event again
;; after a time ;; after a time
(timers/schedule-on-idle #(dwp/update-frame-thumbnail frame-id)) (reset! shape-id nil)
(rx/push! next :next)))] (rx/push! next :next)
(timers/schedule-on-idle (st/emitf (dwp/update-frame-thumbnail frame-id)))))]
(mf/use-effect (mf/use-effect
(mf/deps render-frame) (mf/deps render-frame)

View file

@ -135,7 +135,7 @@
:else "transparent"))) :else "transparent")))
(defn multiple? [{:keys [id file-id value color gradient]}] (defn multiple? [{:keys [id file-id value color gradient opacity]}]
(or (= value :multiple) (or (= value :multiple)
(= color :multiple) (= color :multiple)
(= gradient :multiple) (= gradient :multiple)

View file

@ -22,7 +22,10 @@
(defn add-subpath-command (defn add-subpath-command
"Adds a command to the subpath" "Adds a command to the subpath"
[subpath command] [subpath command]
(let [p (upc/command->point command)] (let [command (if (= :close-path (:command command))
(upc/make-line-to (:from subpath))
command)
p (upc/command->point command)]
(-> subpath (-> subpath
(assoc :to p) (assoc :to p)
(update :data conj command)))) (update :data conj command))))

View file

@ -34,12 +34,13 @@
(-dispose [_] (-dispose [_]
(js/clearInterval sem))))) (js/clearInterval sem)))))
(if (and (exists? js/window) (.-requestIdleCallback js/window)) (if (and (exists? js/window)
(.-requestIdleCallback js/window))
(do (do
(def ^:private request-idle-callback #(js/requestIdleCallback %)) (def ^:private request-idle-callback #(js/requestIdleCallback %))
(def ^:private cancel-idle-callback #(js/cancelIdleCallback %))) (def ^:private cancel-idle-callback #(js/cancelIdleCallback %)))
(do (do
(def ^:private request-idle-callback #(js/setTimeout % 100)) (def ^:private request-idle-callback #(js/setTimeout % 250))
(def ^:private cancel-idle-callback #(js/clearTimeout %)))) (def ^:private cancel-idle-callback #(js/clearTimeout %))))
(defn schedule-on-idle (defn schedule-on-idle