Browse Source

fix(electron): rewrite electron-context-menu

Fix #4274
Andelf 3 years ago
parent
commit
d22df2b922

+ 1 - 1
package.json

@@ -85,7 +85,7 @@
         "d3-force": "3.0.0",
         "diff": "5.0.0",
         "electron": "15.1.2",
-        "electron-context-menu": "3.1.1",
+        "electron-dl": "3.3.0",
         "fs": "0.0.1-security",
         "fs-extra": "9.1.0",
         "fuse.js": "6.4.6",

+ 1 - 1
resources/package.json

@@ -22,7 +22,7 @@
     "better-sqlite3": "7.4.5",
     "chokidar": "^3.5.1",
     "dugite": "1.103.0",
-    "electron-context-menu": "3.1.1",
+    "electron-dl": "3.3.0",
     "electron-log": "4.3.1",
     "electron-squirrel-startup": "1.0.0",
     "electron-window-state": "5.0.3",

+ 95 - 0
src/electron/electron/context_menu.cljs

@@ -0,0 +1,95 @@
+(ns electron.context-menu
+  (:require [clojure.string :as string]
+            [electron.utils :as utils]
+            ["electron" :refer [Menu MenuItem shell] :as electron]
+            ["electron-dl" :refer [download]]))
+
+;; context menu is registerd in window/setup-window-listeners!
+(defn setup-context-menu!
+  [^js win]
+  (let [web-contents (. win -webContents)
+
+        context-menu-handler
+        (fn [_event params]
+          (let [menu (Menu.)
+                suggestions (.-dictionarySuggestions ^js params)
+                edit-flags (.-editFlags ^js params)
+                editable? (.-isEditable ^js params)
+                selection-text (.-selectionText ^js params)
+                has-text? (not (string/blank? (string/trim selection-text)))
+                link-url (not-empty (.-linkURL ^js params))
+                media-type (.-mediaType ^js params)]
+
+            (doseq [suggestion suggestions]
+              (. menu append
+                 (MenuItem. (clj->js {:label
+                                      suggestion
+                                      :click
+                                      #(. web-contents replaceMisspelling suggestion)}))))
+            (when (not-empty suggestions)
+              (. menu append (MenuItem. #js {:type "separator"})))
+            (when-let [misspelled-word (not-empty (.-misspelledWord ^js params))]
+              (. menu append
+                 (MenuItem. (clj->js {:label
+                                      "Add to dictionary"
+                                      :click
+                                      #(.. web-contents -session (addWordToSpellCheckerDictionary misspelled-word))}))))
+
+            (. menu append (MenuItem. #js {:type "separator"}))
+
+            (when (and utils/mac? has-text? (not link-url))
+              (. menu append
+                 (MenuItem. #js {:label (str "Look Up “" selection-text "”")
+                                 :click #(. web-contents showDefinitionForSelection)})))
+            (when has-text?
+              (. menu append
+                 (MenuItem. #js {:label "Search with Google"
+                                 :click #(let [url (js/URL. "https://www.google.com/search")]
+                                           (.. url -searchParams (set "q" selection-text))
+                                           (.. shell (openExternal (.toString url))))})))
+            (. menu append (MenuItem. #js {:type "separator"}))
+
+            (when (and has-text? editable?)
+              (when (.-canCut edit-flags)
+                (. menu append
+                   (MenuItem. #js {:label "Cut"
+                                   :role "cut"})))
+              (when (.-canCopy edit-flags)
+                (. menu append
+                   (MenuItem. #js {:label "Copy"
+                                   :role "copy"}))))
+
+            (when (and editable? (.-canPaste edit-flags))
+              (. menu append
+                 (MenuItem. #js {:label "Paste"
+                                 :role "paste"})))
+
+            (when (= media-type "image")
+              (. menu append
+                 (MenuItem. #js {:label "Save Image"
+                                 :click (fn [menu-item]
+                                          (let [url (.-srcURL ^js params)
+                                                url (if (.-transform menu-item)
+                                                      (. menu-item transform url)
+                                                      url)]
+                                            (download win url)))}))
+
+              (. menu append
+                 (MenuItem. #js {:label "Save Image As..."
+                                 :click (fn [menu-item]
+                                          (let [url (.-srcURL ^js params)
+                                                url (if (.-transform menu-item)
+                                                      (. menu-item transform url)
+                                                      url)]
+                                            (download win url #js {:saveAs true})))}))
+
+              (. menu append
+                 (MenuItem. #js {:label "Copy Image"
+                                 :click #(. web-contents copyImageAt (.-x ^js params) (.-y ^js params))})))
+
+            (. menu popup)))]
+
+    (doto web-contents
+      (.on "context-menu" context-menu-handler))
+
+    context-menu-handler))

+ 3 - 9
src/electron/electron/core.cljs

@@ -16,8 +16,7 @@
             [electron.git :as git]
             [electron.window :as win]
             [electron.exceptions :as exceptions]
-            ["/electron/utils" :as utils]
-            ["electron-context-menu" :as init-context-menu]))
+            ["/electron/utils" :as utils]))
 
 (defonce LSP_SCHEME "lsp")
 (defonce LSP_PROTOCOL (str LSP_SCHEME "://"))
@@ -32,10 +31,6 @@
 ;; Handle creating/removing shortcuts on Windows when installing/uninstalling.
 (when (js/require "electron-squirrel-startup") (.quit app))
 
-(defn setup-context-menu
-  []
-  (init-context-menu #js {:showSaveImageAs true :showInspectElement false}))
-
 (defn setup-updater! [^js win]
   ;; manual/auto updater
   (when-not linux?
@@ -219,12 +214,11 @@
                         (fn []
                           (let [t1 (setup-updater! win)
                                 t2 (setup-app-manager! win)
-                                t3 (setup-context-menu)
-                                t4 (handler/set-ipc-handler! win)
+                                t3 (handler/set-ipc-handler! win)
                                 tt (exceptions/setup-exception-listeners!)]
 
                             (vreset! *teardown-fn
-                                     #(doseq [f [t0 t1 t2 t3 t4 tt]]
+                                     #(doseq [f [t0 t1 t2 t3 tt]]
                                         (and f (f)))))))
 
                ;; setup effects

+ 8 - 26
src/electron/electron/window.cljs

@@ -2,6 +2,7 @@
   (:require ["electron-window-state" :as windowStateKeeper]
             [electron.utils :refer [mac? win32? linux? dev? logger open]]
             [electron.configs :as cfgs]
+            [electron.context-menu :as context-menu]
             ["electron" :refer [BrowserWindow app Menu MenuItem session shell] :as electron]
             ["path" :as path]
             ["url" :as URL]
@@ -101,28 +102,7 @@
 (defn setup-window-listeners!
   [^js win]
   (when win
-    (let [web-contents (. win -webContents)
-          context-menu-handler
-          (fn [_event params]
-            (let [menu (Menu.)
-                  suggestions (.-dictionarySuggestions ^js params)]
-
-              (doseq [suggestion suggestions]
-                (. menu append
-                   (MenuItem. (clj->js {:label
-                                        suggestion
-                                        :click
-                                        (fn [] (. web-contents replaceMisspelling suggestion))}))))
-
-              (when-let [misspelled-word (not-empty (.-misspelledWord ^js params))]
-                (. menu append
-                   (MenuItem. (clj->js {:label
-                                        "Add to dictionary"
-                                        :click
-                                        (fn [] (.. web-contents -session (addWordToSpellCheckerDictionary misspelled-word)))}))))
-
-              (. menu popup)))
-
+    (let [web-contents (. win -webContents)          
           new-win-handler
           (fn [e url]
             (let [url (if (string/starts-with? url "file:")
@@ -130,8 +110,8 @@
                   url (if-not win32? (string/replace url "file://" "") url)]
               (.. logger (info "new-window" url))
               (if (some #(string/includes?
-                           (.normalize path url)
-                           (.join path (. app getAppPath) %))
+                          (.normalize path url)
+                          (.join path (. app getAppPath) %))
                         ["index.html" "electron.html"])
                 (.info logger "pass-window" url)
                 (open-default-app! url open)))
@@ -140,10 +120,12 @@
           will-navigate-handler
           (fn [e url]
             (.preventDefault e)
-            (open-default-app! url open))]
+            (open-default-app! url open))
 
+          context-menu-handler
+          (context-menu/setup-context-menu! win)]
+      
       (doto web-contents
-        (.on "context-menu" context-menu-handler)
         (.on "new-window" new-win-handler)
         (.on "will-navigate" will-navigate-handler))