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:
@@ -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
@@ -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
|
||||
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
"config.json",
|
||||
"BENUTZERHANDBUCH.md",
|
||||
"DISCLAIMER.md",
|
||||
"LICENSE.txt",
|
||||
"!**/*.map"
|
||||
],
|
||||
"win": {
|
||||
|
||||
+53
-2
@@ -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', () => ({
|
||||
|
||||
@@ -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'),
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user