mirror of
https://github.com/penpot/penpot.git
synced 2025-03-31 00:51:19 -05:00
Merge pull request #1554 from penpot/feat/tablet-improvements
Tablet improvements
This commit is contained in:
commit
809a3420c1
27 changed files with 255 additions and 180 deletions
CHANGES.md
frontend
resources
src/app
main
data
snap.cljsui
worker
|
@ -22,6 +22,7 @@
|
|||
- Add update components in bulk option in context menu [Taiga #1975](https://tree.taiga.io/project/penpot/us/1975)
|
||||
- Create first E2E tests [Taiga #2608](https://tree.taiga.io/project/penpot/task/2608), [Taiga #2608](https://tree.taiga.io/project/penpot/task/2608)
|
||||
- Redesign of workspace toolbars [Taiga #2319](https://tree.taiga.io/project/penpot/us/2319)
|
||||
- Graphic Tablet usability improvements [Taiga #1913](https://tree.taiga.io/project/penpot/us/1913)
|
||||
|
||||
### :bug: Bugs fixed
|
||||
|
||||
|
|
1
frontend/resources/images/cursors/zoom-in.svg
Normal file
1
frontend/resources/images/cursors/zoom-in.svg
Normal file
File diff suppressed because one or more lines are too long
After (image error) Size: 5.3 KiB |
1
frontend/resources/images/cursors/zoom-out.svg
Normal file
1
frontend/resources/images/cursors/zoom-out.svg
Normal file
File diff suppressed because one or more lines are too long
After (image error) Size: 5 KiB |
1
frontend/resources/images/cursors/zoom.svg
Normal file
1
frontend/resources/images/cursors/zoom.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 16 16"><path fill="#fff" d="m 6.4964905,0.03321911 0.00744,0.0074534 C 4.6999927,0.031092 2.9450522,0.83074764 1.7486196,2.1649163 0.56182888,3.4260039 -0.04971135,5.156338 0.04177115,6.8680661 0.10288679,8.7605997 1.0637539,10.556814 2.5461426,11.712833 c 0.00192,0.0015 0.00553,-0.0015 0.00745,0 1.2922365,1.023254 2.9766407,1.511254 4.6137085,1.349081 1.1161094,-0.07753 2.1071715,-0.580519 3.0112089,-1.162744 1.296873,1.174846 2.78455,2.703061 3.980162,3.808731 l 0.0298,0.02236 0.03728,0.02236 c 0.700715,0.463588 1.657243,-0.01304 1.699388,-0.857156 0.02838,-0.352217 -0.136032,-0.659199 -0.290686,-0.842243 -0.158745,-0.187888 -0.308651,-0.312341 -0.372674,-0.387582 l -0.0074,-0.0074 -0.01492,-0.01492 C 14.11624,12.47794 12.970225,11.352196 11.84064,10.214682 12.527595,9.1760037 13.099816,8.0101087 13.10028,6.7264501 13.134631,5.6521372 12.907519,4.560056 12.399652,3.5959857 11.415011,1.6579104 9.4457338,0.26063069 7.2567459,0.06303305 h -0.00744 C 7.170251,0.05547197 7.0898604,0.06029116 7.010781,0.05557958 V 0.03321911 H 6.5113973 c -0.00492,6.098e-5 -0.01,-7.114e-5 -0.014921,0 z m 0.00744,1.00622069 h 0.00744 c 0.2157633,-0.00312 0.4353294,0.00918 0.6484535,0.029816 1.8136614,0.1617211 3.512138,1.3634369 4.337929,2.988848 h 0.0074 v 0.00744 c 0.423055,0.8005342 0.620192,1.7218025 0.588861,2.6385444 l -0.0074,0.00744 v 0.00744 C 12.087155,7.2930556 11.696556,7.7880155 11.49778,8.3364032 11.959073,7.0529442 11.954648,5.6116005 11.378524,4.3711484 10.566052,2.5563955 8.6997409,1.2872828 6.690281,1.2854049 c -0.016448,-9.3e-6 -0.025645,-1.064e-4 -0.037284,0 C 5.6835006,1.2469899 4.8054067,1.6884939 3.9846658,2.1723698 4.8051598,1.6924176 5.560624,1.0328147 6.5039441,1.0394398 Z m 0.1043608,1.2521857 h 0.014921 0.00744 c 0.025988,0 0.045886,-7.7e-6 0.059628,0 1.5779426,0.00147 3.1274607,1.05334 3.7714647,2.4969181 v 0.00745 c 0.475311,1.0233978 0.509156,2.2655936 0.09689,3.3168015 C 10.004397,9.5330276 8.6262057,10.634487 7.11513,10.803507 6.4369561,10.879852 5.7520944,10.829918 5.1474095,10.59481 h -0.00744 l -0.014921,-0.0074 C 3.5196969,10.041029 2.3172339,8.3845631 2.3001776,6.6891824 v -0.00744 -0.00744 C 2.2422595,5.3475835 2.8983919,3.9979266 3.9548517,3.1860439 v -0.00745 C 4.7083326,2.59014 5.6662428,2.2542985 6.6082929,2.2916255 Z M 3.2840378,2.4854162 C 2.0227512,3.5031372 1.2335156,5.0761291 1.3014104,6.711543 c 0.02561,2.0689039 1.4556686,3.8931 3.368976,4.650976 C 4.1727677,11.168763 3.588021,11.252807 3.1722355,10.922763 1.921116,9.9503584 1.1044674,8.405061 1.0554453,6.8307988 v -0.00745 -0.00745 C 0.97705516,5.3800416 1.4978773,3.9011665 2.4865147,2.850637 l 0.00745,-0.00745 C 2.692098,2.6215255 3.0509516,2.6712244 3.2840378,2.4854162 Z m 8.1392072,6.0522313 c -0.207774,0.5116264 -0.214629,1.0820609 -0.551558,1.5279645 l -0.26087,0.350314 0.305592,0.313046 c 1.202105,1.215313 2.425542,2.396368 3.600034,3.614941 0.14405,0.163718 0.282012,0.284382 0.350315,0.36522 0.07257,0.08589 0.06228,0.08027 0.05963,0.10435 v 0.01492 0.01492 c -6.59e-4,0.01725 -0.131055,0.07407 -0.141614,0.06708 -1.21107,-1.124754 -2.767494,-2.746602 -4.136689,-3.965283 L 10.34249,10.6768 10.014538,10.915311 C 9.1381844,11.54723 8.128202,11.993164 7.0927694,12.063147 h -0.00744 -0.00744 c -0.5298918,0.05394 -0.9797777,-0.334046 -1.5056281,-0.439756 0.5533968,0.105743 1.111125,0.247527 1.6546738,0.186337 1.8812957,-0.210432 3.4805459,-1.544919 4.1963129,-3.2720805 z"/><path fill="#000" d="M 6.5057886,0.53690631 C 4.8495208,0.52527405 3.2184686,1.2751981 2.1168078,2.5076844 1.0282616,3.6643773 0.4620335,5.2699249 0.54801837,6.8448874 0.60208959,8.5812943 1.4919832,10.255957 2.8619738,11.320751 c 1.1904486,0.944959 2.7570918,1.401161 4.2667258,1.247477 1.1564373,-0.07816 2.2481169,-0.570566 3.1812114,-1.243402 1.363987,1.214045 2.95622,2.865801 4.193161,4.009691 0.357485,0.23651 0.908535,-0.03415 0.92515,-0.468986 0.0427,-0.388292 -0.332082,-0.613376 -0.550464,-0.870022 C 13.695808,12.7692 12.475161,11.581081 11.277545,10.370305 12.070118,9.3213873 12.596425,8.0430886 12.595161,6.721349 12.629307,5.7222245 12.418801,4.7133217 11.950985,3.8280243 11.045283,2.0453248 9.2083701,0.74377285 7.2057503,0.56520271 6.9731801,0.54268863 6.7393907,0.53368305 6.5057886,0.53706014 Z M 6.6915682,1.7899367 C 8.486386,1.791614 10.193952,2.949744 10.921471,4.5805261 11.457485,5.7346187 11.495958,7.110861 11.031677,8.2947057 10.407903,9.8931015 8.8836612,11.117029 7.1695625,11.308758 6.4289257,11.392135 5.6652945,11.338027 4.9659973,11.066132 3.1453092,10.446523 1.8162042,8.6212193 1.7968421,6.6966511 1.7312137,5.1933436 2.4570475,3.6978407 3.6458487,2.7842545 4.4886284,2.1260639 5.5579063,1.7477491 6.6315258,1.7902894 c 0.019882,0 0.040039,-3.602e-4 0.060036,-3.489e-4 z"/></svg>
|
After (image error) Size: 4.7 KiB |
|
@ -2,7 +2,9 @@
|
|||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: scroll;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.debug-icons-preview {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
|
|
@ -834,4 +834,15 @@
|
|||
action (if in-project? file-created project-created)]
|
||||
|
||||
(->> (rp/mutation! action-name params)
|
||||
(rx/map action))))))
|
||||
(rx/map action))))))
|
||||
|
||||
(defn open-selected-file
|
||||
[]
|
||||
(ptk/reify ::open-selected-file
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [files (get-in state [:dashboard-local :selected-files])]
|
||||
(if (= 1 (count files))
|
||||
(let [file (get-in state [:dashboard-files (first files)])]
|
||||
(rx/of (go-to-workspace file)))
|
||||
(rx/empty))))))
|
||||
|
|
|
@ -196,7 +196,7 @@
|
|||
|
||||
(->> stream
|
||||
(rx/filter #(= ::dwc/index-initialized %))
|
||||
(rx/first)
|
||||
(rx/take 1)
|
||||
(rx/map #(file-initialized bundle)))))))))
|
||||
|
||||
ptk/EffectEvent
|
||||
|
@ -1636,7 +1636,7 @@
|
|||
(->> (rx/concat paste-transit-str
|
||||
paste-plain-text-str
|
||||
paste-image-str)
|
||||
(rx/first)
|
||||
(rx/take 1)
|
||||
(rx/catch
|
||||
(fn [err]
|
||||
(js/console.error "Clipboard error:" err)
|
||||
|
|
|
@ -206,11 +206,9 @@
|
|||
stop? (rx/filter (ptk/type? ::stop-picker) stream)
|
||||
|
||||
update-events
|
||||
(fn [[color shift?]]
|
||||
(rx/of (if shift?
|
||||
(change-stroke ids color)
|
||||
(change-fill ids color))
|
||||
(stop-picker)))]
|
||||
(fn [color]
|
||||
(rx/of (change-fill ids color)))]
|
||||
|
||||
(rx/merge
|
||||
;; Stream that updates the stroke/width and stops if `esc` pressed
|
||||
(->> sub
|
||||
|
@ -219,12 +217,12 @@
|
|||
|
||||
;; Hide the modal if the stop event is emitted
|
||||
(->> stop?
|
||||
(rx/first)
|
||||
(rx/take 1)
|
||||
(rx/map #(md/hide))))))
|
||||
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [handle-change-color (fn [color shift?] (rx/push! sub [color shift?]))]
|
||||
(let [handle-change-color (fn [color] (rx/push! sub color))]
|
||||
(-> state
|
||||
(assoc-in [:workspace-local :picking-color?] true)
|
||||
(assoc ::md/modal {:id (random-uuid)
|
||||
|
|
|
@ -314,37 +314,41 @@
|
|||
[redo-changes undo-changes])))
|
||||
|
||||
(defn add-shape
|
||||
[attrs]
|
||||
(us/verify ::shape-attrs attrs)
|
||||
(ptk/reify ::add-shape
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
([attrs]
|
||||
(add-shape attrs {}))
|
||||
|
||||
id (or (:id attrs) (uuid/next))
|
||||
name (-> objects
|
||||
(retrieve-used-names)
|
||||
(generate-unique-name (:name attrs)))
|
||||
([attrs {:keys [no-select?]}]
|
||||
(us/verify ::shape-attrs attrs)
|
||||
(ptk/reify ::add-shape
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
|
||||
selected (wsh/lookup-selected state)
|
||||
id (or (:id attrs) (uuid/next))
|
||||
name (-> objects
|
||||
(retrieve-used-names)
|
||||
(generate-unique-name (:name attrs)))
|
||||
|
||||
[rchanges uchanges] (add-shape-changes
|
||||
page-id
|
||||
objects
|
||||
selected
|
||||
(-> attrs
|
||||
(assoc :id id )
|
||||
(assoc :name name)))]
|
||||
selected (wsh/lookup-selected state)
|
||||
|
||||
(rx/concat
|
||||
(rx/of (dch/commit-changes {:redo-changes rchanges
|
||||
:undo-changes uchanges
|
||||
:origin it})
|
||||
(select-shapes (d/ordered-set id)))
|
||||
(when (= :text (:type attrs))
|
||||
(->> (rx/of (start-edition-mode id))
|
||||
(rx/observe-on :async))))))))
|
||||
[rchanges uchanges] (add-shape-changes
|
||||
page-id
|
||||
objects
|
||||
selected
|
||||
(-> attrs
|
||||
(assoc :id id )
|
||||
(assoc :name name)))]
|
||||
|
||||
(rx/concat
|
||||
(rx/of (dch/commit-changes {:redo-changes rchanges
|
||||
:undo-changes uchanges
|
||||
:origin it})
|
||||
(when-not no-select?
|
||||
(select-shapes (d/ordered-set id))))
|
||||
(when (= :text (:type attrs))
|
||||
(->> (rx/of (start-edition-mode id))
|
||||
(rx/observe-on :async)))))))))
|
||||
|
||||
(defn move-shapes-into-frame [frame-id shapes]
|
||||
(ptk/reify ::move-shapes-into-frame
|
||||
|
|
|
@ -42,6 +42,15 @@
|
|||
(when (= tool :path)
|
||||
(rx/of (start-drawing :path)))
|
||||
|
||||
(when (= tool :curve)
|
||||
(let [stopper (->> stream (rx/filter dwc/interrupt?))]
|
||||
(->> stream
|
||||
(rx/filter (ptk/type? ::common/handle-finish-drawing))
|
||||
(rx/take 1)
|
||||
(rx/observe-on :async)
|
||||
(rx/map #(select-for-drawing tool data))
|
||||
(rx/take-until stopper))))
|
||||
|
||||
;; NOTE: comments are a special case and they manage they
|
||||
;; own interrupt cycle.q
|
||||
(when (and (not= tool :comments)
|
||||
|
@ -74,7 +83,7 @@
|
|||
(rx/of (handle-drawing type))
|
||||
(->> stream
|
||||
(rx/filter (ptk/type? ::common/handle-finish-drawing) )
|
||||
(rx/first)
|
||||
(rx/take 1)
|
||||
(rx/map #(fn [state] (update state :workspace-drawing dissoc :lock)))))))))))
|
||||
|
||||
(defn handle-drawing
|
||||
|
|
|
@ -24,7 +24,8 @@
|
|||
(ptk/reify ::handle-finish-drawing
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [shape (get-in state [:workspace-drawing :object])]
|
||||
(let [tool (get-in state [:workspace-drawing :tool])
|
||||
shape (get-in state [:workspace-drawing :object])]
|
||||
(rx/concat
|
||||
(when (:initialized? shape)
|
||||
(let [page-id (:current-page-id state)
|
||||
|
@ -55,7 +56,7 @@
|
|||
(rx/of (dwu/start-undo-transaction))
|
||||
(rx/empty))
|
||||
|
||||
(rx/of (dwc/add-shape shape))
|
||||
(rx/of (dwc/add-shape shape {:no-select? (= tool :curve)}))
|
||||
|
||||
(if (= :frame (:type shape))
|
||||
(->> (uw/ask! {:cmd :selection/query
|
||||
|
|
|
@ -70,7 +70,7 @@
|
|||
(let [opacity-events (->> stream ;; Stop buffering after time without opacities
|
||||
(rx/filter (ptk/type? ::pressed-opacity))
|
||||
(rx/buffer-time 600)
|
||||
(rx/first)
|
||||
(rx/take 1)
|
||||
(rx/map #(set-opacity (calculate-opacity (map deref %)))))]
|
||||
(rx/concat
|
||||
(rx/of (set-opacity (calculate-opacity [opacity]))) ;; First opacity is always fired
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
[app.common.data :as d]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.shapes :as geom]
|
||||
[app.common.math :as mth]
|
||||
[app.common.pages :as cp]
|
||||
[app.common.spec :as us]
|
||||
[app.common.spec.interactions :as cti]
|
||||
|
@ -47,51 +46,58 @@
|
|||
(assoc-in state [:workspace-local :selrect] selrect))))
|
||||
|
||||
(defn handle-area-selection
|
||||
[preserve?]
|
||||
(letfn [(data->selrect [data]
|
||||
(let [start (:start data)
|
||||
stop (:stop data)
|
||||
start-x (min (:x start) (:x stop))
|
||||
start-y (min (:y start) (:y stop))
|
||||
end-x (max (:x start) (:x stop))
|
||||
end-y (max (:y start) (:y stop))]
|
||||
{:type :rect
|
||||
:x start-x
|
||||
:y start-y
|
||||
:width (mth/abs (- end-x start-x))
|
||||
:height (mth/abs (- end-y start-y))}))]
|
||||
(ptk/reify ::handle-area-selection
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [zoom (get-in state [:workspace-local :zoom] 1)
|
||||
stop? (fn [event] (or (dwc/interrupt? event) (ms/mouse-up? event)))
|
||||
stoper (->> stream (rx/filter stop?))
|
||||
[preserve? ignore-groups?]
|
||||
(ptk/reify ::handle-area-selection
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [zoom (get-in state [:workspace-local :zoom] 1)
|
||||
stop? (fn [event] (or (dwc/interrupt? event) (ms/mouse-up? event)))
|
||||
stoper (->> stream (rx/filter stop?))
|
||||
|
||||
calculate-selrect
|
||||
(fn [data pos]
|
||||
(if data
|
||||
(assoc data :stop pos)
|
||||
{:start pos :stop pos}))
|
||||
init-selrect
|
||||
{:type :rect
|
||||
:x (:x @ms/mouse-position)
|
||||
:y (:y @ms/mouse-position)
|
||||
:width 0
|
||||
:height 0}
|
||||
|
||||
selrect-stream
|
||||
(->> ms/mouse-position
|
||||
(rx/scan calculate-selrect nil)
|
||||
(rx/map data->selrect)
|
||||
(rx/filter #(or (> (:width %) (/ 10 zoom))
|
||||
(> (:height %) (/ 10 zoom))))
|
||||
(rx/take-until stoper))]
|
||||
(rx/concat
|
||||
(if preserve?
|
||||
(rx/empty)
|
||||
(rx/of (deselect-all)))
|
||||
calculate-selrect
|
||||
(fn [selrect [delta space?]]
|
||||
(if space?
|
||||
(-> selrect
|
||||
(update :x + (:x delta))
|
||||
(update :y + (:y delta)))
|
||||
|
||||
(rx/merge
|
||||
(->> selrect-stream (rx/map update-selrect))
|
||||
(->> selrect-stream
|
||||
(rx/debounce 50)
|
||||
(rx/map #(select-shapes-by-current-selrect preserve?))))
|
||||
(-> selrect
|
||||
(update :width + (:x delta))
|
||||
(update :height + (:y delta)))))
|
||||
|
||||
(rx/of (update-selrect nil))))))))
|
||||
selrect-stream
|
||||
(->> ms/mouse-position
|
||||
(rx/buffer 2 1)
|
||||
(rx/map (fn [[from to]] (when (and from to) (gpt/to-vec from to))))
|
||||
(rx/filter some?)
|
||||
(rx/with-latest-from ms/keyboard-space)
|
||||
(rx/scan calculate-selrect init-selrect)
|
||||
(rx/filter #(or (> (:width %) (/ 10 zoom))
|
||||
(> (:height %) (/ 10 zoom))))
|
||||
(rx/take-until stoper))]
|
||||
(rx/concat
|
||||
(if preserve?
|
||||
(rx/empty)
|
||||
(rx/of (deselect-all)))
|
||||
|
||||
(rx/merge
|
||||
(->> selrect-stream
|
||||
(rx/map update-selrect))
|
||||
|
||||
(->> selrect-stream
|
||||
(rx/buffer-time 100)
|
||||
(rx/map #(last %))
|
||||
(rx/dedupe)
|
||||
(rx/map #(select-shapes-by-current-selrect preserve? ignore-groups?))))
|
||||
|
||||
(rx/of (update-selrect nil)))))))
|
||||
|
||||
;; --- Toggle shape's selection status (selected or deselected)
|
||||
|
||||
|
@ -216,7 +222,7 @@
|
|||
;; --- Select Shapes (By selrect)
|
||||
|
||||
(defn select-shapes-by-current-selrect
|
||||
[preserve?]
|
||||
[preserve? ignore-groups?]
|
||||
(ptk/reify ::select-shapes-by-current-selrect
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
|
@ -235,6 +241,7 @@
|
|||
:page-id page-id
|
||||
:rect selrect
|
||||
:include-frames? true
|
||||
:ignore-groups? ignore-groups?
|
||||
:full-frame? true})
|
||||
(rx/map #(cp/clean-loops objects %))
|
||||
(rx/map #(into initial-set (filter (comp not blocked?)) %))
|
||||
|
|
|
@ -80,7 +80,7 @@
|
|||
:fn #(st/emit! (dw/toggle-layout-flags :scale-text))}
|
||||
|
||||
:increase-zoom {:tooltip "+"
|
||||
:command "+"
|
||||
:command ["+" "="]
|
||||
:fn #(st/emit! (dw/increase-zoom nil))}
|
||||
|
||||
:decrease-zoom {:tooltip "-"
|
||||
|
|
|
@ -523,7 +523,7 @@
|
|||
(watch [_ _ stream]
|
||||
(->> stream
|
||||
(rx/filter (ptk/type? ::dws/duplicate-selected))
|
||||
(rx/first)
|
||||
(rx/take 1)
|
||||
(rx/map #(start-move from-position))))))
|
||||
|
||||
(defn- start-move
|
||||
|
@ -612,7 +612,7 @@
|
|||
(rx/filter #(= direction (deref %))))
|
||||
stopper (->> move-events
|
||||
(rx/debounce 100)
|
||||
(rx/first))
|
||||
(rx/take 1))
|
||||
scale (if shift? (gpt/point (:big nudge)) (gpt/point (:small nudge)))
|
||||
mov-vec (gpt/multiply (get-displacement direction) scale)]
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@
|
|||
:frame-id frame-id
|
||||
:axis coord
|
||||
:ranges [[(- value 0.5) (+ value 0.5)]]})
|
||||
(rx/first)
|
||||
(rx/take 1)
|
||||
(rx/map (remove-from-snap-points remove-snap?))
|
||||
(rx/map flatten-to-points))))
|
||||
|
||||
|
@ -98,7 +98,7 @@
|
|||
:frame-id frame-id
|
||||
:axis coord
|
||||
:ranges ranges})
|
||||
(rx/first)
|
||||
(rx/take 1)
|
||||
(rx/map (remove-from-snap-points remove-snap?))
|
||||
(rx/map (get-min-distance-snap points coord)))))
|
||||
|
||||
|
|
|
@ -30,6 +30,9 @@
|
|||
(def pointer-node (cursor-ref :pointer-node 0 0 10 32))
|
||||
(def resize-alt (cursor-ref :resize-alt))
|
||||
(def text (cursor-ref :text))
|
||||
(def zoom (cursor-ref :zoom))
|
||||
(def zoom-in (cursor-ref :zoom-in))
|
||||
(def zoom-out (cursor-ref :zoom-out))
|
||||
|
||||
;; Dynamic cursors
|
||||
(def resize-ew (cursor-fn :resize-h 0))
|
||||
|
|
|
@ -22,7 +22,10 @@
|
|||
[app.main.ui.dashboard.sidebar :refer [sidebar]]
|
||||
[app.main.ui.dashboard.team :refer [team-settings-page team-members-page]]
|
||||
[app.main.ui.hooks :as hooks]
|
||||
[rumext.alpha :as mf]))
|
||||
[app.util.keyboard :as kbd]
|
||||
[goog.events :as events]
|
||||
[rumext.alpha :as mf])
|
||||
(:import goog.events.EventType))
|
||||
|
||||
(defn ^boolean uuid-str?
|
||||
[s]
|
||||
|
@ -95,6 +98,16 @@
|
|||
(mf/with-effect [team-id]
|
||||
(st/emit! (dd/initialize {:id team-id})))
|
||||
|
||||
(mf/use-effect
|
||||
(fn []
|
||||
(let [events [(events/listen goog/global EventType.KEYDOWN
|
||||
(fn [event]
|
||||
(when (kbd/enter? event)
|
||||
(st/emit! (dd/open-selected-file)))))]]
|
||||
(fn []
|
||||
(doseq [key events]
|
||||
(events/unlistenByKey key))))))
|
||||
|
||||
[:& (mf/provider ctx/current-team-id) {:value team-id}
|
||||
[:& (mf/provider ctx/current-project-id) {:value project-id}
|
||||
;; NOTE: dashboard events and other related functions assumes
|
||||
|
|
|
@ -226,9 +226,9 @@
|
|||
|
||||
;; Updates color when used el pixel picker
|
||||
(mf/use-effect
|
||||
(mf/deps picking-color? picked-color-select)
|
||||
(mf/deps picking-color? picked-color picked-color-select)
|
||||
(fn []
|
||||
(when (and picking-color? picked-color-select)
|
||||
(when (and picking-color? picked-color picked-color-select)
|
||||
(let [[r g b alpha] picked-color
|
||||
hex (uc/rgb->hex [r g b])
|
||||
[h s v] (uc/hex->hsv hex)]
|
||||
|
|
|
@ -77,13 +77,11 @@
|
|||
|
||||
update-color
|
||||
(fn [index]
|
||||
(fn [color opacity]
|
||||
(fn [color]
|
||||
(let [color (dissoc color :id :file-id :gradient)]
|
||||
(st/emit! (dch/update-shapes
|
||||
ids
|
||||
#(-> %
|
||||
(assoc-in [:shadow index :color] color)
|
||||
(assoc-in [:shadow index :opacity] opacity)))))))
|
||||
#(assoc-in % [:shadow index :color] color))))))
|
||||
|
||||
detach-color
|
||||
(fn [index]
|
||||
|
|
|
@ -115,21 +115,21 @@
|
|||
node-editing? (and edition (not= :text (get-in base-objects [edition :type])))
|
||||
text-editing? (and edition (= :text (get-in base-objects [edition :type])))
|
||||
|
||||
on-click (actions/on-click hover selected edition drawing-path? drawing-tool)
|
||||
on-click (actions/on-click hover selected edition drawing-path? drawing-tool space?)
|
||||
on-context-menu (actions/on-context-menu hover hover-ids)
|
||||
on-double-click (actions/on-double-click hover hover-ids drawing-path? base-objects edition)
|
||||
on-drag-enter (actions/on-drag-enter)
|
||||
on-drag-over (actions/on-drag-over)
|
||||
on-drop (actions/on-drop file viewport-ref zoom)
|
||||
on-mouse-down (actions/on-mouse-down @hover selected edition drawing-tool text-editing? node-editing?
|
||||
drawing-path? create-comment? space? viewport-ref zoom)
|
||||
drawing-path? create-comment? space? viewport-ref zoom panning)
|
||||
on-mouse-up (actions/on-mouse-up disable-paste)
|
||||
on-pointer-down (actions/on-pointer-down)
|
||||
on-pointer-enter (actions/on-pointer-enter in-viewport?)
|
||||
on-pointer-leave (actions/on-pointer-leave in-viewport?)
|
||||
on-pointer-move (actions/on-pointer-move viewport-ref zoom move-stream)
|
||||
on-pointer-up (actions/on-pointer-up)
|
||||
on-move-selected (actions/on-move-selected hover hover-ids selected)
|
||||
on-move-selected (actions/on-move-selected hover hover-ids selected space?)
|
||||
on-menu-selected (actions/on-menu-selected hover hover-ids selected)
|
||||
|
||||
on-frame-enter (actions/on-frame-enter frame-hover)
|
||||
|
@ -142,7 +142,7 @@
|
|||
show-draw-area? drawing-obj
|
||||
show-gradient-handlers? (= (count selected) 1)
|
||||
show-grids? (contains? layout :display-grid)
|
||||
show-outlines? (and (nil? transform) (not edition) (not drawing-obj) (not (#{:comments :path} drawing-tool)))
|
||||
show-outlines? (and (nil? transform) (not edition) (not drawing-obj) (not (#{:comments :path :curve} drawing-tool)))
|
||||
show-pixel-grid? (>= zoom 8)
|
||||
show-presence? page-id
|
||||
show-prototypes? (= options-mode :prototype)
|
||||
|
@ -162,15 +162,13 @@
|
|||
|
||||
(hooks/setup-dom-events viewport-ref zoom disable-paste in-viewport?)
|
||||
(hooks/setup-viewport-size viewport-ref)
|
||||
(hooks/setup-cursor cursor alt? panning drawing-tool drawing-path? node-editing?)
|
||||
(hooks/setup-cursor cursor alt? ctrl? space? panning drawing-tool drawing-path? node-editing?)
|
||||
(hooks/setup-keyboard alt? ctrl? space?)
|
||||
(hooks/setup-hover-shapes page-id move-stream base-objects transform selected ctrl? hover hover-ids @hover-disabled? zoom)
|
||||
(hooks/setup-viewport-modifiers modifiers base-objects)
|
||||
(hooks/setup-shortcuts node-editing? drawing-path?)
|
||||
(hooks/setup-active-frames base-objects vbox hover active-frames)
|
||||
|
||||
|
||||
|
||||
[:div.viewport
|
||||
[:div.viewport-overlays
|
||||
|
||||
|
@ -245,24 +243,18 @@
|
|||
[:& outline/shape-outlines
|
||||
{:objects base-objects
|
||||
:selected selected
|
||||
:hover (when (not= :frame (:type @hover))
|
||||
:hover (when (or @ctrl? (not= :frame (:type @hover)))
|
||||
#{(or @frame-hover (:id @hover))})
|
||||
:edition edition
|
||||
:zoom zoom}])
|
||||
|
||||
[:& scroll-bars/viewport-scrollbars
|
||||
{:objects base-objects
|
||||
:zoom zoom
|
||||
:vbox vbox
|
||||
:viewport-ref viewport-ref}]
|
||||
|
||||
(when show-selection-handlers?
|
||||
[:& selection/selection-handlers
|
||||
{:selected selected
|
||||
:shapes selected-shapes
|
||||
:zoom zoom
|
||||
:edition edition
|
||||
:disable-handlers (or drawing-tool edition)
|
||||
:disable-handlers (or drawing-tool edition @space?)
|
||||
:on-move-selected on-move-selected
|
||||
:on-context-menu on-menu-selected}])
|
||||
|
||||
|
@ -363,6 +355,12 @@
|
|||
|
||||
[:& widgets/viewport-actions]
|
||||
|
||||
[:& scroll-bars/viewport-scrollbars
|
||||
{:objects base-objects
|
||||
:zoom zoom
|
||||
:vbox vbox
|
||||
:viewport-ref viewport-ref}]
|
||||
|
||||
(when show-rules?
|
||||
[:*
|
||||
[:& rules/rules
|
||||
|
|
|
@ -28,10 +28,11 @@
|
|||
|
||||
(defn on-mouse-down
|
||||
[{:keys [id blocked hidden type]} selected edition drawing-tool text-editing?
|
||||
node-editing? drawing-path? create-comment? space? viewport-ref zoom]
|
||||
node-editing? drawing-path? create-comment? space? viewport-ref zoom panning]
|
||||
(mf/use-callback
|
||||
(mf/deps id blocked hidden type selected edition drawing-tool text-editing?
|
||||
node-editing? drawing-path? create-comment? space? viewport-ref zoom)
|
||||
node-editing? drawing-path? create-comment? @space? viewport-ref zoom
|
||||
panning)
|
||||
(fn [bevent]
|
||||
(when (or (dom/class? (dom/get-target bevent) "viewport-controls")
|
||||
(dom/class? (dom/get-target bevent) "viewport-selrect"))
|
||||
|
@ -42,62 +43,75 @@
|
|||
shift? (kbd/shift? event)
|
||||
alt? (kbd/alt? event)
|
||||
|
||||
left-click? (= 1 (.-which event))
|
||||
middle-click? (= 2 (.-which event))
|
||||
left-click? (and (not panning) (= 1 (.-which event)))
|
||||
middle-click? (and (not panning) (= 2 (.-which event)))
|
||||
|
||||
frame? (= :frame type)
|
||||
selected? (contains? selected id)]
|
||||
|
||||
(when middle-click?
|
||||
(dom/prevent-default bevent)
|
||||
(if ctrl?
|
||||
(let [raw-pt (dom/get-client-position event)
|
||||
viewport (mf/ref-val viewport-ref)
|
||||
pt (utils/translate-point-to-viewport viewport zoom raw-pt)]
|
||||
(st/emit! (dw/start-zooming pt)))
|
||||
(st/emit! (dw/start-panning))))
|
||||
(cond
|
||||
middle-click?
|
||||
(do
|
||||
(dom/prevent-default bevent)
|
||||
(if ctrl?
|
||||
(let [raw-pt (dom/get-client-position event)
|
||||
viewport (mf/ref-val viewport-ref)
|
||||
pt (utils/translate-point-to-viewport viewport zoom raw-pt)]
|
||||
(st/emit! (dw/start-zooming pt)))
|
||||
(st/emit! (dw/start-panning))))
|
||||
|
||||
(when left-click?
|
||||
(st/emit! (ms/->MouseEvent :down ctrl? shift? alt?))
|
||||
|
||||
(when (and (not= edition id) text-editing?)
|
||||
(st/emit! dw/clear-edition-mode))
|
||||
left-click?
|
||||
(do
|
||||
(st/emit! (ms/->MouseEvent :down ctrl? shift? alt?))
|
||||
|
||||
(when (and (not text-editing?)
|
||||
(not blocked)
|
||||
(not hidden)
|
||||
(not create-comment?)
|
||||
(not drawing-path?))
|
||||
(cond
|
||||
drawing-tool
|
||||
(st/emit! (dd/start-drawing drawing-tool))
|
||||
(when (and (not= edition id) text-editing?)
|
||||
(st/emit! dw/clear-edition-mode))
|
||||
|
||||
node-editing?
|
||||
;; Handle path node area selection
|
||||
(st/emit! (dwdp/handle-area-selection shift?))
|
||||
(when (and (not text-editing?)
|
||||
(not blocked)
|
||||
(not hidden)
|
||||
(not create-comment?)
|
||||
(not drawing-path?))
|
||||
(cond
|
||||
node-editing?
|
||||
;; Handle path node area selection
|
||||
(st/emit! (dwdp/handle-area-selection shift?))
|
||||
|
||||
@space?
|
||||
(st/emit! (dw/start-panning))
|
||||
(and @space? ctrl?)
|
||||
(let [raw-pt (dom/get-client-position event)
|
||||
viewport (mf/ref-val viewport-ref)
|
||||
pt (utils/translate-point-to-viewport viewport zoom raw-pt)]
|
||||
(st/emit! (dw/start-zooming pt)))
|
||||
|
||||
(or (not id) (and frame? (not selected?)))
|
||||
(st/emit! (dw/handle-area-selection shift?))
|
||||
@space?
|
||||
(st/emit! (dw/start-panning))
|
||||
|
||||
(not drawing-tool)
|
||||
(st/emit! (when (or shift? (not selected?))
|
||||
(dw/select-shape id shift?))
|
||||
(dw/start-move-selected))))))))))
|
||||
drawing-tool
|
||||
(st/emit! (dd/start-drawing drawing-tool))
|
||||
|
||||
(or (not id) (and frame? (not selected?)) ctrl?)
|
||||
(st/emit! (dw/handle-area-selection shift? ctrl?))
|
||||
|
||||
(not drawing-tool)
|
||||
(st/emit! (when (or shift? (not selected?))
|
||||
(dw/select-shape id shift?))
|
||||
(dw/start-move-selected)))))))))))
|
||||
|
||||
(defn on-move-selected
|
||||
[hover hover-ids selected]
|
||||
[hover hover-ids selected space?]
|
||||
(mf/use-callback
|
||||
(mf/deps @hover @hover-ids selected)
|
||||
(mf/deps @hover @hover-ids selected @space?)
|
||||
(fn [bevent]
|
||||
(let [event (.-nativeEvent bevent)
|
||||
shift? (kbd/shift? event)
|
||||
ctrl? (kbd/ctrl? event)
|
||||
left-click? (= 1 (.-which event))]
|
||||
|
||||
(when (and left-click?
|
||||
(not ctrl?)
|
||||
(not shift?)
|
||||
(not @space?)
|
||||
(or (not @hover)
|
||||
(= :frame (:type @hover))
|
||||
(some #(contains? selected %) @hover-ids)))
|
||||
|
@ -130,9 +144,9 @@
|
|||
(reset! frame-hover nil))))
|
||||
|
||||
(defn on-click
|
||||
[hover selected edition drawing-path? drawing-tool]
|
||||
[hover selected edition drawing-path? drawing-tool space?]
|
||||
(mf/use-callback
|
||||
(mf/deps @hover selected edition drawing-path? drawing-tool)
|
||||
(mf/deps @hover selected edition drawing-path? drawing-tool @space?)
|
||||
(fn [event]
|
||||
(when (or (dom/class? (dom/get-target event) "viewport-controls")
|
||||
(dom/class? (dom/get-target event) "viewport-selrect"))
|
||||
|
@ -147,7 +161,8 @@
|
|||
|
||||
(when (and hovering?
|
||||
(not shift?)
|
||||
(not frame?)
|
||||
(or ctrl? (not frame?))
|
||||
(not @space?)
|
||||
(not selected?)
|
||||
(not edition)
|
||||
(not drawing-path?)
|
||||
|
@ -229,17 +244,17 @@
|
|||
middle-click? (= 2 (.-which event))]
|
||||
|
||||
(when left-click?
|
||||
(st/emit! (dw/finish-panning)
|
||||
(ms/->MouseEvent :up ctrl? shift? alt?)))
|
||||
(st/emit! (ms/->MouseEvent :up ctrl? shift? alt?)))
|
||||
|
||||
(when middle-click?
|
||||
(dom/prevent-default event)
|
||||
|
||||
;; We store this so in Firefox the middle button won't do a paste of the content
|
||||
(reset! disable-paste true)
|
||||
(timers/schedule #(reset! disable-paste false))
|
||||
(st/emit! (dw/finish-panning)
|
||||
(dw/finish-zooming)))))))
|
||||
(timers/schedule #(reset! disable-paste false)))
|
||||
|
||||
(st/emit! (dw/finish-panning)
|
||||
(dw/finish-zooming))))))
|
||||
|
||||
(defn on-pointer-enter [in-viewport?]
|
||||
(mf/use-callback
|
||||
|
|
|
@ -57,13 +57,14 @@
|
|||
;; We schedule the event so it fires after `initialize-page` event
|
||||
(timers/schedule #(st/emit! (dw/initialize-viewport size)))))))
|
||||
|
||||
(defn setup-cursor [cursor alt? panning drawing-tool drawing-path? path-editing?]
|
||||
(defn setup-cursor [cursor alt? ctrl? space? panning drawing-tool drawing-path? path-editing?]
|
||||
(mf/use-effect
|
||||
(mf/deps @cursor @alt? panning drawing-tool drawing-path? path-editing?)
|
||||
(mf/deps @cursor @alt? @ctrl? @space? panning drawing-tool drawing-path? path-editing?)
|
||||
(fn []
|
||||
(let [new-cursor
|
||||
(cond
|
||||
panning (utils/get-cursor :hand)
|
||||
(and @ctrl? @space?) (utils/get-cursor :zoom)
|
||||
(or panning @space?) (utils/get-cursor :hand)
|
||||
(= drawing-tool :comments) (utils/get-cursor :comments)
|
||||
(= drawing-tool :frame) (utils/get-cursor :create-artboard)
|
||||
(= drawing-tool :rect) (utils/get-cursor :create-rectangle)
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
[app.common.uuid :as uuid]
|
||||
[app.main.data.modal :as modal]
|
||||
[app.main.data.workspace.colors :as dwc]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.cursors :as cur]
|
||||
|
@ -101,14 +102,16 @@
|
|||
(fn [event]
|
||||
(dom/prevent-default event)
|
||||
(dom/stop-propagation event)
|
||||
(st/emit! (dwc/pick-color-select true (kbd/shift? event)))))
|
||||
(st/emit! (dwu/start-undo-transaction)
|
||||
(dwc/pick-color-select true (kbd/shift? event)))))
|
||||
|
||||
handle-mouse-up-picker
|
||||
(mf/use-callback
|
||||
(fn [event]
|
||||
(dom/prevent-default event)
|
||||
(dom/stop-propagation event)
|
||||
(st/emit! (dwc/stop-picker))
|
||||
(st/emit! (dwu/commit-undo-transaction)
|
||||
(dwc/stop-picker))
|
||||
(modal/disallow-click-outside!)))
|
||||
|
||||
handle-image-load
|
||||
|
|
|
@ -157,20 +157,20 @@
|
|||
(mf/use-callback
|
||||
(mf/deps v-scrollbar-y scrollbar-height)
|
||||
(fn [event axis]
|
||||
(let [viewport (mf/ref-val viewport-ref)
|
||||
start-pt (dom/get-client-position event)
|
||||
new-v-scrollbar-y (-> (utils/translate-point-to-viewport-raw viewport zoom start-pt) :y)
|
||||
new-h-scrollbar-x (-> (utils/translate-point-to-viewport-raw viewport zoom start-pt) :x)
|
||||
v-scrollbar-y-padding (- v-scrollbar-y new-v-scrollbar-y)
|
||||
h-scrollbar-x-padding (- h-scrollbar-x new-h-scrollbar-x)
|
||||
vbox-rect {:x vbox-x
|
||||
:y vbox-y
|
||||
:x1 vbox-x
|
||||
:y1 vbox-y
|
||||
:x2 (+ vbox-x (:width vbox))
|
||||
:y2 (+ vbox-y (:height vbox))
|
||||
:width (:width vbox)
|
||||
:height (:height vbox)}
|
||||
(let [viewport (mf/ref-val viewport-ref)
|
||||
start-pt (dom/get-client-position event)
|
||||
new-v-scrollbar-y (-> (utils/translate-point-to-viewport-raw viewport zoom start-pt) :y)
|
||||
new-h-scrollbar-x (-> (utils/translate-point-to-viewport-raw viewport zoom start-pt) :x)
|
||||
v-scrollbar-y-padding (- v-scrollbar-y new-v-scrollbar-y)
|
||||
h-scrollbar-x-padding (- h-scrollbar-x new-h-scrollbar-x)
|
||||
vbox-rect {:x vbox-x
|
||||
:y vbox-y
|
||||
:x1 vbox-x
|
||||
:y1 vbox-y
|
||||
:x2 (+ vbox-x (:width vbox))
|
||||
:y2 (+ vbox-y (:height vbox))
|
||||
:width (:width vbox)
|
||||
:height (:height vbox)}
|
||||
containing-rect (gpr/join-selrects [base-objects-rect vbox-rect])
|
||||
height-factor (/ (:height containing-rect) vbox-height)
|
||||
width-factor (/ (:width containing-rect) vbox-width)]
|
||||
|
@ -207,7 +207,9 @@
|
|||
:height scrollbar-height
|
||||
:fill-opacity 0.4
|
||||
:x v-scrollbar-x
|
||||
:y v-scrollbar-y}]])
|
||||
:y v-scrollbar-y
|
||||
:style {:stroke "white"
|
||||
:stroke-width 0.15}}]])
|
||||
(when show-h-scroll?
|
||||
[:g.h-scroll
|
||||
[:rect {:on-mouse-move #(on-mouse-move % :x)
|
||||
|
@ -219,4 +221,6 @@
|
|||
:height (* inv-zoom 7)
|
||||
:fill-opacity 0.4
|
||||
:x h-scrollbar-x
|
||||
:y h-scrollbar-y}]])]))
|
||||
:y h-scrollbar-y
|
||||
:style {:stroke "white"
|
||||
:stroke-width 0.15}}]])]))
|
||||
|
|
|
@ -179,4 +179,7 @@
|
|||
:pencil cur/pencil
|
||||
:create-shape cur/create-shape
|
||||
:duplicate cur/duplicate
|
||||
:zoom cur/zoom
|
||||
:zoom-in cur/zoom-in
|
||||
:zooom-out cur/zoom-out
|
||||
cur/pointer-inner))
|
||||
|
|
|
@ -105,7 +105,7 @@
|
|||
(assoc data :index index :z-index z-index)))
|
||||
|
||||
(defn- query-index
|
||||
[{index :index z-index :z-index} rect frame-id full-frame? include-frames? clip-children? reverse?]
|
||||
[{index :index z-index :z-index} rect frame-id full-frame? include-frames? ignore-groups? clip-children? reverse?]
|
||||
(let [result (-> (qdt/search index (clj->js rect))
|
||||
(es6-iterator-seq))
|
||||
|
||||
|
@ -117,6 +117,7 @@
|
|||
(or (not frame-id) (= frame-id (:frame-id shape)))
|
||||
(case (:type shape)
|
||||
:frame include-frames?
|
||||
(:bool :group) (not ignore-groups?)
|
||||
true)
|
||||
|
||||
(or (not full-frame?)
|
||||
|
@ -189,10 +190,10 @@
|
|||
nil)
|
||||
|
||||
(defmethod impl/handler :selection/query
|
||||
[{:keys [page-id rect frame-id reverse? full-frame? include-frames? clip-children?]
|
||||
[{:keys [page-id rect frame-id reverse? full-frame? include-frames? ignore-groups? clip-children?]
|
||||
:or {reverse? false full-frame? false include-frames? false clip-children? true} :as message}]
|
||||
(when-let [index (get @state page-id)]
|
||||
(query-index index rect frame-id full-frame? include-frames? clip-children? reverse?)))
|
||||
(query-index index rect frame-id full-frame? include-frames? ignore-groups? clip-children? reverse?)))
|
||||
|
||||
(defmethod impl/handler :selection/query-z-index
|
||||
[{:keys [page-id objects ids]}]
|
||||
|
|
Loading…
Add table
Reference in a new issue