mirror of
https://github.com/penpot/penpot.git
synced 2025-01-25 07:58:49 -05:00
✨ Remove unexpected lag on moving shape.
The lag happens when the shape is not initially selected.
This commit is contained in:
parent
1357fed067
commit
792303a833
15 changed files with 106 additions and 121 deletions
|
@ -6,6 +6,7 @@
|
|||
|
||||
(ns ^:figwheel-hooks uxbox.main
|
||||
(:require
|
||||
[cljs.spec.alpha :as s]
|
||||
[rumext.alpha :as mf]
|
||||
[uxbox.main.data.auth :refer [logout]]
|
||||
[uxbox.main.data.users :as udu]
|
||||
|
@ -27,6 +28,7 @@
|
|||
;; --- i18n
|
||||
|
||||
(declare reinit)
|
||||
(s/check-asserts true)
|
||||
|
||||
(i18n/update-locales! (fn [locales]
|
||||
(-> locales
|
||||
|
|
|
@ -20,29 +20,23 @@
|
|||
|
||||
;; --- Initialize
|
||||
|
||||
(defrecord Initialize []
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(assoc-in state [:dashboard :icons] {:selected #{}})))
|
||||
|
||||
(defn initialize
|
||||
[]
|
||||
(Initialize.))
|
||||
(def initialize
|
||||
(ptk/reify ::initialize
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(assoc-in state [:dashboard :icons] {:selected #{}}))))
|
||||
|
||||
;; --- Select a Collection
|
||||
|
||||
(defrecord SelectCollection [type id]
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(rx/of (r/navigate :dashboard/icons
|
||||
{:type type :id id}))))
|
||||
|
||||
(defn select-collection
|
||||
([type]
|
||||
(select-collection type nil))
|
||||
([type id]
|
||||
{:pre [(keyword? type)]}
|
||||
(SelectCollection. type id)))
|
||||
(ptk/reify ::select-collection
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(rx/of (r/navigate :dashboard/icons {:type type :id id}))))))
|
||||
|
||||
;; --- Collections Fetched
|
||||
|
||||
|
@ -61,6 +55,10 @@
|
|||
state
|
||||
items))))
|
||||
|
||||
(defn collections-fetched?
|
||||
[v]
|
||||
(= ::collections-fetched (ptk/type v)))
|
||||
|
||||
;; --- Fetch Collections
|
||||
|
||||
(def fetch-collections
|
||||
|
@ -72,48 +70,37 @@
|
|||
|
||||
;; --- Collection Created
|
||||
|
||||
(defrecord CollectionCreated [item]
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [{:keys [id] :as item} (assoc item :type :own)]
|
||||
(update state :icons-collections assoc id item)))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(rx/of (select-collection :own (:id item)))))
|
||||
|
||||
(defn collection-created
|
||||
[item]
|
||||
(CollectionCreated. item))
|
||||
(ptk/reify ::collection-created
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [{:keys [id] :as item} (assoc item :type :own)]
|
||||
(update state :icons-collections assoc id item)))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(rx/of (select-collection :own (:id item))))))
|
||||
|
||||
;; --- Create Collection
|
||||
|
||||
(defrecord CreateCollection []
|
||||
ptk/WatchEvent
|
||||
(watch [_ state s]
|
||||
(let [name (tr "ds.default-library-title" (gensym "c"))
|
||||
data {:name name}]
|
||||
(->> (rp/mutation! :create-icons-collection data)
|
||||
(rx/map collection-created)))))
|
||||
|
||||
(defn create-collection
|
||||
[]
|
||||
(CreateCollection.))
|
||||
|
||||
(defn collections-fetched?
|
||||
[v]
|
||||
(= ::collections-fetched (ptk/type v)))
|
||||
(def create-collection
|
||||
(ptk/reify ::create-collection
|
||||
ptk/WatchEvent
|
||||
(watch [_ state s]
|
||||
(let [name (tr "ds.default-library-title" (gensym "c"))
|
||||
data {:name name}]
|
||||
(->> (rp/mutation! :create-icons-collection data)
|
||||
(rx/map collection-created))))))
|
||||
|
||||
;; --- Collection Updated
|
||||
|
||||
(defrecord CollectionUpdated [item]
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(update-in state [:icons-collections (:id item)] merge item)))
|
||||
|
||||
(defn collection-updated
|
||||
[item]
|
||||
(CollectionUpdated. item))
|
||||
(ptk/reify ::collection-updated
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(update-in state [:icons-collections (:id item)] merge item))))
|
||||
|
||||
;; --- Update Collection
|
||||
|
||||
|
|
|
@ -245,31 +245,17 @@
|
|||
{:pre [(or (uuid? id) (nil? id)) (fn? on-uploaded)]}
|
||||
(CreateImages. id files on-uploaded)))
|
||||
|
||||
;; --- Image Updated
|
||||
|
||||
(defrecord ImagePersisted [id data]
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(assoc-in state [:images id] data)))
|
||||
|
||||
(defn image-persisted
|
||||
[{:keys [id] :as data}]
|
||||
{:pre [(map? data) (uuid? id)]}
|
||||
(ImagePersisted. id data))
|
||||
|
||||
;; --- Update Image
|
||||
|
||||
(defrecord PersistImage [id]
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [data (get-in state [:images id])]
|
||||
(->> (rp/mutation! :update-image data)
|
||||
(rx/map image-persisted)))))
|
||||
|
||||
(defn persist-image
|
||||
[id]
|
||||
{:pre [(uuid? id)]}
|
||||
(PersistImage. id))
|
||||
(ptk/reify ::persist-image
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [data (get-in state [:images id])]
|
||||
(->> (rp/mutation! :update-image data)
|
||||
(rx/ignore))))))
|
||||
|
||||
;; --- Images Fetched
|
||||
|
||||
|
|
|
@ -378,38 +378,38 @@
|
|||
(reduce ds/dissoc-shape state
|
||||
(map #(get-in state [:shapes %]) ids)))))
|
||||
|
||||
(defrecord SelectShape [id]
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [pid (get-in state [:workspace :current])
|
||||
selected (get-in state [:workspace pid :selected])]
|
||||
(if (contains? selected id)
|
||||
(update-in state [:workspace pid :selected] disj id)
|
||||
(update-in state [:workspace pid :selected] conj id))))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state s]
|
||||
(rx/of (activate-flag :element-options))))
|
||||
|
||||
(defn select-shape
|
||||
"Mark a shape selected for drawing."
|
||||
[id]
|
||||
{:pre [(uuid? id)]}
|
||||
(SelectShape. id))
|
||||
(s/assert ::us/uuid id)
|
||||
(ptk/reify ::select-shape
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(prn "select-shape$update" id)
|
||||
(let [pid (get-in state [:workspace :current])
|
||||
selected (get-in state [:workspace pid :selected])]
|
||||
(update-in state [:workspace pid :selected]
|
||||
(fn [selected]
|
||||
(if (contains? selected id)
|
||||
(disj selected id)
|
||||
(conj selected id))))))
|
||||
|
||||
(defrecord DeselectAll []
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [pid (get-in state [:workspace :current])]
|
||||
(update-in state [:workspace pid] #(-> %
|
||||
(assoc :selected #{})
|
||||
(dissoc :selected-canvas))))))
|
||||
ptk/WatchEvent
|
||||
(watch [_ state s]
|
||||
(prn "select-shape$watch" id)
|
||||
(rx/of (activate-flag :element-options)))))
|
||||
|
||||
(defn deselect-all
|
||||
(def deselect-all
|
||||
"Clear all possible state of drawing, edition
|
||||
or any similar action taken by the user."
|
||||
[]
|
||||
(DeselectAll.))
|
||||
(ptk/reify ::deselect-all
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(prn "deselect-all")
|
||||
(let [pid (get-in state [:workspace :current])]
|
||||
(update-in state [:workspace pid] #(-> %
|
||||
(assoc :selected #{})
|
||||
(dissoc :selected-canvas)))))))
|
||||
|
||||
;; --- Select First Shape
|
||||
|
||||
|
@ -1030,7 +1030,7 @@
|
|||
(rx/buffer-time 300)
|
||||
(rx/map #(into* #{} %))
|
||||
(rx/filter (complement empty?))
|
||||
(rx/tap #(prn "changed" %))
|
||||
;; (rx/tap #(prn "changed" %))
|
||||
(rx/mapcat (fn [items] (rx/from-coll
|
||||
(map rehash-shape-relationship items))))
|
||||
(rx/take-until stoper)))))))
|
||||
|
|
|
@ -425,7 +425,7 @@
|
|||
:else (first colls))
|
||||
id (:id selected-coll)]
|
||||
(mf/use-effect #(st/emit! di/fetch-collections))
|
||||
(mf/use-effect {:fn #(st/emit! (di/initialize)
|
||||
(mf/use-effect {:fn #(st/emit! di/initialize
|
||||
(di/fetch-icons id))
|
||||
:deps #js [id type]})
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
shape (merge canvas-default-props shape)]
|
||||
(letfn [(on-double-click [event]
|
||||
(dom/prevent-default event)
|
||||
(st/emit! (dw/deselect-all)
|
||||
(st/emit! dw/deselect-all
|
||||
(dw/select-shape (:id shape))))]
|
||||
[:g.shape {:class (when selected? "selected")
|
||||
:on-double-click on-double-click
|
||||
|
|
|
@ -4,6 +4,11 @@
|
|||
;;
|
||||
;; Copyright (c) 2016-2019 Andrey Antukh <niwi@niwi.nz>
|
||||
|
||||
;; TODO: we need to consider moving this under uxbox.ui.workspace
|
||||
;; namespace because this is logic only related to workspace
|
||||
;; manipulation. Staying here causes a lot of confusion and finding
|
||||
;; this code is also very difficult.
|
||||
|
||||
(ns uxbox.main.ui.shapes.common
|
||||
(:require
|
||||
[potok.core :as ptk]
|
||||
|
@ -13,26 +18,29 @@
|
|||
[uxbox.main.store :as st]
|
||||
[uxbox.main.ui.keyboard :as kbd]
|
||||
[uxbox.main.ui.workspace.streams :as uws]
|
||||
[uxbox.main.workers :as uwrk]
|
||||
[uxbox.util.geom.matrix :as gmt]
|
||||
[uxbox.util.geom.point :as gpt]
|
||||
[uxbox.util.dom :as dom]))
|
||||
|
||||
;; --- Shape Movement (by mouse)
|
||||
|
||||
(def start-move-selected
|
||||
(reify
|
||||
(ptk/reify ::start-move-selected
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [pid (get-in state [:workspace :current])
|
||||
flags (get-in state [:workspace pid :flags])
|
||||
selected (get-in state [:workspace pid :selected])
|
||||
stoper (rx/filter uws/mouse-up? stream)]
|
||||
stoper (rx/filter uws/mouse-up? stream)
|
||||
position @uws/mouse-position]
|
||||
(rx/concat
|
||||
(when (refs/alignment-activated? flags)
|
||||
(rx/of (dw/initial-selection-align selected)))
|
||||
(->> uws/mouse-position-deltas
|
||||
(->> (uws/mouse-position-deltas position)
|
||||
(rx/map #(dw/apply-temporal-displacement-in-bulk selected %))
|
||||
(rx/take-until stoper))
|
||||
(rx/of (dw/materialize-current-modifier-in-bulk selected)))))))
|
||||
(rx/of (dw/materialize-current-modifier-in-bulk selected)))))))
|
||||
|
||||
(defn on-mouse-down
|
||||
[event {:keys [id type] :as shape} selected]
|
||||
|
@ -51,7 +59,7 @@
|
|||
(and (not selected?) (empty? selected))
|
||||
(do
|
||||
(dom/stop-propagation event)
|
||||
(st/emit! (dw/deselect-all)
|
||||
(st/emit! dw/deselect-all
|
||||
(dw/select-shape id)
|
||||
start-move-selected))
|
||||
|
||||
|
@ -60,7 +68,7 @@
|
|||
(dom/stop-propagation event)
|
||||
(if (kbd/shift? event)
|
||||
(st/emit! (dw/select-shape id))
|
||||
(st/emit! (dw/deselect-all)
|
||||
(st/emit! dw/deselect-all
|
||||
(dw/select-shape id)
|
||||
start-move-selected)))
|
||||
:else
|
||||
|
|
|
@ -154,10 +154,10 @@
|
|||
[{:keys [shape modifiers zoom] :as props}]
|
||||
(letfn [(on-mouse-down [event index]
|
||||
(dom/stop-propagation event)
|
||||
|
||||
;; TODO: this need code ux refactor
|
||||
(let [stoper (get-edition-stream-stoper)
|
||||
stream (rx/take-until stoper ws/mouse-position-deltas)]
|
||||
stream (->> (ws/mouse-position-deltas @ws/mouse-position)
|
||||
(rx/take-until stoper))]
|
||||
(when @refs/selected-alignment
|
||||
(st/emit! (dw/initial-path-point-align (:id shape) index)))
|
||||
(rx/subscribe stream #(on-handler-move % index))))
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
:ctrl+b #(st/emit! (dw/select-for-drawing :rect))
|
||||
:ctrl+e #(st/emit! (dw/select-for-drawing :circle))
|
||||
:ctrl+t #(st/emit! (dw/select-for-drawing :text))
|
||||
:esc #(st/emit! (dw/deselect-all))
|
||||
:esc #(st/emit! dw/deselect-all)
|
||||
:delete #(st/emit! dw/delete-selected)
|
||||
:ctrl+up #(st/emit! (dw/order-selected-shapes :up))
|
||||
:ctrl+down #(st/emit! (dw/order-selected-shapes :down))
|
||||
|
|
|
@ -57,7 +57,7 @@
|
|||
(dw/select-for-drawing tool)))
|
||||
(toggle-ruler [event]
|
||||
(st/emit! (dw/select-for-drawing nil)
|
||||
(dw/deselect-all)
|
||||
dw/deselect-all
|
||||
(dw/toggle-ruler)))]
|
||||
|
||||
(let [selected (mf/deref refs/selected-drawing-tool)
|
||||
|
|
|
@ -100,10 +100,10 @@
|
|||
(st/emit! (dw/select-shape id))
|
||||
|
||||
(> (count selected) 1)
|
||||
(st/emit! (dw/deselect-all)
|
||||
(st/emit! dw/deselect-all
|
||||
(dw/select-shape id))
|
||||
:else
|
||||
(st/emit! (dw/deselect-all)
|
||||
(st/emit! dw/deselect-all
|
||||
(dw/select-shape id)))))
|
||||
|
||||
(on-drop [item monitor]
|
||||
|
@ -161,10 +161,10 @@
|
|||
(st/emit! (dw/select-shape id))
|
||||
|
||||
(> (count selected) 1)
|
||||
(st/emit! (dw/deselect-all)
|
||||
(st/emit! dw/deselect-all
|
||||
(dw/select-shape id))
|
||||
:else
|
||||
(st/emit! (dw/deselect-all)
|
||||
(st/emit! dw/deselect-all
|
||||
(dw/select-shape id)))))
|
||||
|
||||
(on-drop [item monitor]
|
||||
|
|
|
@ -92,7 +92,6 @@
|
|||
|
||||
(mf/defc sitemap-toolbox
|
||||
[{:keys [project-id current-page-id] :as props}]
|
||||
(prn "sitemap-toolbox" props)
|
||||
(let [project-iref (mf/use-memo {:deps #js [project-id]
|
||||
:fn #(-> (l/in [:projects project-id])
|
||||
(l/derive st/state))})
|
||||
|
|
|
@ -94,9 +94,11 @@
|
|||
(rx/subscribe-with ob sub)
|
||||
sub))
|
||||
|
||||
(defonce mouse-position-deltas
|
||||
(->> mouse-position
|
||||
(rx/sample 10)
|
||||
|
||||
(defn mouse-position-deltas
|
||||
[current]
|
||||
(->> (rx/concat (rx/of current)
|
||||
(rx/sample 10 mouse-position))
|
||||
(rx/map #(gpt/divide % @refs/selected-zoom))
|
||||
(rx/mapcat (fn [point]
|
||||
(if @refs/selected-alignment
|
||||
|
@ -104,8 +106,7 @@
|
|||
(rx/of point))))
|
||||
(rx/buffer 2 1)
|
||||
(rx/map (fn [[old new]]
|
||||
(gpt/subtract new old)))
|
||||
(rx/share)))
|
||||
(gpt/subtract new old)))))
|
||||
|
||||
(defonce viewport-scroll
|
||||
(let [sub (rx/behavior-subject nil)
|
||||
|
|
|
@ -90,7 +90,7 @@
|
|||
(watch [_ state stream]
|
||||
(let [stoper (rx/filter #(or (dw/interrupt? %) (uws/mouse-up? %)) stream)]
|
||||
(rx/concat
|
||||
(rx/of (dw/deselect-all))
|
||||
(rx/of dw/deselect-all)
|
||||
(->> uws/mouse-position
|
||||
(rx/map (fn [pos] #(update-state % pos)))
|
||||
(rx/take-until stoper))
|
||||
|
|
|
@ -50,7 +50,6 @@
|
|||
(s/def ::email email?)
|
||||
(s/def ::color color?)
|
||||
(s/def ::string string?)
|
||||
(s/def ::number number?)
|
||||
(s/def ::positive pos?)
|
||||
(s/def ::inst inst?)
|
||||
(s/def ::keyword keyword?)
|
||||
|
@ -62,15 +61,18 @@
|
|||
(s/and string? #(not (str/empty? %))))
|
||||
|
||||
|
||||
(defn- conform-number-str
|
||||
(defn- conform-number
|
||||
[v]
|
||||
(cond
|
||||
(re-matches number-rx v) (js/parseFloat v)
|
||||
(number? v) v
|
||||
(re-matches number-rx v) (js/parseFloat v)
|
||||
:else ::s/invalid))
|
||||
|
||||
(s/def ::number-str
|
||||
(s/conformer conform-number-str str))
|
||||
(s/def ::number
|
||||
(s/conformer conform-number str))
|
||||
|
||||
;; NOTE: backward compatibility (revisit the code and remove)
|
||||
(s/def ::number-str ::number)
|
||||
|
||||
(s/def ::color color?)
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue