Kaputte Links im Info-Dialog beheben, Lizenz-Menüpunkt ergaenzen

Klicks auf Links im gerenderten Markdown (z. B. BENUTZERHANDBUCH.md,
LICENSE.txt) navigierten das Fenster selbst dorthin und liessen einen
leeren, unschliessbaren Dialog zurueck. Main-Prozess faengt jetzt jede
Navigation im Info-Fenster ab: externe http(s)-Links oeffnen im
Standardbrowser, interne Verweise auf Benutzerhandbuch/Disclaimer/
Lizenz wechseln stattdessen den Inhalt desselben Dialogs.

Neuer dritter Menüpunkt "Lizenz" (LICENSE.txt) im Info-Dropdown. Der
README.md-Link in DISCLAIMER.md zeigt jetzt auf die Repo-Seite auf
Gitea statt auf einen kaputten relativen Pfad.

Claude-Session: https://claude.ai/code/session_01VeqoaAZDVSCU4QBtiYDC5C
This commit is contained in:
Winkler, Stefan
2026-09-01 11:58:58 +02:00
parent bb7089f560
commit f8a286f219
8 changed files with 66 additions and 3 deletions
+1
View File
@@ -76,6 +76,7 @@ Position wird gemerkt.
| Statuspunkt | Zeigt den Zustand der Datenquellen, siehe unten |
| Pfeil-Symbol (nur bei neuem Release) | Öffnet die Release-Seite im Browser |
| Zahnrad | Öffnet die Einstellungen |
| `ⓘ` | Öffnet ein Menü mit Benutzerhandbuch, Disclaimer und Lizenz — Klick auf einen Eintrag zeigt den Text in einem eigenen Fenster |
| `` | Blendet das Fenster aus (Rückkehr über das Tray-Symbol) |
**Anzeigebereich**
+2 -1
View File
@@ -40,7 +40,8 @@ Abrechnung ist ausschließlich Anthropic maßgeblich.
Die Anwendung liest lokal vorhandene Claude-Code-Transkripte und optional das
lokale Zugriffstoken, um die genannte Serverabfrage durchzuführen. Details
dazu stehen im Abschnitt „Datenschutz und Sicherheit“ in
[`BENUTZERHANDBUCH.md`](BENUTZERHANDBUCH.md) sowie in [`README.md`](README.md).
[`BENUTZERHANDBUCH.md`](BENUTZERHANDBUCH.md) sowie in
[`README.md`](https://git.conatum.net/swinks/claude-live-dashboard/src/branch/main/README.md).
## Lizenz und Nutzung auf eigene Verantwortung
+1
View File
@@ -75,6 +75,7 @@ ELECTRON_OZONE_PLATFORM_HINT=wayland ./start.sh # nativ Wayland, ohne Position
| Kopfzeile ziehen | Fenster verschieben (Position wird gemerkt) |
| Statuspunkt (links vom Zahnrad) | Fehler-/Ereignis-Log öffnen |
| ⚙ | Einstellungen öffnen |
| ⓘ | Menü mit Benutzerhandbuch/Disclaimer/Lizenz — öffnet den jeweiligen Text in einem eigenen Fenster |
| „Details“ | Modell-Aufschlüsselung, Tempo und Datengrundlage aufklappen |
| `` | Ausblenden — Rückkehr über das Tray-Symbol |
| Tray-Klick | Ein-/Ausblenden |
+1
View File
@@ -37,6 +37,7 @@
"config.json",
"BENUTZERHANDBUCH.md",
"DISCLAIMER.md",
"LICENSE.txt",
"!**/*.map"
],
"win": {
+53 -2
View File
@@ -34,11 +34,23 @@ const ERRORS_HEIGHT = 480;
const INFO_WIDTH = 560;
const INFO_HEIGHT = 680;
/** Feste Whitelist — der Renderer kann nur diese beiden Schlüssel anfragen,
* nie einen beliebigen Dateipfad. */
/** Feste Whitelist — der Renderer kann nur diese Schlüssel anfragen, nie
* einen beliebigen Dateipfad. */
const INFO_DOCS = {
manual: { title: 'Benutzerhandbuch', file: path.join(ROOT, 'BENUTZERHANDBUCH.md') },
disclaimer: { title: 'Disclaimer', file: path.join(ROOT, 'DISCLAIMER.md') },
license: { title: 'Lizenz', file: path.join(ROOT, 'LICENSE.txt') },
};
/**
* Ordnet Dateinamen, wie sie in den Markdown-Texten oben verlinkt sind, dem
* passenden INFO_DOCS-Schlüssel zu — für Links, die innerhalb der Anwendung
* bleiben sollen (siehe will-navigate-Abfangen in openInfoDoc()).
*/
const INFO_LINK_TARGETS = {
'BENUTZERHANDBUCH.md': 'manual',
'DISCLAIMER.md': 'disclaimer',
'LICENSE.txt': 'license',
};
/** Wartezeit vor der einmaligen Update-Prüfung — verzögert, damit sie den
@@ -384,6 +396,32 @@ function escapeHtml(text) {
.replace(/>/g, '>');
}
/**
* Behandelt einen Link-Klick im Info-Dialog. Ohne dieses Abfangen navigiert
* Electron das Fenster selbst zum verlinkten Ziel — bei einem relativen Link
* auf eine .md-Datei bleibt das Fenster dann leer und ohne Titelleiste hängen
* (kein Schließen-Button mehr). Externe http(s)-Links öffnen im Standard-
* browser, interne Verweise auf die drei bekannten Dokumente wechseln den
* Inhalt desselben Dialogs; alles andere wird verworfen.
*/
function handleInfoLink(url) {
let parsed;
try {
parsed = new URL(url);
} catch {
return;
}
if (parsed.protocol === 'http:' || parsed.protocol === 'https:') {
shell.openExternal(url);
return;
}
if (parsed.protocol === 'file:') {
const base = path.basename(decodeURIComponent(parsed.pathname));
const kind = INFO_LINK_TARGETS[base];
if (kind) openInfoDoc(kind);
}
}
/**
* Benutzerhandbuch-/Disclaimer-Dialog — ein Fenster für beide Dokumente
* (Singleton wie oben), Titel und Inhalt werden bei jedem Öffnen aktualisiert.
@@ -438,6 +476,18 @@ function openInfoDoc(kind) {
},
});
// Linkklicks im gerenderten Markdown nie im Fenster selbst navigieren
// lassen (siehe handleInfoLink()) — sonst bleibt ein leeres, unschließbares
// Fenster zurück.
infoWin.webContents.on('will-navigate', (event, url) => {
event.preventDefault();
handleInfoLink(url);
});
infoWin.webContents.setWindowOpenHandler(({ url }) => {
handleInfoLink(url);
return { action: 'deny' };
});
infoWin.loadFile(path.join(__dirname, '..', 'info', 'index.html'));
infoWin.webContents.once('did-finish-load', send);
infoWin.once('ready-to-show', () => infoWin.show());
@@ -503,6 +553,7 @@ function registerIpc() {
});
ipcMain.on('open-manual', () => openInfoDoc('manual'));
ipcMain.on('open-disclaimer', () => openInfoDoc('disclaimer'));
ipcMain.on('open-license', () => openInfoDoc('license'));
ipcMain.on('info:close', () => infoWin && infoWin.close());
ipcMain.handle('settings:load', () => ({
+2
View File
@@ -30,4 +30,6 @@ contextBridge.exposeInMainWorld('dashboard', {
openManual: () => ipcRenderer.send('open-manual'),
/** Öffnet den Disclaimer-Dialog. */
openDisclaimer: () => ipcRenderer.send('open-disclaimer'),
/** Öffnet den Lizenz-Dialog. */
openLicense: () => ipcRenderer.send('open-license'),
});
+5
View File
@@ -53,6 +53,7 @@ const el = {
infoMenu: $('info-menu'),
infoMenuManual: $('info-menu-manual'),
infoMenuDisclaimer: $('info-menu-disclaimer'),
infoMenuLicense: $('info-menu-license'),
btnHide: $('btn-hide'),
btnSettings: $('btn-settings'),
btnExpand: $('btn-expand'),
@@ -501,6 +502,10 @@ el.infoMenuDisclaimer.addEventListener('click', () => {
el.infoMenu.hidden = true;
window.dashboard.openDisclaimer();
});
el.infoMenuLicense.addEventListener('click', () => {
el.infoMenu.hidden = true;
window.dashboard.openLicense();
});
window.dashboard.onState(render);
+1
View File
@@ -35,6 +35,7 @@
<div class="info-menu" id="info-menu" hidden>
<button class="info-menu-item" id="info-menu-manual">Benutzerhandbuch</button>
<button class="info-menu-item" id="info-menu-disclaimer">Disclaimer</button>
<button class="info-menu-item" id="info-menu-license">Lizenz</button>
</div>
</div>
<button class="icon-btn" id="btn-hide" title="Ausblenden (über das Tray-Symbol zurückholen)"></button>