hmgr 0.0.7 → 0.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapter/agents.js +14 -5
- package/dist/adapter/claude-code.js +53 -12
- package/dist/adapter/dateisystem.js +85 -43
- package/dist/adapter/heime.js +76 -0
- package/dist/adapter/hermes.js +16 -7
- package/dist/adapter/npm-registry.js +61 -0
- package/dist/adapter/umgebung.js +6 -1
- package/dist/adapter/verlauf-json.js +39 -0
- package/dist/adapter/wsl.js +212 -0
- package/dist/adapter/zustand-json.js +36 -15
- package/dist/cli/hilfe.js +100 -13
- package/dist/cli/main.js +219 -18
- package/dist/gui/hmgr-cli.js +44 -0
- package/dist/gui/main.js +344 -4
- package/dist/gui/preload.cjs +26 -2
- package/dist/gui/renderer/index.html +67 -15
- package/dist/gui/renderer/renderer.js +441 -228
- package/dist/gui/renderer/styles.css +69 -16
- package/dist/kern/anwendungsfaelle.js +244 -16
- package/dist/kern/modell.js +112 -1
- package/dist/kern/version.js +13 -0
- package/dist/ports/dateizugriff.js +1 -0
- package/dist/ports/harness.js +4 -0
- package/dist/ports/heime.js +1 -0
- package/dist/ports/verlauf.js +4 -0
- package/dist/ports/zustand.js +4 -3
- package/package.json +7 -1
package/dist/gui/main.js
CHANGED
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
// Fenster. Kein zweiter Prozess: der Kern läuft direkt im Main-Prozess, die GUI ist ein zweiter
|
|
4
4
|
// Kompositions-Einstieg neben der CLI (ARCHITEKTUR.md „Eingang").
|
|
5
5
|
import { app, BrowserWindow, dialog, ipcMain, Menu, shell } from 'electron';
|
|
6
|
+
// electron-updater ist CommonJS: in ESM kommt nur der Default-Export an, `autoUpdater` wird aus ihm
|
|
7
|
+
// herausgegriffen. Ein benannter Import (`import { autoUpdater } from …`) scheitert zur Laufzeit.
|
|
8
|
+
import electronUpdater from 'electron-updater';
|
|
6
9
|
import path from 'node:path';
|
|
7
10
|
import { randomUUID } from 'node:crypto';
|
|
8
11
|
import { stat } from 'node:fs/promises';
|
|
@@ -17,6 +20,8 @@ import { entscheideOeffnen } from "./oeffnen.js";
|
|
|
17
20
|
import { mcpUebernahmeSerialisieren, mcpUebersichtSerialisieren, mcpWirkungSerialisieren } from "./mcp-ansicht.js";
|
|
18
21
|
import { beobachten } from "./beobachter.js";
|
|
19
22
|
import { loginPathUebernehmen } from "./login-pfad.js";
|
|
23
|
+
import { hmgrCliVersion } from "./hmgr-cli.js";
|
|
24
|
+
import { cliUpdateHinweis } from "../adapter/npm-registry.js";
|
|
20
25
|
const hierVerzeichnis = path.dirname(fileURLToPath(import.meta.url));
|
|
21
26
|
const smoketest = process.env.HMGR_GUI_SMOKETEST === '1';
|
|
22
27
|
/**
|
|
@@ -118,6 +123,18 @@ const { anwendungsfaelle, ports } = bauen(umgebung, {
|
|
|
118
123
|
rueckfrage,
|
|
119
124
|
...(smoketest ? { claudeAusfuehrer: smoketestClaudeAusfuehrer } : {}),
|
|
120
125
|
});
|
|
126
|
+
/**
|
|
127
|
+
* Wer den laufenden Aktualisieren-Lauf ausgelöst hat (E80): der Renderer reicht es bei jedem Aufruf
|
|
128
|
+
* mit, hier gemerkt für die beiden hmgr-Selbstprüfungen (`update-downloaded`, `cliUpdatePruefen`),
|
|
129
|
+
* die selbst keinen eigenen Auslöser kennen. Default 'start', bevor der erste Lauf gemeldet hat.
|
|
130
|
+
*/
|
|
131
|
+
let letzterAusloeser = 'start';
|
|
132
|
+
// Merkt die GUI-Version beim Start im Verlauf (E80): ein Versionssprung gegen den letzten Start
|
|
133
|
+
// bekommt einen Eintrag „hmgr-GUI X installiert". Läuft auch im Smoke-Test — hmgrHome zeigt dort auf
|
|
134
|
+
// ein Wegwerf-Verzeichnis (fixtureAufbauen in scripts/gui-smoke-test.ts), nie auf das echte ~/.hmgr.
|
|
135
|
+
void anwendungsfaelle.versionsSprungVermerken('gui', paketVersion(), 'start').catch((fehler) => {
|
|
136
|
+
console.log(`[verlauf] ${fehler instanceof Error ? fehler.message : String(fehler)}`);
|
|
137
|
+
});
|
|
121
138
|
async function auffangen(fn) {
|
|
122
139
|
await pathBereit; // erst der Login-PATH (F47=O2), dann der Adapter — sonst findet er die CLI nicht
|
|
123
140
|
try {
|
|
@@ -296,7 +313,25 @@ function registriereIpc() {
|
|
|
296
313
|
lokal: args.ort.art === 'arbeitsverzeichnis',
|
|
297
314
|
})));
|
|
298
315
|
ipcMain.handle('hmgr:eintragLoeschen', async (_event, args) => auffangen(async () => anwendungsfaelle.eintragLoeschen({ ziel: zielAusIpc(args.harness, args.ort), name: args.name })));
|
|
299
|
-
ipcMain.handle('hmgr:aktualisieren', async (_event, args) => auffangen(async () =>
|
|
316
|
+
ipcMain.handle('hmgr:aktualisieren', async (_event, args) => auffangen(async () => {
|
|
317
|
+
if (args?.ausloeser !== undefined)
|
|
318
|
+
letzterAusloeser = args.ausloeser;
|
|
319
|
+
return anwendungsfaelle.aktualisieren(args);
|
|
320
|
+
}));
|
|
321
|
+
// Changelog der letzten Läufe (E80), neueste zuerst.
|
|
322
|
+
ipcMain.handle('hmgr:verlauf', async () => auffangen(async () => anwendungsfaelle.verlauf()));
|
|
323
|
+
// E77: der Prüfen-Knopf stößt zusätzlich zum Quellen-Lauf die Prüfung auf hmgr selbst an. Kein
|
|
324
|
+
// `handle`, sondern `send`/`on`: der Renderer wartet auf nichts, das Ergebnis kommt später von
|
|
325
|
+
// sich aus über 'hmgr:selbstUpdate'.
|
|
326
|
+
ipcMain.on('hmgr:selbstUpdatePruefen', () => selbstUpdatePruefen());
|
|
327
|
+
// Neustart-Knopf an der GUI-Update-Zeile (E80): installiert das geladene Paket sofort, statt auf
|
|
328
|
+
// das nächste Beenden zu warten. Im Smoke-Test ein No-op — dort läuft `updatePruefen` ohnehin nie,
|
|
329
|
+
// der Knopf bleibt verborgen, aber ein Absturz durch ein fehlendes Update darf trotzdem nie sein.
|
|
330
|
+
ipcMain.on('hmgr:neuStarten', () => {
|
|
331
|
+
if (smoketest)
|
|
332
|
+
return;
|
|
333
|
+
autoUpdater.quitAndInstall();
|
|
334
|
+
});
|
|
300
335
|
ipcMain.handle('hmgr:arbeitsverzeichnisHinzufuegen', async (_event, pfad) => auffangen(async () => anwendungsfaelle.arbeitsverzeichnisHinzufuegen(pfad)));
|
|
301
336
|
ipcMain.handle('hmgr:arbeitsverzeichnisVergessen', async (_event, pfad) => auffangen(async () => anwendungsfaelle.arbeitsverzeichnisVergessen(pfad)));
|
|
302
337
|
// Nativer Verzeichnis-Dialog fürs Pfadfeld in „Verzeichnis hinzufügen" (A1). Im Smoke-Test darf
|
|
@@ -319,6 +354,14 @@ function registriereIpc() {
|
|
|
319
354
|
ipcMain.handle('hmgr:harnessAktivieren', async (_event, name) => auffangen(async () => anwendungsfaelle.harnessAktivieren(name)));
|
|
320
355
|
ipcMain.handle('hmgr:harnessDeaktivieren', async (_event, name) => auffangen(async () => anwendungsfaelle.harnessDeaktivieren(name)));
|
|
321
356
|
ipcMain.handle('hmgr:saeubern', async (_event, name) => auffangen(async () => anwendungsfaelle.saeubern(name)));
|
|
357
|
+
// Homedirs je Harness (E78): zeigen, das primäre umstellen (F89), zusätzliche in einer
|
|
358
|
+
// WSL-Distro eintragen und vergessen (F87). Die Distro-Liste kommt aus `wsl -l -q`.
|
|
359
|
+
ipcMain.handle('hmgr:harnessHeime', async () => auffangen(async () => anwendungsfaelle.harnessHeime()));
|
|
360
|
+
ipcMain.handle('hmgr:wslDistros', async () => auffangen(async () => anwendungsfaelle.wslDistros()));
|
|
361
|
+
ipcMain.handle('hmgr:harnessHeimSetzen', async (_event, args) => auffangen(async () => anwendungsfaelle.harnessHeimSetzen(args.harness, args.pfad)));
|
|
362
|
+
ipcMain.handle('hmgr:harnessHeimZuruecksetzen', async (_event, harness) => auffangen(async () => anwendungsfaelle.harnessHeimZuruecksetzen(harness)));
|
|
363
|
+
ipcMain.handle('hmgr:harnessHeimHinzufuegen', async (_event, args) => auffangen(async () => anwendungsfaelle.harnessHeimHinzufuegen(args.harness, args.adresse)));
|
|
364
|
+
ipcMain.handle('hmgr:harnessHeimEntfernen', async (_event, args) => auffangen(async () => anwendungsfaelle.harnessHeimEntfernen(args.harness, args.adresse)));
|
|
322
365
|
// Verwalteter Hermes-Skill-Ordner (E56): Zeigen kommt schon über hmgr:istZustand, hier nur Ändern.
|
|
323
366
|
ipcMain.handle('hmgr:skillOrdnerFestlegen', async (_event, args) => auffangen(async () => anwendungsfaelle.skillOrdnerFestlegen(zielAusIpc(args.harness, args.ort), args.pfad)));
|
|
324
367
|
ipcMain.handle('hmgr:skillOrdnerEntfernen', async (_event, args) => auffangen(async () => anwendungsfaelle.skillOrdnerEntfernen(zielAusIpc(args.harness, args.ort))));
|
|
@@ -474,6 +517,25 @@ function fensterOeffnen() {
|
|
|
474
517
|
var harnessSchalter = Array.from(document.querySelectorAll('#harnessliste input[type=checkbox]'))
|
|
475
518
|
.map((i) => i.dataset.harness + ':' + i.checked)
|
|
476
519
|
.join(',');
|
|
520
|
+
// Homedir-Zeilen unter den Schaltern (E78): je Harness eine Zeile mit dem Pfad, dazu
|
|
521
|
+
// der Ändern-Knopf. Der Weg zu einem WSL-Homedir steht auf dem Mac bewusst nicht da.
|
|
522
|
+
var heimZeilen = Array.from(document.querySelectorAll('#harnessliste .heimzeile'))
|
|
523
|
+
.map((z) => z.textContent.replace(/\\s+/g, ' ').trim())
|
|
524
|
+
.join(' | ');
|
|
525
|
+
var heimWslKnopfVorhanden = Array.from(document.querySelectorAll('#harnessliste .heime > button'))
|
|
526
|
+
.some((b) => b.textContent.indexOf('WSL') !== -1);
|
|
527
|
+
// Der Pfad-Dialog lässt sich öffnen und per Abbrechen wieder schließen, ohne IPC-Lauf.
|
|
528
|
+
var heimPfadFehler = null;
|
|
529
|
+
var dHeimPfadOffenNachOeffnen = false;
|
|
530
|
+
var dHeimPfadOffenNachAbbrechen = true;
|
|
531
|
+
try {
|
|
532
|
+
document.querySelector('#harnessliste .heimknoepfe button')?.click();
|
|
533
|
+
dHeimPfadOffenNachOeffnen = document.getElementById('d-heim-pfad')?.open === true;
|
|
534
|
+
document.querySelector('#d-heim-pfad button[value="abbruch"]')?.click();
|
|
535
|
+
dHeimPfadOffenNachAbbrechen = document.getElementById('d-heim-pfad')?.open === true;
|
|
536
|
+
} catch (fehler) {
|
|
537
|
+
heimPfadFehler = String(fehler);
|
|
538
|
+
}
|
|
477
539
|
// Quellen-Abschnitt der Einstellungen (E54): Knopf und Dialoge vorhanden, der
|
|
478
540
|
// Hinzufügen-Dialog lässt sich öffnen und per Abbrechen ohne Fehler wieder schließen.
|
|
479
541
|
// Kein echter Quellen-Lauf: der Abbrechen-Knopf löst keinen IPC-Aufruf aus.
|
|
@@ -534,6 +596,17 @@ function fensterOeffnen() {
|
|
|
534
596
|
} catch (fehler) {
|
|
535
597
|
quelleUmbenennenFehler = String(fehler);
|
|
536
598
|
}
|
|
599
|
+
// Leertext der Quellenliste (E75): der Smoke-Lauf hat immer eine Quelle, den leeren
|
|
600
|
+
// Zustand erreicht er nie. Geprüft wird darum die Regel, an der er zerbrach — ein
|
|
601
|
+
// <li class="leerhinweis"> in genau dieser Liste ist vom Grid ausgenommen und nimmt
|
|
602
|
+
// die ganze Breite, statt in die 20px-Icon-Spalte zu fallen und Wort für Wort
|
|
603
|
+
// umzubrechen. Die Probe wird sofort wieder entfernt, die Liste bleibt unberührt.
|
|
604
|
+
var quellenLeerProbe = document.createElement('li');
|
|
605
|
+
quellenLeerProbe.className = 'leerhinweis';
|
|
606
|
+
quellenLeerProbe.textContent = 'Probe';
|
|
607
|
+
document.getElementById('quellenliste')?.appendChild(quellenLeerProbe);
|
|
608
|
+
var quellenLeerDisplay = getComputedStyle(quellenLeerProbe).display;
|
|
609
|
+
quellenLeerProbe.remove();
|
|
537
610
|
document.getElementById('d-einstellungen')?.close();
|
|
538
611
|
// Konfigzeile am Hermes-Ziel (E56): der verwaltete Pfad steht in der Karte, auch
|
|
539
612
|
// ungeklappt (hidden ändert textContent nicht). Dazu der Festlegen-Weg am unmanaged
|
|
@@ -553,6 +626,52 @@ function fensterOeffnen() {
|
|
|
553
626
|
} catch (fehler) {
|
|
554
627
|
skillOrdnerFehler = String(fehler);
|
|
555
628
|
}
|
|
629
|
+
// E77: der Ort für die Update-Hinweise steht in der Seitenleiste, direkt vor dem
|
|
630
|
+
// Einstellungen-Knopf, und ist im Ruhezustand leer und verborgen. Der Smoke-Lauf
|
|
631
|
+
// prüft nie nach — er stößt weder Updater noch CLI-Prüfung an, es gibt nichts zu
|
|
632
|
+
// melden. Geprüft wird darum nur, dass der Ort da ist und stumm bleibt.
|
|
633
|
+
var selbstupdateEl = document.getElementById('selbstupdate');
|
|
634
|
+
var selbstupdateVorhanden = selbstupdateEl !== null;
|
|
635
|
+
// Nicht nur das Attribut, sondern das tatsächliche Rendern: die Klasse setzt
|
|
636
|
+
// display:flex, und eine Autoren-Regel überstimmt das hidden-Attribut des Browsers —
|
|
637
|
+
// ohne die eigene hidden-Regel in styles.css stünde hier ein leerer Kasten samt
|
|
638
|
+
// seinem auto-Rand. Das Attribut allein würde den Fehler nicht zeigen.
|
|
639
|
+
var selbstupdateVerborgen =
|
|
640
|
+
selbstupdateEl?.hidden === true && getComputedStyle(selbstupdateEl).display === 'none';
|
|
641
|
+
// Seit E80 steckt im Kasten auch der Neustart-Knopf, sein Text bleibt aber im DOM
|
|
642
|
+
// stehen, auch verborgen (anders als bei display:none zählt hidden nicht für
|
|
643
|
+
// textContent) — „leer" meint deshalb: kein sichtbarer (nicht verborgener) Kindknoten
|
|
644
|
+
// trägt Text, nicht der rohe textContent des ganzen Kastens.
|
|
645
|
+
var selbstupdateLeer = Array.from(selbstupdateEl?.children ?? [])
|
|
646
|
+
.filter((kind) => !kind.hidden)
|
|
647
|
+
.every((kind) => (kind.textContent ?? '').trim() === '');
|
|
648
|
+
// Er sitzt zwischen Stand-Zeile und Einstellungen-Knopf: der Knopf ist sein nächster
|
|
649
|
+
// Geschwister-Knoten, sonst stünde der Hinweis irgendwo anders in der Leiste.
|
|
650
|
+
var selbstupdateVorEinstellungen = selbstupdateEl?.nextElementSibling?.id === 'einstellungen';
|
|
651
|
+
// E80: Neustart-Knopf an der GUI-Update-Zeile, vorhanden und im Ruhezustand verborgen
|
|
652
|
+
// (der Smoke-Lauf löst nie ein update-downloaded aus, das ihn einblenden würde).
|
|
653
|
+
var selbstupdateNeustartVorhanden = document.getElementById('selbstupdate-neustart') !== null;
|
|
654
|
+
var selbstupdateNeustartVerborgen = document.getElementById('selbstupdate-neustart')?.hidden === true;
|
|
655
|
+
// E80: die Seitenleiste zeigt nur noch die Stand-Zeile und ein „›" zum Öffnen der
|
|
656
|
+
// Ansicht, kein „Prüfen"-Wort mehr und kein eigener Lauf am Standknopf-Klick. In der
|
|
657
|
+
// Ansicht selbst ersetzt ein runder Kringel den früheren großen Knopf, und der alte
|
|
658
|
+
// Sitzungsbericht (#bericht) ist ganz weg, ersetzt durch das Changelog (#verlauf).
|
|
659
|
+
var standknopfText = document.getElementById('standknopf')?.textContent ?? null;
|
|
660
|
+
var updatestartKringel = document.getElementById('updatestart')?.classList.contains('kringel') === true;
|
|
661
|
+
var updatestartLaeuft = document.getElementById('updatestart')?.classList.contains('laeuft') === true;
|
|
662
|
+
var berichtVorhanden = document.getElementById('bericht') !== null;
|
|
663
|
+
var verlaufVorhanden = document.getElementById('verlauf') !== null;
|
|
664
|
+
// Der Standknopf öffnet nur noch die Ansicht (kein Lauf mehr an diesem Klick), die
|
|
665
|
+
// Ansicht lädt ihren Verlauf dabei aus der Datei — das ist ein IPC-Aufruf, also kurz
|
|
666
|
+
// nachfassen, bis das Ergebnis im DOM steht (Muster wie bei mcpWahlOeffnen oben).
|
|
667
|
+
document.getElementById('standknopf')?.click();
|
|
668
|
+
var verlaufBloecke = 0;
|
|
669
|
+
for (var wartezeit = 0; wartezeit < 2000; wartezeit += 100) {
|
|
670
|
+
await new Promise((r) => setTimeout(r, 100));
|
|
671
|
+
verlaufBloecke = document.querySelectorAll('#verlauf .block').length;
|
|
672
|
+
if (verlaufBloecke > 0) break;
|
|
673
|
+
}
|
|
674
|
+
var verlaufText = document.getElementById('verlauf')?.textContent?.replace(/\\s+/g, ' ').trim() ?? null;
|
|
556
675
|
// E60: Beschreibung in der Ziel-Tabelle (nicht nur im Katalog), „manuell" entfällt,
|
|
557
676
|
// Zahnrad statt Sonne am Einstellungen-Knopf.
|
|
558
677
|
var zielBeschreibung = document.querySelector('#zielliste .linkliste .was')?.textContent ?? null;
|
|
@@ -567,6 +686,57 @@ function fensterOeffnen() {
|
|
|
567
686
|
// E70/F70=O1: die Herkunftszeile trägt hinter dem Ref das Änderungsdatum des Skills.
|
|
568
687
|
var katalogHerkunft = document.querySelector('#katalog .zeile .herkunft')?.textContent
|
|
569
688
|
?.replace(/\\s+/g, ' ').trim() ?? null;
|
|
689
|
+
// E79: Sortier-Gruppe der Skills-Rubrik. Erst „Zuletzt geändert" klicken und die
|
|
690
|
+
// sichtbaren Änderungsdaten der ersten fünf Zeilen samt Knopfstand festhalten, dann
|
|
691
|
+
// zurück auf „Name", damit die obigen Prüfungen (erste Zeile) unverändert gelten.
|
|
692
|
+
document.getElementById('sortnach-datum')?.click();
|
|
693
|
+
var katalogSortierungGeaendert = Array.from(document.querySelectorAll('#katalog .zeile:not([hidden])'))
|
|
694
|
+
.slice(0, 5)
|
|
695
|
+
.map((li) => li.dataset.geaendert ?? '')
|
|
696
|
+
.join('|');
|
|
697
|
+
var katalogSortierungDatumGedrueckt = document.getElementById('sortnach-datum')?.getAttribute('aria-pressed') ?? null;
|
|
698
|
+
var katalogSortierungNameGedrueckt = document.getElementById('sortnach-name')?.getAttribute('aria-pressed') ?? null;
|
|
699
|
+
// E81: Richtung und Pfeil nach dem ersten Klick. Standardrichtung von „datum" ist
|
|
700
|
+
// 'ab' (jüngste zuerst, wie E79), der Name-Chip ist dabei inaktiv und trägt keinen
|
|
701
|
+
// Pfeil.
|
|
702
|
+
var katalogSortierungDatumRichtung = document.getElementById('sortnach-datum')?.getAttribute('data-richtung') ?? null;
|
|
703
|
+
var katalogSortierungDatumPfeil = document.querySelector('#sortnach-datum .sortpfeil')?.textContent ?? null;
|
|
704
|
+
var katalogSortierungNamePfeil = document.querySelector('#sortnach-name .sortpfeil')?.textContent ?? null;
|
|
705
|
+
// E81: zweiter Klick auf denselben Chip kehrt nur die Richtung um (Schlüssel bleibt
|
|
706
|
+
// „datum", jetzt älteste zuerst).
|
|
707
|
+
document.getElementById('sortnach-datum')?.click();
|
|
708
|
+
var katalogSortierungGeaendertAuf = Array.from(document.querySelectorAll('#katalog .zeile:not([hidden])'))
|
|
709
|
+
.slice(0, 5)
|
|
710
|
+
.map((li) => li.dataset.geaendert ?? '')
|
|
711
|
+
.join('|');
|
|
712
|
+
var katalogSortierungDatumRichtungAuf = document.getElementById('sortnach-datum')?.getAttribute('data-richtung') ?? null;
|
|
713
|
+
var katalogSortierungDatumPfeilAuf = document.querySelector('#sortnach-datum .sortpfeil')?.textContent ?? null;
|
|
714
|
+
document.getElementById('sortnach-name')?.click();
|
|
715
|
+
// Reiner Textknoten des Namens (erstes Kind ist das Quellen-Icon, ein etwaiges
|
|
716
|
+
// Markenfeld käme als weiteres Element danach) statt h3.textContent, sonst würde
|
|
717
|
+
// eine Marke direkt an den Namen geklebt.
|
|
718
|
+
var ersterKatalogH3 = document.querySelector('#katalog .zeile:not([hidden]) h3');
|
|
719
|
+
var katalogErsterNachName = ersterKatalogH3
|
|
720
|
+
? Array.from(ersterKatalogH3.childNodes).find((n) => n.nodeType === 3)?.textContent ?? null
|
|
721
|
+
: null;
|
|
722
|
+
// E81: Chipwechsel (anderer Schlüssel als zuvor „datum") setzt dessen Standardrichtung,
|
|
723
|
+
// hier 'auf' für Name — die bisherige, unveränderte Reihenfolge (A→Z).
|
|
724
|
+
var katalogNamenAuf = Array.from(document.querySelectorAll('#katalog .zeile:not([hidden]) h3'))
|
|
725
|
+
.map((h3) => Array.from(h3.childNodes).find((n) => n.nodeType === 3)?.textContent ?? '')
|
|
726
|
+
.join('|');
|
|
727
|
+
var katalogSortierungNameRichtungAuf = document.getElementById('sortnach-name')?.getAttribute('data-richtung') ?? null;
|
|
728
|
+
var katalogSortierungNamePfeilAuf = document.querySelector('#sortnach-name .sortpfeil')?.textContent ?? null;
|
|
729
|
+
// E81: zweiter Klick auf „Name" kehrt die Richtung um (Z→A).
|
|
730
|
+
document.getElementById('sortnach-name')?.click();
|
|
731
|
+
var katalogNamenAb = Array.from(document.querySelectorAll('#katalog .zeile:not([hidden]) h3'))
|
|
732
|
+
.map((h3) => Array.from(h3.childNodes).find((n) => n.nodeType === 3)?.textContent ?? '')
|
|
733
|
+
.join('|');
|
|
734
|
+
var katalogSortierungNameRichtungAb = document.getElementById('sortnach-name')?.getAttribute('data-richtung') ?? null;
|
|
735
|
+
var katalogSortierungNamePfeilAb = document.querySelector('#sortnach-name .sortpfeil')?.textContent ?? null;
|
|
736
|
+
// E81: dritter Klick stellt name/auf wieder her, damit die restliche Sonde (unten)
|
|
737
|
+
// wie gewohnt gegen die Standardsortierung prüft.
|
|
738
|
+
document.getElementById('sortnach-name')?.click();
|
|
739
|
+
var katalogSortierungNameRichtungNachDrittemKlick = document.getElementById('sortnach-name')?.getAttribute('data-richtung') ?? null;
|
|
570
740
|
// Besonderheiten aus dem Frontmatter (E55): Marken an der Zeile, Details erst nach
|
|
571
741
|
// einem Klick auf den Aufklapp-Knopf.
|
|
572
742
|
var katalogMarken = document.querySelector('#katalog .zeile .marken')?.textContent
|
|
@@ -597,6 +767,17 @@ function fensterOeffnen() {
|
|
|
597
767
|
?.replace(/\\s+/g, ' ').trim() ?? null;
|
|
598
768
|
document.getElementById('d-skills')?.close();
|
|
599
769
|
}
|
|
770
|
+
// Verlinken-Dialog „Wohin?" (E76): er bietet nur Ziele aktiver Harnesses an. Der Text
|
|
771
|
+
// der Wahlliste sagt, welche das sind; ist gar keines aktiv, steht dort der Leerhinweis.
|
|
772
|
+
var dzZieleText = null;
|
|
773
|
+
var dzKnopf = Array.from(document.querySelectorAll('#katalog .zeile button'))
|
|
774
|
+
.find((b) => b.textContent === 'Verlinken');
|
|
775
|
+
if (dzKnopf) {
|
|
776
|
+
dzKnopf.click();
|
|
777
|
+
dzZieleText = document.getElementById('dz-ziele')?.textContent
|
|
778
|
+
?.replace(/\\s+/g, ' ').trim() ?? null;
|
|
779
|
+
document.getElementById('d-ziel')?.close();
|
|
780
|
+
}
|
|
600
781
|
// Bundle-Gruppe an der Ziel-Karte (E69): Kopf mit Name, Quelle und Entfernen, darunter
|
|
601
782
|
// die Zeilen der Mitglieder — sie stehen in der Gruppe, nicht in der allgemeinen Liste.
|
|
602
783
|
var bundleGruppeText = document.querySelector('#zielliste .bundlegruppe .bundlekopf')?.textContent
|
|
@@ -736,6 +917,19 @@ function fensterOeffnen() {
|
|
|
736
917
|
var agentsKarteVorhanden = agentsKarte !== undefined;
|
|
737
918
|
var agentsMcpAbschnittVorhanden = (agentsKarte?.querySelector('.mcpkarteabschnitt') ?? null) !== null;
|
|
738
919
|
var agentsMcpKnopfVorhanden = mcpHinzuKnopfAn(agentsKarte) !== undefined;
|
|
920
|
+
// Warnzahl am Kartenkopf (E75): das Dreieck nennt die Zahl der Auslöser. Im Fixture
|
|
921
|
+
// liegt ein fremder Ordner im Hermes-Home-Ziel (1) und drei im Verzeichnis kunde-x,
|
|
922
|
+
// ungleich auf die zwei Harness-Teile verteilt — dort ist die Zahl die Summe. Die
|
|
923
|
+
// agents-Karte hat keinen Auslöser und darum gar kein Dreieck.
|
|
924
|
+
var warnungVon = function (karte) { return karte?.querySelector('.zielkopf .warnung') ?? null; };
|
|
925
|
+
var warnzahlVon = function (karte) {
|
|
926
|
+
return warnungVon(karte)?.querySelector('.warnzahl')?.textContent?.trim() ?? null;
|
|
927
|
+
};
|
|
928
|
+
var hermesWarnzahl = warnzahlVon(hermesKarte);
|
|
929
|
+
var hermesWarnlabel = warnungVon(hermesKarte)?.getAttribute('aria-label') ?? null;
|
|
930
|
+
var kundeXWarnzahl = warnzahlVon(kundeXKarte);
|
|
931
|
+
var kundeXWarnlabel = warnungVon(kundeXKarte)?.getAttribute('aria-label') ?? null;
|
|
932
|
+
var agentsWarnungVorhanden = warnungVon(agentsKarte) !== null;
|
|
739
933
|
// Dialog „MCP hinzufügen" (E47-Muster): öffnen an der Hermes-Karte und über Abbrechen
|
|
740
934
|
// wieder schließen, ohne IPC-Schreibaktion (mcpEinhaengen liefe erst nach „Einhängen").
|
|
741
935
|
var dmhFehler = null;
|
|
@@ -763,12 +957,34 @@ function fensterOeffnen() {
|
|
|
763
957
|
meldung: document.getElementById('meldungtext')?.textContent,
|
|
764
958
|
einstellungenOffen,
|
|
765
959
|
harnessSchalter,
|
|
960
|
+
heimZeilen,
|
|
961
|
+
heimWslKnopfVorhanden,
|
|
962
|
+
heimPfadFehler,
|
|
963
|
+
dHeimPfadOffenNachOeffnen,
|
|
964
|
+
dHeimPfadOffenNachAbbrechen,
|
|
766
965
|
zielBeschreibung,
|
|
767
966
|
zielMarken,
|
|
768
967
|
zielManuellVorhanden,
|
|
769
968
|
zahnradVorhanden,
|
|
770
969
|
katalogBeschreibung,
|
|
771
970
|
katalogHerkunft,
|
|
971
|
+
katalogSortierungGeaendert,
|
|
972
|
+
katalogSortierungDatumGedrueckt,
|
|
973
|
+
katalogSortierungNameGedrueckt,
|
|
974
|
+
katalogSortierungDatumRichtung,
|
|
975
|
+
katalogSortierungDatumPfeil,
|
|
976
|
+
katalogSortierungNamePfeil,
|
|
977
|
+
katalogSortierungGeaendertAuf,
|
|
978
|
+
katalogSortierungDatumRichtungAuf,
|
|
979
|
+
katalogSortierungDatumPfeilAuf,
|
|
980
|
+
katalogErsterNachName,
|
|
981
|
+
katalogNamenAuf,
|
|
982
|
+
katalogSortierungNameRichtungAuf,
|
|
983
|
+
katalogSortierungNamePfeilAuf,
|
|
984
|
+
katalogNamenAb,
|
|
985
|
+
katalogSortierungNameRichtungAb,
|
|
986
|
+
katalogSortierungNamePfeilAb,
|
|
987
|
+
katalogSortierungNameRichtungNachDrittemKlick,
|
|
772
988
|
katalogMarken,
|
|
773
989
|
katalogDetailsZu,
|
|
774
990
|
katalogAufgeklappt,
|
|
@@ -777,6 +993,7 @@ function fensterOeffnen() {
|
|
|
777
993
|
dskMarken,
|
|
778
994
|
dskBundleBoxSichtbar,
|
|
779
995
|
dskBundleText,
|
|
996
|
+
dzZieleText,
|
|
780
997
|
bundleGruppeText,
|
|
781
998
|
bundleGruppeZeilen,
|
|
782
999
|
bundleZerbrichtText,
|
|
@@ -831,6 +1048,12 @@ function fensterOeffnen() {
|
|
|
831
1048
|
kundeXMcpKnopfVorhanden,
|
|
832
1049
|
kundeXKopfZahl,
|
|
833
1050
|
hermesKopfZahl,
|
|
1051
|
+
hermesWarnzahl,
|
|
1052
|
+
hermesWarnlabel,
|
|
1053
|
+
kundeXWarnzahl,
|
|
1054
|
+
kundeXWarnlabel,
|
|
1055
|
+
agentsWarnungVorhanden,
|
|
1056
|
+
quellenLeerDisplay,
|
|
834
1057
|
agentsKarteVorhanden,
|
|
835
1058
|
agentsMcpAbschnittVorhanden,
|
|
836
1059
|
agentsMcpKnopfVorhanden,
|
|
@@ -838,6 +1061,19 @@ function fensterOeffnen() {
|
|
|
838
1061
|
dMcpHinzuOffenNachAbbrechen,
|
|
839
1062
|
dmhListeText,
|
|
840
1063
|
dmhFehler,
|
|
1064
|
+
selbstupdateVorhanden,
|
|
1065
|
+
selbstupdateVerborgen,
|
|
1066
|
+
selbstupdateLeer,
|
|
1067
|
+
selbstupdateVorEinstellungen,
|
|
1068
|
+
selbstupdateNeustartVorhanden,
|
|
1069
|
+
selbstupdateNeustartVerborgen,
|
|
1070
|
+
standknopfText,
|
|
1071
|
+
updatestartKringel,
|
|
1072
|
+
updatestartLaeuft,
|
|
1073
|
+
berichtVorhanden,
|
|
1074
|
+
verlaufVorhanden,
|
|
1075
|
+
verlaufText,
|
|
1076
|
+
verlaufBloecke,
|
|
841
1077
|
});
|
|
842
1078
|
})()`)
|
|
843
1079
|
.then((auszug) => console.log(`[smoke] DOM-Auszug: ${auszug}`))
|
|
@@ -850,13 +1086,14 @@ function fensterOeffnen() {
|
|
|
850
1086
|
}
|
|
851
1087
|
// Selbsttätiges Aktualisieren (E44): einmal, sobald der Renderer bereit ist, danach alle sechs
|
|
852
1088
|
// Stunden, solange das Fenster offen bleibt. Im Smoke-Test nie, sonst würde ein automatisierter
|
|
853
|
-
// Lauf einen echten Git-Fetch anstoßen.
|
|
1089
|
+
// Lauf einen echten Git-Fetch anstoßen. Der Auslöser (E80) geht mit, damit der Verlauf zeigt, ob
|
|
1090
|
+
// ein Fund vom Start, vom Intervall oder einem Klick kam.
|
|
854
1091
|
if (!smoketest) {
|
|
855
1092
|
const fenster = hauptfenster;
|
|
856
1093
|
fenster.webContents.once('did-finish-load', () => {
|
|
857
|
-
fenster.webContents.send('hmgr:aktualisierenAnstossen');
|
|
1094
|
+
fenster.webContents.send('hmgr:aktualisierenAnstossen', 'start');
|
|
858
1095
|
});
|
|
859
|
-
const intervall = setInterval(() => fenster.webContents.send('hmgr:aktualisierenAnstossen'), SECHS_STUNDEN_MS);
|
|
1096
|
+
const intervall = setInterval(() => fenster.webContents.send('hmgr:aktualisierenAnstossen', 'intervall'), SECHS_STUNDEN_MS);
|
|
860
1097
|
fenster.on('closed', () => clearInterval(intervall));
|
|
861
1098
|
}
|
|
862
1099
|
// Die GUI erfährt von Änderungen außerhalb ihrer selbst (E62): Fokus-Reload und Datei-Watcher.
|
|
@@ -878,6 +1115,107 @@ function fensterOeffnen() {
|
|
|
878
1115
|
}
|
|
879
1116
|
void hauptfenster.loadFile(path.join(hierVerzeichnis, 'renderer', 'index.html'));
|
|
880
1117
|
}
|
|
1118
|
+
const { autoUpdater } = electronUpdater;
|
|
1119
|
+
/** Die Listener hängen am Modul, nicht am Aufruf: `updatePruefen` läuft beim Start und je Prüfen-Klick. */
|
|
1120
|
+
let updaterVerdrahtet = false;
|
|
1121
|
+
/**
|
|
1122
|
+
* Autoupdate der Windows-GUI (E73). Der Feed sind die Gitea-Releases des hmgr-Repos: die
|
|
1123
|
+
* `publish`-Angabe im build-Block der package.json erzeugt beim Bauen die `latest.yml` und legt
|
|
1124
|
+
* `app-update.yml` ins Paket, aus der electron-updater die Feed-URL liest.
|
|
1125
|
+
*
|
|
1126
|
+
* `checkForUpdatesAndNotify()` heißt: im Hintergrund prüfen, ein gefundenes Update herunterladen,
|
|
1127
|
+
* eine Windows-Benachrichtigung zeigen und beim Beenden der App installieren
|
|
1128
|
+
* (`autoInstallOnAppQuit` ist Vorgabe). Das Einspielen bleibt damit der App-Neustart; die GUI zeigt
|
|
1129
|
+
* seit E77 zusätzlich eine Zeile in der Sidebar, sobald das Paket geladen ist (`update-downloaded`).
|
|
1130
|
+
*
|
|
1131
|
+
* Drei Bedingungen, alle nötig:
|
|
1132
|
+
* — `app.isPackaged`: ungepackt gibt es keine `app-update.yml`, die Prüfung stiege ohnehin aus.
|
|
1133
|
+
* — `win32`: macOS lehnt electron-updater unsigniert ab, das wartet auf die Signierung (A4).
|
|
1134
|
+
* — kein Smoke-Test: dieselbe Zurückhaltung wie bei Watcher und Auto-Aktualisieren — ein
|
|
1135
|
+
* automatisierter Lauf greift nie ins Netz.
|
|
1136
|
+
*
|
|
1137
|
+
* Fehler werden nur vermerkt, nie weitergereicht: auf den Team-Rechnern kann das Gitea unerreichbar
|
|
1138
|
+
* sein (VPN, Abschaltung, DNS), und daran darf die App nicht scheitern. Der `error`-Listener ist
|
|
1139
|
+
* dabei nicht optional — electron-updater meldet Fehler als Event, und ein `error`-Event ohne
|
|
1140
|
+
* Zuhörer wirft in Node.
|
|
1141
|
+
*/
|
|
1142
|
+
function updatePruefen() {
|
|
1143
|
+
if (smoketest || !app.isPackaged || process.platform !== 'win32')
|
|
1144
|
+
return;
|
|
1145
|
+
try {
|
|
1146
|
+
if (!updaterVerdrahtet) {
|
|
1147
|
+
updaterVerdrahtet = true;
|
|
1148
|
+
autoUpdater.on('error', (fehler) => {
|
|
1149
|
+
console.log(`[updater] ${fehler instanceof Error ? fehler.message : String(fehler)}`);
|
|
1150
|
+
});
|
|
1151
|
+
// E77: das geladene Paket wird sichtbar, seit E80 mit Neustart-Knopf. Zusätzlich ein
|
|
1152
|
+
// Verlaufseintrag „GUI-Update X geladen" (E80), einmal je neuer Version — vor der Meldung an
|
|
1153
|
+
// die Sidebar, damit die Ansicht ihn beim nächsten `ladeVerlauf()` schon findet.
|
|
1154
|
+
autoUpdater.on('update-downloaded', (info) => {
|
|
1155
|
+
const version = info?.version;
|
|
1156
|
+
const guiVersion = typeof version === 'string' ? version : paketVersion();
|
|
1157
|
+
void anwendungsfaelle
|
|
1158
|
+
.hmgrEreignisVermerken({ art: 'gui-update-geladen', version: guiVersion }, letzterAusloeser)
|
|
1159
|
+
.catch((fehler) => {
|
|
1160
|
+
console.log(`[verlauf] ${fehler instanceof Error ? fehler.message : String(fehler)}`);
|
|
1161
|
+
});
|
|
1162
|
+
selbstUpdateMelden({ art: 'gui', version: guiVersion });
|
|
1163
|
+
});
|
|
1164
|
+
}
|
|
1165
|
+
void autoUpdater.checkForUpdatesAndNotify().catch((fehler) => {
|
|
1166
|
+
console.log(`[updater] ${fehler instanceof Error ? fehler.message : String(fehler)}`);
|
|
1167
|
+
});
|
|
1168
|
+
}
|
|
1169
|
+
catch (fehler) {
|
|
1170
|
+
console.log(`[updater] ${fehler instanceof Error ? fehler.message : String(fehler)}`);
|
|
1171
|
+
}
|
|
1172
|
+
}
|
|
1173
|
+
/** Ein Hinweis für die Sidebar (E77). Ist das Fenster schon zu, verfällt er stillschweigend. */
|
|
1174
|
+
function selbstUpdateMelden(nachricht) {
|
|
1175
|
+
if (hauptfenster === null || hauptfenster.isDestroyed())
|
|
1176
|
+
return;
|
|
1177
|
+
hauptfenster.webContents.send('hmgr:selbstUpdate', nachricht);
|
|
1178
|
+
}
|
|
1179
|
+
/**
|
|
1180
|
+
* Die daneben installierte hmgr-CLI gegen npm (E77, F83=O1). Läuft auf allen Plattformen — anders
|
|
1181
|
+
* als die GUI-Prüfung hängt sie an keinem Paket-Format und an keiner Signierung. Gemeldet wird nur,
|
|
1182
|
+
* nie installiert: ein `npm install -g` aus der App scheitert leicht an nvm-Pfaden und Rechten
|
|
1183
|
+
* (F82).
|
|
1184
|
+
*
|
|
1185
|
+
* Still bei allem, was schiefgehen kann: keine CLI im PATH, Fehlercode, Registry unerreichbar,
|
|
1186
|
+
* gleiche oder ältere Version auf npm. Der Login-PATH (F47) muss vorher stehen, sonst findet der
|
|
1187
|
+
* Aufruf die per nvm installierte CLI nicht.
|
|
1188
|
+
*/
|
|
1189
|
+
async function cliUpdatePruefen() {
|
|
1190
|
+
await pathBereit;
|
|
1191
|
+
const installiert = await hmgrCliVersion();
|
|
1192
|
+
if (installiert === null)
|
|
1193
|
+
return;
|
|
1194
|
+
const hinweis = await cliUpdateHinweis(installiert, { protokoll: (zeile) => console.log(zeile) });
|
|
1195
|
+
if (hinweis === null)
|
|
1196
|
+
return;
|
|
1197
|
+
// Verlaufseintrag „CLI X verfügbar" (E80), einmal je neuer Version, vor der Sidebar-Meldung.
|
|
1198
|
+
await anwendungsfaelle
|
|
1199
|
+
.hmgrEreignisVermerken({ art: 'cli-verfuegbar', version: hinweis.neu }, letzterAusloeser)
|
|
1200
|
+
.catch((fehler) => {
|
|
1201
|
+
console.log(`[verlauf] ${fehler instanceof Error ? fehler.message : String(fehler)}`);
|
|
1202
|
+
});
|
|
1203
|
+
selbstUpdateMelden({ art: 'cli', ...hinweis });
|
|
1204
|
+
}
|
|
1205
|
+
/**
|
|
1206
|
+
* Jeder Aktualisieren-Lauf prüft auch hmgr selbst (E80: Start, Intervall, Klick auf den Kringel) —
|
|
1207
|
+
* der Renderer ruft das aus `aktualisierenLauf`, unabhängig vom Auslöser. Beide Wege sind
|
|
1208
|
+
* unabhängig: die GUI-Prüfung gilt nur unter den E73-Bedingungen, die CLI-Prüfung überall. Im
|
|
1209
|
+
* Smoke-Test unterbleiben beide — kein Spawn, kein Netz.
|
|
1210
|
+
*/
|
|
1211
|
+
function selbstUpdatePruefen() {
|
|
1212
|
+
if (smoketest)
|
|
1213
|
+
return;
|
|
1214
|
+
updatePruefen();
|
|
1215
|
+
void cliUpdatePruefen().catch((fehler) => {
|
|
1216
|
+
console.log(`[cli-update] ${fehler instanceof Error ? fehler.message : String(fehler)}`);
|
|
1217
|
+
});
|
|
1218
|
+
}
|
|
881
1219
|
/**
|
|
882
1220
|
* Holt das vorhandene Fenster nach vorn — die Antwort der laufenden Instanz auf einen zweiten
|
|
883
1221
|
* Start (E67). Minimiert kommt es erst wieder hoch, dann bekommt es den Fokus.
|
|
@@ -912,6 +1250,8 @@ if (einzelinstanz) {
|
|
|
912
1250
|
Menu.setApplicationMenu(null);
|
|
913
1251
|
}
|
|
914
1252
|
fensterOeffnen();
|
|
1253
|
+
// Seit E80 prüft schon der erste Aktualisieren-Lauf (Renderer, ausgelöst bei `did-finish-load`)
|
|
1254
|
+
// auch hmgr selbst über `selbstUpdatePruefen` — ein eigener Start-Aufruf hier wäre der zweite.
|
|
915
1255
|
app.on('activate', () => {
|
|
916
1256
|
if (BrowserWindow.getAllWindows().length === 0)
|
|
917
1257
|
fensterOeffnen();
|
package/dist/gui/preload.cjs
CHANGED
|
@@ -33,6 +33,12 @@ contextBridge.exposeInMainWorld('hmgr', {
|
|
|
33
33
|
eintragLoeschen: (args) => ipcRenderer.invoke('hmgr:eintragLoeschen', args),
|
|
34
34
|
uebernehmen: (args) => ipcRenderer.invoke('hmgr:uebernehmen', args),
|
|
35
35
|
aktualisieren: (args) => ipcRenderer.invoke('hmgr:aktualisieren', args),
|
|
36
|
+
/** Changelog der letzten Läufe (E80), neueste zuerst. */
|
|
37
|
+
verlauf: () => ipcRenderer.invoke('hmgr:verlauf'),
|
|
38
|
+
/** Installiert das geladene GUI-Update und startet neu (E80), Gegenstück zum Neustart-Knopf. */
|
|
39
|
+
neuStarten: () => {
|
|
40
|
+
ipcRenderer.send('hmgr:neuStarten');
|
|
41
|
+
},
|
|
36
42
|
arbeitsverzeichnisHinzufuegen: (pfad) => ipcRenderer.invoke('hmgr:arbeitsverzeichnisHinzufuegen', pfad),
|
|
37
43
|
arbeitsverzeichnisVergessen: (pfad) => ipcRenderer.invoke('hmgr:arbeitsverzeichnisVergessen', pfad),
|
|
38
44
|
/** Nativer Verzeichnis-Dialog fürs Pfadfeld in „Verzeichnis hinzufügen" (A1). */
|
|
@@ -43,6 +49,13 @@ contextBridge.exposeInMainWorld('hmgr', {
|
|
|
43
49
|
harnessAktivieren: (name) => ipcRenderer.invoke('hmgr:harnessAktivieren', name),
|
|
44
50
|
harnessDeaktivieren: (name) => ipcRenderer.invoke('hmgr:harnessDeaktivieren', name),
|
|
45
51
|
saeubern: (name) => ipcRenderer.invoke('hmgr:saeubern', name),
|
|
52
|
+
/** Homedirs je Harness (E78): zeigen, umstellen (F89), zusätzliche eintragen und vergessen (F87). */
|
|
53
|
+
harnessHeime: () => ipcRenderer.invoke('hmgr:harnessHeime'),
|
|
54
|
+
wslDistros: () => ipcRenderer.invoke('hmgr:wslDistros'),
|
|
55
|
+
harnessHeimSetzen: (args) => ipcRenderer.invoke('hmgr:harnessHeimSetzen', args),
|
|
56
|
+
harnessHeimZuruecksetzen: (harness) => ipcRenderer.invoke('hmgr:harnessHeimZuruecksetzen', harness),
|
|
57
|
+
harnessHeimHinzufuegen: (args) => ipcRenderer.invoke('hmgr:harnessHeimHinzufuegen', args),
|
|
58
|
+
harnessHeimEntfernen: (args) => ipcRenderer.invoke('hmgr:harnessHeimEntfernen', args),
|
|
46
59
|
/** Verwalteter Hermes-Skill-Ordner (E56): zeigen kommt über hmgr:istZustand, hier nur Ändern. */
|
|
47
60
|
skillOrdnerFestlegen: (args) => ipcRenderer.invoke('hmgr:skillOrdnerFestlegen', args),
|
|
48
61
|
skillOrdnerEntfernen: (args) => ipcRenderer.invoke('hmgr:skillOrdnerEntfernen', args),
|
|
@@ -54,15 +67,26 @@ contextBridge.exposeInMainWorld('hmgr', {
|
|
|
54
67
|
antwortenRueckfrage: (id, antwort) => {
|
|
55
68
|
ipcRenderer.send('hmgr:rueckfrage:antwort', { id, antwort });
|
|
56
69
|
},
|
|
57
|
-
/** Anstoß zum selbsttätigen Aktualisieren (E44): Main ruft nach dem Start und alle sechs Stunden
|
|
70
|
+
/** Anstoß zum selbsttätigen Aktualisieren (E44): Main ruft nach dem Start und alle sechs Stunden,
|
|
71
|
+
mit dem Auslöser für den Verlauf (E80). */
|
|
58
72
|
onAktualisierenAnstossen: (hoerer) => {
|
|
59
|
-
ipcRenderer.on('hmgr:aktualisierenAnstossen', () => hoerer());
|
|
73
|
+
ipcRenderer.on('hmgr:aktualisierenAnstossen', (_event, ausloeser) => hoerer(ausloeser));
|
|
60
74
|
},
|
|
61
75
|
/** Anstoß zum stillen Neuladen der Anzeige (E62): Main ruft bei Fokus-Wechsel und beobachteten
|
|
62
76
|
Dateiänderungen, nie mit Netzzugriff (im Unterschied zu onAktualisierenAnstossen). */
|
|
63
77
|
onNeuLadenAnstossen: (hoerer) => {
|
|
64
78
|
ipcRenderer.on('hmgr:neuLadenAnstossen', () => hoerer());
|
|
65
79
|
},
|
|
80
|
+
/** Prüfung auf neue hmgr-Stände (E77), angestoßen bei jedem Aktualisieren-Lauf (E80: Start,
|
|
81
|
+
Intervall, Klick). Antwortet nicht, meldet sich später über onSelbstUpdate — Netz und Spawn
|
|
82
|
+
dauern länger als ein Knopfdruck. */
|
|
83
|
+
selbstUpdatePruefen: () => {
|
|
84
|
+
ipcRenderer.send('hmgr:selbstUpdatePruefen');
|
|
85
|
+
},
|
|
86
|
+
/** Ein Fund der Selbst-Prüfung (E77): geladenes GUI-Update oder neuere CLI auf npm. */
|
|
87
|
+
onSelbstUpdate: (hoerer) => {
|
|
88
|
+
ipcRenderer.on('hmgr:selbstUpdate', (_event, nachricht) => hoerer(nachricht));
|
|
89
|
+
},
|
|
66
90
|
/** MCP-Ansicht (E61-Folgerunde): Katalog gelesen, nie geschrieben. */
|
|
67
91
|
mcpUebersicht: () => ipcRenderer.invoke('hmgr:mcpUebersicht'),
|
|
68
92
|
/** Plätze für den Einhängen-Dialog (F42): kommt aus dem Kern, hängt an der Fähigkeit (E16). */
|