core.cljs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. (ns frontend.modules.shortcut.core
  2. (:require [clojure.string :as str]
  3. [frontend.handler.notification :as notification]
  4. [frontend.modules.shortcut.data-helper :as dh]
  5. [frontend.util :as util]
  6. [goog.events :as events]
  7. [goog.ui.KeyboardShortcutHandler.EventType :as EventType]
  8. [lambdaisland.glogi :as log]
  9. [medley.core :as medley])
  10. (:import [goog.events KeyCodes]
  11. [goog.ui KeyboardShortcutHandler]))
  12. (def *installed (atom {}))
  13. (def global-keys #js
  14. [KeyCodes/TAB
  15. KeyCodes/ENTER
  16. KeyCodes/BACKSPACE KeyCodes/DELETE
  17. KeyCodes/UP KeyCodes/LEFT KeyCodes/DOWN KeyCodes/RIGHT])
  18. (defn install-shortcut!
  19. [handler-id {:keys [set-global-keys?
  20. prevent-default?
  21. skip-installed?
  22. state]
  23. :or {set-global-keys? true
  24. prevent-default? false
  25. skip-installed? false}}]
  26. (let [shortcut-map (dh/shortcut-map handler-id state)
  27. handler (new KeyboardShortcutHandler js/window)]
  28. ;; set arrows enter, tab to global
  29. (when set-global-keys?
  30. (.setGlobalKeys handler global-keys))
  31. (.setAlwaysPreventDefault handler prevent-default?)
  32. ;; register shortcuts
  33. ;; TODO add try catch for register conflicts
  34. (doseq [[id _] shortcut-map]
  35. ;; (log/info :shortcut/install-shortcut {:id id :shortcut (dh/shortcut-binding id)})
  36. (doseq [k (dh/shortcut-binding id)]
  37. (try
  38. (.registerShortcut handler (util/keyname id) k)
  39. (catch js/Object e
  40. (log/error :shortcut/register-shortcut {:id id
  41. :binding k
  42. :error e})
  43. (notification/show! (str/join " " [id k (.-message e)]) :error false)))))
  44. (let [f (fn [e]
  45. (let [dispatch-fn (get shortcut-map (keyword (.-identifier e)))]
  46. ;; trigger fn
  47. (dispatch-fn e)))
  48. install-id (medley/random-uuid)
  49. data {install-id
  50. {:group handler-id
  51. :dispatch-fn f
  52. :handler handler}}]
  53. (events/listen handler EventType/SHORTCUT_TRIGGERED f)
  54. (when-not skip-installed?
  55. (swap! *installed merge data))
  56. install-id)))
  57. (defn install-shortcuts!
  58. []
  59. (install-shortcut! :shortcut.handler/misc {:skip-installed? true})
  60. (->> [:shortcut.handler/editor-global
  61. :shortcut.handler/global-non-editing-only
  62. :shortcut.handler/global-prevent-default]
  63. (map #(install-shortcut! % {}))
  64. doall))
  65. (defn uninstall-shortcut! [install-id]
  66. (let [handler
  67. (-> (get @*installed install-id)
  68. :handler)]
  69. (.dispose ^js handler)
  70. (swap! *installed dissoc install-id)))
  71. (defn- uninstall-shortcut-aux!
  72. [state handler-id]
  73. (some-> (get state :shortcut-key)
  74. uninstall-shortcut!))
  75. (defn- install-shortcut-aux!
  76. [state handler-id]
  77. (let [install-id (-> handler-id
  78. (install-shortcut! {:state state}))]
  79. (assoc state :shortcut-key install-id)))
  80. (defn mixin [handler-id]
  81. {:did-mount
  82. (fn [state]
  83. (install-shortcut-aux! state handler-id))
  84. :did-remount (fn [old-state new-state]
  85. ;; uninstall
  86. (uninstall-shortcut-aux! old-state handler-id)
  87. ;; update new states
  88. (install-shortcut-aux! new-state handler-id))
  89. :will-unmount
  90. (fn [state]
  91. (uninstall-shortcut-aux! state handler-id)
  92. (dissoc state :shortcut-key))})
  93. (defn unlisten-all []
  94. (doseq [{:keys [handler]} (vals @*installed)]
  95. (.removeAllListeners handler)))
  96. (defn listen-all []
  97. (doseq [{:keys [handler dispatch-fn]} (vals @*installed)]
  98. (events/listen handler EventType/SHORTCUT_TRIGGERED dispatch-fn)))
  99. (defn disable-all-shortcuts []
  100. {:did-mount
  101. (fn [state]
  102. (unlisten-all)
  103. state)
  104. :will-unmount
  105. (fn [state]
  106. (listen-all)
  107. state)})