0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-01-25 07:58:49 -05:00

♻️ Improves shortcuts lifecycle management.

This commit is contained in:
Andrey Antukh 2021-05-12 10:21:53 +02:00 committed by Andrés Moya
parent c33c3fb2fa
commit 4b7f82a9d9
6 changed files with 130 additions and 55 deletions

View file

@ -5,14 +5,22 @@
;; Copyright (c) UXBOX Labs SL
(ns app.main.data.shortcuts
(:refer-clojure :exclude [meta reset!])
(:require
["mousetrap" :as mousetrap]
[app.common.data :as d]
[app.common.spec :as us]
[app.config :as cfg]
[app.util.logging :as log])
(:refer-clojure :exclude [meta]))
[app.util.logging :as log]
[cljs.spec.alpha :as s]
[potok.core :as ptk]))
(log/set-level! :warn)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Helpers
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(def mac-command "\u2318")
(def mac-option "\u2325")
(def mac-delete "\u232B")
@ -44,30 +52,8 @@
[shortcut]
(c-mod (a-mod shortcut)))
(defn bind-shortcuts
([shortcuts-config]
(bind-shortcuts
shortcuts-config
mousetrap/bind
(fn [key cb]
(fn [event]
(log/debug :msg (str "Shortcut" key))
(.preventDefault event)
(cb event)))))
([shortcuts-config bind-fn cb-fn]
(doseq [[key {:keys [command disabled fn type]}] shortcuts-config]
(when-not disabled
(if (vector? command)
(doseq [cmd (seq command)]
(bind-fn cmd (cb-fn key fn) type))
(bind-fn command (cb-fn key fn) type))))))
(defn remove-shortcuts
[]
(mousetrap/reset))
(defn meta [key]
(defn meta
[key]
;; If the key is "+" we need to surround with quotes
;; otherwise will not be very readable
(let [key (if (and (not (cfg/check-platform? :macos))
@ -80,37 +66,120 @@
"Ctrl+")
key)))
(defn shift [key]
(defn shift
[key]
(str
(if (cfg/check-platform? :macos)
mac-shift
"Shift+")
key))
(defn alt [key]
(defn alt
[key]
(str
(if (cfg/check-platform? :macos)
mac-option
"Alt+")
key))
(defn meta-shift [key]
(defn meta-shift
[key]
(-> key meta shift))
(defn meta-alt [key]
(defn meta-alt
[key]
(-> key meta alt))
(defn supr []
(defn supr
[]
(if (cfg/check-platform? :macos)
mac-delete
"Supr"))
(defn esc []
(defn esc
[]
(if (cfg/check-platform? :macos)
mac-esc
"Escape"))
(defn enter []
(defn enter
[]
(if (cfg/check-platform? :macos)
mac-enter
"Enter"))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Events
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; --- EVENT: push
(s/def ::tooltip ::us/string)
(s/def ::fn fn?)
(s/def ::command
(s/or :str ::us/string
:vec vector?))
(s/def ::shortcut
(s/keys :req-un [::command]
:opt-un [::fn
::tooltip]))
(s/def ::shortcuts
(s/map-of ::us/keyword
::shortcut))
(defn- wrap-cb
[key cb]
(fn [event]
(log/debug :msg (str "Shortcut" key))
(.preventDefault event)
(cb event)))
(defn- bind!
[shortcuts]
(->> shortcuts
(remove #(:disabled (second %)))
(run! (fn [[key {:keys [command fn type]}]]
(if (vector? command)
(run! #(mousetrap/bind % (wrap-cb key fn) type) command)
(mousetrap/bind command (wrap-cb key fn) type))))))
(defn- reset!
([]
(mousetrap/reset))
([shortcuts]
(mousetrap/reset)
(bind! shortcuts)))
(defn push-shortcuts
[key shortcuts]
(us/assert ::us/keyword key)
(us/assert ::shortcuts shortcuts)
(ptk/reify ::push-shortcuts
ptk/UpdateEvent
(update [_ state]
(-> state
(update :shortcuts (fnil conj '()) [key shortcuts])))
ptk/EffectEvent
(effect [_ state stream]
(let [[key shortcuts] (peek (:shortcuts state))]
(reset! shortcuts)))))
(defn pop-shortcuts
[key]
(ptk/reify ::pop-shortcuts
ptk/UpdateEvent
(update [_ state]
(update state :shortcuts (fn [shortcuts]
(let [current-key (first (peek shortcuts))]
(if (= key current-key)
(pop shortcuts)
shortcuts)))))
ptk/EffectEvent
(effect [_ state stream]
(let [[key* shortcuts] (peek (:shortcuts state))]
(when (not= key key*)
(reset! shortcuts))))))

View file

@ -33,7 +33,7 @@
:toggle-assets {:tooltip (ds/alt "I")
:command (ds/a-mod "i")
:fn #(st/emit! (dw/go-to-layout :assets))}
:toggle-history {:tooltip (ds/alt "H")
:command (ds/a-mod "h")
:fn #(st/emit! (dw/go-to-layout :document-history))}
@ -45,7 +45,7 @@
:toggle-rules {:tooltip (ds/meta-shift "R")
:command (ds/c-mod "shift+r")
:fn #(st/emit! (dw/toggle-layout-flags :rules))}
:select-all {:tooltip (ds/meta "A")
:command (ds/c-mod "a")
:fn #(st/emit! (dw/select-all))}
@ -73,7 +73,7 @@
:decrease-zoom {:tooltip "-"
:command "-"
:fn #(st/emit! (dw/decrease-zoom nil))}
:group {:tooltip (ds/meta "G")
:command (ds/c-mod "g")
:fn #(st/emit! dw/group-selected)}
@ -173,7 +173,8 @@
:paste {:tooltip (ds/meta "V")
:disabled true
:command (ds/c-mod "v")}
:command (ds/c-mod "v")
:fn (constantly nil)}
:delete {:tooltip (ds/supr)
:command ["del" "backspace"]

View file

@ -91,7 +91,7 @@
(events/unlistenByKey key1))))]
(mf/use-effect on-mount)
(hooks/use-shortcuts sc/shortcuts)
(hooks/use-shortcuts ::handoff sc/shortcuts)
[:div.handoff-layout {:class (dom/classnames :force-visible
(:show-thumbnails state))}

View file

@ -9,10 +9,11 @@
(:require
[app.common.spec :as us]
[app.main.data.shortcuts :as dsc]
[app.main.store :as st]
[app.util.dom :as dom]
[app.util.object :as obj]
[app.util.dom.dnd :as dnd]
[app.util.logging :as log]
[app.util.object :as obj]
[app.util.timers :as ts]
[app.util.transit :as t]
[app.util.webapi :as wapi]
@ -35,11 +36,13 @@
state))
(defn use-shortcuts
[shortcuts]
[key shortcuts]
(mf/use-effect
#js [(str key) shortcuts]
(fn []
(dsc/bind-shortcuts shortcuts)
(fn [] (dsc/remove-shortcuts)))))
(st/emit! (dsc/push-shortcuts key shortcuts))
(fn []
(st/emit! (dsc/pop-shortcuts key))))))
(defn invisible-image
[]

View file

@ -237,7 +237,7 @@
(events/unlistenByKey key3))))]
(mf/use-effect on-mount)
(hooks/use-shortcuts sc/shortcuts)
(hooks/use-shortcuts ::viewer sc/shortcuts)
[:div.viewer-layout {:class (dom/classnames :force-visible
(:show-thumbnails state))}

View file

@ -153,18 +153,6 @@
(utils/update-transform render-node roots modifiers)
(utils/remove-transform render-node roots))))))
(defn setup-shortcuts [path-editing? drawing-path?]
(mf/use-effect
(mf/deps path-editing? drawing-path?)
(fn []
(cond
(or drawing-path? path-editing?)
(dsc/bind-shortcuts psc/shortcuts)
:else
(dsc/bind-shortcuts wsc/shortcuts))
dsc/remove-shortcuts)))
(defn inside-vbox [vbox objects frame-id]
(let [frame (get objects frame-id)]
@ -195,3 +183,17 @@
(:frame-id @hover))]
(when (not (contains? @active-frames frame-id))
(swap! active-frames assoc frame-id true))))))
;; NOTE: this is executed on each page change, maybe we need to move
;; this shortcuts outside the viewport?
(defn setup-shortcuts
[path-editing? drawing-path?]
(hooks/use-shortcuts ::workspace wsc/shortcuts)
(mf/use-effect
(mf/deps path-editing? drawing-path?)
(fn []
(when (or drawing-path? path-editing?)
(st/emit! (dsc/push-shortcuts ::path psc/shortcuts))
(st/emitf (dsc/pop-shortcuts ::path))))))