mirror of
https://github.com/penpot/penpot.git
synced 2025-08-07 14:38:33 +02:00
Merge pull request #1728 from penpot/alotor/bugfixes
Safari/MacOS Fixes
This commit is contained in:
commit
a44f1df0d4
24 changed files with 238 additions and 136 deletions
|
@ -58,6 +58,11 @@
|
||||||
- Fix problem when importing SVG's with uses with overriding properties [#Taiga 2884](https://tree.taiga.io/project/penpot/issue/2884)
|
- Fix problem when importing SVG's with uses with overriding properties [#Taiga 2884](https://tree.taiga.io/project/penpot/issue/2884)
|
||||||
- Fix inconsistency with radius in SVG an CSS [#1587](https://github.com/penpot/penpot/issues/1587)
|
- Fix inconsistency with radius in SVG an CSS [#1587](https://github.com/penpot/penpot/issues/1587)
|
||||||
- Fix clickable area in layers [#1680](https://github.com/penpot/penpot/issues/1680)
|
- Fix clickable area in layers [#1680](https://github.com/penpot/penpot/issues/1680)
|
||||||
|
- Fix problems with trackpad zoom and scroll in MacOS [#1161](https://github.com/penpot/penpot/issues/1161)
|
||||||
|
- Fix problem with copy/paste in Safari [#1209](https://github.com/penpot/penpot/issues/1209)
|
||||||
|
- Fix paste ordering for frames not being respected [Taiga #3097](https://tree.taiga.io/project/penpot/issue/3097)
|
||||||
|
- Improved command support for MacOS [Taiga #2789](https://tree.taiga.io/project/penpot/issue/2789)
|
||||||
|
- Fix shift+2 shortcut in MacOS with non-english keyboards [Taiga #3038](https://tree.taiga.io/project/penpot/issue/3038)
|
||||||
|
|
||||||
### :arrow_up: Deps updates
|
### :arrow_up: Deps updates
|
||||||
### :heart: Community contributions by (Thank you!)
|
### :heart: Community contributions by (Thank you!)
|
||||||
|
|
|
@ -81,9 +81,7 @@
|
||||||
shapes
|
shapes
|
||||||
|
|
||||||
(nil? index)
|
(nil? index)
|
||||||
(if (= :frame (:type obj))
|
(conj shapes id)
|
||||||
(into [id] shapes)
|
|
||||||
(conj shapes id))
|
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(cph/insert-at-index shapes index [id]))))
|
(cph/insert-at-index shapes index [id]))))
|
||||||
|
|
|
@ -198,8 +198,7 @@
|
||||||
(assert-page-id changes)
|
(assert-page-id changes)
|
||||||
(let [obj (cond-> obj
|
(let [obj (cond-> obj
|
||||||
(not= index ::undefined)
|
(not= index ::undefined)
|
||||||
(assoc :index index))
|
(assoc ::index index))
|
||||||
|
|
||||||
add-change
|
add-change
|
||||||
{:type :add-obj
|
{:type :add-obj
|
||||||
:id (:id obj)
|
:id (:id obj)
|
||||||
|
|
|
@ -52,7 +52,7 @@ services:
|
||||||
- PENPOT_SMTP_PASSWORD=
|
- PENPOT_SMTP_PASSWORD=
|
||||||
- PENPOT_SMTP_SSL=false
|
- PENPOT_SMTP_SSL=false
|
||||||
- PENPOT_SMTP_TLS=false
|
- PENPOT_SMTP_TLS=false
|
||||||
- PENPOT_FLAGS="enable-cors enable-insecure-register enable-audit-log"
|
- PENPOT_FLAGS="enable-cors enable-insecure-register enable-audit-log disable-secure-session-cookies"
|
||||||
|
|
||||||
# LDAP setup
|
# LDAP setup
|
||||||
- PENPOT_LDAP_HOST=ldap
|
- PENPOT_LDAP_HOST=ldap
|
||||||
|
|
|
@ -1198,13 +1198,10 @@
|
||||||
[]
|
[]
|
||||||
(letfn [;; Sort objects so they have the same relative ordering
|
(letfn [;; Sort objects so they have the same relative ordering
|
||||||
;; when pasted later.
|
;; when pasted later.
|
||||||
(sort-selected [state data]
|
(sort-selected-async [state data]
|
||||||
(let [selected (:selected data)
|
(let [selected (wsh/lookup-selected state)
|
||||||
page-id (:current-page-id state)
|
objects (wsh/lookup-page-objects state)
|
||||||
objects (get-in state [:workspace-data
|
page-id (:current-page-id state)]
|
||||||
:pages-index
|
|
||||||
page-id
|
|
||||||
:objects])]
|
|
||||||
(->> (uw/ask! {:cmd :selection/query-z-index
|
(->> (uw/ask! {:cmd :selection/query-z-index
|
||||||
:page-id page-id
|
:page-id page-id
|
||||||
:objects objects
|
:objects objects
|
||||||
|
@ -1216,6 +1213,24 @@
|
||||||
(map first)
|
(map first)
|
||||||
(into (d/ordered-set)))))))))
|
(into (d/ordered-set)))))))))
|
||||||
|
|
||||||
|
;; We cannot call to a remote procedure in Safari (for the copy) so we need
|
||||||
|
;; to calculate it here instead of on the worker
|
||||||
|
(sort-selected-sync [state data]
|
||||||
|
(let [selected (wsh/lookup-selected state)
|
||||||
|
objects (wsh/lookup-page-objects state)
|
||||||
|
z-index (cp/calculate-z-index objects)
|
||||||
|
z-values (->> selected
|
||||||
|
(map #(vector %
|
||||||
|
(+ (get z-index %)
|
||||||
|
(get z-index (get-in objects [% :frame-id]))))))
|
||||||
|
selected
|
||||||
|
(->> z-values
|
||||||
|
(sort-by second)
|
||||||
|
(map first)
|
||||||
|
(into (d/ordered-set)))]
|
||||||
|
|
||||||
|
(assoc data :selected selected)))
|
||||||
|
|
||||||
;; Retrieve all ids of selected shapes with corresponding
|
;; Retrieve all ids of selected shapes with corresponding
|
||||||
;; children; this is needed because each shape should be
|
;; children; this is needed because each shape should be
|
||||||
;; processed one by one because of async events (data url
|
;; processed one by one because of async events (data url
|
||||||
|
@ -1277,11 +1292,18 @@
|
||||||
:file-id (:current-file-id state)
|
:file-id (:current-file-id state)
|
||||||
:selected selected
|
:selected selected
|
||||||
:objects {}
|
:objects {}
|
||||||
:images #{}}]
|
:images #{}}
|
||||||
|
|
||||||
|
sort-results
|
||||||
|
(fn [obs]
|
||||||
|
;; Safari doesn't allow asynchronous sorting on the copy
|
||||||
|
(if (cfg/check-browser? :safari)
|
||||||
|
(rx/map (partial sort-selected-sync state) obs)
|
||||||
|
(rx/mapcat (partial sort-selected-async state) obs)))]
|
||||||
(->> (rx/from (seq (vals pdata)))
|
(->> (rx/from (seq (vals pdata)))
|
||||||
(rx/merge-map (partial prepare-object objects selected))
|
(rx/merge-map (partial prepare-object objects selected))
|
||||||
(rx/reduce collect-data initial)
|
(rx/reduce collect-data initial)
|
||||||
(rx/mapcat (partial sort-selected state))
|
(sort-results)
|
||||||
(rx/map t/encode-str)
|
(rx/map t/encode-str)
|
||||||
(rx/map wapi/write-to-clipboard)
|
(rx/map wapi/write-to-clipboard)
|
||||||
(rx/catch on-copy-error)
|
(rx/catch on-copy-error)
|
||||||
|
@ -1502,21 +1524,18 @@
|
||||||
;; Calculate position for the pasted elements
|
;; Calculate position for the pasted elements
|
||||||
[frame-id parent-id delta index] (calculate-paste-position state mouse-pos in-viewport?)
|
[frame-id parent-id delta index] (calculate-paste-position state mouse-pos in-viewport?)
|
||||||
|
|
||||||
paste-objects (->> paste-objects
|
process-shape
|
||||||
(d/mapm (fn [_ shape]
|
(fn [_ shape]
|
||||||
(-> shape
|
(-> shape
|
||||||
(assoc :frame-id frame-id)
|
(assoc :frame-id frame-id)
|
||||||
(assoc :parent-id parent-id)
|
(assoc :parent-id parent-id)
|
||||||
|
|
||||||
(cond->
|
|
||||||
;; if foreign instance, detach the shape
|
;; if foreign instance, detach the shape
|
||||||
(foreign-instance? shape paste-objects state)
|
(cond-> (foreign-instance? shape paste-objects state)
|
||||||
(dissoc :component-id
|
(dissoc :component-id :component-file :component-root?
|
||||||
:component-file
|
:remote-synced? :shape-ref :touched))))
|
||||||
:component-root?
|
|
||||||
:remote-synced?
|
paste-objects (->> paste-objects (d/mapm process-shape))
|
||||||
:shape-ref
|
|
||||||
:touched))))))
|
|
||||||
|
|
||||||
all-objects (merge (:objects page) paste-objects)
|
all-objects (merge (:objects page) paste-objects)
|
||||||
|
|
||||||
|
@ -1750,3 +1769,4 @@
|
||||||
(dm/export dwz/zoom-to-fit-all)
|
(dm/export dwz/zoom-to-fit-all)
|
||||||
(dm/export dwz/decrease-zoom)
|
(dm/export dwz/decrease-zoom)
|
||||||
(dm/export dwz/increase-zoom)
|
(dm/export dwz/increase-zoom)
|
||||||
|
(dm/export dwz/set-zoom)
|
||||||
|
|
|
@ -325,7 +325,7 @@
|
||||||
selected)
|
selected)
|
||||||
|
|
||||||
changes (-> (pcb/empty-changes it page-id)
|
changes (-> (pcb/empty-changes it page-id)
|
||||||
(pcb/add-object shape))]
|
(pcb/add-object shape {:index (when (= :frame (:type shape)) 0)}))]
|
||||||
|
|
||||||
(rx/concat
|
(rx/concat
|
||||||
(rx/of (dch/commit-changes changes)
|
(rx/of (dch/commit-changes changes)
|
||||||
|
|
|
@ -284,15 +284,27 @@
|
||||||
(let [shapes (map (d/getf all-objects) ids)
|
(let [shapes (map (d/getf all-objects) ids)
|
||||||
unames (volatile! (dwc/retrieve-used-names (:objects page)))
|
unames (volatile! (dwc/retrieve-used-names (:objects page)))
|
||||||
update-unames! (fn [new-name] (vswap! unames conj new-name))
|
update-unames! (fn [new-name] (vswap! unames conj new-name))
|
||||||
all-ids (reduce #(into %1 (cons %2 (cph/get-children-ids all-objects %2))) #{} ids)
|
all-ids (reduce #(into %1 (cons %2 (cph/get-children-ids all-objects %2))) (d/ordered-set) ids)
|
||||||
ids-map (into {} (map #(vector % (uuid/next))) all-ids)]
|
ids-map (into {} (map #(vector % (uuid/next))) all-ids)
|
||||||
(-> (reduce (fn [changes shape]
|
|
||||||
(prepare-duplicate-change changes all-objects page unames update-unames! ids-map shape delta))
|
init-changes
|
||||||
(-> (pcb/empty-changes it)
|
(-> (pcb/empty-changes it)
|
||||||
(pcb/with-page page)
|
(pcb/with-page page)
|
||||||
(pcb/with-objects all-objects))
|
(pcb/with-objects all-objects))
|
||||||
shapes)
|
|
||||||
(prepare-duplicate-flows shapes page ids-map))))
|
changes
|
||||||
|
(->> shapes
|
||||||
|
(reduce #(prepare-duplicate-change %1
|
||||||
|
all-objects
|
||||||
|
page
|
||||||
|
unames
|
||||||
|
update-unames!
|
||||||
|
ids-map
|
||||||
|
%2
|
||||||
|
delta)
|
||||||
|
init-changes))]
|
||||||
|
|
||||||
|
(prepare-duplicate-flows changes shapes page ids-map)))
|
||||||
|
|
||||||
(defn- prepare-duplicate-change
|
(defn- prepare-duplicate-change
|
||||||
[changes objects page unames update-unames! ids-map shape delta]
|
[changes objects page unames update-unames! ids-map shape delta]
|
||||||
|
@ -349,7 +361,6 @@
|
||||||
(geom/move delta)
|
(geom/move delta)
|
||||||
(d/update-when :interactions #(cti/remap-interactions % ids-map objects)))
|
(d/update-when :interactions #(cti/remap-interactions % ids-map objects)))
|
||||||
|
|
||||||
changes (pcb/add-object changes new-obj {:ignore-touched true})
|
|
||||||
changes (-> (pcb/add-object changes new-obj {:ignore-touched true})
|
changes (-> (pcb/add-object changes new-obj {:ignore-touched true})
|
||||||
(pcb/amend-last-change #(assoc % :old-id (:id obj))))]
|
(pcb/amend-last-change #(assoc % :old-id (:id obj))))]
|
||||||
|
|
||||||
|
|
|
@ -140,7 +140,7 @@
|
||||||
:fn #(st/emit! dw/zoom-to-fit-all)}
|
:fn #(st/emit! dw/zoom-to-fit-all)}
|
||||||
|
|
||||||
:zoom-selected {:tooltip (ds/shift "2")
|
:zoom-selected {:tooltip (ds/shift "2")
|
||||||
:command "shift+2"
|
:command ["shift+2" "@" "\""]
|
||||||
:fn #(st/emit! dw/zoom-to-selected-shape)}
|
:fn #(st/emit! dw/zoom-to-selected-shape)}
|
||||||
|
|
||||||
:duplicate {:tooltip (ds/meta "D")
|
:duplicate {:tooltip (ds/meta "D")
|
||||||
|
|
|
@ -541,13 +541,13 @@
|
||||||
initial-angle (gpt/angle @ms/mouse-position group-center)
|
initial-angle (gpt/angle @ms/mouse-position group-center)
|
||||||
|
|
||||||
calculate-angle
|
calculate-angle
|
||||||
(fn [pos ctrl? shift?]
|
(fn [pos mod? shift?]
|
||||||
(let [angle (- (gpt/angle pos group-center) initial-angle)
|
(let [angle (- (gpt/angle pos group-center) initial-angle)
|
||||||
angle (if (neg? angle) (+ 360 angle) angle)
|
angle (if (neg? angle) (+ 360 angle) angle)
|
||||||
angle (if (= angle 360)
|
angle (if (= angle 360)
|
||||||
0
|
0
|
||||||
angle)
|
angle)
|
||||||
angle (if ctrl?
|
angle (if mod?
|
||||||
(* (mth/floor (/ angle 45)) 45)
|
(* (mth/floor (/ angle 45)) 45)
|
||||||
angle)
|
angle)
|
||||||
angle (if shift?
|
angle (if shift?
|
||||||
|
@ -556,11 +556,11 @@
|
||||||
angle))]
|
angle))]
|
||||||
(rx/concat
|
(rx/concat
|
||||||
(->> ms/mouse-position
|
(->> ms/mouse-position
|
||||||
(rx/with-latest vector ms/mouse-position-ctrl)
|
(rx/with-latest vector ms/mouse-position-mod)
|
||||||
(rx/with-latest vector ms/mouse-position-shift)
|
(rx/with-latest vector ms/mouse-position-shift)
|
||||||
(rx/map
|
(rx/map
|
||||||
(fn [[[pos ctrl?] shift?]]
|
(fn [[[pos mod?] shift?]]
|
||||||
(let [delta-angle (calculate-angle pos ctrl? shift?)]
|
(let [delta-angle (calculate-angle pos mod? shift?)]
|
||||||
(set-rotation-modifiers delta-angle shapes group-center))))
|
(set-rotation-modifiers delta-angle shapes group-center))))
|
||||||
(rx/take-until stoper))
|
(rx/take-until stoper))
|
||||||
(rx/of (apply-modifiers (map :id shapes))
|
(rx/of (apply-modifiers (map :id shapes))
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
(ns app.main.streams
|
(ns app.main.streams
|
||||||
"User interaction events and streams."
|
"User interaction events and streams."
|
||||||
(:require
|
(:require
|
||||||
|
[app.config :as cfg]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.util.globals :as globals]
|
[app.util.globals :as globals]
|
||||||
[app.util.keyboard :as kbd]
|
[app.util.keyboard :as kbd]
|
||||||
|
@ -20,7 +21,7 @@
|
||||||
[v]
|
[v]
|
||||||
(instance? KeyboardEvent v))
|
(instance? KeyboardEvent v))
|
||||||
|
|
||||||
(defrecord MouseEvent [type ctrl shift alt])
|
(defrecord MouseEvent [type ctrl shift alt meta])
|
||||||
|
|
||||||
(defn mouse-event?
|
(defn mouse-event?
|
||||||
[v]
|
[v]
|
||||||
|
@ -46,7 +47,7 @@
|
||||||
(and (mouse-event? v)
|
(and (mouse-event? v)
|
||||||
(= :double-click (:type v))))
|
(= :double-click (:type v))))
|
||||||
|
|
||||||
(defrecord PointerEvent [source pt ctrl shift alt])
|
(defrecord PointerEvent [source pt ctrl shift alt meta])
|
||||||
|
|
||||||
(defn pointer-event?
|
(defn pointer-event?
|
||||||
[v]
|
[v]
|
||||||
|
@ -83,6 +84,20 @@
|
||||||
(rx/subscribe-with ob sub)
|
(rx/subscribe-with ob sub)
|
||||||
sub))
|
sub))
|
||||||
|
|
||||||
|
(defonce mouse-position-meta
|
||||||
|
(let [sub (rx/behavior-subject nil)
|
||||||
|
ob (->> st/stream
|
||||||
|
(rx/filter pointer-event?)
|
||||||
|
(rx/map :meta)
|
||||||
|
(rx/dedupe))]
|
||||||
|
(rx/subscribe-with ob sub)
|
||||||
|
sub))
|
||||||
|
|
||||||
|
(defonce mouse-position-mod
|
||||||
|
(if (cfg/check-platform? :macos)
|
||||||
|
mouse-position-meta
|
||||||
|
mouse-position-ctrl))
|
||||||
|
|
||||||
(defonce mouse-position-shift
|
(defonce mouse-position-shift
|
||||||
(let [sub (rx/behavior-subject nil)
|
(let [sub (rx/behavior-subject nil)
|
||||||
ob (->> st/stream
|
ob (->> st/stream
|
||||||
|
@ -111,7 +126,7 @@
|
||||||
ob (->> (rx/merge
|
ob (->> (rx/merge
|
||||||
(->> st/stream
|
(->> st/stream
|
||||||
(rx/filter keyboard-event?)
|
(rx/filter keyboard-event?)
|
||||||
(rx/filter kbd/altKey?)
|
(rx/filter kbd/alt-key?)
|
||||||
(rx/map #(= :down (:type %))))
|
(rx/map #(= :down (:type %))))
|
||||||
;; Fix a situation caused by using `ctrl+alt` kind of shortcuts,
|
;; Fix a situation caused by using `ctrl+alt` kind of shortcuts,
|
||||||
;; that makes keyboard-alt stream registering the key pressed but
|
;; that makes keyboard-alt stream registering the key pressed but
|
||||||
|
@ -127,7 +142,7 @@
|
||||||
ob (->> (rx/merge
|
ob (->> (rx/merge
|
||||||
(->> st/stream
|
(->> st/stream
|
||||||
(rx/filter keyboard-event?)
|
(rx/filter keyboard-event?)
|
||||||
(rx/filter kbd/ctrlKey?)
|
(rx/filter kbd/ctrl-key?)
|
||||||
(rx/map #(= :down (:type %))))
|
(rx/map #(= :down (:type %))))
|
||||||
;; Fix a situation caused by using `ctrl+alt` kind of shortcuts,
|
;; Fix a situation caused by using `ctrl+alt` kind of shortcuts,
|
||||||
;; that makes keyboard-alt stream registering the key pressed but
|
;; that makes keyboard-alt stream registering the key pressed but
|
||||||
|
@ -138,6 +153,27 @@
|
||||||
(rx/subscribe-with ob sub)
|
(rx/subscribe-with ob sub)
|
||||||
sub))
|
sub))
|
||||||
|
|
||||||
|
(defonce keyboard-meta
|
||||||
|
(let [sub (rx/behavior-subject nil)
|
||||||
|
ob (->> (rx/merge
|
||||||
|
(->> st/stream
|
||||||
|
(rx/filter keyboard-event?)
|
||||||
|
(rx/filter kbd/meta-key?)
|
||||||
|
(rx/map #(= :down (:type %))))
|
||||||
|
;; Fix a situation caused by using `ctrl+alt` kind of shortcuts,
|
||||||
|
;; that makes keyboard-alt stream registering the key pressed but
|
||||||
|
;; on blurring the window (unfocus) the key down is never arrived.
|
||||||
|
(->> window-blur
|
||||||
|
(rx/map (constantly false))))
|
||||||
|
(rx/dedupe))]
|
||||||
|
(rx/subscribe-with ob sub)
|
||||||
|
sub))
|
||||||
|
|
||||||
|
(defonce keyboard-mod
|
||||||
|
(if (cfg/check-platform? :macos)
|
||||||
|
keyboard-meta
|
||||||
|
keyboard-ctrl))
|
||||||
|
|
||||||
(defonce keyboard-space
|
(defonce keyboard-space
|
||||||
(let [sub (rx/behavior-subject nil)
|
(let [sub (rx/behavior-subject nil)
|
||||||
ob (->> st/stream
|
ob (->> st/stream
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
[app.main.ui.dashboard.sidebar :refer [profile-section]]
|
[app.main.ui.dashboard.sidebar :refer [profile-section]]
|
||||||
[app.main.ui.icons :as i]
|
[app.main.ui.icons :as i]
|
||||||
[app.util.i18n :as i18n :refer [tr]]
|
[app.util.i18n :as i18n :refer [tr]]
|
||||||
|
[app.util.keyboard :as kbd]
|
||||||
[app.util.router :as rt]
|
[app.util.router :as rt]
|
||||||
[potok.core :as ptk]
|
[potok.core :as ptk]
|
||||||
[rumext.alpha :as mf]))
|
[rumext.alpha :as mf]))
|
||||||
|
@ -55,8 +56,7 @@
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(let [version (:main @cf/version)]
|
(let [version (:main @cf/version)]
|
||||||
(st/emit! (ptk/event ::ev/event {::ev/name "show-release-notes" :version version}))
|
(st/emit! (ptk/event ::ev/event {::ev/name "show-release-notes" :version version}))
|
||||||
(if (and (.-ctrlKey ^js event)
|
(if (and (kbd/alt? event) (kbd/mod? event))
|
||||||
(.-altKey ^js event))
|
|
||||||
(st/emit! (modal/show {:type :onboarding}))
|
(st/emit! (modal/show {:type :onboarding}))
|
||||||
(st/emit! (modal/show {:type :release-notes :version version}))))))]
|
(st/emit! (modal/show {:type :release-notes :version version}))))))]
|
||||||
|
|
||||||
|
|
|
@ -51,8 +51,8 @@
|
||||||
[:> :g group-props
|
[:> :g group-props
|
||||||
(for [[index data] (d/enumerate position-data)]
|
(for [[index data] (d/enumerate position-data)]
|
||||||
(let [props (-> #js {:x (mth/round (:x data))
|
(let [props (-> #js {:x (mth/round (:x data))
|
||||||
:y (mth/round (:y data))
|
:y (mth/round (- (:y data) (:height data)))
|
||||||
:dominantBaseline "ideographic"
|
:alignmentBaseline "text-before-edge"
|
||||||
:style (-> #js {:fontFamily (:font-family data)
|
:style (-> #js {:fontFamily (:font-family data)
|
||||||
:fontSize (:font-size data)
|
:fontSize (:font-size data)
|
||||||
:fontWeight (:font-weight data)
|
:fontWeight (:font-weight data)
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
[{:keys [local file page frame]}]
|
[{:keys [local file page frame]}]
|
||||||
(let [on-mouse-wheel
|
(let [on-mouse-wheel
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(when (or (kbd/ctrl? event) (kbd/meta? event))
|
(when (kbd/mod? event)
|
||||||
(dom/prevent-default event)
|
(dom/prevent-default event)
|
||||||
(let [event (.getBrowserEvent ^js event)
|
(let [event (.getBrowserEvent ^js event)
|
||||||
delta (+ (.-deltaY ^js event)
|
delta (+ (.-deltaY ^js event)
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
(dom/prevent-default event)
|
(dom/prevent-default event)
|
||||||
(let [id (:id item)]
|
(let [id (:id item)]
|
||||||
(cond
|
(cond
|
||||||
(or (kbd/ctrl? event) (kbd/meta? event))
|
(kbd/mod? event)
|
||||||
(st/emit! (dv/toggle-selection id))
|
(st/emit! (dv/toggle-selection id))
|
||||||
|
|
||||||
(kbd/shift? event)
|
(kbd/shift? event)
|
||||||
|
|
|
@ -61,7 +61,7 @@
|
||||||
|
|
||||||
on-mouse-wheel
|
on-mouse-wheel
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(when (or (kbd/ctrl? event) (kbd/meta? event))
|
(when (kbd/mod? event)
|
||||||
(dom/prevent-default event)
|
(dom/prevent-default event)
|
||||||
(let [event (.getBrowserEvent ^js event)
|
(let [event (.getBrowserEvent ^js event)
|
||||||
delta (+ (.-deltaY ^js event) (.-deltaX ^js event))]
|
delta (+ (.-deltaY ^js event) (.-deltaX ^js event))]
|
||||||
|
|
|
@ -47,15 +47,15 @@
|
||||||
(st/emit! (drp/create-node-at-position (meta position))))
|
(st/emit! (drp/create-node-at-position (meta position))))
|
||||||
|
|
||||||
(let [shift? (kbd/shift? event)
|
(let [shift? (kbd/shift? event)
|
||||||
ctrl? (kbd/ctrl? event)]
|
mod? (kbd/mod? event)]
|
||||||
(cond
|
(cond
|
||||||
last-p?
|
last-p?
|
||||||
(st/emit! (drp/reset-last-handler))
|
(st/emit! (drp/reset-last-handler))
|
||||||
|
|
||||||
(and (= edit-mode :move) ctrl? (not curve?))
|
(and (= edit-mode :move) mod? (not curve?))
|
||||||
(st/emit! (drp/make-curve position))
|
(st/emit! (drp/make-curve position))
|
||||||
|
|
||||||
(and (= edit-mode :move) ctrl? curve?)
|
(and (= edit-mode :move) mod? curve?)
|
||||||
(st/emit! (drp/make-corner position))
|
(st/emit! (drp/make-corner position))
|
||||||
|
|
||||||
(= edit-mode :move)
|
(= edit-mode :move)
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
[app.util.timers :as timers]
|
[app.util.timers :as timers]
|
||||||
[app.util.webapi :as wapi]
|
[app.util.webapi :as wapi]
|
||||||
[beicon.core :as rx]
|
[beicon.core :as rx]
|
||||||
|
[debug :refer [debug?]]
|
||||||
[okulary.core :as l]
|
[okulary.core :as l]
|
||||||
[rumext.alpha :as mf]))
|
[rumext.alpha :as mf]))
|
||||||
|
|
||||||
|
@ -224,4 +225,22 @@
|
||||||
|
|
||||||
(when show-svg-text?
|
(when show-svg-text?
|
||||||
[:g.text-svg {:pointer-events "none"}
|
[:g.text-svg {:pointer-events "none"}
|
||||||
[:& svg/text-shape {:shape shape}]])]]))
|
[:& svg/text-shape {:shape shape}]])
|
||||||
|
|
||||||
|
(when (debug? :text-outline)
|
||||||
|
(for [data (:position-data shape)]
|
||||||
|
(let [{:keys [x y width height]} data]
|
||||||
|
[:*
|
||||||
|
;; Text fragment bounding box
|
||||||
|
[:rect {:x x
|
||||||
|
:y (- y height)
|
||||||
|
:width width
|
||||||
|
:height height
|
||||||
|
:style {:fill "none" :stroke "red"}}]
|
||||||
|
|
||||||
|
;; Text baselineazo
|
||||||
|
[:line {:x1 (mth/round x)
|
||||||
|
:y1 (mth/round (- (:y data) (:height data)))
|
||||||
|
:x2 (mth/round (+ x width))
|
||||||
|
:y2 (mth/round (- (:y data) (:height data)))
|
||||||
|
:style {:stroke "blue"}}]])))]]))
|
||||||
|
|
|
@ -1491,7 +1491,7 @@
|
||||||
(mf/deps extend-selected-assets selected-assets)
|
(mf/deps extend-selected-assets selected-assets)
|
||||||
(fn [asset-type asset-groups event asset-id default-click]
|
(fn [asset-type asset-groups event asset-id default-click]
|
||||||
(cond
|
(cond
|
||||||
(kbd/ctrl? event)
|
(kbd/mod? event)
|
||||||
(do
|
(do
|
||||||
(dom/stop-propagation event)
|
(dom/stop-propagation event)
|
||||||
(st/emit! (dw/toggle-selected-assets asset-id asset-type)))
|
(st/emit! (dw/toggle-selected-assets asset-id asset-type)))
|
||||||
|
|
|
@ -134,7 +134,7 @@
|
||||||
(kbd/shift? event)
|
(kbd/shift? event)
|
||||||
(st/emit! (dw/shift-select-shapes id))
|
(st/emit! (dw/shift-select-shapes id))
|
||||||
|
|
||||||
(or (kbd/ctrl? event) (kbd/meta? event))
|
(kbd/mod? event)
|
||||||
(st/emit! (dw/select-shape id true))
|
(st/emit! (dw/select-shape id true))
|
||||||
|
|
||||||
(> (count selected) 1)
|
(> (count selected) 1)
|
||||||
|
|
|
@ -77,7 +77,7 @@
|
||||||
|
|
||||||
;; STATE
|
;; STATE
|
||||||
alt? (mf/use-state false)
|
alt? (mf/use-state false)
|
||||||
ctrl? (mf/use-state false)
|
mod? (mf/use-state false)
|
||||||
space? (mf/use-state false)
|
space? (mf/use-state false)
|
||||||
cursor (mf/use-state (utils/get-cursor :pointer-inner))
|
cursor (mf/use-state (utils/get-cursor :pointer-inner))
|
||||||
hover-ids (mf/use-state nil)
|
hover-ids (mf/use-state nil)
|
||||||
|
@ -171,9 +171,9 @@
|
||||||
|
|
||||||
(hooks/setup-dom-events viewport-ref zoom disable-paste in-viewport?)
|
(hooks/setup-dom-events viewport-ref zoom disable-paste in-viewport?)
|
||||||
(hooks/setup-viewport-size viewport-ref)
|
(hooks/setup-viewport-size viewport-ref)
|
||||||
(hooks/setup-cursor cursor alt? ctrl? space? panning drawing-tool drawing-path? node-editing?)
|
(hooks/setup-cursor cursor alt? mod? space? panning drawing-tool drawing-path? node-editing?)
|
||||||
(hooks/setup-keyboard alt? ctrl? space?)
|
(hooks/setup-keyboard alt? mod? space?)
|
||||||
(hooks/setup-hover-shapes page-id move-stream base-objects transform selected ctrl? hover hover-ids @hover-disabled? focus zoom)
|
(hooks/setup-hover-shapes page-id move-stream base-objects transform selected mod? hover hover-ids @hover-disabled? focus zoom)
|
||||||
(hooks/setup-viewport-modifiers modifiers base-objects)
|
(hooks/setup-viewport-modifiers modifiers base-objects)
|
||||||
(hooks/setup-shortcuts node-editing? drawing-path?)
|
(hooks/setup-shortcuts node-editing? drawing-path?)
|
||||||
(hooks/setup-active-frames base-objects vbox hover active-frames)
|
(hooks/setup-active-frames base-objects vbox hover active-frames)
|
||||||
|
@ -258,7 +258,7 @@
|
||||||
{:objects base-objects
|
{:objects base-objects
|
||||||
:selected selected
|
:selected selected
|
||||||
:hover (cond
|
:hover (cond
|
||||||
(and @hover (or @ctrl? (not= :frame (:type @hover))))
|
(and @hover (or @mod? (not= :frame (:type @hover))))
|
||||||
#{(:id @hover)}
|
#{(:id @hover)}
|
||||||
|
|
||||||
@frame-hover
|
@frame-hover
|
||||||
|
@ -271,7 +271,7 @@
|
||||||
{:shapes selected-shapes
|
{:shapes selected-shapes
|
||||||
:zoom zoom
|
:zoom zoom
|
||||||
:edition edition
|
:edition edition
|
||||||
:disable-handlers (or drawing-tool edition @space? @ctrl?)
|
:disable-handlers (or drawing-tool edition @space? @mod?)
|
||||||
:on-move-selected on-move-selected
|
:on-move-selected on-move-selected
|
||||||
:on-context-menu on-menu-selected}])
|
:on-context-menu on-menu-selected}])
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
(ns app.main.ui.workspace.viewport.actions
|
(ns app.main.ui.workspace.viewport.actions
|
||||||
(:require
|
(:require
|
||||||
[app.common.geom.point :as gpt]
|
[app.common.geom.point :as gpt]
|
||||||
|
[app.common.math :as mth]
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
[app.config :as cfg]
|
[app.config :as cfg]
|
||||||
[app.main.data.workspace :as dw]
|
[app.main.data.workspace :as dw]
|
||||||
|
@ -40,8 +41,10 @@
|
||||||
|
|
||||||
(let [event (.-nativeEvent bevent)
|
(let [event (.-nativeEvent bevent)
|
||||||
ctrl? (kbd/ctrl? event)
|
ctrl? (kbd/ctrl? event)
|
||||||
|
meta? (kbd/meta? event)
|
||||||
shift? (kbd/shift? event)
|
shift? (kbd/shift? event)
|
||||||
alt? (kbd/alt? event)
|
alt? (kbd/alt? event)
|
||||||
|
mod? (kbd/mod? event)
|
||||||
|
|
||||||
left-click? (and (not panning) (= 1 (.-which event)))
|
left-click? (and (not panning) (= 1 (.-which event)))
|
||||||
middle-click? (and (not panning) (= 2 (.-which event)))
|
middle-click? (and (not panning) (= 2 (.-which event)))
|
||||||
|
@ -53,7 +56,7 @@
|
||||||
middle-click?
|
middle-click?
|
||||||
(do
|
(do
|
||||||
(dom/prevent-default bevent)
|
(dom/prevent-default bevent)
|
||||||
(if ctrl?
|
(if mod?
|
||||||
(let [raw-pt (dom/get-client-position event)
|
(let [raw-pt (dom/get-client-position event)
|
||||||
viewport (mf/ref-val viewport-ref)
|
viewport (mf/ref-val viewport-ref)
|
||||||
pt (utils/translate-point-to-viewport viewport zoom raw-pt)]
|
pt (utils/translate-point-to-viewport viewport zoom raw-pt)]
|
||||||
|
@ -63,7 +66,7 @@
|
||||||
|
|
||||||
left-click?
|
left-click?
|
||||||
(do
|
(do
|
||||||
(st/emit! (ms/->MouseEvent :down ctrl? shift? alt?))
|
(st/emit! (ms/->MouseEvent :down ctrl? shift? alt? meta?))
|
||||||
|
|
||||||
(when (and (not= edition id) text-editing?)
|
(when (and (not= edition id) text-editing?)
|
||||||
(st/emit! dw/clear-edition-mode))
|
(st/emit! dw/clear-edition-mode))
|
||||||
|
@ -78,7 +81,7 @@
|
||||||
;; Handle path node area selection
|
;; Handle path node area selection
|
||||||
(st/emit! (dwdp/handle-area-selection shift?))
|
(st/emit! (dwdp/handle-area-selection shift?))
|
||||||
|
|
||||||
(and @space? ctrl?)
|
(and @space? mod?)
|
||||||
(let [raw-pt (dom/get-client-position event)
|
(let [raw-pt (dom/get-client-position event)
|
||||||
viewport (mf/ref-val viewport-ref)
|
viewport (mf/ref-val viewport-ref)
|
||||||
pt (utils/translate-point-to-viewport viewport zoom raw-pt)]
|
pt (utils/translate-point-to-viewport viewport zoom raw-pt)]
|
||||||
|
@ -90,8 +93,8 @@
|
||||||
drawing-tool
|
drawing-tool
|
||||||
(st/emit! (dd/start-drawing drawing-tool))
|
(st/emit! (dd/start-drawing drawing-tool))
|
||||||
|
|
||||||
(or (not id) (and frame? (not selected?)) ctrl?)
|
(or (not id) (and frame? (not selected?)) mod?)
|
||||||
(st/emit! (dw/handle-area-selection shift? ctrl?))
|
(st/emit! (dw/handle-area-selection shift? mod?))
|
||||||
|
|
||||||
(not drawing-tool)
|
(not drawing-tool)
|
||||||
(st/emit! (when (or shift? (not selected?))
|
(st/emit! (when (or shift? (not selected?))
|
||||||
|
@ -105,11 +108,11 @@
|
||||||
(fn [bevent]
|
(fn [bevent]
|
||||||
(let [event (.-nativeEvent bevent)
|
(let [event (.-nativeEvent bevent)
|
||||||
shift? (kbd/shift? event)
|
shift? (kbd/shift? event)
|
||||||
ctrl? (kbd/ctrl? event)
|
mod? (kbd/mod? event)
|
||||||
left-click? (= 1 (.-which event))]
|
left-click? (= 1 (.-which event))]
|
||||||
|
|
||||||
(when (and left-click?
|
(when (and left-click?
|
||||||
(not ctrl?)
|
(not mod?)
|
||||||
(not shift?)
|
(not shift?)
|
||||||
(not @space?)
|
(not @space?)
|
||||||
(or (not @hover)
|
(or (not @hover)
|
||||||
|
@ -153,14 +156,16 @@
|
||||||
(let [ctrl? (kbd/ctrl? event)
|
(let [ctrl? (kbd/ctrl? event)
|
||||||
shift? (kbd/shift? event)
|
shift? (kbd/shift? event)
|
||||||
alt? (kbd/alt? event)
|
alt? (kbd/alt? event)
|
||||||
|
meta? (kbd/meta? event)
|
||||||
|
mod? (kbd/mod? event)
|
||||||
|
|
||||||
hovering? (some? @hover)
|
hovering? (some? @hover)
|
||||||
frame? (= :frame (:type @hover))
|
frame? (= :frame (:type @hover))
|
||||||
selected? (contains? selected (:id @hover))]
|
selected? (contains? selected (:id @hover))]
|
||||||
(st/emit! (ms/->MouseEvent :click ctrl? shift? alt?))
|
(st/emit! (ms/->MouseEvent :click ctrl? shift? alt? meta?))
|
||||||
|
|
||||||
(when (and hovering?
|
(when (and hovering?
|
||||||
(or (not frame?) ctrl?)
|
(or (not frame?) mod?)
|
||||||
(not @space?)
|
(not @space?)
|
||||||
(not selected?)
|
(not selected?)
|
||||||
(not edition)
|
(not edition)
|
||||||
|
@ -177,13 +182,14 @@
|
||||||
(let [ctrl? (kbd/ctrl? event)
|
(let [ctrl? (kbd/ctrl? event)
|
||||||
shift? (kbd/shift? event)
|
shift? (kbd/shift? event)
|
||||||
alt? (kbd/alt? event)
|
alt? (kbd/alt? event)
|
||||||
|
meta? (kbd/meta? event)
|
||||||
|
|
||||||
{:keys [id type] :as shape} @hover
|
{:keys [id type] :as shape} @hover
|
||||||
|
|
||||||
frame? (= :frame type)
|
frame? (= :frame type)
|
||||||
group? (= :group type)]
|
group? (= :group type)]
|
||||||
|
|
||||||
(st/emit! (ms/->MouseEvent :double-click ctrl? shift? alt?))
|
(st/emit! (ms/->MouseEvent :double-click ctrl? shift? alt? meta?))
|
||||||
|
|
||||||
;; Emit asynchronously so the double click to exit shapes won't break
|
;; Emit asynchronously so the double click to exit shapes won't break
|
||||||
(timers/schedule
|
(timers/schedule
|
||||||
|
@ -242,12 +248,13 @@
|
||||||
ctrl? (kbd/ctrl? event)
|
ctrl? (kbd/ctrl? event)
|
||||||
shift? (kbd/shift? event)
|
shift? (kbd/shift? event)
|
||||||
alt? (kbd/alt? event)
|
alt? (kbd/alt? event)
|
||||||
|
meta? (kbd/meta? event)
|
||||||
|
|
||||||
left-click? (= 1 (.-which event))
|
left-click? (= 1 (.-which event))
|
||||||
middle-click? (= 2 (.-which event))]
|
middle-click? (= 2 (.-which event))]
|
||||||
|
|
||||||
(when left-click?
|
(when left-click?
|
||||||
(st/emit! (ms/->MouseEvent :up ctrl? shift? alt?)))
|
(st/emit! (ms/->MouseEvent :up ctrl? shift? alt? meta?)))
|
||||||
|
|
||||||
(when middle-click?
|
(when middle-click?
|
||||||
(dom/prevent-default event)
|
(dom/prevent-default event)
|
||||||
|
@ -343,11 +350,13 @@
|
||||||
(st/emit! (ms/->PointerEvent :delta delta
|
(st/emit! (ms/->PointerEvent :delta delta
|
||||||
(kbd/ctrl? event)
|
(kbd/ctrl? event)
|
||||||
(kbd/shift? event)
|
(kbd/shift? event)
|
||||||
(kbd/alt? event)))
|
(kbd/alt? event)
|
||||||
|
(kbd/meta? event)))
|
||||||
(st/emit! (ms/->PointerEvent :viewport pt
|
(st/emit! (ms/->PointerEvent :viewport pt
|
||||||
(kbd/ctrl? event)
|
(kbd/ctrl? event)
|
||||||
(kbd/shift? event)
|
(kbd/shift? event)
|
||||||
(kbd/alt? event))))))))
|
(kbd/alt? event)
|
||||||
|
(kbd/meta? event))))))))
|
||||||
|
|
||||||
(defn on-pointer-move [viewport-ref zoom move-stream]
|
(defn on-pointer-move [viewport-ref zoom move-stream]
|
||||||
(mf/use-callback
|
(mf/use-callback
|
||||||
|
@ -362,27 +371,18 @@
|
||||||
(mf/use-callback
|
(mf/use-callback
|
||||||
(mf/deps zoom)
|
(mf/deps zoom)
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(let [event (.getBrowserEvent ^js event)
|
(let [viewport (mf/ref-val viewport-ref)
|
||||||
raw-pt (dom/get-client-position event)
|
event (.getBrowserEvent ^js event)
|
||||||
viewport (mf/ref-val viewport-ref)
|
|
||||||
pt (utils/translate-point-to-viewport viewport zoom raw-pt)
|
|
||||||
|
|
||||||
ctrl? (kbd/ctrl? event)
|
|
||||||
meta? (kbd/meta? event)
|
|
||||||
target (dom/get-target event)]
|
target (dom/get-target event)]
|
||||||
(cond
|
(when (.contains ^js viewport target)
|
||||||
(or ctrl? meta?)
|
|
||||||
(do
|
|
||||||
(dom/prevent-default event)
|
(dom/prevent-default event)
|
||||||
(dom/stop-propagation event)
|
(dom/stop-propagation event)
|
||||||
(let [delta (+ (.-deltaY ^js event)
|
(let [pt (->> (dom/get-client-position event)
|
||||||
(.-deltaX ^js event))]
|
(utils/translate-point-to-viewport viewport zoom))
|
||||||
(if (pos? delta)
|
|
||||||
(st/emit! (dw/decrease-zoom pt))
|
|
||||||
(st/emit! (dw/increase-zoom pt)))))
|
|
||||||
|
|
||||||
(.contains ^js viewport target)
|
mod? (kbd/mod? event)
|
||||||
(let [delta-mode (.-deltaMode ^js event)
|
|
||||||
|
delta-mode (.-deltaMode ^js event)
|
||||||
|
|
||||||
unit (cond
|
unit (cond
|
||||||
(= delta-mode WheelEvent.DeltaMode.PIXEL) 1
|
(= delta-mode WheelEvent.DeltaMode.PIXEL) 1
|
||||||
|
@ -396,13 +396,16 @@
|
||||||
delta-x (-> (.-deltaX ^js event)
|
delta-x (-> (.-deltaX ^js event)
|
||||||
(* unit)
|
(* unit)
|
||||||
(/ zoom))]
|
(/ zoom))]
|
||||||
(dom/prevent-default event)
|
(if mod?
|
||||||
(dom/stop-propagation event)
|
(let [delta (* -1 (+ (.-deltaY ^js event) (.-deltaX ^js event)))
|
||||||
(if (and (not (cfg/check-platform? :macos)) ;; macos sends delta-x automatically, don't need to do it
|
scale (-> (+ 1 (/ delta 100)) (mth/clamp 0.77 1.3))]
|
||||||
|
(st/emit! (dw/set-zoom pt scale)))
|
||||||
|
(if (and (not (cfg/check-platform? :macos))
|
||||||
|
;; macos sends delta-x automatically, don't need to do it
|
||||||
(kbd/shift? event))
|
(kbd/shift? event))
|
||||||
(st/emit! (dw/update-viewport-position {:x #(+ % delta-y)}))
|
(st/emit! (dw/update-viewport-position {:x #(+ % delta-y)}))
|
||||||
(st/emit! (dw/update-viewport-position {:x #(+ % delta-x)
|
(st/emit! (dw/update-viewport-position {:x #(+ % delta-x)
|
||||||
:y #(+ % delta-y)})))))))))
|
:y #(+ % delta-y)}))))))))))
|
||||||
|
|
||||||
(defn on-drag-enter []
|
(defn on-drag-enter []
|
||||||
(mf/use-callback
|
(mf/use-callback
|
||||||
|
|
|
@ -58,16 +58,16 @@
|
||||||
;; We schedule the event so it fires after `initialize-page` event
|
;; We schedule the event so it fires after `initialize-page` event
|
||||||
(timers/schedule #(st/emit! (dw/initialize-viewport size)))))))
|
(timers/schedule #(st/emit! (dw/initialize-viewport size)))))))
|
||||||
|
|
||||||
(defn setup-cursor [cursor alt? ctrl? space? panning drawing-tool drawing-path? path-editing?]
|
(defn setup-cursor [cursor alt? mod? space? panning drawing-tool drawing-path? path-editing?]
|
||||||
(mf/use-effect
|
(mf/use-effect
|
||||||
(mf/deps @cursor @alt? @ctrl? @space? panning drawing-tool drawing-path? path-editing?)
|
(mf/deps @cursor @alt? @mod? @space? panning drawing-tool drawing-path? path-editing?)
|
||||||
(fn []
|
(fn []
|
||||||
(let [show-pen? (or (= drawing-tool :path)
|
(let [show-pen? (or (= drawing-tool :path)
|
||||||
(and drawing-path?
|
(and drawing-path?
|
||||||
(not= drawing-tool :curve)))
|
(not= drawing-tool :curve)))
|
||||||
new-cursor
|
new-cursor
|
||||||
(cond
|
(cond
|
||||||
(and @ctrl? @space?) (utils/get-cursor :zoom)
|
(and @mod? @space?) (utils/get-cursor :zoom)
|
||||||
(or panning @space?) (utils/get-cursor :hand)
|
(or panning @space?) (utils/get-cursor :hand)
|
||||||
(= drawing-tool :comments) (utils/get-cursor :comments)
|
(= drawing-tool :comments) (utils/get-cursor :comments)
|
||||||
(= drawing-tool :frame) (utils/get-cursor :create-artboard)
|
(= drawing-tool :frame) (utils/get-cursor :create-artboard)
|
||||||
|
@ -82,9 +82,9 @@
|
||||||
(when (not= @cursor new-cursor)
|
(when (not= @cursor new-cursor)
|
||||||
(reset! cursor new-cursor))))))
|
(reset! cursor new-cursor))))))
|
||||||
|
|
||||||
(defn setup-keyboard [alt? ctrl? space?]
|
(defn setup-keyboard [alt? mod? space?]
|
||||||
(hooks/use-stream ms/keyboard-alt #(reset! alt? %))
|
(hooks/use-stream ms/keyboard-alt #(reset! alt? %))
|
||||||
(hooks/use-stream ms/keyboard-ctrl #(reset! ctrl? %))
|
(hooks/use-stream ms/keyboard-mod #(reset! mod? %))
|
||||||
(hooks/use-stream ms/keyboard-space #(reset! space? %)))
|
(hooks/use-stream ms/keyboard-space #(reset! space? %)))
|
||||||
|
|
||||||
(defn group-empty-space?
|
(defn group-empty-space?
|
||||||
|
@ -100,10 +100,10 @@
|
||||||
(some #(cph/is-parent? objects % group-id))
|
(some #(cph/is-parent? objects % group-id))
|
||||||
(not))))
|
(not))))
|
||||||
|
|
||||||
(defn setup-hover-shapes [page-id move-stream objects transform selected ctrl? hover hover-ids hover-disabled? focus zoom]
|
(defn setup-hover-shapes [page-id move-stream objects transform selected mod? hover hover-ids hover-disabled? focus zoom]
|
||||||
(let [;; We use ref so we don't recreate the stream on a change
|
(let [;; We use ref so we don't recreate the stream on a change
|
||||||
zoom-ref (mf/use-ref zoom)
|
zoom-ref (mf/use-ref zoom)
|
||||||
ctrl-ref (mf/use-ref @ctrl?)
|
mod-ref (mf/use-ref @mod?)
|
||||||
transform-ref (mf/use-ref nil)
|
transform-ref (mf/use-ref nil)
|
||||||
selected-ref (mf/use-ref selected)
|
selected-ref (mf/use-ref selected)
|
||||||
hover-disabled-ref (mf/use-ref hover-disabled?)
|
hover-disabled-ref (mf/use-ref hover-disabled?)
|
||||||
|
@ -114,7 +114,7 @@
|
||||||
(mf/deps page-id)
|
(mf/deps page-id)
|
||||||
(fn [point]
|
(fn [point]
|
||||||
(let [zoom (mf/ref-val zoom-ref)
|
(let [zoom (mf/ref-val zoom-ref)
|
||||||
ctrl? (mf/ref-val ctrl-ref)
|
mod? (mf/ref-val mod-ref)
|
||||||
rect (gsh/center->rect point (/ 5 zoom) (/ 5 zoom))]
|
rect (gsh/center->rect point (/ 5 zoom) (/ 5 zoom))]
|
||||||
(if (mf/ref-val hover-disabled-ref)
|
(if (mf/ref-val hover-disabled-ref)
|
||||||
(rx/of nil)
|
(rx/of nil)
|
||||||
|
@ -123,7 +123,7 @@
|
||||||
:page-id page-id
|
:page-id page-id
|
||||||
:rect rect
|
:rect rect
|
||||||
:include-frames? true
|
:include-frames? true
|
||||||
:clip-children? (not ctrl?)
|
:clip-children? (not mod?)
|
||||||
:reverse? true}))))) ;; we want the topmost shape to be selected first
|
:reverse? true}))))) ;; we want the topmost shape to be selected first
|
||||||
|
|
||||||
over-shapes-stream
|
over-shapes-stream
|
||||||
|
@ -150,8 +150,8 @@
|
||||||
#(mf/set-ref-val! zoom-ref zoom))
|
#(mf/set-ref-val! zoom-ref zoom))
|
||||||
|
|
||||||
(mf/use-effect
|
(mf/use-effect
|
||||||
(mf/deps @ctrl?)
|
(mf/deps @mod?)
|
||||||
#(mf/set-ref-val! ctrl-ref @ctrl?))
|
#(mf/set-ref-val! mod-ref @mod?))
|
||||||
|
|
||||||
(mf/use-effect
|
(mf/use-effect
|
||||||
(mf/deps selected)
|
(mf/deps selected)
|
||||||
|
@ -176,14 +176,14 @@
|
||||||
selected (mf/ref-val selected-ref)
|
selected (mf/ref-val selected-ref)
|
||||||
focus (mf/ref-val focus-ref)
|
focus (mf/ref-val focus-ref)
|
||||||
|
|
||||||
ctrl? (mf/ref-val ctrl-ref)
|
mod? (mf/ref-val mod-ref)
|
||||||
|
|
||||||
remove-xfm (mapcat #(cph/get-parent-ids objects %))
|
remove-xfm (mapcat #(cph/get-parent-ids objects %))
|
||||||
remove-id? (cond-> (into #{} remove-xfm selected)
|
remove-id? (cond-> (into #{} remove-xfm selected)
|
||||||
(not ctrl?)
|
(not mod?)
|
||||||
(into (filter #(group-empty-space? % objects ids)) ids)
|
(into (filter #(group-empty-space? % objects ids)) ids)
|
||||||
|
|
||||||
ctrl?
|
mod?
|
||||||
(into (filter is-group?) ids))
|
(into (filter is-group?) ids))
|
||||||
|
|
||||||
hover-shape (->> ids
|
hover-shape (->> ids
|
||||||
|
|
|
@ -4,37 +4,45 @@
|
||||||
;;
|
;;
|
||||||
;; Copyright (c) UXBOX Labs SL
|
;; Copyright (c) UXBOX Labs SL
|
||||||
|
|
||||||
(ns app.util.keyboard)
|
(ns app.util.keyboard
|
||||||
|
(:require
|
||||||
|
[app.config :as cfg]))
|
||||||
|
|
||||||
(defn is-key?
|
(defn is-key?
|
||||||
[key]
|
[^string key]
|
||||||
(fn [e]
|
(fn [^js e]
|
||||||
(= (.-key e) key)))
|
(= (.-key e) key)))
|
||||||
|
|
||||||
(defn ^boolean alt?
|
(defn ^boolean alt?
|
||||||
[event]
|
[^js event]
|
||||||
(.-altKey event))
|
(.-altKey event))
|
||||||
|
|
||||||
(defn ^boolean ctrl?
|
(defn ^boolean ctrl?
|
||||||
[event]
|
[^js event]
|
||||||
(.-ctrlKey event))
|
(.-ctrlKey event))
|
||||||
|
|
||||||
(defn ^boolean meta?
|
(defn ^boolean meta?
|
||||||
[event]
|
[^js event]
|
||||||
(.-metaKey event))
|
(.-metaKey event))
|
||||||
|
|
||||||
(defn ^boolean shift?
|
(defn ^boolean shift?
|
||||||
[event]
|
[^js event]
|
||||||
(.-shiftKey event))
|
(.-shiftKey event))
|
||||||
|
|
||||||
|
(defn ^boolean mod?
|
||||||
|
[^js event]
|
||||||
|
(if (cfg/check-platform? :macos)
|
||||||
|
(meta? event)
|
||||||
|
(ctrl? event)))
|
||||||
|
|
||||||
(def esc? (is-key? "Escape"))
|
(def esc? (is-key? "Escape"))
|
||||||
(def enter? (is-key? "Enter"))
|
(def enter? (is-key? "Enter"))
|
||||||
(def space? (is-key? " "))
|
(def space? (is-key? " "))
|
||||||
(def up-arrow? (is-key? "ArrowUp"))
|
(def up-arrow? (is-key? "ArrowUp"))
|
||||||
(def down-arrow? (is-key? "ArrowDown"))
|
(def down-arrow? (is-key? "ArrowDown"))
|
||||||
(def altKey? (is-key? "Alt"))
|
(def alt-key? (is-key? "Alt"))
|
||||||
(def ctrlKey? (or (is-key? "Control")
|
(def ctrl-key? (is-key? "Control"))
|
||||||
(is-key? "Meta")))
|
(def meta-key? (is-key? "Meta"))
|
||||||
(def comma? (is-key? ","))
|
(def comma? (is-key? ","))
|
||||||
(def backspace? (is-key? "Backspace"))
|
(def backspace? (is-key? "Backspace"))
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,9 @@
|
||||||
|
|
||||||
;; When active we can check in the browser the export values
|
;; When active we can check in the browser the export values
|
||||||
:show-export-metadata
|
:show-export-metadata
|
||||||
|
|
||||||
|
;; Show text fragments outlines
|
||||||
|
:text-outline
|
||||||
})
|
})
|
||||||
|
|
||||||
;; These events are excluded when we activate the :events flag
|
;; These events are excluded when we activate the :events flag
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue