0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-02-15 11:38:24 -05:00

Simplify changes detection and commit.

With minor code cleaning.
This commit is contained in:
Andrey Antukh 2020-01-21 17:38:07 +01:00
parent 8dd6c8457f
commit 1d726564df
4 changed files with 279 additions and 265 deletions

View file

@ -23,7 +23,6 @@
[uxbox.main.streams :as ms] [uxbox.main.streams :as ms]
[uxbox.main.websockets :as ws] [uxbox.main.websockets :as ws]
[uxbox.main.workers :as uwrk] [uxbox.main.workers :as uwrk]
[uxbox.util.data :refer [dissoc-in index-of]]
[uxbox.util.geom.matrix :as gmt] [uxbox.util.geom.matrix :as gmt]
[uxbox.util.geom.point :as gpt] [uxbox.util.geom.point :as gpt]
[uxbox.util.math :as mth] [uxbox.util.math :as mth]
@ -234,6 +233,8 @@
(let [file (get-in state [:files file-id])] (let [file (get-in state [:files file-id])]
(assoc state :workspace-file file))))) (assoc state :workspace-file file)))))
(declare diff-and-commit-changes)
(defn initialize-page (defn initialize-page
[page-id] [page-id]
(ptk/reify ::initialize-page (ptk/reify ::initialize-page
@ -244,6 +245,7 @@
(assoc state (assoc state
:workspace-local workspace-default :workspace-local workspace-default
:workspace-data data :workspace-data data
:workspace-data-prev data
:workspace-page page))) :workspace-page page)))
ptk/WatchEvent ptk/WatchEvent
@ -254,7 +256,7 @@
(->> stream (->> stream
(rx/filter #(satisfies? IBatchedChange %)) (rx/filter #(satisfies? IBatchedChange %))
(rx/debounce 500) (rx/debounce 500)
(rx/map (constantly commit-batched-changes)) (rx/map (constantly diff-and-commit-changes))
(rx/take-until stoper)))))) (rx/take-until stoper))))))
(defn finalize (defn finalize
@ -268,6 +270,29 @@
:workspace-page :workspace-page
:workspace-data)))) :workspace-data))))
(def diff-and-commit-changes
(ptk/reify ::diff-and-commit-changes
ptk/WatchEvent
(watch [_ state stream]
(let [curr (get-in state [:workspace-data :shapes-by-id])
prev (get-in state [:workspace-data-prev :shapes-by-id])
diff (d/diff-maps prev curr)
changes (loop [scs (rest diff)
sc (first diff)
res []]
(if (nil? sc)
res
(let [[_ id shape] sc]
(recur (rest scs)
(first scs)
(conj res {:type :mod-shape
:session-id (:session-id state)
:operations (d/diff-maps (get prev id) shape)
:id id})))))]
(when-not (empty? changes)
(rx/of (commit-changes changes)))))))
;; --- Fetch Workspace Users ;; --- Fetch Workspace Users
(declare users-fetched) (declare users-fetched)
@ -465,7 +490,7 @@
ptk/UpdateEvent ptk/UpdateEvent
(update [_ state] (update [_ state]
(let [increase #(nth c/zoom-levels (let [increase #(nth c/zoom-levels
(+ (index-of c/zoom-levels %) 1) (+ (d/index-of c/zoom-levels %) 1)
(last c/zoom-levels))] (last c/zoom-levels))]
(update-in state [:workspace-local :zoom] (fnil increase 1)))))) (update-in state [:workspace-local :zoom] (fnil increase 1))))))
@ -474,7 +499,7 @@
ptk/UpdateEvent ptk/UpdateEvent
(update [_ state] (update [_ state]
(let [decrease #(nth c/zoom-levels (let [decrease #(nth c/zoom-levels
(- (index-of c/zoom-levels %) 1) (- (d/index-of c/zoom-levels %) 1)
(first c/zoom-levels))] (first c/zoom-levels))]
(update-in state [:workspace-local :zoom] (fnil decrease 1)))))) (update-in state [:workspace-local :zoom] (fnil decrease 1))))))
@ -632,11 +657,7 @@
(fn [selected] (fn [selected]
(if (contains? selected id) (if (contains? selected id)
(disj selected id) (disj selected id)
(conj selected id))))) (conj selected id)))))))
ptk/WatchEvent
(watch [_ state s]
(rx/of (activate-flag :element-options)))))
(def deselect-all (def deselect-all
"Clear all possible state of drawing, edition "Clear all possible state of drawing, edition
@ -694,16 +715,7 @@
IBatchedChange IBatchedChange
ptk/UpdateEvent ptk/UpdateEvent
(update [_ state] (update [_ state]
(let [shape-old (get-in state [:workspace-data :shapes-by-id id]) (update-in state [:workspace-data :shapes-by-id id] merge attrs))))
shape-new (merge shape-old attrs)
operations (d/diff-maps shape-old shape-new)
change {:type :mod-shape
:session-id (:session-id state)
:operations operations
:id id}]
(-> state
(assoc-in [:workspace-data :shapes-by-id id] shape-new)
(update ::batched-changes (fnil conj []) change))))))
;; --- Update Page Options ;; --- Update Page Options
@ -714,15 +726,7 @@
IBatchedChange IBatchedChange
ptk/UpdateEvent ptk/UpdateEvent
(update [_ state] (update [_ state]
(let [opts-old (get-in state [:workspace-data :options]) (update-in state [:workspace-data :options] merge opts))))
opts-new (merge opts-old opts)
operations (d/diff-maps opts-old opts-new)
change {:type :mod-opts
:session-id (:session-id state)
:operations operations}]
(-> state
(assoc-in [:workspace-data :options] opts-new)
(update ::batched-changes (fnil conj []) change))))))
;; --- Update Selected Shapes attrs ;; --- Update Selected Shapes attrs
@ -787,16 +791,15 @@
;; --- Delete Selected ;; --- Delete Selected
(defn impl-dissoc-shape (defn impl-dissoc-shape
"Given a shape, removes it from the state." "Given a shape id, removes it from the state."
[state id] [id]
(-> state (ptk/reify ::impl-dissoc-shape
(update-in [:workspace-data :canvas] (fn [items] (filterv #(not= % id) items))) ptk/UpdateEvent
(update-in [:workspace-data :shapes] (fn [items] (filterv #(not= % id) items))) (update [_ state]
(update-in [:workspace-data :shapes-by-id] dissoc id))) (-> state
(update-in [:workspace-data :canvas] (fn [items] (filterv #(not= % id) items)))
(defn impl-lookup-shape (update-in [:workspace-data :shapes] (fn [items] (filterv #(not= % id) items)))
[state id] (update-in [:workspace-data :shapes-by-id] dissoc id)))))
(get-in state [:workspace-data :shapes-by-id id]))
(def delete-selected (def delete-selected
"Deselect all and remove all selected shapes." "Deselect all and remove all selected shapes."
@ -813,9 +816,9 @@
{:type (if (= type :canvas) :del-canvas :del-shape) {:type (if (= type :canvas) :del-canvas :del-shape)
:session-id session-id :session-id session-id
:id id})))] :id id})))]
(rx/merge (rx/concat
(rx/of deselect-all) (rx/of deselect-all)
(rx/from (map (fn [id] #(impl-dissoc-shape % id)) selected)) (rx/from (map impl-dissoc-shape selected))
(rx/of (commit-changes changes))))))) (rx/of (commit-changes changes)))))))
;; --- Rename Shape ;; --- Rename Shape
@ -846,6 +849,7 @@
[loc] [loc]
(us/assert ::direction loc) (us/assert ::direction loc)
(ptk/reify ::move-selected-layer (ptk/reify ::move-selected-layer
IBatchedChange
ptk/UpdateEvent ptk/UpdateEvent
(update [_ state] (update [_ state]
(let [id (first (get-in state [:workspace-local :selected])) (let [id (first (get-in state [:workspace-local :selected]))
@ -860,8 +864,8 @@
(let [shapes (get-in state [:workspace-data :shapes]) (let [shapes (get-in state [:workspace-data :shapes])
index (case opt index (case opt
:top 0 :top 0
:down (min (- (count shapes) 1) (inc (index-of shapes sid))) :down (min (- (count shapes) 1) (inc (d/index-of shapes sid)))
:up (max 0 (- (index-of shapes sid) 1)) :up (max 0 (- (d/index-of shapes sid) 1))
:bottom (- (count shapes) 1))] :bottom (- (count shapes) 1))]
(update-in state [:workspace-data :shapes] (update-in state [:workspace-data :shapes]
(fn [items] (fn [items]
@ -977,16 +981,8 @@
xfmt (or (:modifier-mtx shape) (gmt/matrix)) xfmt (or (:modifier-mtx shape) (gmt/matrix))
shape-old (dissoc shape :modifier-mtx) shape-old (dissoc shape :modifier-mtx)
shape-new (geom/transform shape-old xfmt) shape-new (geom/transform shape-old xfmt)
shape-new (recalculate-shape-canvas-relation state shape-new) shape-new (recalculate-shape-canvas-relation state shape-new)]
operations (d/diff-maps shape-old shape-new) (assoc-in state [:workspace-data :shapes-by-id id] shape-new)))]
change {:type :mod-shape
:session-id (:session-id state)
:operations operations
:id id}]
(-> state
(assoc-in [:workspace-data :shapes-by-id id] shape-new)
(update ::batched-changes (fnil conj []) change))))]
(ptk/reify ::materialize-temporal-modifier-in-bulk (ptk/reify ::materialize-temporal-modifier-in-bulk
IBatchedChange IBatchedChange
ptk/UpdateEvent ptk/UpdateEvent
@ -1001,7 +997,9 @@
(update [_ state] (update [_ state]
(let [pid (get-in state [:workspace-page :id]) (let [pid (get-in state [:workspace-page :id])
data (get-in state [:pages-data pid])] data (get-in state [:pages-data pid])]
(update-in state [:pages-data pid] cp/process-changes changes))) (-> state
(update-in [:pages-data pid] cp/process-changes changes)
(assoc :workspace-data-prev (:workspace-data state)))))
ptk/WatchEvent ptk/WatchEvent
(watch [_ state stream] (watch [_ state stream]
@ -1059,7 +1057,7 @@
(->> stream (->> stream
(rx/filter #(= % :interrupt)) (rx/filter #(= % :interrupt))
(rx/take 1) (rx/take 1)
(rx/map (fn [_] #(dissoc-in % [:workspace-local :edition]))))))) (rx/map (fn [_] #(d/dissoc-in % [:workspace-local :edition])))))))
;; --- Select for Drawing ;; --- Select for Drawing
@ -1106,16 +1104,7 @@
IBatchedChange IBatchedChange
ptk/UpdateEvent ptk/UpdateEvent
(update [_ state] (update [_ state]
(let [shape-old (get-in state [:workspace-data :shapes-by-id id]) (update-in state [:workspace-data :shapes-by-id id] geom/resize-dim dimensions))))
shape-new (geom/resize-dim shape-old dimensions)
operations (d/diff-maps shape-old shape-new)
change {:type :mod-shape
:session-id (:session-id state)
:operations operations
:id id}]
(-> state
(assoc-in [:workspace-data :shapes-by-id id] shape-new)
(update ::batched-changes (fnil conj []) change))))))
;; --- Shape Proportions ;; --- Shape Proportions
@ -1143,21 +1132,20 @@
;; --- Path Modifications ;; --- Path Modifications
;; TODO: revisit
(deftype UpdatePath [id index delta]
ptk/UpdateEvent
(update [_ state]
(update-in state [:workspace-data :shapes-by-id id :segments index] gpt/add delta)))
(defn update-path (defn update-path
"Update a concrete point in the path shape." "Update a concrete point in the path shape."
[id index delta] [id index delta]
{:pre [(uuid? id) (number? index) (gpt/point? delta)]} (us/assert ::us/uuid id)
(UpdatePath. id index delta)) (us/assert ::us/integer index)
(us/assert gpt/point? delta)
(ptk/reify ::update-path
ptk/UpdateEvent
(update [_ state]
(update-in state [:workspace-data :shapes-by-id id :segments index] gpt/add delta))))
;; --- Initial Path Point Alignment ;; --- Initial Path Point Alignment
;; TODO: revisit ;; TODO: revisit on alignemt refactor
(deftype InitialPathPointAlign [id index] (deftype InitialPathPointAlign [id index]
ptk/WatchEvent ptk/WatchEvent
(watch [_ state s] (watch [_ state s]
@ -1177,88 +1165,71 @@
;; --- Shape Visibility ;; --- Shape Visibility
;; TODO: revisit (declare impl-update-shape-hidden)
(defn set-hidden-attr
[id value] (defn hide-shape
[id]
(us/assert ::us/uuid id) (us/assert ::us/uuid id)
(us/assert ::us/boolean value) (ptk/reify ::hide-shape
(letfn [(impl-set-hidden [state id] ptk/UpdateEvent
(let [{:keys [type] :as shape} (get-in state [:shapes id])] (update [_ state]
(as-> state $ (impl-update-shape-hidden state id true))))
(assoc-in $ [:shapes id :hidden] value)
(if (= :canvas type) (defn show-shape
(let [shapes (get-in state [:pages (:page shape) :shapes]) [id]
xform (comp (map #(get-in state [:shapes %])) (us/assert ::us/uuid id)
(filter #(= id (:canvas %))) (ptk/reify ::hide-shape
(map :id))] ptk/UpdateEvent
(reduce impl-set-hidden $ (sequence xform shapes))) (update [_ state]
$))))] (impl-update-shape-hidden state id false))))
(ptk/reify ::set-hidden-attr
ptk/UpdateEvent (defn- impl-update-shape-hidden
(update [_ state] [state id hidden?]
(impl-set-hidden state id))))) (let [type (get-in state [:workspace-data :shapes-by-id id :type])
state (update-in state [:workspace-data :shapes-by-id id] assoc :hidden hidden?)]
(cond-> state
(= type :canvas)
(update-in [:workspace-data :shapes-by-id]
(fn [shapes]
(reduce-kv (fn [shapes key {:keys [canvas] :as val}]
(cond-> shapes
(= id canvas) (update key assoc :hidden hidden?)))
shapes
shapes))))))
;; --- Shape Blocking ;; --- Shape Blocking
;; TODO: revisit (declare impl-update-shape-blocked)
(defn set-blocked-attr
[id value] (defn block-shape
[id]
(us/assert ::us/uuid id) (us/assert ::us/uuid id)
(us/assert ::us/boolean value) (ptk/reify ::hide-shape
(letfn [(impl-set-blocked [state id] ptk/UpdateEvent
(let [{:keys [type] :as shape} (get-in state [:shapes id])] (update [_ state]
(as-> state $ (impl-update-shape-blocked state id true))))
(assoc-in $ [:shapes id :blocked] value)
(if (= :canvas type)
(let [shapes (get-in state [:pages (:page shape) :shapes])
xform (comp (map #(get-in state [:shapes %]))
(filter #(= id (:canvas %)))
(map :id))]
(reduce impl-set-blocked $ (sequence xform shapes)))
$))))]
(ptk/reify ::set-blocked-attr
ptk/UpdateEvent
(update [_ state]
(impl-set-blocked state id)))))
;; --- Shape Locking (defn unblock-shape
;; TODO: revisit
(deftype LockShape [id]
ptk/UpdateEvent
(update [_ state]
(letfn [(mark-locked [state id]
(let [shape (get-in state [:shapes id])]
(if (= :group (:type shape))
(as-> state $
(assoc-in $ [:shapes id :locked] true)
(reduce mark-locked $ (:items shape)))
(assoc-in state [:shapes id :locked] true))))]
(mark-locked state id))))
;; TODO: revisit
(defn lock-shape
[id] [id]
{:pre [(uuid? id)]} (us/assert ::us/uuid id)
(LockShape. id)) (ptk/reify ::hide-shape
ptk/UpdateEvent
(update [_ state]
(impl-update-shape-blocked state id false))))
(deftype UnlockShape [id] (defn- impl-update-shape-blocked
ptk/UpdateEvent [state id hidden?]
(update [_ state] (let [type (get-in state [:workspace-data :shapes-by-id id :type])
(letfn [(mark-unlocked [state id] state (update-in state [:workspace-data :shapes-by-id id] assoc :blocked hidden?)]
(let [shape (get-in state [:shapes id])] (cond-> state
(if (= :group (:type shape)) (= type :canvas)
(as-> state $ (update-in [:workspace-data :shapes-by-id]
(assoc-in $ [:shapes id :locked] false) (fn [shapes]
(reduce mark-unlocked $ (:items shape))) (reduce-kv (fn [shapes key {:keys [canvas] :as val}]
(assoc-in state [:shapes id :locked] false))))] (cond-> shapes
(mark-unlocked state id)))) (= id canvas) (update key assoc :blocked hidden?)))
shapes
;; TODO: revisit shapes))))))
(defn unlock-shape
[id]
{:pre [(uuid? id)]}
(UnlockShape. id))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Canvas Interactions ;; Canvas Interactions

View file

@ -29,7 +29,7 @@
(fn [own props] (fn [own props]
[] []
(letfn [(on-paste [item] (letfn [(on-paste [item]
(st/emit! (udw/paste-from-clipboard (:id item))) #_(st/emit! (udw/paste-from-clipboard (:id item)))
(udl/close!)) (udl/close!))
(on-close [event] (on-close [event]
(dom/prevent-default event) (dom/prevent-default event)

View file

@ -2,13 +2,17 @@
;; License, v. 2.0. If a copy of the MPL was not distributed with this ;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/. ;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;; ;;
;; This Source Code Form is "Incompatible With Secondary Licenses", as
;; defined by the Mozilla Public License, v. 2.0.
;;
;; Copyright (c) 2015-2016 Juan de la Cruz <delacruzgarciajuan@gmail.com> ;; Copyright (c) 2015-2016 Juan de la Cruz <delacruzgarciajuan@gmail.com>
;; Copyright (c) 2015-2019 Andrey Antukh <niwi@niwi.nz> ;; Copyright (c) 2015-2020 Andrey Antukh <niwi@niwi.nz>
(ns uxbox.main.ui.workspace.sidebar.layers (ns uxbox.main.ui.workspace.sidebar.layers
(:require (:require
[lentes.core :as l] [lentes.core :as l]
[rumext.alpha :as mf] [rumext.alpha :as mf]
[uxbox.common.data :as d]
[uxbox.builtins.icons :as i] [uxbox.builtins.icons :as i]
[uxbox.main.data.workspace :as dw] [uxbox.main.data.workspace :as dw]
[uxbox.main.refs :as refs] [uxbox.main.refs :as refs]
@ -16,7 +20,6 @@
[uxbox.main.ui.keyboard :as kbd] [uxbox.main.ui.keyboard :as kbd]
[uxbox.main.ui.shapes.icon :as icon] [uxbox.main.ui.shapes.icon :as icon]
[uxbox.main.ui.workspace.sortable :refer [use-sortable]] [uxbox.main.ui.workspace.sortable :refer [use-sortable]]
[uxbox.util.data :refer [classnames enumerate]]
[uxbox.util.dom :as dom] [uxbox.util.dom :as dom]
[uxbox.util.i18n :as i18n :refer [t]])) [uxbox.util.i18n :as i18n :refer [t]]))
@ -77,138 +80,163 @@
(mf/defc layer-item (mf/defc layer-item
[{:keys [shape selected index] :as props}] [{:keys [shape selected index] :as props}]
;; (prn "layer-item" index (:name shape)) (let [selected? (contains? selected (:id shape))
(letfn [(toggle-blocking [event]
(dom/stop-propagation event)
(let [{:keys [id blocked]} shape]
(st/emit! (dw/set-blocked-attr id (not blocked)))))
(toggle-visibility [event] toggle-blocking
(dom/stop-propagation event) (fn [event]
(let [{:keys [id hidden]} shape] (prn "toggle-blocking" (:blocked shape))
(st/emit! (dw/set-hidden-attr id (not hidden))))) (dom/stop-propagation event)
(if (:blocked shape)
(st/emit! (dw/unblock-shape (:id shape)))
(st/emit! (dw/block-shape (:id shape)))))
(select-shape [event] toggle-visibility
(dom/prevent-default event) (fn [event]
(let [id (:id shape)] (dom/stop-propagation event)
(cond (if (:hidden shape)
(or (:blocked shape) (st/emit! (dw/show-shape (:id shape)))
(:hidden shape)) (st/emit! (dw/hide-shape (:id shape)))))
nil
(.-ctrlKey event) select-shape
(st/emit! (dw/select-shape id)) (fn [event]
(dom/prevent-default event)
(let [id (:id shape)]
(cond
(or (:blocked shape)
(:hidden shape))
nil
(> (count selected) 1) (.-ctrlKey event)
(st/emit! dw/deselect-all (st/emit! (dw/select-shape id))
(dw/select-shape id))
:else
(st/emit! dw/deselect-all
(dw/select-shape id)))))
(on-drop [item monitor] (> (count selected) 1)
(st/emit! dw/commit-shape-order-change)) (st/emit! dw/deselect-all
(dw/select-shape id))
:else
(st/emit! dw/deselect-all
(dw/select-shape id)))))
(on-hover [item monitor] on-drop
(st/emit! (dw/temporal-shape-order-change (:shape-id item) index)))] (fn [item monitor]
(let [selected? (contains? selected (:id shape)) (st/emit! dw/commit-shape-order-change))
[dprops dnd-ref] (use-sortable
{:type "layer-item" on-hover
:data {:shape-id (:id shape) (fn [item monitor]
:page-id (:page shape) (st/emit! (dw/temporal-shape-order-change (:shape-id item) index)))
:index index}
:on-hover on-hover [dprops dnd-ref] (use-sortable
:on-drop on-drop})] {:type "layer-item"
[:li {:ref dnd-ref :data {:shape-id (:id shape)
:class (classnames :page-id (:page shape)
:selected selected? :index index}
:dragging-TODO (:dragging? dprops))} :on-hover on-hover
[:div.element-list-body {:class (classnames :selected selected?) :on-drop on-drop})]
:on-click select-shape [:li {:ref dnd-ref
:on-double-click #(dom/stop-propagation %)} :class (dom/classnames
[:div.element-actions :selected selected?
[:div.toggle-element {:class (when-not (:hidden shape) "selected") :dragging-TODO (:dragging? dprops))}
:on-click toggle-visibility} [:div.element-list-body {:class (dom/classnames :selected selected?)
i/eye] :on-click select-shape
[:div.block-element {:class (when (:blocked shape) "selected") :on-double-click #(dom/stop-propagation %)}
:on-click toggle-blocking} [:div.element-actions
i/lock]] [:div.toggle-element {:class (when-not (:hidden shape) "selected")
[:div.element-icon (element-icon shape)] :on-click toggle-visibility}
[:& layer-name {:shape shape}]]]))) i/eye]
[:div.block-element {:class (when (:blocked shape) "selected")
:on-click toggle-blocking}
i/lock]]
[:div.element-icon (element-icon shape)]
[:& layer-name {:shape shape}]]]))
(mf/defc canvas-item (mf/defc canvas-item
[{:keys [canvas shapes selected index] :as props}] [{:keys [canvas shapes selected index] :as props}]
(letfn [(toggle-blocking [event] (let [selected? (contains? selected (:id canvas))
(dom/stop-propagation event) local (mf/use-state {:collapsed false})
(let [{:keys [id blocked]} canvas] collapsed? (:collapsed @local)
(st/emit! (dw/set-blocked-attr id (not blocked)))))
(toggle-visibility [event] shapes (filter #(= (:canvas (second %)) (:id canvas)) shapes)
(dom/stop-propagation event)
(let [{:keys [id hidden]} canvas]
(st/emit! (dw/set-hidden-attr id (not hidden)))))
(select-shape [event] toggle-collapse
(dom/prevent-default event) (fn [event]
(let [id (:id canvas)] (dom/stop-propagation event)
(cond (swap! local update :collapsed not))
(or (:blocked canvas)
(:hidden canvas))
nil
(.-ctrlKey event) toggle-blocking
(st/emit! (dw/select-shape id)) (fn [event]
(dom/stop-propagation event)
(if (:blocked canvas)
(st/emit! (dw/unblock-shape (:id canvas)))
(st/emit! (dw/block-shape (:id canvas)))))
(> (count selected) 1) toggle-visibility
(st/emit! dw/deselect-all (fn [event]
(dw/select-shape id)) (dom/stop-propagation event)
:else (if (:hidden canvas)
(st/emit! dw/deselect-all (st/emit! (dw/show-shape (:id canvas)))
(dw/select-shape id))))) (st/emit! (dw/hide-shape (:id canvas)))))
(on-drop [item monitor] select-shape
(st/emit! ::dw/page-data-update)) (fn [event]
(dom/prevent-default event)
(let [id (:id canvas)]
(cond
(or (:blocked canvas)
(:hidden canvas))
nil
(on-hover [item monitor] (.-ctrlKey event)
(st/emit! (dw/change-canvas-order {:id (:canvas-id item) (st/emit! (dw/select-shape id))
:index index})))]
(let [selected? (contains? selected (:id canvas))
collapsed? (:collapsed canvas false)
shapes (filter #(= (:canvas (second %)) (:id canvas)) shapes) (> (count selected) 1)
[dprops dnd-ref] (use-sortable (st/emit! dw/deselect-all
{:type "canvas-item" (dw/select-shape id))
:data {:canvas-id (:id canvas) :else
:page-id (:page canvas) (st/emit! dw/deselect-all
:index index} (dw/select-shape id)))))
:on-hover on-hover
:on-drop on-drop})] on-drop
[:li.group {:ref dnd-ref (fn [item monitor]
:class (classnames (st/emit! ::dw/page-data-update))
:selected selected?
:dragging-TODO (:dragging? dprops))} on-hover
[:div.element-list-body {:class (classnames :selected selected?) (fn [item monitor]
:on-click select-shape (st/emit! (dw/change-canvas-order {:id (:canvas-id item)
:on-double-click #(dom/stop-propagation %)} :index index})))
[:div.element-actions
[:div.toggle-element {:class (when-not (:hidden canvas) "selected") [dprops dnd-ref] (use-sortable
:on-click toggle-visibility} {:type "canvas-item"
i/eye] :data {:canvas-id (:id canvas)
[:div.block-element {:class (when (:blocked canvas) "selected") :page-id (:page canvas)
:on-click toggle-blocking} :index index}
:on-hover on-hover
:on-drop on-drop})]
[:li.group {:ref dnd-ref
:class (dom/classnames
:selected selected?
:dragging-TODO (:dragging? dprops))}
[:div.element-list-body {:class (dom/classnames :selected selected?)
:on-click select-shape
:on-double-click #(dom/stop-propagation %)}
[:div.element-actions
[:div.toggle-element {:class (when-not (:hidden canvas) "selected")
:on-click toggle-visibility}
i/eye]
#_[:div.block-element {:class (when (:blocked canvas) "selected")
:on-click toggle-blocking}
i/lock]] i/lock]]
[:div.element-icon i/folder] [:div.element-icon i/folder]
[:& layer-name {:shape canvas}] [:& layer-name {:shape canvas}]
[:span.toggle-content [:span.toggle-content
{ ;; :on-click toggle-collapse {:on-click toggle-collapse
:class (when-not collapsed? "inverse")} :class (when-not collapsed? "inverse")}
i/arrow-slide]] i/arrow-slide]]
(when-not collapsed?
[:ul [:ul
(for [[index shape] (reverse shapes)] (for [[index shape] (reverse shapes)]
[:& layer-item {:shape shape [:& layer-item {:shape shape
:selected selected :selected selected
:index index :index index
:key (:id shape)}])]]))) :key (:id shape)}])])]))
;; --- Layers List ;; --- Layers List
@ -245,15 +273,15 @@
canvas (->> (:canvas data) canvas (->> (:canvas data)
(map #(get shapes-by-id %)) (map #(get shapes-by-id %))
(enumerate)) (d/enumerate))
shapes (->> (:shapes data) shapes (->> (:shapes data)
(map #(get shapes-by-id %))) (map #(get shapes-by-id %)))
all-shapes (enumerate shapes) all-shapes (d/enumerate shapes)
unc-shapes (->> shapes unc-shapes (->> shapes
(filter #(nil? (:canvas %))) (filter #(nil? (:canvas %)))
(enumerate))] (d/enumerate))]
[:div#layers.tool-window [:div#layers.tool-window
[:div.tool-window-bar [:div.tool-window-bar

View file

@ -2,11 +2,16 @@
;; License, v. 2.0. If a copy of the MPL was not distributed with this ;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/. ;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;; ;;
;; Copyright (c) 2015-2016 Andrey Antukh <niwi@niwi.nz> ;; This Source Code Form is "Incompatible With Secondary Licenses", as
;; defined by the Mozilla Public License, v. 2.0.
;;
;; Copyright (c) 2015-2016 Juan de la Cruz <delacruzgarciajuan@gmail.com> ;; Copyright (c) 2015-2016 Juan de la Cruz <delacruzgarciajuan@gmail.com>
;; Copyright (c) 2015-2020 Andrey Antukh <niwi@niwi.nz>
(ns uxbox.util.dom (ns uxbox.util.dom
(:require [goog.dom :as dom])) (:require
[goog.dom :as dom]
[cuerdas.core :as str]))
;; --- Deprecated methods ;; --- Deprecated methods
@ -22,6 +27,16 @@
[e] [e]
(.-target e)) (.-target e))
(defn classnames
[& params]
(assert (even? (count params)))
(str/join " " (reduce (fn [acc [k v]]
(if (true? v)
(conj acc (name k))
acc))
[]
(partition 2 params))))
;; --- New methods ;; --- New methods
(defn get-element-by-class (defn get-element-by-class