Feature: Testen-Button neben der Webhook-URL

Schickt sofort eine Test-Nachricht (inkl. Discord-Ping falls gesetzt) an die
EINGETRAGENEN Entwurfs-Werte — funktioniert also schon vor dem Speichern der
Einstellungen. Toast meldet Erfolg bzw. verweist bei Fehlschlag auf
Hilfe -> Letzte Fehler (dort steht der HTTP-Status/Fehlertext aus notify.ts).
Neuer IPC TEST_NOTIFY (main.ts ruft sendNotification direkt), Button im
input-row-Muster, deaktiviert solange die URL leer ist.
This commit is contained in:
Sucukdeluxe 2026-06-09 23:42:15 +02:00
parent b92808a637
commit 25f226db43
5 changed files with 24 additions and 1 deletions

View File

@ -6,6 +6,7 @@ import { AppController } from "./app-controller";
import { IPC_CHANNELS } from "../shared/ipc";
import { getLogFilePath, logger } from "./logger";
import { getRecentErrors } from "./error-ring";
import { sendNotification } from "./notify";
import { APP_NAME } from "./constants";
import { extractHttpLinksFromText } from "./utils";
import { cleanupStaleSubstDrives, shutdownDaemon } from "./extractor";
@ -629,6 +630,15 @@ function registerIpcHandlers(): void {
ipcMain.handle(IPC_CHANNELS.GET_RECENT_ERRORS, async () => getRecentErrors());
ipcMain.handle(IPC_CHANNELS.TEST_NOTIFY, async (_event: IpcMainInvokeEvent, url: string, mention: string) => {
validateString(url, "url");
return sendNotification(url, {
title: "🔔 Test-Benachrichtigung",
message: "Webhook funktioniert — Benachrichtigungen kommen hier an.",
mention: typeof mention === "string" ? mention : ""
});
});
ipcMain.handle(IPC_CHANNELS.GET_TRACE_CONFIG, async () => controller.getTraceConfig());
ipcMain.handle(IPC_CHANNELS.SET_TRACE_ENABLED, async (_event: IpcMainInvokeEvent, enabled: boolean, note?: string, durationMinutes?: number) => {

View File

@ -70,6 +70,7 @@ const api: ElectronApi = {
openItemLog: (itemId: string): Promise<void> => ipcRenderer.invoke(IPC_CHANNELS.OPEN_ITEM_LOG, itemId),
getDebugSetupCheck: () => ipcRenderer.invoke(IPC_CHANNELS.GET_DEBUG_SETUP_CHECK),
getRecentErrors: () => ipcRenderer.invoke(IPC_CHANNELS.GET_RECENT_ERRORS),
testNotification: (url: string, mention: string) => ipcRenderer.invoke(IPC_CHANNELS.TEST_NOTIFY, url, mention),
getTraceConfig: () => ipcRenderer.invoke(IPC_CHANNELS.GET_TRACE_CONFIG),
setTraceEnabled: (enabled: boolean, note?: string, durationMinutes?: number) => ipcRenderer.invoke(IPC_CHANNELS.SET_TRACE_ENABLED, enabled, note, durationMinutes),
rotateDebugToken: (): Promise<{ path: string }> => ipcRenderer.invoke(IPC_CHANNELS.ROTATE_DEBUG_TOKEN),

View File

@ -4958,7 +4958,17 @@ export function App(): ReactElement {
<label className="toggle-line"><input type="checkbox" checked={settingsDraft.confirmDeleteSelection} onChange={(e) => setBool("confirmDeleteSelection", e.target.checked)} /> Vor dem Löschen bestätigen</label>
<label className="toggle-line"><input type="checkbox" checked={settingsDraft.backupIncludeDownloads} onChange={(e) => setBool("backupIncludeDownloads", e.target.checked)} /> Download-Liste in Sicherung mitsichern (Standard: nur Einstellungen)</label>
<label>Webhook-URL (Discord)</label>
<input value={settingsDraft.notifyUrl} placeholder="https://discord.com/api/webhooks/..." onChange={(e) => setText("notifyUrl", e.target.value)} />
<div className="input-row">
<input value={settingsDraft.notifyUrl} placeholder="https://discord.com/api/webhooks/..." onChange={(e) => setText("notifyUrl", e.target.value)} />
<button className="btn" disabled={!settingsDraft.notifyUrl.trim()} onClick={() => {
void performQuickAction(async () => {
const ok = await window.rd.testNotification(settingsDraft.notifyUrl, settingsDraft.notifyMention);
showToast(ok ? "Test-Nachricht gesendet — schau in Discord" : "Test fehlgeschlagen — Webhook-URL prüfen (Details unter Hilfe → Letzte Fehler)", 4200);
}, (error) => {
showToast(`Test fehlgeschlagen: ${String(error)}`, 3600);
});
}}>Testen</button>
</div>
<div className="hint">In Discord: Servereinstellungen Integrationen Webhooks Neuer Webhook URL kopieren und hier eintragen. Die gewählten Ereignisse landen als Nachricht im Kanal.</div>
<label>Discord-Ping (optional)</label>
<input value={settingsDraft.notifyMention} placeholder="Deine User-ID, @everyone oder @here" onChange={(e) => setText("notifyMention", e.target.value)} />

View File

@ -48,6 +48,7 @@ export const IPC_CHANNELS = {
OPEN_ITEM_LOG: "app:open-item-log",
GET_DEBUG_SETUP_CHECK: "app:get-debug-setup-check",
GET_RECENT_ERRORS: "app:get-recent-errors",
TEST_NOTIFY: "app:test-notify",
GET_TRACE_CONFIG: "app:get-trace-config",
SET_TRACE_ENABLED: "app:set-trace-enabled",
ROTATE_DEBUG_TOKEN: "app:rotate-debug-token",

View File

@ -67,6 +67,7 @@ export interface ElectronApi {
openItemLog: (itemId: string) => Promise<void>;
getDebugSetupCheck: () => Promise<DebugSetupCheckResult>;
getRecentErrors: () => Promise<Array<{ ts: string; level: string; message: string }>>;
testNotification: (url: string, mention: string) => Promise<boolean>;
getTraceConfig: () => Promise<SupportTraceConfig>;
setTraceEnabled: (enabled: boolean, note?: string, durationMinutes?: number) => Promise<SupportTraceConfig>;
rotateDebugToken: () => Promise<{ path: string }>;