@inpageedit/core 0.13.1 → 0.14.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/LICENSE +20 -20
  2. package/README.md +13 -4
  3. package/dist/{BasePlugin-Bf2UuIHF.js → BasePlugin-YOi2_vUo.js} +17 -26
  4. package/dist/BasePlugin-YOi2_vUo.js.map +1 -0
  5. package/dist/IconQuickEdit-CMCQncyj.js.map +1 -1
  6. package/dist/InputBox-nQKtiWtZ.js.map +1 -1
  7. package/dist/{PluginPrefSync-Dn1Xsiqz.js → PluginPrefSync-jTNlRQE-.js} +124 -128
  8. package/dist/PluginPrefSync-jTNlRQE-.js.map +1 -0
  9. package/dist/PluginStoreApp-CGNxKXAN.js +453 -0
  10. package/dist/PluginStoreApp-CGNxKXAN.js.map +1 -0
  11. package/dist/{endpoints-DgyuoRZd.js → Preferences-BF2fcXrn.js} +608 -576
  12. package/dist/Preferences-BF2fcXrn.js.map +1 -0
  13. package/dist/WatchlistAction-BbNAyryN.js.map +1 -1
  14. package/dist/components/index.js.map +1 -1
  15. package/dist/index-3NZkG2a3.js +116 -0
  16. package/dist/index-3NZkG2a3.js.map +1 -0
  17. package/dist/{index-BJ7_Q1mB.js → index-BBNseJXG.js} +17 -16
  18. package/dist/index-BBNseJXG.js.map +1 -0
  19. package/dist/{index-BQ-cHWkJ.js → index-Bb0FiU2c.js} +66 -48
  20. package/dist/index-Bb0FiU2c.js.map +1 -0
  21. package/dist/{index-DqA6EAM6.js → index-BgkZW91u.js} +1429 -928
  22. package/dist/index-BgkZW91u.js.map +1 -0
  23. package/dist/index-BrYKe18j.js +179 -0
  24. package/dist/index-BrYKe18j.js.map +1 -0
  25. package/dist/index-CG38LlAh.js.map +1 -1
  26. package/dist/index-CM_6yF2v.js.map +1 -1
  27. package/dist/index-D-fW3ESK.js +195 -0
  28. package/dist/index-D-fW3ESK.js.map +1 -0
  29. package/dist/index-D6zFqL2u.js +173 -0
  30. package/dist/index-D6zFqL2u.js.map +1 -0
  31. package/dist/{index-CCRMmnwk.js → index-D97lUU3h.js} +67 -66
  32. package/dist/index-D97lUU3h.js.map +1 -0
  33. package/dist/index-DD5CVCfD.js.map +1 -1
  34. package/dist/{index-B7c6jL9x.js → index-DELHsLHS.js} +146 -137
  35. package/dist/index-DELHsLHS.js.map +1 -0
  36. package/dist/{index-BwdWyHLe.js → index-DTHY5rAO.js} +93 -93
  37. package/dist/index-DTHY5rAO.js.map +1 -0
  38. package/dist/index-DmLoihN1.js +394 -0
  39. package/dist/index-DmLoihN1.js.map +1 -0
  40. package/dist/index.d.ts +362 -43
  41. package/dist/index.js +32 -26
  42. package/dist/index.js.map +1 -1
  43. package/dist/makeCallable-LDU0xZMJ.js.map +1 -1
  44. package/dist/models/index.js +174 -154
  45. package/dist/models/index.js.map +1 -1
  46. package/dist/noop-ClDc6zv4.js.map +1 -1
  47. package/dist/plugins/index.js +10 -10
  48. package/dist/services/index.js +1 -1
  49. package/dist/style.css +1 -1
  50. package/dist/vueHooks-l04s8cIl.js.map +1 -1
  51. package/lib/index.umd.js +20 -12
  52. package/lib/index.umd.js.map +1 -1
  53. package/lib/style.css +1 -1
  54. package/package.json +4 -4
  55. package/dist/BasePlugin-Bf2UuIHF.js.map +0 -1
  56. package/dist/PluginPrefSync-Dn1Xsiqz.js.map +0 -1
  57. package/dist/PluginStoreApp-CpOLArL7.js +0 -452
  58. package/dist/PluginStoreApp-CpOLArL7.js.map +0 -1
  59. package/dist/Preferences-DS4-CFWe.js +0 -9
  60. package/dist/Preferences-DS4-CFWe.js.map +0 -1
  61. package/dist/endpoints-DgyuoRZd.js.map +0 -1
  62. package/dist/index-2RfILgXm.js +0 -180
  63. package/dist/index-2RfILgXm.js.map +0 -1
  64. package/dist/index-B7c6jL9x.js.map +0 -1
  65. package/dist/index-BJ7_Q1mB.js.map +0 -1
  66. package/dist/index-BNh95-x2.js +0 -115
  67. package/dist/index-BNh95-x2.js.map +0 -1
  68. package/dist/index-BQ-cHWkJ.js.map +0 -1
  69. package/dist/index-BwdWyHLe.js.map +0 -1
  70. package/dist/index-CCRMmnwk.js.map +0 -1
  71. package/dist/index-CnIpUF9x.js +0 -173
  72. package/dist/index-CnIpUF9x.js.map +0 -1
  73. package/dist/index-CyG7_IYz.js +0 -394
  74. package/dist/index-CyG7_IYz.js.map +0 -1
  75. package/dist/index-DqA6EAM6.js.map +0 -1
  76. package/dist/index-eSlbrNqF.js +0 -146
  77. package/dist/index-eSlbrNqF.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PluginPrefSync-jTNlRQE-.js","sources":["../src/plugins/preferences-ui/PluginPrefSync.tsx"],"sourcesContent":["import { Inject, InPageEdit } from '@/InPageEdit.js'\nimport { WatchlistAction } from '@/models/WikiPage/types/WatchlistAction.js'\nimport { IWikiTitle } from '@/models/WikiTitle/index.js'\n\ndeclare module '@/InPageEdit' {\n export interface InPageEdit {\n prefSync: PluginPrefSync\n }\n}\n\n@Inject(['preferences', 'wiki', 'wikiPage', 'wikiTitle', 'modal', 'preferencesUI', '$'])\nexport class PluginPrefSync extends BasePlugin {\n constructor(public ctx: InPageEdit) {\n super(ctx, {}, 'pref-sync')\n ctx.set('prefSync', this)\n }\n\n protected start(): Promise<void> | void {\n const ctx = this.ctx\n const $ = ctx.$\n ctx.preferences.defineCategory({\n name: 'pref-sync',\n label: $`Sync`,\n description: $`Import and export preferences`,\n index: 98,\n customRenderer: () => {\n const userPageTitle = this.getUserPrefsPageTitle()\n return (\n <div className=\"theme-ipe-prose\">\n {userPageTitle && (\n <section>\n <h3>{$`Backup your preferences via user page`}</h3>\n <p>\n <a href={userPageTitle?.getURL().toString()} target=\"_blank\">\n {userPageTitle?.getPrefixedText()} →\n </a>\n </p>\n <div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>\n <ActionButton\n type=\"primary\"\n onClick={(e) => {\n e.preventDefault()\n const btn = e.target as HTMLButtonElement\n btn.disabled = true\n const modal = ctx.preferencesUI.getCurrentModal()\n modal?.setLoadingState(true)\n this.exportToUserPage()\n .then((title) => {\n ctx.modal.notify('success', {\n title: $`Preferences Exported`,\n content: (\n <p>\n Your preferences have been exported to{' '}\n <a href={title.getURL().toString()} target=\"_blank\">\n {title.getPrefixedText()}\n </a>\n .\n </p>\n ),\n })\n })\n .finally(() => {\n btn.disabled = false\n modal?.setLoadingState(false)\n })\n }}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n class=\"icon icon-tabler icons-tabler-outline icon-tabler-cloud-up\"\n >\n <path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\" />\n <path d=\"M12 18.004h-5.343c-2.572 -.004 -4.657 -2.011 -4.657 -4.487c0 -2.475 2.085 -4.482 4.657 -4.482c.393 -1.762 1.794 -3.2 3.675 -3.773c1.88 -.572 3.956 -.193 5.444 1c1.488 1.19 2.162 3.007 1.77 4.769h.99c1.38 0 2.57 .811 3.128 1.986\" />\n <path d=\"M19 22v-6\" />\n <path d=\"M22 19l-3 -3l-3 3\" />\n </svg>{' '}\n {$`Backup`}\n </ActionButton>\n <ActionButton\n onClick={(e) => {\n e.preventDefault()\n const modal = ctx.preferencesUI.getCurrentModal()\n const btn = e.target as HTMLButtonElement\n btn.disabled = true\n modal?.setLoadingState(true)\n this.importFromUserPage()\n .then((record) => {\n this.notifyImportSuccess(record)\n })\n .finally(() => {\n btn.disabled = false\n modal?.setLoadingState(false)\n })\n }}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n class=\"icon icon-tabler icons-tabler-outline icon-tabler-cloud-down\"\n >\n <path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\" />\n <path d=\"M12 18.004h-5.343c-2.572 -.004 -4.657 -2.011 -4.657 -4.487c0 -2.475 2.085 -4.482 4.657 -4.482c.393 -1.762 1.794 -3.2 3.675 -3.773c1.88 -.572 3.956 -.193 5.444 1c1.488 1.19 2.162 3.007 1.77 4.769h.99c1.38 0 2.573 .813 3.13 1.99\" />\n <path d=\"M19 16v6\" />\n <path d=\"M22 19l-3 3l-3 -3\" />\n </svg>{' '}\n {$`Restore`}\n </ActionButton>\n </div>\n </section>\n )}\n <section>\n <h3>{$`Import and export preferences`}</h3>\n <div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>\n <ActionButton\n onClick={(e) => {\n e.preventDefault()\n const modal = ctx.preferencesUI.getCurrentModal()\n modal?.setLoadingState(true)\n const input = document.createElement('input')\n input.type = 'file'\n input.accept = 'application/json'\n // Mobile Safari (and some older browsers) do not fire a 'cancel' event when\n // the file picker is dismissed without selecting a file. We use a\n // window 'focus' listener as a heuristic: once the picker closes\n // the window regains focus; if no file was chosen we treat it as cancel.\n // Fuck you Apple\n let handled = false\n const onDialogClose = () => {\n // If change handler did not run, treat as cancel\n if (!handled) {\n modal?.setLoadingState(false)\n }\n window.removeEventListener('focus', onDialogClose)\n }\n window.addEventListener('focus', onDialogClose, { once: true })\n\n input.addEventListener('change', async (e) => {\n handled = true\n try {\n const file = (e.target as HTMLInputElement).files?.[0]\n if (!file) {\n return\n }\n const record = await this.importFromFile(file)\n this.notifyImportSuccess(record)\n } catch (e) {\n ctx.modal.notify('error', {\n title: 'Import failed',\n content: e instanceof Error ? e.message : String(e),\n })\n } finally {\n modal?.setLoadingState(false)\n }\n })\n input.click()\n }}\n >\n {$`Import from file`}\n </ActionButton>\n <ActionButton\n onClick={(e) => {\n e.preventDefault()\n const input = (\n <input type=\"url\" style={{ width: '100%' }}></input>\n ) as HTMLInputElement\n const modal = ctx.preferencesUI.getCurrentModal()\n ctx.modal.confirm(\n {\n title: $`Import from URL`,\n content: (\n <div className=\"ipe-input-box\">\n <label htmlFor=\"url-input\">\n {$`Enter the URL of the preferences JSON file:`}\n </label>\n {input}\n </div>\n ),\n },\n async (result) => {\n const url = input.value.trim()\n if (!result || !url) {\n return\n }\n try {\n modal?.setLoadingState(true)\n const record = await this.importFromUrl(url)\n this.notifyImportSuccess(record)\n } catch (e) {\n ctx.modal.notify('error', {\n title: 'Import failed',\n content: e instanceof Error ? e.message : String(e),\n })\n } finally {\n modal?.setLoadingState(false)\n }\n }\n )\n }}\n >\n {$`Import from URL`}\n </ActionButton>\n <ActionButton\n onClick={async (e) => {\n e.preventDefault()\n // 首先尝试保存当前的表单内容\n await ctx.preferencesUI.dispatchFormSave()\n const data = await ctx.preferences.getExportableRecord()\n const json = JSON.stringify(data, null, 2)\n ctx.modal.dialog(\n {\n title: $`Save to file`,\n content: (\n <div>\n <label htmlFor=\"data\">{$`Your InPageEdit preferences:`}</label>\n <textarea\n name=\"data\"\n id=\"data\"\n rows={10}\n value={json}\n readOnly\n style={{ width: '100%' }}\n ></textarea>\n </div>\n ),\n buttons: [\n {\n label: 'Copy',\n method: (_, m) => {\n navigator.clipboard.writeText(json)\n ctx.modal.notify('success', {\n content: $`Copied to clipboard`,\n })\n m.close()\n },\n },\n {\n label: $`Download`,\n method: (_, m) => {\n const a = document.createElement('a')\n a.href = `data:text/json;charset=utf-8,${encodeURIComponent(json)}`\n a.download = `ipe-prefs-${new Date().toISOString()}.json`\n a.click()\n m.close()\n },\n },\n ],\n },\n () => {}\n )\n }}\n >\n {$`Save as file`}\n </ActionButton>\n </div>\n </section>\n </div>\n )\n },\n })\n }\n\n protected stop(): Promise<void> | void {}\n\n /**\n * 获取用户页配置文件的标题\n */\n private getUserPrefsPageTitle(): IWikiTitle | null {\n try {\n const userName = this.ctx.wiki?.userInfo?.name\n if (!userName) {\n return null\n }\n // 使用 User: 命名空间\n return this.ctx.wikiTitle.newTitle(`User:${userName}/ipe-prefs.json`, 2)\n } catch {\n return null\n }\n }\n\n /**\n * 从用户页加载配置\n */\n async importFromUserPage(): Promise<Record<string, unknown>> {\n const title = this.getUserPrefsPageTitle()\n if (!title) {\n this.logger.debug('Cannot get user page title, skipping load')\n return {}\n }\n\n try {\n // 使用 raw action 获取 JSON 内容\n const rawUrl = title.getURL({ action: 'raw', ctype: 'application/json' })\n const changed = await this.importFromUrl(rawUrl.toString())\n this.logger.info('Loaded preferences from user page:', title)\n return changed\n } catch (error) {\n this.logger.error('Failed to load preferences from user page:', error)\n return {}\n }\n }\n\n /**\n * 导出配置到用户页\n */\n async exportToUserPage(): Promise<IWikiTitle> {\n const ctx = this.ctx\n const title = this.getUserPrefsPageTitle()\n if (!title) {\n throw new Error('Cannot get user page title')\n }\n\n // 首先尝试保存当前的表单内容\n await ctx.preferencesUI.dispatchFormSave()\n\n const json = await ctx.preferences.getExportableRecord()\n const text = JSON.stringify(json, null, 2)\n\n try {\n const page = this.ctx.wikiPage.newBlankPage({\n title: title.toString(),\n ns: 2, // User namespace\n })\n await page.edit({\n text,\n summary: 'Update InPageEdit preferences',\n watchlist: WatchlistAction.nochange,\n })\n\n this.logger.info('Exported preferences to user page:', title)\n return title\n } catch (error) {\n this.logger.error('Failed to export preferences to user page:', error)\n throw error\n }\n }\n\n async importFromUrl(input: string): Promise<Record<string, unknown>> {\n const response = await fetch(input)\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`)\n }\n const blob = await response.blob()\n const changed = await this.importFromFile(blob)\n return changed\n }\n\n async importFromFile(input: Blob): Promise<Record<string, unknown>> {\n const text = await input.text()\n const data = JSON.parse(text)\n const changed = await this.ctx.preferences.setMany(data)\n return changed\n }\n\n private notifyImportSuccess(configs?: Record<string, unknown>) {\n const $ = this.ctx.$\n const keys = Object.keys(configs ?? {})\n const count = keys.length\n return this.ctx.modal.notify('success', {\n title: $`Preferences Imported`,\n content: (\n <section>\n <p>\n {$({\n count,\n })`Successfully imported {{ count }} {{ count > 1 ? \"settings\" : \"setting\" }}:`}\n </p>\n <ol style={{ listStyle: 'auto', paddingLeft: '1em' }}>\n {keys.map((key) => (\n <li key={key}>{key}</li>\n ))}\n </ol>\n </section>\n ),\n })\n }\n}\n"],"names":["_PluginPrefSync_decorators","_init","_a","Inject","PluginPrefSync","BasePlugin","ctx","$","userPageTitle","jsxs","jsx","ActionButton","e","btn","modal","title","record","input","handled","onDialogClose","file","result","url","data","json","_","m","a","userName","rawUrl","changed","error","text","WatchlistAction","response","blob","configs","keys","count","key","__decoratorStart","__decorateElement","__runInitializers"],"mappings":"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"}
@@ -0,0 +1,453 @@
1
+ import { a as K, l as P, e as d, h as u, y as U, C as te, k as G, r as w, f as q, q as i, D as L, z as l, B as f, E as Y, G as J, H as D, I as F, F as Q, x as W, v as A, g as ie } from "./vueHooks-l04s8cIl.js";
2
+ import { c as T } from "./index-CM_6yF2v.js";
3
+ import { E as re } from "./Preferences-BF2fcXrn.js";
4
+ import { _ as O } from "./_plugin-vue_export-helper-CHgC5LLL.js";
5
+ const H = /* @__PURE__ */ K({
6
+ __name: "UIBaseButton",
7
+ props: {
8
+ variant: { default: "neutral" },
9
+ active: { type: Boolean, default: !1 }
10
+ },
11
+ setup(x) {
12
+ const t = x, c = P(() => ({
13
+ "is-active": t.active,
14
+ "is-danger": t.variant === "danger",
15
+ "is-primary": t.variant === "primary",
16
+ "is-ghost": t.variant === "ghost",
17
+ "is-accent": t.variant === "accent"
18
+ }));
19
+ return (p, y) => (u(), d("button", {
20
+ class: U(["ipeps-button", c.value])
21
+ }, [
22
+ te(p.$slots, "default")
23
+ ], 2));
24
+ }
25
+ }), ne = { id: "ipe-registry-manager" }, ae = { class: "ipeps-header" }, oe = { class: "ipeps-header-title" }, le = { class: "ipeps-input-wrapper" }, ce = ["placeholder", "disabled"], de = {
26
+ key: 0,
27
+ class: "ipeps-list"
28
+ }, ue = { class: "registry-info" }, ge = { class: "item-name" }, pe = { class: "item-desc" }, ye = { class: "homepage" }, ve = ["href"], fe = { class: "url" }, me = { class: "item-meta" }, _e = { class: "ipeps-actions" }, he = {
29
+ key: 1,
30
+ class: "ipeps-empty"
31
+ }, ke = { class: "text" }, be = { class: "description" }, $e = /* @__PURE__ */ K({
32
+ __name: "RegistryManager",
33
+ setup(x) {
34
+ const t = G(), c = t.$, p = t.$$, y = w([]), _ = w(""), k = w(!1), b = (a) => {
35
+ try {
36
+ return new URL(a).hostname;
37
+ } catch {
38
+ return a;
39
+ }
40
+ };
41
+ async function $() {
42
+ const a = await t.preferences.get("pluginStore.registries") || [], o = await Promise.allSettled(
43
+ a.map(async (n) => {
44
+ const v = await t.store.getRegistryInfo(n);
45
+ return {
46
+ registryUrl: n,
47
+ label: b(n),
48
+ ...v
49
+ };
50
+ })
51
+ );
52
+ y.value = o.filter((n) => n.status === "fulfilled").map((n) => n.value);
53
+ }
54
+ async function M() {
55
+ const a = _.value.trim();
56
+ if (a) {
57
+ if (y.value.some((o) => o.registryUrl === a)) {
58
+ t.modal.notify("info", { content: "Registry already exists." });
59
+ return;
60
+ }
61
+ k.value = !0;
62
+ try {
63
+ const o = await t.store.getRegistryInfo(a, "online_manifest", !0);
64
+ if (!o)
65
+ throw new Error("Invalid registry or unreachable");
66
+ const n = await t.preferences.get("pluginStore.registries") || [];
67
+ n.push(a), await t.preferences.set("pluginStore.registries", n), y.value.push({
68
+ registryUrl: a,
69
+ label: b(a),
70
+ ...o
71
+ }), _.value = "", t.modal.notify("success", { content: "Registry added." });
72
+ } catch (o) {
73
+ t.modal.notify("error", {
74
+ content: o instanceof Error ? o.message : String(o)
75
+ });
76
+ } finally {
77
+ k.value = !1;
78
+ }
79
+ }
80
+ }
81
+ async function h(a) {
82
+ const n = (await t.preferences.get("pluginStore.registries") || []).filter((v) => v !== a);
83
+ await t.preferences.set("pluginStore.registries", n), y.value = y.value.filter((v) => v.registryUrl !== a);
84
+ }
85
+ async function N(a) {
86
+ const n = (await t.preferences.get("pluginStore.plugins") || []).filter((v) => v.registry === a);
87
+ if (n.length === 0) {
88
+ t.modal.confirm(
89
+ {
90
+ title: p`plugin-store.remove-registry.title`,
91
+ content: p`plugin-store.remove-registry.tip-content` + `
92
+ ${a}`,
93
+ cancelBtn: {
94
+ label: c`Cancel`,
95
+ className: "is-ghost"
96
+ },
97
+ okBtn: {
98
+ label: c`Remove`,
99
+ className: "is-danger"
100
+ }
101
+ },
102
+ async (v) => {
103
+ v && (await h(a), t.modal.notify("success", { content: p`plugin-store.remove-registry.remove-success` }));
104
+ }
105
+ );
106
+ return;
107
+ }
108
+ t.modal.dialog(
109
+ {
110
+ title: p`plugin-store.remove-registry.title`,
111
+ content: T("div", { class: "theme-ipe-prose" }, [
112
+ T("p", {}, p({ $1: n.length })`plugin-store.remove-registry.confirm-content`),
113
+ T(
114
+ "ul",
115
+ {},
116
+ n.map((v) => T("li", {}, v.id))
117
+ )
118
+ ]),
119
+ buttons: [
120
+ {
121
+ label: p`plugin-store.remove-registry.buttons.remove-only`,
122
+ className: "is-danger is-ghost",
123
+ method: async (v, I) => {
124
+ await h(a), t.modal.notify("success", {
125
+ content: p`plugin-store.remove-registry.remove-success`
126
+ }), I.close();
127
+ }
128
+ },
129
+ {
130
+ label: p`plugin-store.remove-registry.buttons.remove-and-uninstall`,
131
+ className: "is-danger",
132
+ method: async (v, I) => {
133
+ await h(a);
134
+ for (const C of n)
135
+ try {
136
+ await t.store.uninstallAndRemovePreference(C.registry, C.id);
137
+ } catch (V) {
138
+ t.modal.notify("error", {
139
+ content: V instanceof Error ? `Failed to uninstall ${C.id}: ${V.message}` : `Failed to uninstall ${C.id}`
140
+ });
141
+ }
142
+ t.modal.notify("success", {
143
+ content: p({
144
+ $1: n.length
145
+ })`plugin-store.remove-registry.remove-with-plugins-success`
146
+ }), I.close();
147
+ }
148
+ }
149
+ ]
150
+ },
151
+ () => {
152
+ }
153
+ );
154
+ }
155
+ function B(a) {
156
+ const o = a.changes["pluginStore.registries"];
157
+ Array.isArray(o) && $();
158
+ }
159
+ function E() {
160
+ const a = re.PLUGIN_REGISTRY_URL;
161
+ _.value = a, M();
162
+ }
163
+ return q(() => {
164
+ $(), t.on("preferences/changed", B);
165
+ }), (a, o) => (u(), d("div", ne, [
166
+ i("div", ae, [
167
+ i("div", oe, l(f(c)`Registries`), 1),
168
+ i("div", le, [
169
+ Y(i("input", {
170
+ class: "ipeps-input with-icon",
171
+ "onUpdate:modelValue": o[0] || (o[0] = (n) => _.value = n),
172
+ type: "url",
173
+ placeholder: f(c)`Add registry URL` + " (https://...)",
174
+ disabled: k.value
175
+ }, null, 8, ce), [
176
+ [
177
+ J,
178
+ _.value,
179
+ void 0,
180
+ { trim: !0 }
181
+ ]
182
+ ]),
183
+ o[1] || (o[1] = i("div", { class: "ipeps-input-icon" }, "📦", -1))
184
+ ]),
185
+ L(H, {
186
+ onClick: M,
187
+ disabled: k.value || !_.value,
188
+ variant: "primary"
189
+ }, {
190
+ default: D(() => [
191
+ F(l(k.value ? f(c)`Adding...` : f(c)`Add`), 1)
192
+ ]),
193
+ _: 1
194
+ }, 8, ["disabled"])
195
+ ]),
196
+ y.value.length ? (u(), d("div", de, [
197
+ (u(!0), d(Q, null, W(y.value, (n) => (u(), d("div", {
198
+ class: "ipeps-item",
199
+ key: n.registryUrl
200
+ }, [
201
+ i("div", ue, [
202
+ i("div", ge, l(n.label), 1),
203
+ i("div", pe, [
204
+ i("div", ye, [
205
+ n.homepage ? (u(), d("a", {
206
+ key: 0,
207
+ href: n.homepage,
208
+ target: "_blank"
209
+ }, l(n.homepage), 9, ve)) : A("", !0)
210
+ ]),
211
+ i("div", fe, l(n.registryUrl), 1)
212
+ ]),
213
+ i("div", me, l(n.packages.length) + " packages", 1)
214
+ ]),
215
+ i("div", _e, [
216
+ L(H, {
217
+ onClick: (v) => N(n.registryUrl),
218
+ variant: "danger"
219
+ }, {
220
+ default: D(() => [
221
+ F(l(f(c)`Remove`), 1)
222
+ ]),
223
+ _: 1
224
+ }, 8, ["onClick"])
225
+ ])
226
+ ]))), 128))
227
+ ])) : (u(), d("div", he, [
228
+ o[2] || (o[2] = i("div", { class: "icon" }, "🗂️", -1)),
229
+ i("div", ke, l(f(c)`No registries configured`), 1),
230
+ i("div", be, [
231
+ L(H, {
232
+ onClick: E,
233
+ variant: "primary",
234
+ style: { padding: "0.25rem 0.5rem" }
235
+ }, {
236
+ default: D(() => [
237
+ F(l(f(c)`Setup default registry`), 1)
238
+ ]),
239
+ _: 1
240
+ })
241
+ ])
242
+ ]))
243
+ ]));
244
+ }
245
+ }), Re = /* @__PURE__ */ O($e, [["__scopeId", "data-v-971ee6d5"]]), we = { id: "ipe-plugin-install-manager" }, Se = { class: "ipeps-header" }, Ue = { class: "ipeps-header-title" }, Ce = { class: "ipeps-input-wrapper" }, Pe = ["disabled"], Le = ["disabled"], Be = {
246
+ key: 0,
247
+ class: "ipeps-loading"
248
+ }, Ie = { class: "loading-text" }, Ae = {
249
+ key: 1,
250
+ class: "ipeps-list"
251
+ }, xe = { class: "plugin-info" }, Me = { class: "plugin-header" }, Ne = { class: "item-name" }, Ee = { class: "ipeps-tags" }, Ve = ["href", "title"], Te = ["title"], De = { class: "plugin-meta" }, Fe = {
252
+ key: 0,
253
+ class: "version"
254
+ }, He = {
255
+ key: 1,
256
+ class: "author"
257
+ }, Ke = {
258
+ key: 2,
259
+ class: "license"
260
+ }, Oe = {
261
+ key: 2,
262
+ class: "ipeps-empty"
263
+ }, je = { class: "plugin-empty-text" }, ze = /* @__PURE__ */ K({
264
+ __name: "PluginInstallManager",
265
+ setup(x) {
266
+ const t = G(), c = t.$, p = t.$$, y = w([]), _ = w([]), k = w(""), b = w(!1), $ = (s, r) => `${s}
267
+ ${r}`, M = P(
268
+ () => new Set(_.value.map((s) => $(s.registry, s.id)))
269
+ ), h = (s) => M.value.has(s), N = (s) => {
270
+ try {
271
+ return new URL(s).hostname;
272
+ } catch {
273
+ return s;
274
+ }
275
+ }, B = w(!1), E = P(() => y.value.length > 0), a = P(
276
+ () => y.value.flatMap(
277
+ (s) => (s.packages || []).map((r) => ({
278
+ ...r,
279
+ _key: $(s.registryUrl, r.id),
280
+ registry: s.registryUrl,
281
+ registryHomepage: s.homepage,
282
+ registryLabel: N(s.registryUrl),
283
+ isBroken: !1,
284
+ isRegistryMissing: !1
285
+ }))
286
+ )
287
+ ), o = P(() => {
288
+ const s = k.value.trim().toLowerCase(), r = a.value, e = new Set(r.map((g) => g._key)), R = new Set(y.value.map((g) => g.registryUrl)), S = _.value.filter((g) => !e.has($(g.registry, g.id))).map((g) => {
289
+ const m = y.value.find((se) => se.registryUrl === g.registry);
290
+ return {
291
+ id: g.id,
292
+ name: void 0,
293
+ description: void 0,
294
+ version: void 0,
295
+ author: void 0,
296
+ license: void 0,
297
+ _key: $(g.registry, g.id),
298
+ registry: g.registry,
299
+ registryHomepage: m?.homepage,
300
+ registryLabel: N(g.registry),
301
+ isBroken: !0,
302
+ isRegistryMissing: !R.has(g.registry)
303
+ };
304
+ }), z = (g) => s ? g.filter(
305
+ (m) => m.name && m.name.toLowerCase().includes(s) || m.id && m.id.toLowerCase().includes(s) || m.description && m.description.toLowerCase().includes(s) || m.author && m.author.toLowerCase().includes(s) || m.registry && m.registry.toLowerCase().includes(s)
306
+ ) : g;
307
+ return [...z(S), ...z(r)];
308
+ }), n = P(() => o.value), v = (s) => s.description ? s.description : s.isBroken ? s.isRegistryMissing ? p`plugin-store.broken.registry-unavailable` : p`plugin-store.broken.plugin-removed` : "", I = async (s, r) => {
309
+ t.store.installAndSetPreference(s, r);
310
+ }, C = async (s, r) => {
311
+ t.store.uninstallAndRemovePreference(s, r);
312
+ }, V = (s, r) => h($(s, r)) ? C(s, r) : I(s, r), X = (s) => V(s.registry, s.id), Z = async () => {
313
+ if (b.value) return;
314
+ if (y.value.length === 0) {
315
+ t.modal.notify("info", {
316
+ content: "No registry configured. Please add a registry first."
317
+ });
318
+ return;
319
+ }
320
+ b.value = !0;
321
+ const s = await t.store.refreshAllRegistryCaches(), r = Object.entries(s).filter(([R, S]) => S !== null);
322
+ y.value = r.map(([R, S]) => ({
323
+ ...S,
324
+ registryUrl: R
325
+ }));
326
+ const e = Object.entries(s).filter(([R, S]) => S === null).map(([R]) => R);
327
+ b.value = !1, r.length === 0 ? t.modal.notify("error", {
328
+ content: "All registries failed to refresh"
329
+ }) : (t.modal.notify("success", {
330
+ content: `${r.length} ${r.length === 1 ? "registry" : "registries"} refreshed successfully.`
331
+ }), e.length > 0 && t.modal.notify("warning", {
332
+ content: `${e.length} ${e.length === 1 ? "registry" : "registries"} failed to refresh:
333
+ ${e.join(`
334
+ `)}`
335
+ }));
336
+ }, j = async () => {
337
+ B.value = !1;
338
+ const s = await t.store.ctx.preferences.get("pluginStore.registries") || [], r = await Promise.allSettled(
339
+ s.map(async (e) => ({
340
+ ...await t.store.getRegistryInfo(e),
341
+ registryUrl: e
342
+ }))
343
+ );
344
+ y.value = r.filter((e) => e.status === "fulfilled").map((e) => e.value), _.value = await t.preferences.get("pluginStore.plugins") || [], B.value = !0;
345
+ };
346
+ function ee(s) {
347
+ const r = s.changes["pluginStore.registries"], e = s.changes["pluginStore.plugins"];
348
+ Array.isArray(e) && (_.value = e), Array.isArray(r) && j();
349
+ }
350
+ return q(() => {
351
+ j(), t.on("preferences/changed", ee);
352
+ }), ie(() => {
353
+ }), (s, r) => (u(), d("div", we, [
354
+ i("div", Se, [
355
+ i("div", Ue, l(f(c)`Plugins`), 1),
356
+ i("div", Ce, [
357
+ Y(i("input", {
358
+ class: "ipeps-input with-icon",
359
+ "onUpdate:modelValue": r[0] || (r[0] = (e) => k.value = e),
360
+ type: "text",
361
+ placeholder: "{{ $`Search plugins...` }}",
362
+ disabled: !a.value.length
363
+ }, null, 8, Pe), [
364
+ [
365
+ J,
366
+ k.value,
367
+ void 0,
368
+ { trim: !0 }
369
+ ]
370
+ ]),
371
+ r[1] || (r[1] = i("div", { class: "ipeps-input-icon" }, "🔍", -1))
372
+ ]),
373
+ i("button", {
374
+ class: U(["ipeps-button", { refreshing: b.value }]),
375
+ onClick: Z,
376
+ disabled: b.value || !E.value,
377
+ variant: "primary"
378
+ }, l(b.value ? f(c)`Refreshing...` : f(c)`Refresh`), 11, Le)
379
+ ]),
380
+ !E.value && !B.value ? (u(), d("div", Be, [
381
+ r[2] || (r[2] = i("div", { class: "loading-spinner" }, null, -1)),
382
+ i("div", Ie, l(f(c)`Loading...`), 1)
383
+ ])) : n.value.length ? (u(), d("div", Ae, [
384
+ (u(!0), d(Q, null, W(n.value, (e) => (u(), d("div", {
385
+ class: U(["ipeps-item", { installed: h(e._key), broken: e.isBroken }]),
386
+ key: e._key
387
+ }, [
388
+ i("div", xe, [
389
+ i("div", Me, [
390
+ i("div", Ne, l(e.name || e.id), 1),
391
+ h(e._key) || e.isBroken ? (u(), d("span", {
392
+ key: 0,
393
+ class: U(["ipeps-badge", { "is-installed": h(e._key), "is-broken": e.isBroken }])
394
+ }, l(e.isBroken ? f(p)`plugin-store.tags.broken` : f(p)`plugin-store.tags.installed`), 3)) : A("", !0)
395
+ ]),
396
+ i("div", Ee, [
397
+ e.registryHomepage && !e.isRegistryMissing ? (u(), d("a", {
398
+ key: 0,
399
+ class: "ipeps-tag registry-tag",
400
+ href: e.registryHomepage,
401
+ target: "_blank",
402
+ title: e.registryLabel
403
+ }, l(e.registryLabel), 9, Ve)) : (u(), d("span", {
404
+ key: 1,
405
+ class: U(["ipeps-tag registry-tag", { broken: e.isRegistryMissing }]),
406
+ title: e.registryLabel
407
+ }, l(e.registryLabel), 11, Te)),
408
+ i("div", {
409
+ class: U(["plugin-id ipeps-tag", { broken: e.isBroken && !e.isRegistryMissing }])
410
+ }, l(e.id), 3)
411
+ ]),
412
+ i("div", {
413
+ class: U(["plugin-desc", { "broken-desc": e.isBroken }])
414
+ }, l(v(e)), 3),
415
+ i("div", De, [
416
+ e.version ? (u(), d("span", Fe, "v" + l(e.version), 1)) : A("", !0),
417
+ e.author ? (u(), d("span", He, "👤 " + l(e.author), 1)) : A("", !0),
418
+ e.license ? (u(), d("span", Ke, "📜 " + l(e.license), 1)) : A("", !0)
419
+ ])
420
+ ]),
421
+ L(H, {
422
+ active: h(e._key),
423
+ variant: h(e._key) ? "danger" : "primary",
424
+ onClick: (R) => X(e)
425
+ }, {
426
+ default: D(() => [
427
+ F(l(h(e._key) ? f(c)`Remove` : f(c)`Install`), 1)
428
+ ]),
429
+ _: 2
430
+ }, 1032, ["active", "variant", "onClick"])
431
+ ], 2))), 128))
432
+ ])) : (u(), d("div", Oe, [
433
+ r[3] || (r[3] = i("div", { class: "plugin-empty-icon" }, "📦", -1)),
434
+ i("div", je, l(f(c)`No matching plugins found`), 1)
435
+ ]))
436
+ ]));
437
+ }
438
+ }), Ge = /* @__PURE__ */ O(ze, [["__scopeId", "data-v-f11a3331"]]), qe = { id: "ipe-plugin-store-app" }, Ye = /* @__PURE__ */ K({
439
+ __name: "PluginStoreApp",
440
+ setup(x) {
441
+ return (t, c) => (u(), d("div", qe, [
442
+ L(Ge),
443
+ c[0] || (c[0] = i("div", { class: "divider-wrapper" }, [
444
+ i("hr", { class: "divider" })
445
+ ], -1)),
446
+ L(Re)
447
+ ]));
448
+ }
449
+ }), Ze = /* @__PURE__ */ O(Ye, [["__scopeId", "data-v-1b3d0d80"]]);
450
+ export {
451
+ Ze as default
452
+ };
453
+ //# sourceMappingURL=PluginStoreApp-CGNxKXAN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PluginStoreApp-CGNxKXAN.js","sources":["../src/plugins/plugin-store/components/ui/UIBaseButton.vue","../src/plugins/plugin-store/components/RegistryManager.vue","../src/plugins/plugin-store/components/PluginInstallManager.vue"],"sourcesContent":["<template lang=\"pug\">\nbutton.ipeps-button(:class='buttonClass')\n slot\n</template>\n\n<script setup lang=\"ts\" vapor>\nimport { computed } from 'vue'\n\nconst props = withDefaults(\n defineProps<{\n variant?: 'neutral' | 'primary' | 'danger' | 'ghost' | 'accent'\n active?: boolean\n }>(),\n {\n variant: 'neutral',\n active: false,\n }\n)\n\nconst buttonClass = computed(() => ({\n 'is-active': props.active,\n 'is-danger': props.variant === 'danger',\n 'is-primary': props.variant === 'primary',\n 'is-ghost': props.variant === 'ghost',\n 'is-accent': props.variant === 'accent',\n}))\n</script>\n","<template lang=\"pug\">\n#ipe-registry-manager\n .ipeps-header\n .ipeps-header-title {{ $`Registries` }}\n .ipeps-input-wrapper\n input.ipeps-input.with-icon(\n v-model.trim='inputValue',\n type='url',\n :placeholder='$`Add registry URL` + ` (https://...)`',\n :disabled='isAdding'\n )\n .ipeps-input-icon 📦\n UIBaseButton(@click='onAddRegistry', :disabled='isAdding || !inputValue', variant='primary') {{ isAdding ? $`Adding...` : $`Add` }}\n\n .ipeps-list(v-if='registries.length')\n .ipeps-item(v-for='reg in registries', :key='reg.registryUrl')\n .registry-info\n .item-name {{ reg.label }}\n .item-desc\n .homepage: a(v-if='reg.homepage', :href='reg.homepage', target='_blank') {{ reg.homepage }}\n .url {{ reg.registryUrl }}\n .item-meta {{ reg.packages.length }} packages\n .ipeps-actions\n UIBaseButton(@click='onRemoveRegistry(reg.registryUrl)', variant='danger') {{ $`Remove` }}\n .ipeps-empty(v-else)\n .icon 🗂️\n .text {{ $`No registries configured` }}\n .description\n UIBaseButton(\n @click='onAddOfficialRegistry',\n variant='primary',\n style='padding: 0.25rem 0.5rem'\n ) {{ $`Setup default registry` }}\n</template>\n\n<script setup lang=\"ts\" vapor>\nimport { onMounted, ref } from 'vue'\nimport { h } from 'jsx-dom'\nimport type { PluginStoreRegistry } from '../schema.js'\nimport UIBaseButton from './ui/UIBaseButton.vue'\n\nconst ctx = useIPE()\nconst $ = ctx.$\nconst $$ = ctx.$$\n\ninterface RegistryViewModel extends PluginStoreRegistry {\n registryUrl: string\n label: string\n}\n\nconst registries = ref<RegistryViewModel[]>([])\nconst inputValue = ref('')\nconst isAdding = ref(false)\n\nconst urlToLabel = (u: string) => {\n try {\n return new URL(u).hostname\n } catch {\n return u\n }\n}\n\nasync function loadRegistries() {\n const urls = (await ctx.preferences.get<string[]>('pluginStore.registries')) || []\n const results = await Promise.allSettled(\n urls.map(async (url) => {\n const info = await ctx.store.getRegistryInfo(url)\n return {\n registryUrl: url,\n label: urlToLabel(url),\n ...info,\n } as RegistryViewModel\n })\n )\n registries.value = results\n .filter((r) => r.status === 'fulfilled')\n .map((r) => (r as PromiseFulfilledResult<RegistryViewModel>).value)\n}\n\nasync function onAddRegistry() {\n const url = inputValue.value.trim()\n if (!url) return\n if (registries.value.some((r) => r.registryUrl === url)) {\n ctx.modal.notify('info', { content: 'Registry already exists.' })\n return\n }\n isAdding.value = true\n try {\n // try load immediately\n const info = await ctx.store.getRegistryInfo(url, 'online_manifest', true)\n if (!info) {\n throw new Error('Invalid registry or unreachable')\n }\n const current = (await ctx.preferences.get<string[]>('pluginStore.registries')) || []\n current.push(url)\n await ctx.preferences.set('pluginStore.registries', current)\n registries.value.push({\n registryUrl: url,\n label: urlToLabel(url),\n ...info,\n })\n inputValue.value = ''\n ctx.modal.notify('success', { content: 'Registry added.' })\n } catch (e) {\n ctx.modal.notify('error', {\n content: e instanceof Error ? e.message : String(e),\n })\n } finally {\n isAdding.value = false\n }\n}\n\nasync function removeRegistryUrl(url: string) {\n const current = (await ctx.preferences.get<string[]>('pluginStore.registries')) || []\n const next = current.filter((u) => u !== url)\n await ctx.preferences.set('pluginStore.registries', next)\n registries.value = registries.value.filter((r) => r.registryUrl !== url)\n}\n\nasync function onRemoveRegistry(url: string) {\n const installed =\n (await ctx.preferences.get<{ registry: string; id: string }[]>('pluginStore.plugins')) || []\n const installedOfReg = installed.filter((p) => p.registry === url)\n if (installedOfReg.length === 0) {\n ctx.modal.confirm(\n {\n title: $$`plugin-store.remove-registry.title`,\n content: $$`plugin-store.remove-registry.tip-content` + `\\n${url}`,\n cancelBtn: {\n label: $`Cancel`,\n className: 'is-ghost',\n },\n okBtn: {\n label: $`Remove`,\n className: 'is-danger',\n },\n },\n async (ok) => {\n if (!ok) return\n await removeRegistryUrl(url)\n ctx.modal.notify('success', { content: $$`plugin-store.remove-registry.remove-success` })\n }\n )\n return\n }\n\n ctx.modal.dialog(\n {\n title: $$`plugin-store.remove-registry.title`,\n content: h('div', { class: 'theme-ipe-prose' }, [\n h('p', {}, $$({ $1: installedOfReg.length })`plugin-store.remove-registry.confirm-content`),\n h(\n 'ul',\n {},\n installedOfReg.map((p) => h('li', {}, p.id))\n ),\n ]),\n buttons: [\n {\n label: $$`plugin-store.remove-registry.buttons.remove-only`,\n className: 'is-danger is-ghost',\n method: async (_, m) => {\n await removeRegistryUrl(url)\n ctx.modal.notify('success', {\n content: $$`plugin-store.remove-registry.remove-success`,\n })\n m.close()\n },\n },\n {\n label: $$`plugin-store.remove-registry.buttons.remove-and-uninstall`,\n className: 'is-danger',\n method: async (_, m) => {\n await removeRegistryUrl(url)\n for (const p of installedOfReg) {\n try {\n await ctx.store.uninstallAndRemovePreference(p.registry, p.id)\n } catch (e) {\n // best-effort; notify but continue\n ctx.modal.notify('error', {\n content:\n e instanceof Error\n ? `Failed to uninstall ${p.id}: ${e.message}`\n : `Failed to uninstall ${p.id}`,\n })\n }\n }\n ctx.modal.notify('success', {\n content: $$({\n $1: installedOfReg.length,\n })`plugin-store.remove-registry.remove-with-plugins-success`,\n })\n m.close()\n },\n },\n ],\n },\n () => {}\n )\n}\n\nfunction onPreferencesChanged(payload: { changes: Record<string, unknown> }) {\n const regs = payload.changes['pluginStore.registries'] as string[]\n if (Array.isArray(regs)) {\n loadRegistries()\n }\n}\n\nfunction onAddOfficialRegistry() {\n const url = Endpoints.PLUGIN_REGISTRY_URL\n inputValue.value = url\n onAddRegistry()\n}\n\nonMounted(() => {\n loadRegistries()\n ctx.on('preferences/changed', onPreferencesChanged)\n})\n</script>\n\n<style scoped lang=\"scss\">\n@use './style.scss' as *;\n\n.registry-info {\n flex: 1;\n min-width: 0;\n .homepage {\n margin-top: 0.25rem;\n a {\n color: var(--ipe-modal-accent);\n text-decoration: none;\n font-size: 0.8125rem;\n transition: all 0.2s ease;\n &:hover {\n color: color-mix(in srgb, var(--ipe-modal-accent) 80%, var(--ipe-modal-text));\n text-decoration: underline;\n }\n }\n }\n .url {\n font-family: monospace;\n font-size: 0.75rem;\n color: var(--ipe-modal-muted);\n margin-top: 0.125rem;\n word-break: break-all;\n }\n}\n</style>\n","<template lang=\"pug\">\n#ipe-plugin-install-manager\n .ipeps-header\n .ipeps-header-title {{ $`Plugins` }}\n .ipeps-input-wrapper\n input.ipeps-input.with-icon(\n v-model.trim='searchInput',\n type='text',\n placeholder='{{ $`Search plugins...` }}',\n :disabled='!pluginsFromRegistries.length'\n )\n .ipeps-input-icon 🔍\n button.ipeps-button(\n @click='refreshRegistries',\n :disabled='isRefreshing || !hasRegistries',\n :class='{ refreshing: isRefreshing }',\n variant='primary'\n ) {{ isRefreshing ? $`Refreshing...` : $`Refresh` }}\n\n .ipeps-loading(v-if='!hasRegistries && !firstInit')\n .loading-spinner\n .loading-text {{ $`Loading...` }}\n\n .ipeps-list(v-else-if='allPluginsToDisplay.length')\n .ipeps-item(\n v-for='plugin in allPluginsToDisplay',\n :key='plugin._key',\n :class='{ installed: isInstalledKey(plugin._key), broken: plugin.isBroken }'\n )\n .plugin-info\n .plugin-header\n .item-name {{ plugin.name || plugin.id }}\n span.ipeps-badge(\n v-if='isInstalledKey(plugin._key) || plugin.isBroken',\n :class='{ \"is-installed\": isInstalledKey(plugin._key), \"is-broken\": plugin.isBroken }'\n ) {{ plugin.isBroken ? $$`plugin-store.tags.broken` : $$`plugin-store.tags.installed` }}\n .ipeps-tags\n a.ipeps-tag.registry-tag(\n v-if='plugin.registryHomepage && !plugin.isRegistryMissing',\n :href='plugin.registryHomepage',\n target='_blank',\n :title='plugin.registryLabel'\n ) {{ plugin.registryLabel }}\n span.ipeps-tag.registry-tag(\n v-else,\n :title='plugin.registryLabel',\n :class='{ broken: plugin.isRegistryMissing }'\n ) {{ plugin.registryLabel }}\n .plugin-id.ipeps-tag(:class='{ broken: plugin.isBroken && !plugin.isRegistryMissing }') {{ plugin.id }}\n .plugin-desc(:class='{ \"broken-desc\": plugin.isBroken }') {{ getDesc(plugin) }}\n .plugin-meta\n span.version(v-if='plugin.version') v{{ plugin.version }}\n span.author(v-if='plugin.author') 👤 {{ plugin.author }}\n span.license(v-if='plugin.license') 📜 {{ plugin.license }}\n UIBaseButton(\n :active='isInstalledKey(plugin._key)',\n :variant='isInstalledKey(plugin._key) ? \"danger\" : \"primary\"',\n @click='togglePluginByKey(plugin)'\n ) {{ isInstalledKey(plugin._key) ? $`Remove` : $`Install` }}\n\n .ipeps-empty(v-else)\n .plugin-empty-icon 📦\n .plugin-empty-text {{ $`No matching plugins found` }}\n</template>\n\n<script setup lang=\"ts\" vapor>\nimport { computed, onBeforeUnmount, onMounted, ref } from 'vue'\nimport type { PluginStorePackage, PluginStoreRegistry } from '../schema.js'\nimport UIBaseButton from './ui/UIBaseButton.vue'\n\ninterface RegistryWithUrl extends PluginStoreRegistry {\n registryUrl: string\n}\ninterface PluginIdentifier {\n registry: string\n id: string\n}\n\ninterface PluginViewModel extends PluginStorePackage {\n _key: string\n registry: string\n registryHomepage: string\n registryLabel: string\n isBroken: boolean\n isRegistryMissing: boolean\n}\n\n// --- state ---\nconst ctx = useIPE()\nconst $ = ctx.$\nconst $$ = ctx.$$\nconst registryInfos = ref<RegistryWithUrl[]>([])\nconst installedPlugins = ref<PluginIdentifier[]>([])\nconst searchInput = ref('')\nconst isRefreshing = ref(false)\n\n// helpers\nconst makeKey = (r: string, id: string) => `${r}\\n${id}` // stable + O(1)\n\nconst installedKeySet = computed(\n () => new Set(installedPlugins.value.map((p) => makeKey(p.registry, p.id)))\n)\nconst isInstalledKey = (key: string) => installedKeySet.value.has(key)\n\nconst urlToLabel = (registryUrl: string) => {\n try {\n return new URL(registryUrl).hostname\n } catch {\n return registryUrl\n }\n}\n\nconst firstInit = ref(false)\nconst hasRegistries = computed(() => registryInfos.value.length > 0)\n\nconst pluginsFromRegistries = computed<PluginViewModel[]>(\n () =>\n registryInfos.value.flatMap((reg) =>\n (reg.packages || []).map((pkg) => ({\n ...pkg,\n _key: makeKey(reg.registryUrl, pkg.id),\n registry: reg.registryUrl,\n registryHomepage: reg.homepage,\n registryLabel: urlToLabel(reg.registryUrl),\n isBroken: false,\n isRegistryMissing: false,\n }))\n ) as PluginViewModel[]\n)\n\n// merge normal + broken, and normalize once here\nconst normalizedPlugins = computed(() => {\n const q = searchInput.value.trim().toLowerCase()\n\n const all: Array<any> = pluginsFromRegistries.value\n\n // broken installed plugins (installed but not available now)\n const availableKeys = new Set(all.map((p) => p._key))\n const availableRegs = new Set(registryInfos.value.map((r) => r.registryUrl))\n\n const broken = installedPlugins.value\n .filter((p) => !availableKeys.has(makeKey(p.registry, p.id)))\n .map((p) => {\n const regInfo = registryInfos.value.find((r) => r.registryUrl === p.registry)\n return {\n id: p.id,\n name: undefined,\n description: undefined,\n version: undefined,\n author: undefined,\n license: undefined,\n _key: makeKey(p.registry, p.id),\n registry: p.registry,\n registryHomepage: regInfo?.homepage,\n registryLabel: urlToLabel(p.registry),\n isBroken: true,\n isRegistryMissing: !availableRegs.has(p.registry),\n }\n })\n\n const filtered = (list: any[]) => {\n if (!q) return list\n return list.filter(\n (p) =>\n (p.name && p.name.toLowerCase().includes(q)) ||\n (p.id && p.id.toLowerCase().includes(q)) ||\n (p.description && p.description.toLowerCase().includes(q)) ||\n (p.author && p.author.toLowerCase().includes(q)) ||\n (p.registry && p.registry.toLowerCase().includes(q))\n )\n }\n\n // broken on top\n return [...filtered(broken), ...filtered(all)]\n})\n\nconst allPluginsToDisplay = computed(() => normalizedPlugins.value)\n\nconst getDesc = (p: any) => {\n if (p.description) return p.description\n if (!p.isBroken) return ''\n return p.isRegistryMissing\n ? $$`plugin-store.broken.registry-unavailable`\n : $$`plugin-store.broken.plugin-removed`\n}\n\n// actions\nconst enablePlugin = async (registry: string, id: string) => {\n ctx.store.installAndSetPreference(registry, id)\n}\nconst disablePlugin = async (registry: string, id: string) => {\n ctx.store.uninstallAndRemovePreference(registry, id)\n}\nconst togglePlugin = (registry: string, id: string) =>\n isInstalledKey(makeKey(registry, id)) ? disablePlugin(registry, id) : enablePlugin(registry, id)\nconst togglePluginByKey = (p: any) => togglePlugin(p.registry, p.id)\n\nconst refreshRegistries = async () => {\n if (isRefreshing.value) return\n if (registryInfos.value.length === 0) {\n ctx.modal.notify('info', {\n content: 'No registry configured. Please add a registry first.',\n })\n return\n }\n\n isRefreshing.value = true\n const results = await ctx.store.refreshAllRegistryCaches()\n const okResults = Object.entries(results).filter(([_, r]) => r !== null)\n registryInfos.value = okResults.map(([url, r]) => ({\n ...r!,\n registryUrl: url,\n }))\n const failedUrls = Object.entries(results)\n .filter(([_, r]) => r === null)\n .map(([url]) => url)\n isRefreshing.value = false\n\n if (okResults.length === 0) {\n ctx.modal.notify('error', {\n content: 'All registries failed to refresh',\n })\n } else {\n ctx.modal.notify('success', {\n content: `${okResults.length} ${okResults.length === 1 ? 'registry' : 'registries'} refreshed successfully.`,\n })\n if (failedUrls.length > 0) {\n ctx.modal.notify('warning', {\n content: `${failedUrls.length} ${failedUrls.length === 1 ? 'registry' : 'registries'} failed to refresh:\\n${failedUrls.join('\\n')}`,\n })\n }\n }\n}\n\n// init\nconst init = async () => {\n firstInit.value = false\n const urls = (await ctx.store.ctx.preferences.get('pluginStore.registries')) || []\n const regResults = await Promise.allSettled(\n urls.map(async (url: string) => ({\n ...(await ctx.store.getRegistryInfo(url)),\n registryUrl: url,\n }))\n )\n registryInfos.value = regResults\n .filter((r) => r.status === 'fulfilled')\n .map((r) => (r as PromiseFulfilledResult<RegistryWithUrl>).value)\n\n installedPlugins.value = (await ctx.preferences.get('pluginStore.plugins')) || []\n\n firstInit.value = true\n}\n\nfunction onPreferencesChanged(payload: { changes: Record<string, unknown> }) {\n const regs = payload.changes['pluginStore.registries'] as string[]\n const plugins = payload.changes['pluginStore.plugins'] as PluginIdentifier[]\n if (Array.isArray(plugins)) installedPlugins.value = plugins\n if (Array.isArray(regs)) {\n init()\n }\n}\n\nonMounted(() => {\n init()\n ctx.on('preferences/changed', onPreferencesChanged)\n})\nonBeforeUnmount(() => {})\n</script>\n\n<style scoped lang=\"scss\">\n@use './style.scss' as *;\n\n.plugin-info {\n flex: 1;\n min-width: 0;\n}\n.plugin-header {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n margin-bottom: 0.375rem;\n}\n.registry-tag {\n color: var(--ipe-modal-accent);\n background: color-mix(in srgb, var(--ipe-modal-accent) 8%, transparent);\n border: 1px solid color-mix(in srgb, var(--ipe-modal-accent) 18%, transparent);\n text-decoration: none;\n transition: all 0.2s ease;\n &:hover {\n background: color-mix(in srgb, var(--ipe-modal-accent) 12%, transparent);\n border-color: color-mix(in srgb, var(--ipe-modal-accent) 30%, transparent);\n }\n &.broken {\n text-decoration: line-through;\n opacity: 0.65;\n cursor: not-allowed;\n }\n}\n.plugin-id {\n &.broken {\n opacity: 0.65;\n text-decoration: line-through;\n }\n}\n.plugin-desc {\n font-size: 0.8125rem;\n color: var(--ipe-modal-muted);\n margin-bottom: 0.5rem;\n line-height: 1.6;\n &.broken-desc {\n color: color-mix(in srgb, var(--ipe-modal-warning) 80%, var(--ipe-modal-text));\n font-style: italic;\n }\n}\n.plugin-meta {\n font-size: 0.75rem;\n color: var(--ipe-modal-muted);\n display: flex;\n gap: 1rem;\n align-items: center;\n .version {\n font-family: monospace;\n font-weight: 500;\n color: color-mix(in srgb, var(--ipe-modal-text) 80%, var(--ipe-modal-muted));\n }\n .author {\n display: flex;\n align-items: center;\n gap: 0.25rem;\n }\n .license {\n display: flex;\n align-items: center;\n gap: 0.25rem;\n }\n}\n</style>\n"],"names":["props","__props","buttonClass","computed","ctx","useIPE","$","$$","registries","ref","inputValue","isAdding","urlToLabel","u","loadRegistries","urls","results","url","info","r","onAddRegistry","current","e","removeRegistryUrl","next","onRemoveRegistry","installedOfReg","p","ok","h","_","m","onPreferencesChanged","payload","regs","onAddOfficialRegistry","Endpoints","onMounted","registryInfos","installedPlugins","searchInput","isRefreshing","makeKey","id","installedKeySet","isInstalledKey","key","registryUrl","firstInit","hasRegistries","pluginsFromRegistries","reg","pkg","normalizedPlugins","q","all","availableKeys","availableRegs","broken","regInfo","filtered","list","allPluginsToDisplay","getDesc","enablePlugin","registry","disablePlugin","togglePlugin","togglePluginByKey","refreshRegistries","okResults","failedUrls","init","regResults","plugins","onBeforeUnmount"],"mappings":"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"}