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:
parent
b92808a637
commit
25f226db43
@ -6,6 +6,7 @@ import { AppController } from "./app-controller";
|
|||||||
import { IPC_CHANNELS } from "../shared/ipc";
|
import { IPC_CHANNELS } from "../shared/ipc";
|
||||||
import { getLogFilePath, logger } from "./logger";
|
import { getLogFilePath, logger } from "./logger";
|
||||||
import { getRecentErrors } from "./error-ring";
|
import { getRecentErrors } from "./error-ring";
|
||||||
|
import { sendNotification } from "./notify";
|
||||||
import { APP_NAME } from "./constants";
|
import { APP_NAME } from "./constants";
|
||||||
import { extractHttpLinksFromText } from "./utils";
|
import { extractHttpLinksFromText } from "./utils";
|
||||||
import { cleanupStaleSubstDrives, shutdownDaemon } from "./extractor";
|
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.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.GET_TRACE_CONFIG, async () => controller.getTraceConfig());
|
||||||
|
|
||||||
ipcMain.handle(IPC_CHANNELS.SET_TRACE_ENABLED, async (_event: IpcMainInvokeEvent, enabled: boolean, note?: string, durationMinutes?: number) => {
|
ipcMain.handle(IPC_CHANNELS.SET_TRACE_ENABLED, async (_event: IpcMainInvokeEvent, enabled: boolean, note?: string, durationMinutes?: number) => {
|
||||||
|
|||||||
@ -70,6 +70,7 @@ const api: ElectronApi = {
|
|||||||
openItemLog: (itemId: string): Promise<void> => ipcRenderer.invoke(IPC_CHANNELS.OPEN_ITEM_LOG, itemId),
|
openItemLog: (itemId: string): Promise<void> => ipcRenderer.invoke(IPC_CHANNELS.OPEN_ITEM_LOG, itemId),
|
||||||
getDebugSetupCheck: () => ipcRenderer.invoke(IPC_CHANNELS.GET_DEBUG_SETUP_CHECK),
|
getDebugSetupCheck: () => ipcRenderer.invoke(IPC_CHANNELS.GET_DEBUG_SETUP_CHECK),
|
||||||
getRecentErrors: () => ipcRenderer.invoke(IPC_CHANNELS.GET_RECENT_ERRORS),
|
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),
|
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),
|
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),
|
rotateDebugToken: (): Promise<{ path: string }> => ipcRenderer.invoke(IPC_CHANNELS.ROTATE_DEBUG_TOKEN),
|
||||||
|
|||||||
@ -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.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 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>
|
<label>Webhook-URL (Discord)</label>
|
||||||
|
<div className="input-row">
|
||||||
<input value={settingsDraft.notifyUrl} placeholder="https://discord.com/api/webhooks/..." onChange={(e) => setText("notifyUrl", e.target.value)} />
|
<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>
|
<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>
|
<label>Discord-Ping (optional)</label>
|
||||||
<input value={settingsDraft.notifyMention} placeholder="Deine User-ID, @everyone oder @here" onChange={(e) => setText("notifyMention", e.target.value)} />
|
<input value={settingsDraft.notifyMention} placeholder="Deine User-ID, @everyone oder @here" onChange={(e) => setText("notifyMention", e.target.value)} />
|
||||||
|
|||||||
@ -48,6 +48,7 @@ export const IPC_CHANNELS = {
|
|||||||
OPEN_ITEM_LOG: "app:open-item-log",
|
OPEN_ITEM_LOG: "app:open-item-log",
|
||||||
GET_DEBUG_SETUP_CHECK: "app:get-debug-setup-check",
|
GET_DEBUG_SETUP_CHECK: "app:get-debug-setup-check",
|
||||||
GET_RECENT_ERRORS: "app:get-recent-errors",
|
GET_RECENT_ERRORS: "app:get-recent-errors",
|
||||||
|
TEST_NOTIFY: "app:test-notify",
|
||||||
GET_TRACE_CONFIG: "app:get-trace-config",
|
GET_TRACE_CONFIG: "app:get-trace-config",
|
||||||
SET_TRACE_ENABLED: "app:set-trace-enabled",
|
SET_TRACE_ENABLED: "app:set-trace-enabled",
|
||||||
ROTATE_DEBUG_TOKEN: "app:rotate-debug-token",
|
ROTATE_DEBUG_TOKEN: "app:rotate-debug-token",
|
||||||
|
|||||||
@ -67,6 +67,7 @@ export interface ElectronApi {
|
|||||||
openItemLog: (itemId: string) => Promise<void>;
|
openItemLog: (itemId: string) => Promise<void>;
|
||||||
getDebugSetupCheck: () => Promise<DebugSetupCheckResult>;
|
getDebugSetupCheck: () => Promise<DebugSetupCheckResult>;
|
||||||
getRecentErrors: () => Promise<Array<{ ts: string; level: string; message: string }>>;
|
getRecentErrors: () => Promise<Array<{ ts: string; level: string; message: string }>>;
|
||||||
|
testNotification: (url: string, mention: string) => Promise<boolean>;
|
||||||
getTraceConfig: () => Promise<SupportTraceConfig>;
|
getTraceConfig: () => Promise<SupportTraceConfig>;
|
||||||
setTraceEnabled: (enabled: boolean, note?: string, durationMinutes?: number) => Promise<SupportTraceConfig>;
|
setTraceEnabled: (enabled: boolean, note?: string, durationMinutes?: number) => Promise<SupportTraceConfig>;
|
||||||
rotateDebugToken: () => Promise<{ path: string }>;
|
rotateDebugToken: () => Promise<{ path: string }>;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user