mirror of https://github.com/logseq/logseq
Fix more bugs, move plugins.edn and add enabled
- Move plugins.edn to config/ as it is user configuration - Add plugin-config enabled flag and moved plugin enabled - Fixed bugs with manual install - Refactored plugin-config component to have its own listener - Split out shared plugin fns to a common ns - plugin-config shouldn't need to depend on a component like plugin-handler - Bump rewrite-edn to include upstream fix and avoid tons of cljs warnings with earlier versions - Fix react warning introduced outside this PR in ui/iconpull/6911/head
parent
784ad7cce3
commit
0c570a0300
|
@ -43,12 +43,15 @@
|
|||
frontend.handler.extract extract
|
||||
frontend.handler.common common-handler
|
||||
frontend.handler.common.file file-common-handler
|
||||
frontend.handler.common.plugin plugin-common-handler
|
||||
frontend.handler.config config-handler
|
||||
frontend.handler.events events
|
||||
frontend.handler.global-config global-config-handler
|
||||
frontend.handler.ui ui-handler
|
||||
frontend.handler.notification notification
|
||||
frontend.handler.page page-handler
|
||||
frontend.handler.plugin plugin-handler
|
||||
frontend.handler.plugin-config plugin-config-handler
|
||||
frontend.handler.repo repo-handler
|
||||
frontend.handler.repo-config repo-config-handler
|
||||
frontend.handler.search search-handler
|
||||
|
|
4
deps.edn
4
deps.edn
|
@ -4,7 +4,9 @@
|
|||
rum/rum {:mvn/version "0.12.9"}
|
||||
datascript/datascript {:mvn/version "1.3.8"}
|
||||
datascript-transit/datascript-transit {:mvn/version "0.3.0"}
|
||||
borkdude/rewrite-edn {:mvn/version "0.1.0"}
|
||||
;; TODO: bump to mvn/version when released
|
||||
borkdude/rewrite-edn {:git/url "https://github.com/borkdude/rewrite-edn"
|
||||
:sha "80f246139b1a43b6f2cbab329521d060ee7c1b7b"}
|
||||
funcool/promesa {:mvn/version "4.0.2"}
|
||||
medley/medley {:mvn/version "1.4.0"}
|
||||
metosin/reitit-frontend {:mvn/version "0.3.10"}
|
||||
|
|
|
@ -1503,7 +1503,7 @@
|
|||
(= name "embed")
|
||||
(macro-embed-cp config arguments)
|
||||
|
||||
(and plugin-handler/lsp-enabled? (= name "renderer"))
|
||||
(and config/lsp-enabled? (= name "renderer"))
|
||||
(when-let [block-uuid (str (:block/uuid config))]
|
||||
(plugins/hook-ui-slot :macro-renderer-slotted (assoc options :uuid block-uuid)))
|
||||
|
||||
|
|
|
@ -75,12 +75,12 @@
|
|||
:options {:on-click state/open-settings!}
|
||||
:icon (ui/icon "settings")})
|
||||
|
||||
(when plugin-handler/lsp-enabled?
|
||||
(when config/lsp-enabled?
|
||||
{:title (t :plugins)
|
||||
:options {:on-click #(plugin-handler/goto-plugins-dashboard!)}
|
||||
:icon (ui/icon "apps")})
|
||||
|
||||
(when plugin-handler/lsp-enabled?
|
||||
(when config/lsp-enabled?
|
||||
{:title (t :themes)
|
||||
:options {:on-click #(plugins/open-select-theme!)}
|
||||
:icon (ui/icon "palette")})
|
||||
|
@ -209,7 +209,7 @@
|
|||
(when sync-enabled?
|
||||
(login))
|
||||
|
||||
(when plugin-handler/lsp-enabled?
|
||||
(when config/lsp-enabled?
|
||||
(plugins/hook-ui-items :toolbar))
|
||||
|
||||
(when (util/electron?)
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
[frontend.handler.graph :as graph-handler]
|
||||
[frontend.handler.notification :as notification]
|
||||
[frontend.handler.page :as page-handler]
|
||||
[frontend.handler.plugin :as plugin-handler]
|
||||
[frontend.handler.route :as route-handler]
|
||||
[frontend.mixins :as mixins]
|
||||
[frontend.mobile.util :as mobile-util]
|
||||
|
@ -425,7 +424,7 @@
|
|||
[:h1.title.ls-page-title (page-title page-name icon title format fmt-journal?)]])
|
||||
(when (not config/publishing?)
|
||||
[:div.flex.flex-row
|
||||
(when plugin-handler/lsp-enabled?
|
||||
(when config/lsp-enabled?
|
||||
(plugins/hook-ui-slot :page-head-actions-slotted nil)
|
||||
(plugins/hook-ui-items :pagebar))])])
|
||||
[:div
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
[frontend.util :as util]
|
||||
[frontend.util.url :as url-util]
|
||||
[frontend.handler.shell :as shell]
|
||||
[frontend.handler.plugin :as plugin-handler]
|
||||
[frontend.mobile.util :as mobile-util]
|
||||
[electron.ipc :as ipc]
|
||||
[frontend.config :as config]
|
||||
|
@ -152,7 +151,7 @@
|
|||
(fn []
|
||||
(ipc/ipc "openFileBackupDir" (config/get-local-dir repo) file-path))}})
|
||||
|
||||
(when plugin-handler/lsp-enabled?
|
||||
(when config/lsp-enabled?
|
||||
(for [[_ {:keys [label] :as cmd} action pid] (state/get-plugins-commands-with-type :page-menu-item)]
|
||||
{:title label
|
||||
:options {:on-click #(commands/exec-plugin-simple-command!
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
[frontend.context.i18n :refer [t]]
|
||||
[frontend.ui :as ui]
|
||||
[frontend.handler.ui :as ui-handler]
|
||||
[frontend.handler.plugin-config :as plugin-config]
|
||||
[frontend.handler.plugin-config :as plugin-config-handler]
|
||||
[frontend.handler.common.plugin :as plugin-common-handler]
|
||||
[frontend.search :as search]
|
||||
[frontend.util :as util]
|
||||
[frontend.mixins :as mixins]
|
||||
|
@ -199,7 +200,7 @@
|
|||
[:a.btn
|
||||
{:class (util/classnames [{:disabled (or installed? installing-or-updating?)
|
||||
:installing installing-or-updating?}])
|
||||
:on-click #(plugin-handler/install-marketplace-plugin item)}
|
||||
:on-click #(plugin-common-handler/install-marketplace-plugin item)}
|
||||
(if installed?
|
||||
(t :plugin/installed)
|
||||
(if installing-or-updating?
|
||||
|
@ -224,8 +225,8 @@
|
|||
{:title (t :plugin/delete-alert name)
|
||||
:on-confirm (fn [_ {:keys [close-fn]}]
|
||||
(close-fn)
|
||||
(plugin-handler/unregister-plugin id)
|
||||
(plugin-config/remove-plugin id))})]
|
||||
(plugin-common-handler/unregister-plugin id)
|
||||
(plugin-config-handler/remove-plugin id))})]
|
||||
(state/set-sub-modal! confirm-fn {:center? true}))}
|
||||
(t :plugin/uninstall)]]]
|
||||
|
||||
|
@ -548,7 +549,7 @@
|
|||
:options {:on-click #(state/pub-event! [:go/proxy-settings agent-opts])}}]
|
||||
|
||||
[{:title [:span.flex.items-center (ui/icon "arrow-down-circle") (t :plugin/install-from-file)]
|
||||
:options {:on-click plugin-config/open-sync-modal}}]
|
||||
:options {:on-click plugin-config-handler/open-sync-modal}}]
|
||||
|
||||
(when (state/developer-mode?)
|
||||
[{:hr true}
|
||||
|
@ -822,7 +823,7 @@
|
|||
[:div.pt-5
|
||||
(ui/button [:span "Install"]
|
||||
:on-click #(do
|
||||
(plugin-config/update-plugins plugins)
|
||||
(plugin-config-handler/replace-plugins plugins)
|
||||
(state/close-sub-modal! "ls-plugins-from-file-modal")))]]
|
||||
;; all done
|
||||
[:div.py-4 [:strong.text-xl "\uD83C\uDF89 All synced!"]])])
|
||||
|
|
|
@ -726,7 +726,7 @@
|
|||
(let [current-repo (state/sub :git/current-repo)
|
||||
;; enable-block-timestamps? (state/enable-block-timestamps?)
|
||||
_installed-plugins (state/sub :plugin/installed-plugins)
|
||||
plugins-of-settings (and plugin-handler/lsp-enabled? (seq (plugin-handler/get-enabled-plugins-if-setting-schema)))
|
||||
plugins-of-settings (and config/lsp-enabled? (seq (plugin-handler/get-enabled-plugins-if-setting-schema)))
|
||||
*active (::active state)]
|
||||
|
||||
[:div#settings.cp__settings-main
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
(ns frontend.components.theme
|
||||
(:require [frontend.extensions.pdf.highlights :as pdf]
|
||||
[frontend.config :as config]
|
||||
[frontend.handler.plugin :refer [lsp-enabled?] :as plugin-handler]
|
||||
[frontend.handler.plugin :as plugin-handler]
|
||||
[frontend.handler.plugin-config :as plugin-config-handler]
|
||||
[frontend.handler.route :as route-handler]
|
||||
[frontend.handler.ui :as ui-handler]
|
||||
[frontend.ui :as ui]
|
||||
|
@ -41,9 +42,12 @@
|
|||
[sidebar-open? restored-sidebar? sidebar-blocks-len])
|
||||
|
||||
(rum/use-effect!
|
||||
#(when lsp-enabled?
|
||||
#(when config/lsp-enabled?
|
||||
(plugin-handler/setup-install-listener!)
|
||||
(plugin-handler/load-plugin-preferences))
|
||||
(plugin-config-handler/setup-install-listener!)
|
||||
(plugin-handler/load-plugin-preferences)
|
||||
(fn []
|
||||
(js/window.apis.removeAllListeners "lsp-installed")))
|
||||
[])
|
||||
|
||||
(rum/use-effect!
|
||||
|
|
|
@ -35,16 +35,32 @@
|
|||
(def API-DOMAIN "api-dev.logseq.com")
|
||||
(def WS-URL "wss://ws-dev.logseq.com/file-sync?graphuuid=%s")))
|
||||
|
||||
;; feature flags
|
||||
;; Feature flags
|
||||
;; =============
|
||||
|
||||
(goog-define ENABLE-PLUGINS true)
|
||||
(defonce enable-plugins? ENABLE-PLUGINS)
|
||||
|
||||
(swap! state/state assoc :plugin/enabled enable-plugins?)
|
||||
|
||||
;; Desktop only as other platforms requires better understanding of their
|
||||
;; multi-graph workflows and optimal place for a "global" dir
|
||||
(def global-config-enabled? util/electron?)
|
||||
|
||||
;; User level configuration for whether plugins are enabled
|
||||
(defonce lsp-enabled?
|
||||
(and (util/electron?)
|
||||
(state/lsp-enabled?-or-theme)))
|
||||
|
||||
(defn plugin-config-enabled?
|
||||
[]
|
||||
(and lsp-enabled? (global-config-enabled?)))
|
||||
|
||||
;; :TODO: How to do this?
|
||||
;; (defonce desktop? ^boolean goog.DESKTOP)
|
||||
|
||||
;; ============
|
||||
|
||||
(def app-name "logseq")
|
||||
(def website
|
||||
(if dev?
|
||||
|
@ -289,10 +305,6 @@
|
|||
|
||||
(def config-default-content (rc/inline "config.edn"))
|
||||
|
||||
;; Desktop only as other platforms requires better understanding of their
|
||||
;; multi-graph workflows and optimal place for a "global" dir
|
||||
(def global-config-enabled? util/electron?)
|
||||
|
||||
(defonce idb-db-prefix "logseq-db/")
|
||||
(defonce local-db-prefix "logseq_local_")
|
||||
(defonce local-handle "handle")
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
[frontend.ui :as ui]
|
||||
[frontend.config :as config]
|
||||
[frontend.util :as util]
|
||||
[frontend.handler.plugin :refer [lsp-enabled? hook-extensions-enhancer-by-type] :as plugin-handler]
|
||||
[frontend.handler.plugin :refer [hook-extensions-enhancer-by-type] :as plugin-handler]
|
||||
[promesa.core :as p]
|
||||
[goog.dom :as gdom]))
|
||||
|
||||
|
@ -42,7 +42,7 @@
|
|||
(config/asset-uri "/static/js/mhchem.min.js")
|
||||
(fn []
|
||||
(p/finally
|
||||
(p/all (when-let [enhancers (and lsp-enabled? (seq (hook-extensions-enhancer-by-type :katex)))]
|
||||
(p/all (when-let [enhancers (and config/lsp-enabled? (seq (hook-extensions-enhancer-by-type :katex)))]
|
||||
(for [{f :enhancer} enhancers]
|
||||
(when (fn? f) (f js/window.katex)))))
|
||||
(fn []
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
[frontend.extensions.pdf.utils :as pdf-utils]
|
||||
[frontend.extensions.pdf.toolbar :refer [pdf-toolbar *area-dashed? *area-mode? *highlight-mode? *highlights-ctx*]]
|
||||
[frontend.handler.notification :as notification]
|
||||
[frontend.handler.plugin :as plugin-handler]
|
||||
[frontend.config :as config]
|
||||
[frontend.modules.shortcut.core :as shortcut]
|
||||
[frontend.commands :as commands]
|
||||
[frontend.rum :refer [use-atom]]
|
||||
|
@ -193,7 +193,7 @@
|
|||
|
||||
(and id [:li.item {:data-action "del"} (t :delete)])
|
||||
|
||||
(when (and plugin-handler/lsp-enabled? text?)
|
||||
(when (and config/lsp-enabled? text?)
|
||||
(for [[_ {:keys [key label extras] :as _cmd} action pid]
|
||||
(state/get-plugins-commands-with-type :highlight-context-menu-item)]
|
||||
[:li.item {:key key
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
[frontend.handler.user :as user-handler]
|
||||
[frontend.handler.repo-config :as repo-config-handler]
|
||||
[frontend.handler.global-config :as global-config-handler]
|
||||
[frontend.handler.plugin-config :as plugin-config]
|
||||
[frontend.handler.plugin-config :as plugin-config-handler]
|
||||
[frontend.handler.metadata :as metadata-handler]
|
||||
[frontend.idb :as idb]
|
||||
[frontend.mobile.util :as mobile-util]
|
||||
|
@ -93,8 +93,7 @@
|
|||
(p/do! (repo-config-handler/start {:repo repo})
|
||||
(when (config/global-config-enabled?)
|
||||
(global-config-handler/start {:repo repo}))
|
||||
;; TODO: Is there a better place for this setup?
|
||||
(plugin-config/start))
|
||||
(when (config/plugin-config-enabled?) (plugin-config-handler/start)))
|
||||
(p/finally
|
||||
(fn []
|
||||
;; install after config is restored
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
(ns frontend.handler.common.plugin
|
||||
"Common plugin related fns for handlers and api"
|
||||
(:require [frontend.state :as state]
|
||||
[promesa.core :as p]
|
||||
[electron.ipc :as ipc]))
|
||||
|
||||
(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
|
||||
"Installs plugin given plugin map with id"
|
||||
[{:keys [id] :as mft}]
|
||||
(when-not (and (:plugin/installing @state/state)
|
||||
(installed? id))
|
||||
(p/create
|
||||
(fn [resolve]
|
||||
(state/set-state! :plugin/installing mft)
|
||||
(ipc/ipc :installMarketPlugin mft)
|
||||
(resolve id)))))
|
||||
|
||||
(defn unregister-plugin
|
||||
"Unregister and uninstall plugin given plugin id"
|
||||
[id]
|
||||
(js/LSPluginCore.unregister id))
|
|
@ -6,7 +6,7 @@
|
|||
[clojure.walk :as walk]
|
||||
[logseq.graph-parser.mldoc :as gp-mldoc]
|
||||
[frontend.handler.notification :as notification]
|
||||
[frontend.handler.plugin-config :as plugin-config]
|
||||
[frontend.handler.common.plugin :as plugin-common-handler]
|
||||
[camel-snake-kebab.core :as csk]
|
||||
[frontend.state :as state]
|
||||
[medley.core :as medley]
|
||||
|
@ -17,12 +17,9 @@
|
|||
[lambdaisland.glogi :as log]
|
||||
[frontend.components.svg :as svg]
|
||||
[frontend.context.i18n :refer [t]]
|
||||
[frontend.config :as config]
|
||||
[frontend.format :as format]))
|
||||
|
||||
(defonce lsp-enabled?
|
||||
(and (util/electron?)
|
||||
(state/lsp-enabled?-or-theme)))
|
||||
|
||||
(defn- normalize-keyword-for-json
|
||||
[input]
|
||||
(when input
|
||||
|
@ -112,25 +109,10 @@
|
|||
(util/fetch stats-url on-ok reject)))))
|
||||
(p/resolved nil)))
|
||||
|
||||
(defn 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
|
||||
[{:keys [id] :as mft}]
|
||||
(when-not (and (:plugin/installing @state/state)
|
||||
(installed? id))
|
||||
(p/create
|
||||
(fn [resolve]
|
||||
(state/set-state! :plugin/installing mft)
|
||||
(ipc/ipc :installMarketPlugin mft)
|
||||
(resolve id)))))
|
||||
|
||||
(defn check-or-update-marketplace-plugin
|
||||
[{:keys [id] :as pkg} error-handler]
|
||||
(when-not (and (:plugin/installing @state/state)
|
||||
(not (installed? id)))
|
||||
(not (plugin-common-handler/installed? id)))
|
||||
(p/catch
|
||||
(p/then
|
||||
(do (state/set-state! :plugin/installing pkg)
|
||||
|
@ -198,7 +180,7 @@
|
|||
name (or title name "Untitled")]
|
||||
(if only-check
|
||||
(state/consume-updates-coming-plugin payload false)
|
||||
(if (installed? id)
|
||||
(if (plugin-common-handler/installed? id)
|
||||
(when-let [^js pl (get-plugin-inst id)] ;; update
|
||||
(p/then
|
||||
(.reload pl)
|
||||
|
@ -212,10 +194,6 @@
|
|||
(p/then
|
||||
(js/LSPluginCore.register (bean/->js {:key id :url dst}))
|
||||
(fn [] (when theme (js/setTimeout #(select-a-plugin-theme id) 300))))
|
||||
(plugin-config/add-or-update-plugin
|
||||
(assoc payload
|
||||
:version (:installed-version payload)
|
||||
:name name))
|
||||
(notification/show!
|
||||
(str (t :plugin/installed) (t :plugins) ": " name) :success)))))
|
||||
|
||||
|
@ -252,23 +230,15 @@
|
|||
(js/setTimeout #(state/set-state! :plugin/installing nil) 512)
|
||||
true)]
|
||||
|
||||
(js/window.apis.addListener channel listener)
|
||||
|
||||
;; clear
|
||||
(fn []
|
||||
(js/window.apis.removeAllListeners channel))))
|
||||
(js/window.apis.addListener channel listener)))
|
||||
|
||||
(defn register-plugin
|
||||
[pl]
|
||||
(swap! state/state update-in [:plugin/installed-plugins] assoc (keyword (:id pl)) pl))
|
||||
|
||||
(defn unregister-plugin
|
||||
[id]
|
||||
(js/LSPluginCore.unregister id))
|
||||
|
||||
(defn host-mounted!
|
||||
[]
|
||||
(and lsp-enabled? (js/LSPluginCore.hostMounted)))
|
||||
(and config/lsp-enabled? (js/LSPluginCore.hostMounted)))
|
||||
|
||||
(defn register-plugin-slash-command
|
||||
[pid [cmd actions]]
|
||||
|
@ -469,7 +439,7 @@
|
|||
|
||||
(defn hook-plugin
|
||||
[tag type payload plugin-id]
|
||||
(when lsp-enabled?
|
||||
(when config/lsp-enabled?
|
||||
(try
|
||||
(js-invoke js/LSPluginCore
|
||||
(str "hook" (string/capitalize (name tag)))
|
||||
|
@ -706,6 +676,6 @@
|
|||
(defn setup!
|
||||
"setup plugin core handler"
|
||||
[callback]
|
||||
(if (not lsp-enabled?)
|
||||
(if (not config/lsp-enabled?)
|
||||
(callback)
|
||||
(init-plugins! callback)))
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
(ns frontend.handler.plugin-config
|
||||
"This ns is a system component that encapsulate the global plugin.edn.
|
||||
This component depends on TODO"
|
||||
"This system component encapsulates the global plugin.edn and depends on the
|
||||
global-config component. This component is only enabled? if both the
|
||||
global-config and plugin components are enabled"
|
||||
(:require [frontend.handler.global-config :as global-config-handler]
|
||||
["path" :as path]
|
||||
[promesa.core :as p]
|
||||
|
@ -8,24 +9,26 @@ This component depends on TODO"
|
|||
[frontend.fs :as fs]
|
||||
[frontend.state :as state]
|
||||
[frontend.handler.notification :as notification]
|
||||
[electron.ipc :as ipc]
|
||||
[frontend.handler.common.plugin :as plugin-common-handler]
|
||||
[clojure.edn :as edn]
|
||||
[clojure.set :as set]
|
||||
[clojure.pprint :as pprint]
|
||||
[malli.core :as m]
|
||||
[malli.error :as me]
|
||||
[frontend.schema.handler.plugin-config :as plugin-config-schema]
|
||||
[cljs-bean.core :as bean]
|
||||
[lambdaisland.glogi :as log]))
|
||||
|
||||
(defn- plugin-config-path
|
||||
(defn plugin-config-path
|
||||
[]
|
||||
(path/join @global-config-handler/root-dir "plugins.edn"))
|
||||
(path/join (global-config-handler/global-config-dir) "plugins.edn"))
|
||||
|
||||
(def common-plugin-keys
|
||||
"Vec of plugin keys to store in plugins.edn and to compare with installed-plugins state"
|
||||
(->> plugin-config-schema/Plugin rest (mapv first)))
|
||||
|
||||
(defn add-or-update-plugin
|
||||
"Adds or updates a plugin from plugin.edn"
|
||||
[{:keys [id] :as plugin}]
|
||||
(p/let [content (fs/read-file "" (plugin-config-path))
|
||||
updated-content (-> content
|
||||
|
@ -37,6 +40,7 @@ This component depends on TODO"
|
|||
(fs/write-file! nil "" (plugin-config-path) updated-content {:skip-compare? true})))
|
||||
|
||||
(defn remove-plugin
|
||||
"Removes a plugin from plugin.edn"
|
||||
[plugin-id]
|
||||
(p/let [content (fs/read-file "" (plugin-config-path))
|
||||
updated-content (-> content rewrite/parse-string (rewrite/dissoc (keyword plugin-id)) str)]
|
||||
|
@ -54,13 +58,18 @@ This component depends on TODO"
|
|||
"Given installed plugins state and plugins from plugins.edn,
|
||||
returns map of plugins to install and uninstall"
|
||||
[installed-plugins edn-plugins]
|
||||
;; :name is removed from comparison because it isn't used for reproducible builds
|
||||
;; and is just for display purposes
|
||||
(let [installed-plugins-set (->> installed-plugins
|
||||
vals
|
||||
(map #(assoc (select-keys % common-plugin-keys)
|
||||
:id (keyword (:id %))))
|
||||
(map #(-> (select-keys % common-plugin-keys)
|
||||
(assoc :id (keyword (:id %)))
|
||||
(dissoc :name)))
|
||||
set)
|
||||
edn-plugins-set (->> edn-plugins
|
||||
(map (fn [[k v]] (assoc v :id k)))
|
||||
(map (fn [[k v]] (-> v
|
||||
(assoc :id k)
|
||||
(dissoc :name))))
|
||||
set)]
|
||||
(if (= installed-plugins-set edn-plugins-set)
|
||||
{}
|
||||
|
@ -89,34 +98,36 @@ returns map of plugins to install and uninstall"
|
|||
:error)
|
||||
(log/error :unexpected-error e)))))
|
||||
|
||||
;; TODO: Extract from handler.plugin
|
||||
(defn 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
|
||||
[{:keys [id] :as mft}]
|
||||
; (prn :IN {:k1 (:plugin/installing @state/state)
|
||||
; :k2 (installed? id)})
|
||||
;; TODO:
|
||||
(when-not (and (:plugin/installing @state/state)
|
||||
(installed? id))
|
||||
(p/create
|
||||
(fn [resolve]
|
||||
(state/set-state! :plugin/installing mft)
|
||||
(ipc/ipc :installMarketPlugin mft)
|
||||
(resolve id)))))
|
||||
|
||||
(defn update-plugins
|
||||
(defn replace-plugins
|
||||
"Replaces current plugins given plugins to install and uninstall"
|
||||
[plugins]
|
||||
(log/info :uninstall-plugins (:uninstall plugins))
|
||||
(doseq [plugin (:uninstall plugins)]
|
||||
(js/LSPluginCore.unregister (name (:id plugin))))
|
||||
(plugin-common-handler/unregister-plugin (name (:id plugin))))
|
||||
(log/info :install-plugins (:install plugins))
|
||||
(doseq [plugin (:install plugins)]
|
||||
(install-marketplace-plugin plugin)))
|
||||
(plugin-common-handler/install-marketplace-plugin plugin)))
|
||||
|
||||
(defn setup-install-listener!
|
||||
"Sets up a listener for the lsp-installed event to update plugins.edn"
|
||||
[]
|
||||
(let [listener (fn listener [_ e]
|
||||
(when-let [{:keys [status payload only-check]} (bean/->clj e)]
|
||||
(when (and (= status "completed") (not only-check))
|
||||
(let [{:keys [name title theme]} payload
|
||||
;; Same defaults as plugin/setup-install-listener!
|
||||
name (or title name "Untitled")]
|
||||
(add-or-update-plugin
|
||||
(assoc payload
|
||||
:version (:installed-version payload)
|
||||
;; Manual install doesn't have theme field but
|
||||
;; plugin.edn requires this field
|
||||
:theme (if (some? theme) theme false)
|
||||
:name name))))))]
|
||||
(js/window.apis.addListener "lsp-installed" listener)))
|
||||
|
||||
(defn start
|
||||
"This component has just one reponsibility on start, to create a plugins.edn
|
||||
if none exists"
|
||||
[]
|
||||
(create-plugin-config-file-if-not-exists))
|
||||
|
|
|
@ -14,12 +14,13 @@
|
|||
[frontend.handler.plugin :as plugin-handler]
|
||||
[frontend.handler.export :as export-handler]
|
||||
[frontend.handler.whiteboard :as whiteboard-handler]
|
||||
[frontend.handler.plugin-config :as plugin-config]
|
||||
[frontend.handler.plugin-config :as plugin-config-handler]
|
||||
[frontend.modules.shortcut.dicts :as dicts]
|
||||
[frontend.modules.shortcut.before :as m]
|
||||
[frontend.state :as state]
|
||||
[frontend.util :refer [mac?] :as util]
|
||||
[frontend.commands :as commands]
|
||||
[frontend.config :as config]
|
||||
[electron.ipc :as ipc]
|
||||
[promesa.core :as p]
|
||||
[clojure.data :as data]
|
||||
|
@ -406,13 +407,13 @@
|
|||
:fn plugin-handler/show-themes-modal!}
|
||||
|
||||
:ui/goto-plugins {:binding "t p"
|
||||
:inactive (not plugin-handler/lsp-enabled?)
|
||||
:inactive (not config/lsp-enabled?)
|
||||
:fn plugin-handler/goto-plugins-dashboard!}
|
||||
|
||||
:ui/install-plugins-from-file {:binding false
|
||||
:inactive (not plugin-handler/lsp-enabled?)
|
||||
:inactive (not (config/plugin-config-enabled?))
|
||||
;; TODO: Remove dev convenience
|
||||
:fn (fn [] (plugin-config/open-sync-modal))}
|
||||
:fn (fn [] (plugin-config-handler/open-sync-modal))}
|
||||
|
||||
:editor/toggle-open-blocks {:binding "t o"
|
||||
:fn editor-handler/toggle-open!}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
[datascript.core :as d]
|
||||
[electron.ipc :as ipc]
|
||||
[frontend.components.svg :as svg]
|
||||
[frontend.config :as config]
|
||||
[frontend.context.i18n :refer [t]]
|
||||
[frontend.db-mixins :as db-mixins]
|
||||
[frontend.handler.notification :as notification]
|
||||
|
@ -32,7 +33,6 @@
|
|||
[goog.object :as gobj]
|
||||
[lambdaisland.glogi :as log]
|
||||
[medley.core :as medley]
|
||||
[frontend.config :as config]
|
||||
[promesa.core :as p]
|
||||
[rum.core :as rum]))
|
||||
|
||||
|
@ -361,7 +361,7 @@
|
|||
style)))
|
||||
|
||||
(defn apply-custom-theme-effect! [theme]
|
||||
(when plugin-handler/lsp-enabled?
|
||||
(when config/lsp-enabled?
|
||||
(when-let [custom-theme (state/sub [:ui/custom-theme (keyword theme)])]
|
||||
(when-let [url (:url custom-theme)]
|
||||
(js/LSPluginCore.selectTheme (bean/->js custom-theme)
|
||||
|
@ -939,7 +939,7 @@
|
|||
(when (:class opts)
|
||||
(str " " (string/trim (:class opts)))))
|
||||
(if extension? "tie tie" "ti ti"))}
|
||||
(dissoc opts :class :extension?))]
|
||||
(dissoc opts :class :extension? :font?))]
|
||||
|
||||
;; tabler svg react
|
||||
(when-let [klass (gobj/get js/tablerIcons (str "Icon" (csk/->PascalCase class)))]
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
[frontend.handler.notification :as notification]
|
||||
[frontend.handler.page :as page-handler]
|
||||
[frontend.handler.plugin :as plugin-handler]
|
||||
[frontend.handler.common.plugin :as plugin-common-handler]
|
||||
[frontend.modules.outliner.core :as outliner]
|
||||
[frontend.modules.outliner.tree :as outliner-tree]
|
||||
[frontend.handler.command-palette :as palette-handler]
|
||||
|
@ -776,7 +777,7 @@
|
|||
(when-let [{:keys [repo id] :as mft} (bean/->clj manifest)]
|
||||
(if-not (and repo id)
|
||||
(throw (js/Error. "[required] :repo :id"))
|
||||
(plugin-handler/install-marketplace-plugin mft)))))
|
||||
(plugin-common-handler/install-marketplace-plugin mft)))))
|
||||
|
||||
;; db
|
||||
(defn ^:export q
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
(:require [clojure.test :refer [is use-fixtures testing deftest]]
|
||||
[frontend.test.helper :as test-helper :include-macros true :refer [deftest-async]]
|
||||
[frontend.test.fixtures :as fixtures]
|
||||
[frontend.handler.plugin-config :as plugin-config]
|
||||
[frontend.handler.plugin-config :as plugin-config-handler]
|
||||
[frontend.handler.global-config :as global-config-handler]
|
||||
[frontend.schema.handler.plugin-config :as plugin-config-schema]
|
||||
["fs" :as fs-node]
|
||||
|
@ -15,88 +15,81 @@
|
|||
|
||||
(use-fixtures :once fixtures/redef-get-fs)
|
||||
|
||||
(defn- create-global-config-dir
|
||||
[]
|
||||
(let [dir (test-helper/create-tmp-dir "config")
|
||||
root-dir (path/dirname dir)]
|
||||
(reset! global-config-handler/root-dir root-dir)
|
||||
dir))
|
||||
|
||||
(defn- delete-global-config-dir
|
||||
[config-dir]
|
||||
(doseq [relative-file (fs-node/readdirSync config-dir)]
|
||||
(fs-node/unlinkSync (path/join config-dir relative-file)))
|
||||
(reset! global-config-handler/root-dir nil)
|
||||
(fs-node/rmdirSync config-dir)
|
||||
(fs-node/rmdirSync (path/dirname config-dir)))
|
||||
|
||||
(deftest-async add-or-update-plugin
|
||||
(let [dir (test-helper/create-tmp-dir)
|
||||
plugins-file (path/join dir "plugins.edn")
|
||||
(let [dir (create-global-config-dir)
|
||||
plugin-to-add {:id :foo :name "Foo" :repo "some-user/foo" :version "v0.9.0"}
|
||||
body (pr-str (mg/generate plugin-config-schema/Plugins-edn {:size 10}))]
|
||||
(fs-node/writeFileSync plugins-file body)
|
||||
(reset! global-config-handler/root-dir dir)
|
||||
(fs-node/writeFileSync (plugin-config-handler/plugin-config-path) body)
|
||||
|
||||
(->
|
||||
(p/do!
|
||||
(plugin-config/add-or-update-plugin plugin-to-add)
|
||||
(plugin-config-handler/add-or-update-plugin plugin-to-add)
|
||||
(is (= (dissoc plugin-to-add :id)
|
||||
(:foo (edn/read-string (str (fs-node/readFileSync plugins-file)))))))
|
||||
(:foo (edn/read-string (str (fs-node/readFileSync (plugin-config-handler/plugin-config-path))))))))
|
||||
|
||||
(.finally
|
||||
(fn []
|
||||
(reset! global-config-handler/root-dir nil)
|
||||
(fs-node/unlinkSync plugins-file)
|
||||
(fs-node/rmdirSync dir))))))
|
||||
(p/finally #(delete-global-config-dir dir)))))
|
||||
|
||||
(deftest-async remove-plugin
|
||||
(let [dir (test-helper/create-tmp-dir)
|
||||
plugins-file (path/join dir "plugins.edn")
|
||||
(let [dir (create-global-config-dir)
|
||||
;; use seed to consistently generate 5 plugins
|
||||
;; if we want more randomness we could look into gen/such-that
|
||||
plugins (mg/generate plugin-config-schema/Plugins-edn {:size 5 :seed 1})
|
||||
some-plugin-id (first (keys plugins))]
|
||||
(fs-node/writeFileSync plugins-file (pr-str plugins))
|
||||
(reset! global-config-handler/root-dir dir)
|
||||
(fs-node/writeFileSync (plugin-config-handler/plugin-config-path) (pr-str plugins))
|
||||
|
||||
(->
|
||||
(p/do!
|
||||
(plugin-config/remove-plugin some-plugin-id)
|
||||
(plugin-config-handler/remove-plugin some-plugin-id)
|
||||
(is (= nil
|
||||
(get (edn/read-string (str (fs-node/readFileSync plugins-file)))
|
||||
(get (edn/read-string (str (fs-node/readFileSync (plugin-config-handler/plugin-config-path))))
|
||||
some-plugin-id))))
|
||||
|
||||
(.finally
|
||||
(fn []
|
||||
(reset! global-config-handler/root-dir nil)
|
||||
(fs-node/unlinkSync plugins-file)
|
||||
(fs-node/rmdirSync dir))))))
|
||||
(p/finally #(delete-global-config-dir dir)))))
|
||||
|
||||
(deftest-async open-sync-modal-malformed-edn
|
||||
(let [dir (test-helper/create-tmp-dir)
|
||||
plugins-file (path/join dir "plugins.edn")
|
||||
(let [dir (create-global-config-dir)
|
||||
error-message (atom nil)]
|
||||
(fs-node/writeFileSync plugins-file "{:id {}")
|
||||
(reset! global-config-handler/root-dir dir)
|
||||
(fs-node/writeFileSync (plugin-config-handler/plugin-config-path) "{:id {}")
|
||||
|
||||
(test-helper/with-reset reset
|
||||
[notification/show! (fn [msg _] (reset! error-message msg))]
|
||||
(->
|
||||
(p/do!
|
||||
(plugin-config/open-sync-modal)
|
||||
(plugin-config-handler/open-sync-modal)
|
||||
(is (string/starts-with? @error-message "Malformed plugins.edn")
|
||||
"User sees correct notification"))
|
||||
(p/finally (fn []
|
||||
(reset)
|
||||
(reset! global-config-handler/root-dir nil)
|
||||
(fs-node/unlinkSync plugins-file)
|
||||
(fs-node/rmdirSync dir)))))))
|
||||
(p/finally #(delete-global-config-dir dir))))))
|
||||
|
||||
(deftest-async open-sync-modal-invalid-edn
|
||||
(let [dir (test-helper/create-tmp-dir)
|
||||
plugins-file (path/join dir "plugins.edn")
|
||||
(let [dir (create-global-config-dir)
|
||||
error-message (atom nil)]
|
||||
;; Missing a couple plugin keys
|
||||
(fs-node/writeFileSync plugins-file (pr-str {:id {:theme true :repo "user/repo"}}))
|
||||
(reset! global-config-handler/root-dir dir)
|
||||
(fs-node/writeFileSync (plugin-config-handler/plugin-config-path)
|
||||
(pr-str {:id {:theme true :repo "user/repo"}}))
|
||||
|
||||
(test-helper/with-reset reset
|
||||
[notification/show! (fn [msg _] (reset! error-message msg))]
|
||||
(->
|
||||
(p/do!
|
||||
(plugin-config/open-sync-modal)
|
||||
(plugin-config-handler/open-sync-modal)
|
||||
(is (string/starts-with? @error-message "Invalid plugins.edn")
|
||||
"User sees correct notification"))
|
||||
(p/finally (fn []
|
||||
(reset)
|
||||
(fs-node/unlinkSync plugins-file)
|
||||
(fs-node/rmdirSync dir)))))))
|
||||
(p/finally #(delete-global-config-dir dir))))))
|
||||
|
||||
(defn- installed-plugins->edn-plugins
|
||||
"Converts installed plugins state to edn.plugins format"
|
||||
|
@ -107,26 +100,26 @@
|
|||
;; install and uninstall
|
||||
(deftest determine-plugins-to-change
|
||||
(testing "no changes to make"
|
||||
(let [plugins {:foo {:id :foo :name "Foo" :repo "some-user/foo" :version "v0.9.0"}
|
||||
:bar {:id :bar :name "Bar" :repo "some-user/bar" :version "v0.1.0"}}]
|
||||
(is (= {} (#'plugin-config/determine-plugins-to-change
|
||||
(let [plugins {:foo {:id :foo :repo "some-user/foo" :version "v0.9.0"}
|
||||
:bar {:id :bar :repo "some-user/bar" :version "v0.1.0"}}]
|
||||
(is (= {} (#'plugin-config-handler/determine-plugins-to-change
|
||||
plugins
|
||||
(installed-plugins->edn-plugins plugins))))))
|
||||
|
||||
(testing "differing versions are uninstalled and installed"
|
||||
(let [plugins {:bar {:id :bar :name "Bar" :repo "some-user/bar" :version "v0.1.0"}}]
|
||||
(let [plugins {:bar {:id :bar :repo "some-user/bar" :version "v0.1.0"}}]
|
||||
(is (= {:uninstall [(:bar plugins)]
|
||||
:install [(assoc (:bar plugins) :version "v1.0.0" :plugin-action "install")]}
|
||||
(#'plugin-config/determine-plugins-to-change
|
||||
(#'plugin-config-handler/determine-plugins-to-change
|
||||
plugins
|
||||
(installed-plugins->edn-plugins (assoc-in plugins [:bar :version] "v1.0.0")))))))
|
||||
|
||||
(testing "replaced plugins are uninstalled and new plugins are installed"
|
||||
(let [plugins {:foo {:id :foo :name "Foo" :repo "some-user/foo" :version "v0.9.0"}
|
||||
:bar {:id :bar :name "Bar" :repo "some-user/bar" :version "v0.1.0"}}
|
||||
new-plugin {:id :baz :name "Baz" :repo "some-user/baz" :version "v0.5.0"}]
|
||||
(let [plugins {:foo {:id :foo :repo "some-user/foo" :version "v0.9.0"}
|
||||
:bar {:id :bar :repo "some-user/bar" :version "v0.1.0"}}
|
||||
new-plugin {:id :baz :repo "some-user/baz" :version "v0.5.0"}]
|
||||
(is (= {:uninstall [(:foo plugins)]
|
||||
:install [(assoc new-plugin :plugin-action "install")]}
|
||||
(#'plugin-config/determine-plugins-to-change
|
||||
(#'plugin-config-handler/determine-plugins-to-change
|
||||
plugins
|
||||
(-> plugins (dissoc :foo) (assoc :baz new-plugin) installed-plugins->edn-plugins)))))))
|
||||
|
|
|
@ -121,8 +121,9 @@
|
|||
;; only test file name parsing, don't consider title prop overriding
|
||||
rename-target (:target (#'conversion-handler/calc-rename-target-impl :legacy :triple-lowbar original-body nil))]
|
||||
(if rename-target
|
||||
(do (prn "conversion triple-lowbar: " original-body " -> " rename-target)
|
||||
(#'page-handler/compute-new-file-path path rename-target))
|
||||
#_:clj-kondo/ignore
|
||||
(do #_(prn "conversion triple-lowbar: " original-body " -> " rename-target)
|
||||
(#'page-handler/compute-new-file-path path rename-target))
|
||||
path)))
|
||||
|
||||
(defn- convert-graph-files-path
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
(conn/destroy-all!))
|
||||
|
||||
(defn load-test-files
|
||||
"Given a collection of file maps, loads them into the current test-db.
|
||||
This can be called in synchronous contexts as no async fns should be invoked"
|
||||
[files]
|
||||
(repo-handler/parse-files-and-load-to-db!
|
||||
test-db
|
||||
|
@ -24,6 +26,14 @@
|
|||
{:re-render? false :verbose false :refresh? true}))
|
||||
|
||||
(defn create-tmp-dir
|
||||
[]
|
||||
(when-not (fs-node/existsSync "tmp") (fs-node/mkdirSync "tmp"))
|
||||
(fs-node/mkdtempSync (path/join "tmp" "unit-test-")))
|
||||
"Creates a temporary directory under tmp/. If a subdir is given, creates an
|
||||
additional subdirectory under the newly created temp directory."
|
||||
([] (create-tmp-dir nil))
|
||||
([subdir]
|
||||
(when-not (fs-node/existsSync "tmp") (fs-node/mkdirSync "tmp"))
|
||||
(let [dir (fs-node/mkdtempSync (path/join "tmp" "unit-test-"))]
|
||||
(if subdir
|
||||
(do
|
||||
(fs-node/mkdirSync (path/join dir subdir))
|
||||
(path/join dir subdir))
|
||||
dir))))
|
||||
|
|
Loading…
Reference in New Issue