Browse Source

enhance(plugin): WIP install plugin from web

charlie 10 months ago
parent
commit
e8732f9d44

+ 1 - 1
src/main/frontend/components/plugins.cljs

@@ -231,7 +231,7 @@
     [:a.btn
      {:class    (util/classnames [{:disabled   (or installed? installing-or-updating?)
                                    :installing installing-or-updating?}])
-      :on-click #(plugin-common-handler/install-marketplace-plugin item)}
+      :on-click #(plugin-common-handler/install-marketplace-plugin! item)}
      (if installed?
        (t :plugin/installed)
        (if installing-or-updating?

+ 47 - 2
src/main/frontend/handler/common/plugin.cljs

@@ -1,16 +1,59 @@
 (ns frontend.handler.common.plugin
   "Common plugin related fns for handlers and api"
   (:require [frontend.state :as state]
+            [frontend.util :as util]
             [promesa.core :as p]
+            [cljs-bean.core :as bean]
             [electron.ipc :as ipc]))
 
+(defn get-web-plugin-checker-url!
+  ([repo] (get-web-plugin-checker-url! repo ""))
+  ([repo version]
+   (util/node-path.join "https://plugins.logseq.io/r2"
+     repo (if (not (string? version)) "" version))))
+
+(defn fetch-web-plugin-entry-info
+  [repo version]
+  (p/let [url (get-web-plugin-checker-url! repo version)
+          ^js res (js/window.fetch url)]
+    (if (and (.-ok res)
+          (= (.-status res) 200))
+      (-> (.json res)
+        (p/then #(bean/->clj %)))
+      (-> (.text res)
+        (p/then
+          (fn [error-text]
+            (throw (js/Error. (str "web-plugin-entry-error:" error-text)))))))))
+
 (defn installed?
   "For the given plugin id, returns boolean indicating if it is installed"
   [id]
   (and (contains? (:plugin/installed-plugins @state/state) (keyword id))
        (get-in @state/state [:plugin/installed-plugins (keyword id) :iir])))
 
-(defn install-marketplace-plugin
+(defn emit-lsp-updates!
+  [payload]
+  (js/console.log "debug:lsp-updates:" payload)
+  (js/window.apis.emit (name :lsp-updates) (bean/->js payload)))
+
+(defn async-install-or-update-for-web!
+  [{:keys [version repo only-check _plugin-action] :as mft}]
+  (js/console.log "debug:install-or-update" mft)
+  (-> (fetch-web-plugin-entry-info repo version)
+    (p/then (fn [{:keys [version]}]
+              (emit-lsp-updates!
+                {:status :completed
+                 :only-check only-check
+                 :payload (if only-check
+                            (assoc mft :latest-version version :latest-notes "TODO: update notes")
+                            (assoc mft :dst repo :installed-version version :web true))})))
+    (p/catch (fn [^js e]
+               (emit-lsp-updates!
+                 {:status :error
+                  :only-check only-check
+                  :payload (assoc mft :error-code (.-message e))})))))
+
+(defn install-marketplace-plugin!
   "Installs plugin given plugin map with id"
   [{:keys [id] :as mft}]
   (when-not (and (:plugin/installing @state/state)
@@ -18,7 +61,9 @@
     (p/create
      (fn [resolve]
        (state/set-state! :plugin/installing mft)
-       (ipc/ipc :installMarketPlugin mft)
+       (if (util/electron?)
+         (ipc/ipc :installMarketPlugin mft)
+         (async-install-or-update-for-web! mft))
        (resolve id)))))
 
 (defn unregister-plugin

+ 58 - 53
src/main/frontend/handler/plugin.cljs

@@ -197,62 +197,67 @@
 (defn setup-install-listener!
   []
   (let [channel (name :lsp-updates)
-        listener (fn [_ ^js e]
-                   (when-let [{:keys [status payload only-check]} (bean/->clj e)]
-                     (case (keyword status)
-
-                       :completed
-                       (let [{:keys [id dst name title theme]} payload
-                             name (or title name "Untitled")]
-                         (if only-check
-                           (state/consume-updates-from-coming-plugin! payload false)
-                           (if (plugin-common-handler/installed? id)
-                             (when-let [^js pl (get-plugin-inst id)] ;; update
-                               (p/then
-                                 (.reload pl)
-                                 #(do
-                                    ;;(if theme (select-a-plugin-theme id))
-                                    (notification/show!
-                                      (t :plugin/update-plugin name (.-version (.-options pl))) :success)
-                                    (state/consume-updates-from-coming-plugin! payload true))))
-
-                             (do                            ;; register new
-                               (p/then
-                                 (js/LSPluginCore.register (bean/->js {:key id :url dst}))
-                                 (fn [] (when theme (js/setTimeout #(select-a-plugin-theme id) 300))))
+        listener (fn [_ctx ^js _e]
+                   (let [e (or _e _ctx)]
+                     (when-let [{:keys [status payload only-check]} (bean/->clj e)]
+                       (case (keyword status)
+
+                         :completed
+                         (let [{:keys [id dst name title theme]} payload
+                               name (or title name "Untitled")]
+                           (if only-check
+                             (state/consume-updates-from-coming-plugin! payload false)
+                             (if (plugin-common-handler/installed? id)
+                               ;; update plugin
+                               (when-let [^js pl (get-plugin-inst id)]
+                                 (p/then
+                                   (.reload pl)
+                                   #(do
+                                      ;;(if theme (select-a-plugin-theme id))
+                                      (notification/show!
+                                        (t :plugin/update-plugin name (.-version (.-options pl))) :success)
+                                      (state/consume-updates-from-coming-plugin! payload true))))
+                               ;; register plugin
+                               (-> (js/LSPluginCore.register (bean/->js {:key id :url dst}))
+                                 (p/then (fn []
+                                           (when theme (js/setTimeout #(select-a-plugin-theme id) 300))
+                                           (notification/show!
+                                             (t :plugin/installed-plugin name) :success)))
+                                 (p/catch (fn [^js e]
+                                            (notification/show!
+                                              (str "Install failed: " name "\n" (.-message e))
+                                              :error)))))))
+
+                         :error
+                         (let [error-code (keyword (string/replace (:error-code payload) #"^[\s\:\[]+" ""))
+                               fake-error? (contains? #{:no-new-version} error-code)
+                               [msg type] (case error-code
+
+                                            :no-new-version
+                                            [(t :plugin/up-to-date ":)") :success]
+
+                                            [error-code :error])
+                               pending? (seq (:plugin/updates-pending @state/state))]
+
+                           (if (and only-check pending?)
+                             (state/consume-updates-from-coming-plugin! payload false)
+
+                             (do
+                               ;; consume failed download updates
+                               (when (and (not only-check) (not pending?))
+                                 (state/consume-updates-from-coming-plugin! payload true))
+
+                               ;; notify human tips
                                (notification/show!
-                                 (t :plugin/installed-plugin name) :success)))))
+                                 (str
+                                   (if (= :error type) "[Error]" "")
+                                   (str "<" (:id payload) "> ")
+                                   msg) type)))
 
-                       :error
-                       (let [error-code (keyword (string/replace (:error-code payload) #"^[\s\:\[]+" ""))
-                             fake-error? (contains? #{:no-new-version} error-code)
-                             [msg type] (case error-code
+                           (when-not fake-error?
+                             (js/console.error "Update Error:" (:error-code payload))))
 
-                                          :no-new-version
-                                          [(t :plugin/up-to-date ":)") :success]
-
-                                          [error-code :error])
-                             pending? (seq (:plugin/updates-pending @state/state))]
-
-                         (if (and only-check pending?)
-                           (state/consume-updates-from-coming-plugin! payload false)
-
-                           (do
-                             ;; consume failed download updates
-                             (when (and (not only-check) (not pending?))
-                               (state/consume-updates-from-coming-plugin! payload true))
-
-                             ;; notify human tips
-                             (notification/show!
-                               (str
-                                 (if (= :error type) "[Error]" "")
-                                 (str "<" (:id payload) "> ")
-                                 msg) type)))
-
-                         (when-not fake-error?
-                           (js/console.error "Update Error:" (:error-code payload))))
-
-                       :default))
+                         :default)))
 
                    ;; reset
                    (js/setTimeout #(state/set-state! :plugin/installing nil) 512)

+ 6 - 3
src/main/frontend/handler/plugin_config.cljs

@@ -11,6 +11,7 @@ when a plugin is installed, updated or removed"
             [frontend.state :as state]
             [frontend.handler.notification :as notification]
             [frontend.handler.common.plugin :as plugin-common-handler]
+            [frontend.util :as util]
             [clojure.edn :as edn]
             [clojure.set :as set]
             [clojure.pprint :as pprint]
@@ -103,7 +104,7 @@ returns map of plugins to install and uninstall"
     (plugin-common-handler/unregister-plugin (name (:id plugin))))
   (log/info :install-plugins (:install plugins))
   (doseq [plugin (:install plugins)]
-    (plugin-common-handler/install-marketplace-plugin
+    (plugin-common-handler/install-marketplace-plugin!
      ;; Add :name so that install notifications are readable
      (assoc plugin :name (name (:id plugin))))))
 
@@ -122,10 +123,12 @@ returns map of plugins to install and uninstall"
                              ;; Manual installation doesn't have theme field but
                              ;; plugin.edn requires this field
                              :theme (boolean theme)))))))]
-    (js/window.apis.addListener channel listener)
+    (when (util/electron?)
+      (js/window.apis.addListener channel listener))
     ;;teardown
     (fn []
-      (js/window.apis.removeListener channel listener))))
+      (when (util/electron?)
+        (js/window.apis.removeListener channel listener)))))
 
 (defn start
   "This component has just one responsibility on start, to create a plugins.edn

+ 1 - 1
src/main/logseq/api.cljs

@@ -1026,7 +1026,7 @@
     (when-let [{:keys [repo id] :as mft} (bean/->clj manifest)]
       (if-not (and repo id)
         (throw (js/Error. "[required] :repo :id"))
-        (plugin-common-handler/install-marketplace-plugin mft)))))
+        (plugin-common-handler/install-marketplace-plugin! mft)))))
 
 ;; db
 (defn ^:export q