plugins.cljs 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. (ns frontend.components.plugins
  2. (:require [rum.core :as rum]
  3. [frontend.state :as state]
  4. [cljs-bean.core :as bean]
  5. [frontend.ui :as ui]
  6. [frontend.util :as util]
  7. [electron.ipc :as ipc]
  8. [promesa.core :as p]
  9. [frontend.components.svg :as svg]
  10. [frontend.handler.notification :as notification]
  11. [frontend.handler.plugin :as plugin-handler]))
  12. (rum/defc installed-themes
  13. < rum/reactive
  14. []
  15. (let [themes (state/sub :plugin/installed-themes)
  16. selected (state/sub :plugin/selected-theme)]
  17. [:div.cp__themes-installed
  18. [:h2.mb-4.text-xl "Installed Themes"]
  19. (for [opt themes]
  20. (let [current-selected (= selected (:url opt))]
  21. [:div.it.flex.px-3.py-2.mb-2.rounded-sm.justify-between
  22. {:key (:url opt)
  23. :class [(if current-selected "selected")]
  24. :on-click #(do (js/LSPluginCore.selectTheme (if current-selected nil (clj->js opt)))
  25. (state/set-modal! nil))}
  26. [:section
  27. [:strong.block (:name opt)]
  28. [:small.opacity-30 (:description opt)]]
  29. [:small.flex-shrink-0.flex.items-center.opacity-10
  30. (if current-selected "current")]]))]))
  31. (rum/defc unpacked-plugin-loader
  32. [unpacked-pkg-path]
  33. (rum/use-effect!
  34. (fn []
  35. (let [err-handle
  36. (fn [^js e]
  37. (case (keyword (aget e "name"))
  38. :IllegalPluginPackageError
  39. (notification/show! "Illegal Logseq plugin package." :error)
  40. :ExistedImportedPluginPackageError
  41. (notification/show! "Existed Imported plugin package." :error)
  42. :default)
  43. (plugin-handler/reset-unpacked-state))
  44. reg-handle #(plugin-handler/reset-unpacked-state)]
  45. (when unpacked-pkg-path
  46. (doto js/LSPluginCore
  47. (.once "error" err-handle)
  48. (.once "registered" reg-handle)
  49. (.register (bean/->js {:url unpacked-pkg-path}))))
  50. #(doto js/LSPluginCore
  51. (.off "error" err-handle)
  52. (.off "registered" reg-handle))))
  53. [unpacked-pkg-path])
  54. (when unpacked-pkg-path
  55. [:strong.inline-flex.px-3 "Loading ..."]))
  56. (rum/defc simple-markdown-display
  57. < rum/reactive
  58. []
  59. (let [content (state/sub :plugin/active-readme)]
  60. [:textarea.p-1.bg-transparent.border-none
  61. {:style {:width "700px" :min-height "60vw"}}
  62. content]))
  63. (rum/defc plugin-item-card
  64. [{:keys [id name settings version url description author icon usf] :as item}]
  65. (let [disabled (:disabled settings)]
  66. [:div.cp__plugins-item-card
  67. [:div.l.link-block
  68. {:on-click #(plugin-handler/open-readme! url simple-markdown-display)}
  69. (if icon
  70. [:img.icon {:src icon}]
  71. svg/folder)]
  72. [:div.r
  73. [:h3.head.text-xl.font-bold.pt-1.5
  74. {:on-click #(plugin-handler/open-readme! url simple-markdown-display)}
  75. [:span name]
  76. [:sup.inline-block.px-1.text-xs.opacity-30 version]]
  77. [:div.desc.text-xs.opacity-60
  78. [:p description]
  79. [:small (js/JSON.stringify (bean/->js settings))]]
  80. [:div.flag
  81. [:p.text-xs.text-gray-300.pr-2.flex.justify-between.dark:opacity-40
  82. [:small author]
  83. [:small (str "ID: " id)]]]
  84. [:div.ctl
  85. [:div.l
  86. [:div.de
  87. [:strong svg/settings-sm]
  88. [:ul.menu-list
  89. [:li {:on-click #(if usf (js/apis.openPath usf))} "Open settings"]
  90. [:li {:on-click
  91. #(let [confirm-fn
  92. (ui/make-confirm-modal
  93. {:title (str "Are you sure uninstall plugin - " name "?")
  94. :on-confirm (fn [_ {:keys [close-fn]}]
  95. (close-fn)
  96. (plugin-handler/unregister-plugin id))})]
  97. (state/set-modal! confirm-fn))}
  98. "Uninstall plugin"]]]]
  99. [:div.flex.items-center
  100. [:small.de (if disabled "Disabled" "Enabled")]
  101. (ui/toggle (not disabled)
  102. (fn []
  103. (js-invoke js/LSPluginCore (if disabled "enable" "disable") id))
  104. true)]]]]))
  105. (rum/defc installed-page
  106. < rum/reactive
  107. []
  108. (let [installed-plugins (state/sub :plugin/installed-plugins)
  109. selected-unpacked-pkg (state/sub :plugin/selected-unpacked-pkg)]
  110. [:div.cp__plugins-page-installed
  111. [:h1 "Installed Plugins"]
  112. [:div.mb-6.flex.items-center.justify-between
  113. (ui/button
  114. "Load unpacked plugin"
  115. :intent "logseq"
  116. :on-click plugin-handler/load-unpacked-plugin)
  117. (unpacked-plugin-loader selected-unpacked-pkg)
  118. (when (util/electron?)
  119. (ui/button
  120. [:span.flex.items-center
  121. ;;svg/settings-sm
  122. "Open plugin preferences file"]
  123. :intent "logseq"
  124. :on-click (fn []
  125. (p/let [root (plugin-handler/get-ls-dotdir-root)]
  126. (js/apis.openPath (str root "/preferences.json"))))))]
  127. [:div.cp__plugins-item-lists.grid-cols-1.md:grid-cols-2.lg:grid-cols-3
  128. (for [[_ item] installed-plugins]
  129. (rum/with-key (plugin-item-card item) (:id item)))]]))
  130. (defn open-select-theme!
  131. []
  132. (state/set-modal! installed-themes))
  133. (rum/defc hook-ui-slot
  134. ([type payload] (hook-ui-slot type payload nil))
  135. ([type payload opts]
  136. (let [id (str "slot__" (util/rand-str 8))]
  137. (rum/use-effect!
  138. (fn []
  139. (plugin-handler/hook-plugin-app type {:slot id :payload payload} nil)
  140. #())
  141. [])
  142. [:div.lsp-hook-ui-slot
  143. (merge opts {:id id})])))