Enhance/plugins (#8202)

* improve(plugins): install hooks with user options

* improve(plugin): remove todos

* improve(plugin): hook for a specific plugin

* e2e tests

* improve(ui): global search bar for the results from the custom search service
pull/8197/head
Charlie 2023-01-05 19:30:41 +08:00 committed by GitHub
parent 1eb94092f0
commit 675811ccde
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 112 additions and 26 deletions

72
e2e-tests/plugins.spec.ts Normal file
View File

@ -0,0 +1,72 @@
import { expect } from '@playwright/test'
import { test } from './fixtures'
test('enabled plugin system default', async ({ page }) => {
const callAPI = callPageAPI.bind(null, page)
const pluginEnabled = await callAPI('get_state_from_store', 'plugin/enabled')
await expect(pluginEnabled).toBe(true)
expect(await page.evaluate(`typeof logseq.api.get_current_graph`))
.toBe('function')
const currentGraph = await callAPI('get_current_graph')
expect(Object.keys(currentGraph)).toEqual(['url', 'name', 'path'])
})
test('play a plugin<logseq-journals-calendar> from the Marketplace', async ({ page }) => {
await page.keyboard.press('t+p')
const searchInput = page.locator('.search-ctls .form-input')
await searchInput.type('journals')
const pluginCards = page.locator('.cp__plugins-item-card')
if (await pluginCards.count()) {
await pluginCards.locator('.ctl .ls-icon-settings').hover()
await page.locator('text=Uninstall').click()
const confirmYes = page.locator('button').locator('text=Yes')
await confirmYes.click()
}
// install a plugin from Marketplace
await page.locator('button').locator('text=Marketplace').click()
await page.locator('text=Journals calendar')
await page.locator('.cp__plugins-item-card').first().locator('text=Install').click()
// wait for the plugin installed
await page.locator('.cp__plugins-item-card').first().locator('text=Installed')
await page.locator('a.ui__modal-close').click()
// toolbar plugins manager
const pluginFlag = page.locator('.toolbar-plugins-manager-trigger')
await expect(pluginFlag).toBeVisible()
await pluginFlag.click()
await expect(pluginFlag.locator('text=Plugins')).toBeVisible()
await expect(pluginFlag.locator('text=Settings')).toBeVisible()
await page.locator('text=goto-today').click()
await page.locator('body').click()
const goToToday = page.locator('#logseq-journals-calendar--goto-today').locator('a.button')
await expect(goToToday).toBeVisible()
await goToToday.click()
// TODO: debug
await expect(page.locator('body[data-page="page"]')).toBeVisible()
})
/**
* @param page
* @param method
* @param args
*/
async function callPageAPI(page, method, ...args) {
return await page.evaluate(([method, args]) => {
// @ts-ignore
return window.logseq.api[method]?.(...args)
}, [method, args])
}

View File

@ -308,7 +308,6 @@ class LSPluginCaller extends EventEmitter {
this._callUserModel = async (type, ...payloads: any[]) => {
if (type.startsWith(FLAG_AWAIT)) {
// TODO: attach arguments with method call
return await refChild.get(
type.replace(FLAG_AWAIT, ''),
...payloads

View File

@ -1398,8 +1398,15 @@ class LSPluginCore
})
}
const p = pid && this._registeredPlugins.get(pid)
if (p && !p.disabled && p.options.entry) {
act(p)
return
}
for (const [_, p] of this._registeredPlugins) {
if (p.options.theme || p.disabled) {
if (!p.options.entry || p.disabled) {
continue
}

View File

@ -518,7 +518,7 @@ export interface IAppProxy {
onSidebarVisibleChanged: IUserHook<{ visible: boolean }>
// internal
_installPluginHook: (pid: string, hook: string) => void
_installPluginHook: (pid: string, hook: string, opts?: any) => void
_uninstallPluginHook: (pid: string, hookOrAll: string | boolean) => void
}

View File

@ -737,6 +737,7 @@ export class LSPluginUser
const type = `hook:${tag}:${safeSnakeCase(e)}`
const handler = args[0]
const opts = args[1]
caller[f](type, handler)
const unlisten = () => {
@ -747,7 +748,7 @@ export class LSPluginUser
}
if (!isOff) {
that.App._installPluginHook(pid, type)
that.App._installPluginHook(pid, type, opts)
} else {
unlisten()
return

File diff suppressed because one or more lines are too long

View File

@ -636,7 +636,8 @@
(reload-fn false)
(assoc s ::reload (partial reload-fn true))))}
[state]
(let [pkgs (state/sub :plugin/marketplace-pkgs)
(let [*list-node-ref (rum/create-ref)
pkgs (state/sub :plugin/marketplace-pkgs)
stats (state/sub :plugin/marketplace-stats)
installed-plugins (state/sub :plugin/installed-plugins)
installing (state/sub :plugin/installing)
@ -688,7 +689,7 @@
fn-query-flag (fn [] (string/join "_" (map #(str @%) [*filter-by *sort-by *search-key *category])))
str-query-flag (fn-query-flag)
_ (when (not= str-query-flag @*cached-query-flag)
(when-let [^js list-cnt (rum/ref-node state "list-ref")]
(when-let [^js list-cnt (rum/deref *list-node-ref)]
(set! (.-scrollTop list-cnt) 0))
(reset! *current-page 1))
_ (reset! *cached-query-flag str-query-flag)
@ -723,7 +724,7 @@
[:div.cp__plugins-marketplace-cnt
{:class (util/classnames [{:has-installing (boolean installing)}])}
[:div.cp__plugins-item-lists
{:ref "list-ref"}
{:ref *list-node-ref}
[:div.cp__plugins-item-lists-inner
;; items list
(for [item sorted-plugins]
@ -750,7 +751,8 @@
(rum/local nil ::cached-query-flag)
(rum/local 1 ::current-page)
[state]
(let [installed-plugins (state/sub [:plugin/installed-plugins])
(let [*list-node-ref (rum/create-ref)
installed-plugins (state/sub [:plugin/installed-plugins])
installed-plugins (vals installed-plugins)
updating (state/sub :plugin/installing)
develop-mode? (state/sub :ui/developer-mode?)
@ -799,7 +801,7 @@
fn-query-flag (fn [] (string/join "_" (map #(str @%) [*filter-by *sort-by *search-key *category])))
str-query-flag (fn-query-flag)
_ (when (not= str-query-flag @*cached-query-flag)
(when-let [^js list-cnt (rum/ref-node state "list-ref")]
(when-let [^js list-cnt (rum/deref *list-node-ref)]
(set! (.-scrollTop list-cnt) 0))
(reset! *current-page 1))
_ (reset! *cached-query-flag str-query-flag)
@ -822,7 +824,7 @@
agent-opts)
[:div.cp__plugins-item-lists.pb-6
{:ref "list-ref"}
{:ref *list-node-ref}
[:div.cp__plugins-item-lists-inner
(for [item sorted-plugins]
(rum/with-key
@ -928,7 +930,6 @@
;; all done
[:div.py-4 [:strong.text-xl (str "\uD83C\uDF89 " (t :plugin.install-from-file/success))]])])
(defn open-select-theme!
[]
(state/set-sub-modal! installed-themes))

View File

@ -370,7 +370,7 @@
[{:type :graph-add-filter}]
result)
repo (state/get-current-repo)]
[:div
[:div.results-inner
(ui/auto-complete
result
{:class "search-results"
@ -554,7 +554,7 @@
[:span.pr-2 (ui/icon "puzzle")]
(:name v)
(when-let [result (and v (:result v))]
(str " (" (count (:blocks result)) ")"))]
(str " (" (apply + (map count ((juxt :blocks :pages :files) result))) ")"))]
:on-click #(reset! *active-engine-tab k))])])
(if-not (nil? @*active-engine-tab)

View File

@ -20,7 +20,11 @@
@apply flex flex-col overflow-auto;
> .search-results-wrap {
@apply flex-1 overflow-auto h-full;
@apply flex flex-col flex-1 overflow-hidden h-full;
> .results-inner {
@apply h-full overflow-y-auto;
}
}
}
@ -30,7 +34,7 @@
.search-results-engines {
&-tabs {
@apply flex list-none -mx-2 mb-2;
@apply flex list-none -mx-2 mb-2 px-2;
background: var(--ls-primary-background-color);
@ -43,6 +47,7 @@
background: transparent;
border-radius: 0;
line-height: 1;
color: var(--ls-primary-text-color);
}
&.is-active .ui__button {

View File

@ -1542,21 +1542,22 @@ Similar to re-frame subscriptions"
(update-vals engines #(assoc % :result nil)))))
(defn install-plugin-hook
[pid hook]
(when-let [pid (keyword pid)]
(set-state!
([pid hook] (install-plugin-hook pid hook true))
([pid hook opts]
(when-let [pid (keyword pid)]
(set-state!
[:plugin/installed-hooks hook]
(conj
((fnil identity #{}) (get-in @state [:plugin/installed-hooks hook]))
pid)) true))
(assoc
((fnil identity {}) (get-in @state [:plugin/installed-hooks hook]))
pid opts)) true)))
(defn uninstall-plugin-hook
[pid hook-or-all]
(when-let [pid (keyword pid)]
(if (nil? hook-or-all)
(swap! state update :plugin/installed-hooks #(update-vals % (fn [ids] (disj ids pid))))
(swap! state update :plugin/installed-hooks #(update-vals % (fn [ids] (dissoc ids pid))))
(when-let [coll (get-in @state [:plugin/installed-hooks hook-or-all])]
(set-state! [:plugin/installed-hooks hook-or-all] (disj coll pid))))
(set-state! [:plugin/installed-hooks hook-or-all] (dissoc coll pid))))
true))
(defn slot-hook-exist?

View File

@ -80,8 +80,8 @@
(js/console.error "[parse hiccup error]" e) input))))
(defn ^:export install-plugin-hook
[pid hook]
(state/install-plugin-hook pid hook))
[pid hook ^js opts]
(state/install-plugin-hook pid hook (bean/->clj opts)))
(defn ^:export uninstall-plugin-hook
[pid hook-or-all]