use toastFrontend for error msgs in plugins

Alessandro committed Mar 11, 2026 at 13:01 UTC a9722e70fd62591800e5ca8bdf0fc4cc373bf3e3
6 files changed +12 -96
plugins/_plugin_installer/webui/install-detail.html
-19
@@ -148,10 +148,6 @@
148 </template>
149 </div>
150
151 - <div x-show="$store.pluginInstallStore.error" class="pi-message pi-message-error">
152 - <span x-text="$store.pluginInstallStore.error"></span>
153 - </div>
154 -
151 <div class="pi-readme-section" x-show="$store.pluginInstallStore.readmeContent || $store.pluginInstallStore.readmeLoading">
152 <div class="pi-readme-header">Readme</div>
153 <div x-show="$store.pluginInstallStore.readmeLoading" class="pi-loading-text">
@@ -466,21 +462,6 @@
462 padding: 0.75rem 0;
463 }
464
469 - .pi-message {
470 - display: flex;
471 - align-items: center;
472 - gap: 0.75rem;
473 - padding: 1rem;
474 - border-radius: 8px;
475 - margin-bottom: 1rem;
476 - }
477 -
478 - .pi-message-error {
479 - background: rgba(239,68,68,0.1);
480 - border: 1px solid rgba(239,68,68,0.3);
481 - color: var(--color-error);
482 - }
483 -
465 .pi-screenshots-section {
466 margin: var(--spacing-lg) 0;
467 padding-top: var(--spacing-lg);
plugins/_plugin_installer/webui/install-git.html
-12
@@ -45,10 +45,6 @@
45 </button>
46 </div>
47
48 - <div x-show="$store.pluginInstallStore.error" class="pi-error">
49 - <span x-text="$store.pluginInstallStore.error"></span>
50 - </div>
51 -
48 <div x-show="$store.pluginInstallStore.result" class="pi-result">
49 <div class="pi-result-icon">
50 <span class="material-symbols-outlined">check_circle</span>
@@ -109,14 +105,6 @@
105 gap: 0.5rem;
106 }
107
112 - .pi-error {
113 - color: var(--color-error);
114 - padding: 0.75rem;
115 - background: var(--color-error-bg, rgba(239,68,68,0.1));
116 - border-radius: 4px;
117 - margin-top: 0.75rem;
118 - }
119 -
108 .pi-result {
109 display: flex;
110 align-items: center;
plugins/_plugin_installer/webui/install-index.html
-14
@@ -62,14 +62,6 @@
62 </div>
63 </div>
64
65 - <div x-show="$store.pluginInstallStore.error && !$store.pluginInstallStore.loading" class="pi-state-card pi-state-error">
66 - <span class="material-symbols-outlined">error</span>
67 - <div>
68 - <div class="pi-state-title">Marketplace unavailable</div>
69 - <div class="pi-state-text" x-text="$store.pluginInstallStore.error"></div>
70 - </div>
71 - </div>
72 -
65 <div x-show="$store.pluginInstallStore.index && !$store.pluginInstallStore.loading && $store.pluginInstallStore.filteredPlugins.length > 0"
66 class="pi-grid">
67 <template x-for="plugin in $store.pluginInstallStore.paginatedPlugins" :key="plugin.key">
@@ -343,12 +335,6 @@
335 color: var(--color-highlight);
336 }
337
346 - .pi-state-error {
347 - border-color: rgba(239, 68, 68, 0.28);
348 - background: rgba(239, 68, 68, 0.1);
349 - color: var(--color-error);
350 - }
351 -
338 .pi-state-empty .material-symbols-outlined {
339 color: var(--color-text-muted);
340 }
plugins/_plugin_installer/webui/install-zip.html
-12
@@ -35,10 +35,6 @@
35 <span x-text="$store.pluginInstallStore.loadingMessage || 'Processing...'"></span>
36 </div>
37
38 - <div x-show="$store.pluginInstallStore.error" class="pi-error">
39 - <span x-text="$store.pluginInstallStore.error"></span>
40 - </div>
41 -
38 <div x-show="$store.pluginInstallStore.result" class="pi-result">
39 <div class="pi-result-icon">
40 <span class="material-symbols-outlined">check_circle</span>
@@ -94,14 +90,6 @@
90 color: var(--color-text-secondary);
91 }
92
97 - .pi-error {
98 - color: var(--color-error);
99 - padding: 0.75rem;
100 - background: var(--color-error-bg, rgba(239,68,68,0.1));
101 - border-radius: 4px;
102 - margin-top: 0.75rem;
103 - }
104 -
93 .pi-result {
94 display: flex;
95 align-items: center;
plugins/_plugin_installer/webui/main.html
-15
@@ -421,13 +421,6 @@
421 color: var(--color-highlight);
422 }
423
424 - .pi-state-error {
425 - border-color: rgba(239, 68, 68, 0.28);
426 - background: rgba(239, 68, 68, 0.1);
427 - color: var(--color-error);
428 - margin-top: 0;
429 - }
430 -
424 .pi-state-empty .material-symbols-outlined {
425 color: var(--color-text-muted);
426 }
@@ -541,14 +534,6 @@
534 color: var(--color-text-secondary);
535 }
536
544 - .pi-error {
545 - color: var(--color-error);
546 - padding: 0.75rem;
547 - background: var(--color-error-bg, rgba(239, 68, 68, 0.1));
548 - border-radius: 4px;
549 - margin-top: 0.75rem;
550 - }
551 -
537 .pi-empty {
538 text-align: center;
539 padding: 2rem;
plugins/_plugin_installer/webui/pluginInstallStore.js
+12 -24
@@ -2,7 +2,7 @@ import { createStore } from "/js/AlpineStore.js";
2 import * as api from "/js/api.js";
3 import { openModal } from "/js/modals.js";
4 import { marked } from "/vendor/marked/marked.esm.js";
5 -import { toastFrontendSuccess } from "/components/notifications/notification-store.js";
5 +import { toastFrontendSuccess, toastFrontendError } from "/components/notifications/notification-store.js";
6 import { showConfirmDialog } from "/js/confirmDialog.js";
7 import { store as imageViewerStore } from "/components/modals/image-viewer/image-viewer-store.js";
8 import { store as pluginListStore } from "/components/plugins/list/pluginListStore.js";
@@ -48,7 +48,6 @@ const model = {
48 // Shared state
49 loading: false,
50 loadingMessage: "",
51 - error: "",
51 result: null,
52
53 // README state
@@ -65,7 +64,6 @@ const model = {
64
65 setTab(tab) {
66 this.activeTab = tab;
68 - this.error = "";
67 this.result = null;
68 },
69
@@ -113,13 +111,12 @@ const model = {
111 if (!file) return;
112 this.zipFile = file;
113 this.zipFileName = file.name;
116 - this.error = "";
114 this.result = null;
115 },
116
117 async installZip() {
118 if (!this.zipFile) {
122 - this.error = "Please select a ZIP file first";
119 + void toastFrontendError("Please select a ZIP file first", "Plugin Installer");
120 return;
121 }
122
@@ -129,7 +126,6 @@ const model = {
126 try {
127 this.loading = true;
128 this.loadingMessage = "Installing plugin from ZIP...";
132 - this.error = "";
129 this.result = null;
130
131 const formData = new FormData();
@@ -143,7 +139,7 @@ const model = {
139
140 const data = await response.json();
141 if (!data.success) {
146 - this.error = data.error || "Installation failed";
142 + void toastFrontendError(data.error || "Installation failed", "Plugin Installer");
143 return;
144 }
145
@@ -155,7 +151,7 @@ const model = {
151 );
152 } catch (e) {
153 const message = e instanceof Error ? e.message : String(e);
158 - this.error = `Installation error: ${message}`;
154 + void toastFrontendError(`Installation error: ${message}`, "Plugin Installer");
155 } finally {
156 this.loading = false;
157 this.loadingMessage = "";
@@ -167,7 +163,7 @@ const model = {
163 async installGit() {
164 const url = (this.gitUrl || "").trim();
165 if (!url) {
170 - this.error = "Please enter a Git URL";
166 + void toastFrontendError("Please enter a Git URL", "Plugin Installer");
167 return;
168 }
169
@@ -177,7 +173,6 @@ const model = {
173 try {
174 this.loading = true;
175 this.loadingMessage = "Cloning repository...";
180 - this.error = "";
176 this.result = null;
177
178 const data = await api.callJsonApi(PLUGIN_API, {
@@ -187,7 +182,7 @@ const model = {
182 });
183
184 if (!data.success) {
190 - this.error = data.error || "Clone failed";
185 + void toastFrontendError(data.error || "Clone failed", "Plugin Installer");
186 return;
187 }
188
@@ -199,7 +194,7 @@ const model = {
194 );
195 } catch (e) {
196 const message = e instanceof Error ? e.message : String(e);
202 - this.error = `Clone error: ${message}`;
197 + void toastFrontendError(`Clone error: ${message}`, "Plugin Installer");
198 } finally {
199 this.loading = false;
200 this.loadingMessage = "";
@@ -212,15 +207,13 @@ const model = {
207 try {
208 this.loading = true;
209 this.loadingMessage = "Loading plugin index...";
215 - this.error = "";
216 - // this.index = null;
210
211 const data = await api.callJsonApi(PLUGIN_API, {
212 action: "fetch_index",
213 });
214
215 if (!data.success) {
223 - this.error = data.error || "Failed to load index";
216 + void toastFrontendError(data.error || "Failed to load index", "Plugin Installer");
217 return;
218 }
219
@@ -229,7 +222,7 @@ const model = {
222 this.page = 1;
223 } catch (e) {
224 const message = e instanceof Error ? e.message : String(e);
232 - this.error = `Failed to load plugin index: ${message}`;
225 + void toastFrontendError(`Failed to load plugin index: ${message}`, "Plugin Installer");
226 } finally {
227 this.loading = false;
228 this.loadingMessage = "";
@@ -343,7 +336,6 @@ const model = {
336
337 openDetail(plugin) {
338 this.selectedPlugin = { ...plugin, name: plugin?.key || "" };
346 - this.error = "";
339 this.result = null;
340 this.installedPluginInfo = null;
341 this.readmeContent = null;
@@ -387,7 +379,7 @@ const model = {
379
380 async installFromIndex(plugin) {
381 if (!plugin?.github) {
390 - this.error = "No GitHub URL available for this plugin";
382 + void toastFrontendError("No GitHub URL available for this plugin", "Plugin Installer");
383 return;
384 }
385
@@ -406,7 +398,6 @@ const model = {
398 try {
399 this.loading = true;
400 this.loadingMessage = `Installing ${plugin.title || plugin.key}...`;
409 - this.error = "";
401
402 const data = await api.callJsonApi(PLUGIN_API, {
403 action: "install_git",
@@ -415,7 +406,7 @@ const model = {
406 });
407
408 if (!data.success) {
418 - this.error = data.error || "Installation failed";
409 + void toastFrontendError(data.error || "Installation failed", "Plugin Installer");
410 return;
411 }
412
@@ -438,7 +429,7 @@ const model = {
429 );
430 } catch (e) {
431 const message = e instanceof Error ? e.message : String(e);
441 - this.error = `Installation error: ${message}`;
432 + void toastFrontendError(`Installation error: ${message}`, "Plugin Installer");
433 } finally {
434 this.loading = false;
435 this.loadingMessage = "";
@@ -533,14 +524,12 @@ const model = {
524 resetZip() {
525 this.zipFile = null;
526 this.zipFileName = "";
536 - this.error = "";
527 this.result = null;
528 },
529
530 resetGit() {
531 this.gitUrl = "";
532 this.gitToken = "";
543 - this.error = "";
533 this.result = null;
534 },
535
@@ -549,7 +538,6 @@ const model = {
538 this.page = 1;
539 this.sortBy = "stars";
540 this.browseFilter = "all";
552 - this.error = "";
541 this.result = null;
542 this.selectedPlugin = null;
543 },