diff --git a/frontend/package-lock.json b/frontend/package-lock.json index e3a3f2a1f..559a0d696 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -3945,6 +3945,11 @@ } } }, + "mousetrap": { + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/mousetrap/-/mousetrap-1.6.5.tgz", + "integrity": "sha512-QNo4kEepaIBwiT8CDhP98umTetp+JNfQYBWvC1pc6/OAibuXtRcxZ58Qz8skvEHYvURne/7R8T5VoOI7rDsEUA==" + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index cc478e876..fb278caac 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -29,6 +29,7 @@ }, "dependencies": { "date-fns": "^2.11.1", + "mousetrap": "^1.6.5", "randomcolor": "^0.5.4", "react": "^16.13.1", "react-color": "^2.18.0", diff --git a/frontend/src/uxbox/main/data/workspace.cljs b/frontend/src/uxbox/main/data/workspace.cljs index 72fbb56f1..2683d9496 100644 --- a/frontend/src/uxbox/main/data/workspace.cljs +++ b/frontend/src/uxbox/main/data/workspace.cljs @@ -2263,63 +2263,41 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (def shortcuts - {"ctrl+shift+m" #(rx/of (toggle-layout-flag :sitemap)) - "ctrl+shift+f" #(rx/of (toggle-layout-flag :drawtools)) - "ctrl+shift+i" #(rx/of (toggle-layout-flag :icons)) - "ctrl+shift+l" #(rx/of (toggle-layout-flag :layers)) - "equals" #(rx/of increase-zoom) ; keyName for the key with = and + in US keyboards (see https://unixpapa.com/js/key.html) - "dash" #(rx/of decrease-zoom) ; keyName for the key with - and _ in US keyboards - "shift+0" #(rx/of zoom-to-50) - "shift+1" #(rx/of reset-zoom) - "shift+2" #(rx/of zoom-to-200) - "ctrl+d" #(rx/of duplicate-selected) - "ctrl+z" #(rx/of undo) - "ctrl+shift+z" #(rx/of redo) - "ctrl+y" #(rx/of redo) - "ctrl+q" #(rx/of reinitialize-undo) - "ctrl+b" #(rx/of (select-for-drawing :rect)) - "ctrl+e" #(rx/of (select-for-drawing :circle)) - "ctrl+t" #(rx/of (select-for-drawing :text)) - "ctrl+c" #(rx/of copy-selected) - "ctrl+v" #(rx/of paste) - "ctrl+g" #(rx/of (create-group)) - "ctrl+shift+g" #(rx/of (remove-group)) - "esc" #(rx/of :interrupt deselect-all) - "delete" #(rx/of delete-selected) - "ctrl+up" #(rx/of (vertical-order-selected :up)) - "ctrl+down" #(rx/of (vertical-order-selected :down)) - "ctrl+shift+up" #(rx/of (vertical-order-selected :top)) - "ctrl+shift+down" #(rx/of (vertical-order-selected :bottom)) - "shift+up" #(rx/of (move-selected :up true)) - "shift+down" #(rx/of (move-selected :down true)) - "shift+right" #(rx/of (move-selected :right true)) - "shift+left" #(rx/of (move-selected :left true)) - "up" #(rx/of (move-selected :up false)) - "down" #(rx/of (move-selected :down false)) - "right" #(rx/of (move-selected :right false)) - "left" #(rx/of (move-selected :left false))}) + {"ctrl+shift+m" #(st/emit! (toggle-layout-flag :sitemap)) + "ctrl+shift+i" #(st/emit! (toggle-layout-flag :libraries)) + "ctrl+shift+l" #(st/emit! (toggle-layout-flag :layers)) + "+" #(st/emit! increase-zoom) + "-" #(st/emit! decrease-zoom) -(def initialize-shortcuts - (letfn [(initialize [sink] - (let [handler (KeyboardShortcutHandler. js/document)] + "ctrl+g" #(st/emit! (create-group)) + "ctrl+shift+g" #(st/emit! (remove-group)) - ;; Register shortcuts. - (run! #(.registerShortcut handler % %) (keys shortcuts)) - - ;; Initialize shortcut listener. - (let [event KeyboardShortcutHandler.EventType.SHORTCUT_TRIGGERED - callback #(sink (gobj/get % "identifier")) - key (events/listen handler event callback)] - (fn [] - (events/unlistenByKey key) - (.clearKeyListener handler)))))] - (ptk/reify ::initialize-shortcuts - ptk/WatchEvent - (watch [_ state stream] - (let [stoper (rx/filter #(= ::finalize-shortcuts %) stream)] - (->> (rx/create initialize) - (rx/pr-log "[debug]: shortcut:") - (rx/map #(get shortcuts %)) - (rx/filter fn?) - (rx/merge-map (fn [f] (f))) - (rx/take-until stoper))))))) + "shift+0" #(st/emit! zoom-to-50) + "shift+1" #(st/emit! reset-zoom) + "shift+2" #(st/emit! zoom-to-200) + "ctrl+d" #(st/emit! duplicate-selected) + "ctrl+z" #(st/emit! undo) + "ctrl+shift+z" #(st/emit! redo) + "ctrl+y" #(st/emit! redo) + "ctrl+q" #(st/emit! reinitialize-undo) + "ctrl+b" #(st/emit! (select-for-drawing :rect)) + "ctrl+e" #(st/emit! (select-for-drawing :circle)) + "ctrl+t" #(st/emit! (select-for-drawing :text)) + "ctrl+c" #(st/emit! copy-selected) + "ctrl+v" #(st/emit! paste) + "ctrl+g" #(st/emit! (create-group)) + ;; "ctrl+shift+g" #(st/emit! remove-group) + "esc" #(st/emit! :interrupt deselect-all) + "delete" #(st/emit! delete-selected) + "ctrl+up" #(st/emit! (vertical-order-selected :up)) + "ctrl+down" #(st/emit! (vertical-order-selected :down)) + "ctrl+shift+up" #(st/emit! (vertical-order-selected :top)) + "ctrl+shift+down" #(st/emit! (vertical-order-selected :bottom)) + "shift+up" #(st/emit! (move-selected :up true)) + "shift+down" #(st/emit! (move-selected :down true)) + "shift+right" #(st/emit! (move-selected :right true)) + "shift+left" #(st/emit! (move-selected :left true)) + "up" #(st/emit! (move-selected :up false)) + "down" #(st/emit! (move-selected :down false)) + "right" #(st/emit! (move-selected :right false)) + "left" #(st/emit! (move-selected :left false))}) diff --git a/frontend/src/uxbox/main/ui/react_hooks.cljs b/frontend/src/uxbox/main/ui/react_hooks.cljs index 35da9ee1d..9fcbdcfaa 100644 --- a/frontend/src/uxbox/main/ui/react_hooks.cljs +++ b/frontend/src/uxbox/main/ui/react_hooks.cljs @@ -10,9 +10,12 @@ (ns uxbox.main.ui.react-hooks "A collection of general purpose react hooks." (:require + [cljs.spec.alpha :as s] + [uxbox.common.spec :as us] [beicon.core :as rx] [goog.events :as events] - [rumext.alpha :as mf]) + [rumext.alpha :as mf] + ["mousetrap" :as mousetrap]) (:import goog.events.EventType)) (defn use-rxsub @@ -24,3 +27,22 @@ #(rx/cancel! sub))) #js [ob]) state)) + + +(s/def ::shortcuts + (s/map-of ::us/string fn?)) + +(defn use-shortcuts + [shortcuts] + (us/assert ::shortcuts shortcuts) + (mf/use-effect + (fn [] + (->> (seq shortcuts) + (run! (fn [[key f]] + (mousetrap/bind key (fn [event] + (js/console.log "[debug]: shortcut:" key) + (.preventDefault event) + (f event)))))) + (fn [] (mousetrap/reset)))) + nil) + diff --git a/frontend/src/uxbox/main/ui/workspace.cljs b/frontend/src/uxbox/main/ui/workspace.cljs index 74aac1c2a..b8e0c57d0 100644 --- a/frontend/src/uxbox/main/ui/workspace.cljs +++ b/frontend/src/uxbox/main/ui/workspace.cljs @@ -19,6 +19,7 @@ [uxbox.main.streams :as ms] [uxbox.main.ui.confirm] [uxbox.main.ui.keyboard :as kbd] + [uxbox.main.ui.react-hooks :as hooks] [uxbox.main.ui.messages :refer [messages-widget]] [uxbox.main.ui.workspace.viewport :refer [viewport]] [uxbox.main.ui.workspace.colorpalette :refer [colorpalette]] @@ -111,11 +112,7 @@ (st/emit! (dw/initialize-ws file-id)) #(st/emit! (dw/finalize-ws file-id))))) - (-> (mf/deps file-id) - (mf/use-effect - (fn [] - (st/emit! dw/initialize-shortcuts) - #(st/emit! ::dw/finalize-shortcuts)))) + (hooks/use-shortcuts dw/shortcuts) (mf/use-effect #(st/emit! dw/initialize-layout))