mirror of
https://github.com/penpot/penpot.git
synced 2026-05-14 12:34:10 +00:00
Mainly leave shadow-cljs for build cljs stuff and use esbuild for bundle all js dependencies, completly avoiding all possible incompatibility issues between js libraries and google closure compiler.
204 lines
4.7 KiB
Clojure
204 lines
4.7 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
|
|
["@penpot/mousetrap$default" :as mousetrap]
|
|
[app.common.data.macros :as dm]
|
|
[app.common.logging :as log]
|
|
[app.common.schema :as sm]
|
|
[app.config :as cf]
|
|
[cuerdas.core :as str]
|
|
[potok.v2.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")
|
|
(def tab "tab")
|
|
|
|
(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 alt-shift
|
|
[key]
|
|
(-> key alt shift))
|
|
|
|
(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"))
|
|
|
|
(defn split-sc
|
|
[sc]
|
|
(let [sc (cond-> sc (str/includes? sc "++")
|
|
(str/replace "++" "+plus"))]
|
|
(if (= (count sc) 1)
|
|
[sc]
|
|
(str/split sc #"\+| "))))
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; Events
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;; --- EVENT: push
|
|
|
|
(def ^:private
|
|
schema:shortcuts
|
|
[:map-of :keyword
|
|
[:map
|
|
[:command [:or :string [:vector :any]]]
|
|
[:fn {:optional true} fn?]
|
|
[:tooltip {:optional true} :string]]])
|
|
|
|
(def check-shortcuts!
|
|
(sm/check-fn schema:shortcuts))
|
|
|
|
(defn- wrap-cb
|
|
[key cb]
|
|
(fn [event]
|
|
(log/debug :msg (str "Shortcut" key))
|
|
(when (aget event "preventDefault")
|
|
(.preventDefault event))
|
|
(cb event)))
|
|
|
|
(defn- bind!
|
|
[shortcuts]
|
|
(let [msbind (fn [command callback type]
|
|
(if type
|
|
(mousetrap/bind command callback type)
|
|
(mousetrap/bind command callback)))]
|
|
(->> shortcuts
|
|
(remove #(:disabled (second %)))
|
|
(run! (fn [[key {:keys [command fn type]}]]
|
|
(let [callback (wrap-cb key fn)]
|
|
(if (vector? command)
|
|
(run! #(msbind % callback type) command)
|
|
(msbind command callback type))))))))
|
|
|
|
(defn- reset!
|
|
([]
|
|
(mousetrap/reset))
|
|
([shortcuts]
|
|
(mousetrap/reset)
|
|
(bind! shortcuts)))
|
|
|
|
(defn push-shortcuts
|
|
[key shortcuts]
|
|
|
|
(dm/assert!
|
|
"expected valid parameters"
|
|
(and (keyword? key)
|
|
(check-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))))))
|