mirror of
https://github.com/penpot/penpot.git
synced 2026-05-08 17:48:39 +00:00
185 lines
4.1 KiB
Clojure
185 lines
4.1 KiB
Clojure
;; This Source Code Form is subject to the terms of the Mozilla Public
|
|
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
;;
|
|
;; Copyright (c) KALEIDOS INC
|
|
|
|
(ns app.main.data.shortcuts
|
|
(:refer-clojure :exclude [meta reset!])
|
|
(:require
|
|
["mousetrap" :as mousetrap]
|
|
[app.common.logging :as log]
|
|
[app.common.spec :as us]
|
|
[app.config :as cf]
|
|
[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")
|
|
(def mac-shift "\u21E7")
|
|
(def mac-control "\u2303")
|
|
(def mac-esc "\u238B")
|
|
(def mac-enter "\u23CE")
|
|
|
|
(def left-arrow "\u2190")
|
|
(def up-arrow "\u2191")
|
|
(def right-arrow "\u2192")
|
|
(def down-arrow "\u2193")
|
|
|
|
(defn c-mod
|
|
"Adds the control/command modifier to a shortcuts depending on the
|
|
operating system for the user"
|
|
[shortcut]
|
|
(if (cf/check-platform? :macos)
|
|
(str "command+" shortcut)
|
|
(str "ctrl+" shortcut)))
|
|
|
|
(defn a-mod
|
|
"Adds the alt/option modifier to a shortcuts depending on the
|
|
operating system for the user"
|
|
[shortcut]
|
|
(str "alt+" shortcut))
|
|
|
|
(defn ca-mod
|
|
[shortcut]
|
|
(c-mod (a-mod shortcut)))
|
|
|
|
(defn meta
|
|
[key]
|
|
;; If the key is "+" we need to surround with quotes
|
|
;; otherwise will not be very readable
|
|
(let [key (if (and (not (cf/check-platform? :macos))
|
|
(= key "+"))
|
|
"\"+\""
|
|
key)]
|
|
(str
|
|
(if (cf/check-platform? :macos)
|
|
mac-command
|
|
"Ctrl+")
|
|
key)))
|
|
|
|
(defn shift
|
|
[key]
|
|
(str
|
|
(if (cf/check-platform? :macos)
|
|
mac-shift
|
|
"Shift+")
|
|
key))
|
|
|
|
(defn alt
|
|
[key]
|
|
(str
|
|
(if (cf/check-platform? :macos)
|
|
mac-option
|
|
"Alt+")
|
|
key))
|
|
|
|
(defn meta-shift
|
|
[key]
|
|
(-> key meta shift))
|
|
|
|
(defn meta-alt
|
|
[key]
|
|
(-> key meta alt))
|
|
|
|
(defn supr
|
|
[]
|
|
(if (cf/check-platform? :macos)
|
|
mac-delete
|
|
"Del"))
|
|
|
|
(defn esc
|
|
[]
|
|
(if (cf/check-platform? :macos)
|
|
mac-esc
|
|
"Escape"))
|
|
|
|
(defn enter
|
|
[]
|
|
(if (cf/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 _]
|
|
(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 _]
|
|
(let [[key* shortcuts] (peek (:shortcuts state))]
|
|
(when (not= key key*)
|
|
(reset! shortcuts))))))
|