diff --git a/.gitattributes b/.gitattributes index c614c3e..9ca5958 100644 --- a/.gitattributes +++ b/.gitattributes @@ -15,7 +15,11 @@ testdaten/** -text *.pdf binary *.ttf binary *.xlsx binary +*.icns binary # Linux-Skripte und -Dateien (Chromebook-Pakete) brauchen LF *.sh text eol=lf *.desktop text eol=lf + +# macOS-Paket: Skript und Info.plist mit LF +*.plist text eol=lf diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8f69577..eba0fd0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,4 +1,6 @@ # Baut die Solution und führt alle Tests aus – bei jedem Push und Pull Request. +# Zusätzlich auf macOS: Tests, App-Paket bauen und einmal starten (ersetzt einen fehlenden Test-Mac), und auf Windows +# mit ARM-Prozessor: Tests (ersetzt einen fehlenden Snapdragon-Laptop). # Warnungen (auch StyleCop und SonarAnalyzer) gelten als Fehler, siehe Directory.Build.props. name: Build und Tests @@ -40,3 +42,62 @@ jobs: path: | TestResults/**/*.trx TestResults/**/*.cobertura.xml + + macos: + runs-on: macos-latest + steps: + - uses: actions/checkout@v7 + + - uses: actions/setup-dotnet@v6 + with: + dotnet-version: '10.0.x' + + - name: Bauen + run: dotnet build AndiGenerator.slnx -c Release -nologo + + - name: Testen + run: dotnet test AndiGenerator.slnx -c Release --no-build -nologo --filter "Kategorie!=Messung" --logger "console;verbosity=minimal" + + - name: App-Paket bauen + run: | + dotnet publish src/AndiGenerator.Desktop -c Release -r osx-arm64 --self-contained -nologo -o publish -p:Version=0.0.0-ci + mkdir -p pakete + bash src/AndiGenerator.Desktop/macOS/paket-bauen.sh osx-arm64 0.0.0-ci publish pakete + + # Startet das Programm aus dem Disk-Image und prüft, dass es nach 20 Sekunden noch läuft (Laufzeit, Signatur, + # native Bibliotheken, Hauptfenster); ein Bildschirmfoto davon wird mit aufgehoben. + - name: Starten (Rauchtest) + run: | + hdiutil attach pakete/*.dmg -mountpoint /tmp/andigen -nobrowse + /tmp/andigen/AndiGenerator.NET.app/Contents/MacOS/AndiGenerator.NET > start.log 2>&1 & + pid=$! + sleep 20 + screencapture -x start.png || true + if ! kill -0 "$pid" 2>/dev/null; then cat start.log; echo "Programm ist beim Start beendet worden" >&2; exit 1; fi + kill "$pid" + hdiutil detach /tmp/andigen + + - name: Paket und Startbild aufheben + if: always() + uses: actions/upload-artifact@v7 + with: + name: macos + path: | + pakete/*.dmg + start.png + start.log + + windows-arm: + runs-on: windows-11-arm + steps: + - uses: actions/checkout@v7 + + - uses: actions/setup-dotnet@v6 + with: + dotnet-version: '10.0.x' + + - name: Bauen + run: dotnet build AndiGenerator.slnx -c Release -nologo + + - name: Testen + run: dotnet test AndiGenerator.slnx -c Release --no-build -nologo --filter "Kategorie!=Messung" --logger "console;verbosity=minimal" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7687389..a9b303b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,7 +1,8 @@ # Erzeugt eine neue Version auf GitHub Releases, sobald ein Tag wie v1.0.0 gepusht wird: -# bauen und testen, veröffentlichen (win-x64, eigenständig), mit Velopack Setup, portable ZIP und Update-Pakete +# bauen und testen, veröffentlichen (win-x64 und win-arm64, eigenständig), mit Velopack Setup, portable ZIP und Update-Pakete # erzeugen und alles als Release hochladen. Das installierte Programm findet die neue Version dort selbst. -# Danach kommen Linux-Pakete für Chromebooks dazu (x64 und arm64, je .deb und portables tar.gz; ohne Selbst-Update). +# Danach kommen Linux-Pakete für Chromebooks dazu (x64 und arm64, je .deb und portables tar.gz; ohne Selbst-Update) +# und macOS-Pakete (Apple-Chip und Intel, je .dmg mit ad hoc signiertem App-Paket; ohne Selbst-Update). name: Release on: @@ -43,6 +44,11 @@ jobs: - name: Veröffentlichen run: dotnet publish src/AndiGenerator.Desktop -c Release -r win-x64 --self-contained -nologo -o publish -p:Version=${{ steps.version.outputs.version }} + # Windows-Laptops mit ARM-Prozessor (Snapdragon): eigener Velopack-Kanal win-arm64 mit eigenem Setup; ein so + # installiertes Programm sucht Updates nur in diesem Kanal. + - name: Veröffentlichen (ARM64) + run: dotnet publish src/AndiGenerator.Desktop -c Release -r win-arm64 --self-contained -nologo -o publish-arm64 -p:Version=${{ steps.version.outputs.version }} + - name: Velopack installieren run: dotnet tool install -g vpk --version ${{ env.VPK_VERSION }} @@ -50,12 +56,23 @@ jobs: continue-on-error: true run: vpk download github --repoUrl ${{ github.server_url }}/${{ github.repository }} --token ${{ secrets.GITHUB_TOKEN }} + - name: Vorige ARM64-Version für Delta-Updates holen + continue-on-error: true + run: vpk download github --channel win-arm64 --repoUrl ${{ github.server_url }}/${{ github.repository }} --token ${{ secrets.GITHUB_TOKEN }} + - name: Pakete erzeugen run: > vpk pack --packId AndiGeneratorNET --packVersion ${{ steps.version.outputs.version }} --packDir publish --mainExe AndiGenerator.NET.exe --packTitle "AndiGenerator.NET" --packAuthors "Peter Buchmann" --icon src/AndiGenerator.UI/Assets/AndiGenerator.NET.ico + - name: Pakete erzeugen (ARM64) + run: > + vpk pack --packId AndiGeneratorNET --packVersion ${{ steps.version.outputs.version }} + --packDir publish-arm64 --mainExe AndiGenerator.NET.exe --packTitle "AndiGenerator.NET" + --packAuthors "Peter Buchmann" --icon src/AndiGenerator.UI/Assets/AndiGenerator.NET.ico + --channel win-arm64 --runtime win-arm64 + # Stückliste und Nachweise sind Zugaben: Scheitern sie, wird das Release trotzdem veröffentlicht. - name: Stückliste (SBOM) der ausgelieferten Dateien continue-on-error: true @@ -80,7 +97,7 @@ jobs: continue-on-error: true uses: actions/attest-sbom@v4 with: - subject-path: Releases/*-Setup.exe + subject-path: Releases/AndiGeneratorNET-win-Setup.exe sbom-path: AndiGeneratorNET-${{ steps.version.outputs.version }}-sbom.spdx.json - name: Auf GitHub Releases hochladen @@ -89,6 +106,12 @@ jobs: --token ${{ secrets.GITHUB_TOKEN }} --publish --releaseName "AndiGenerator.NET ${{ steps.version.outputs.version }}" --tag ${{ github.ref_name }} + - name: ARM64-Pakete zum Release hinzufügen + run: > + vpk upload github --channel win-arm64 --repoUrl ${{ github.server_url }}/${{ github.repository }} + --token ${{ secrets.GITHUB_TOKEN }} --publish --merge + --releaseName "AndiGenerator.NET ${{ steps.version.outputs.version }}" --tag ${{ github.ref_name }} + - name: Stückliste an das Release hängen continue-on-error: true env: @@ -133,3 +156,42 @@ jobs: env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: gh release upload ${{ github.ref_name }} pakete/* --clobber --repo ${{ github.repository }} + + # macOS (MacBook, iMac, Mac mini …): eigenständig veröffentlichen, zum App-Paket bündeln, ad hoc signieren und als + # Disk-Image an das Release hängen. Ohne Apple-Entwicklerkonto keine Beglaubigung (Notarisierung); siehe Anleitung. + macos: + needs: release + runs-on: macos-latest + strategy: + matrix: + rid: [ osx-arm64, osx-x64 ] + steps: + - uses: actions/checkout@v7 + + - uses: actions/setup-dotnet@v6 + with: + dotnet-version: 10.0.x + + - name: Version aus dem Tag + id: version + run: echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT" + + - name: Veröffentlichen + run: dotnet publish src/AndiGenerator.Desktop -c Release -r ${{ matrix.rid }} --self-contained -nologo -o publish -p:Version=${{ steps.version.outputs.version }} + + - name: Paket erzeugen + run: | + mkdir -p pakete + bash src/AndiGenerator.Desktop/macOS/paket-bauen.sh ${{ matrix.rid }} ${{ steps.version.outputs.version }} publish pakete + ls -l pakete + + - name: Herkunftsnachweis + continue-on-error: true + uses: actions/attest-build-provenance@v4 + with: + subject-path: pakete/* + + - name: An das Release hängen + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: gh release upload ${{ github.ref_name }} pakete/* --clobber --repo ${{ github.repository }} diff --git a/Doku/ANLEITUNG.md b/Doku/ANLEITUNG.md index 3d8aab2..b3993f8 100644 --- a/Doku/ANLEITUNG.md +++ b/Doku/ANLEITUNG.md @@ -38,16 +38,16 @@ Wenn Sie vorher mit dem Original-AndiGenerator gearbeitet haben, übernimmt Andi ## 2. Installation -AndiGenerator.NET läuft unter Windows 10 und 11 (64 Bit), auf Chromebooks und unter Linux (siehe unten). Administratorrechte sind nicht nötig, und .NET muss nicht installiert sein – alles Nötige ist dabei. +AndiGenerator.NET läuft unter Windows 10 und 11 (64 Bit), auf dem Mac (macOS 14 oder neuer), auf Chromebooks und unter Linux (siehe unten). Administratorrechte sind nicht nötig, und .NET muss nicht installiert sein – alles Nötige ist dabei. **Mit Setup (empfohlen)** -1. Auf der Seite [Releases](https://github.com/PBuchmann/AndiGenerator.NET/releases) bei der neuesten Version die Datei `AndiGeneratorNET-win-Setup.exe` herunterladen. +1. Auf der Seite [Releases](https://github.com/PBuchmann/AndiGenerator.NET/releases) bei der neuesten Version die Datei `AndiGeneratorNET-win-Setup.exe` herunterladen. Für Windows-Laptops mit ARM-Prozessor (z. B. Snapdragon) gibt es `AndiGeneratorNET-win-arm64-Setup.exe`; sie rechnet dort deutlich schneller. Welcher Prozessor eingebaut ist, steht unter *Einstellungen → System → Info → Systemtyp* („ARM-basierter Prozessor“). 2. Die Datei starten. Das Programm wird für Ihr Benutzerkonto installiert (im Ordner `%LOCALAPPDATA%\AndiGeneratorNET`), erscheint im Startmenü und auf dem Desktop und startet gleich. **Ohne Installation** -Stattdessen `AndiGeneratorNET-win-Portable.zip` herunterladen, in einen beliebigen Ordner entpacken und dort `AndiGenerator.NET.exe` starten. Diese Variante eignet sich z. B. für einen USB-Stick. +Stattdessen `AndiGeneratorNET-win-Portable.zip` (bzw. `AndiGeneratorNET-win-arm64-Portable.zip`) herunterladen, in einen beliebigen Ordner entpacken und dort `AndiGenerator.NET.exe` starten. Diese Variante eignet sich z. B. für einen USB-Stick. **Warnung von Windows beim ersten Start** @@ -61,14 +61,25 @@ Das installierte Programm sucht nach dem Start selbst nach einer neuen Version u Über *Einstellungen → Apps → Installierte Apps → AndiGenerator.NET → Deinstallieren*. Ihre Daten im Ordner `%LOCALAPPDATA%\AndiGenerator.NET` und Ihre click-TT-Dateien bleiben erhalten. +**Auf dem Mac** + +1. Auf der Seite [Releases](https://github.com/PBuchmann/AndiGenerator.NET/releases) das passende Disk-Image herunterladen: `AndiGeneratorNET--macos-arm64.dmg` für Macs mit Apple-Chip (M1 und neuer), `…-macos-x64.dmg` für ältere Macs mit Intel-Prozessor. Welcher Chip eingebaut ist, steht unter * → Über diesen Mac*. +2. Das Disk-Image öffnen und **AndiGenerator.NET** auf den Ordner **Programme** ziehen. +3. Beim ersten Start meldet macOS, dass Apple das Programm nicht überprüfen konnte, und öffnet es nicht – das Programm ist noch nicht von Apple beglaubigt. Die Meldung mit **Fertig** schließen, dann *Systemeinstellungen → Datenschutz & Sicherheit* öffnen, nach unten blättern und bei AndiGenerator.NET **Dennoch öffnen** wählen und mit dem Passwort bestätigen. Danach startet das Programm normal. + +Statt **Strg** gilt auf dem Mac die Befehlstaste **⌘** (z. B. ⌘ + Plus zum Vergrößern). Die eigenen Daten liegen im Ordner `~/Library/Application Support/AndiGenerator.NET`. Neue Versionen werden auf dem Mac nicht selbst gesucht – zum Aktualisieren das neue Disk-Image herunterladen und das Programm genauso in *Programme* ziehen (ersetzen). + **Auf einem Chromebook (und unter Linux)** Auf Chromebooks läuft das Programm in der Linux-Entwicklungsumgebung, die ChromeOS mitbringt. 1. Einmalig Linux einschalten: *Einstellungen → Info zu ChromeOS → Entwickler → Linux-Entwicklungsumgebung → Aktivieren* (bei älteren Versionen *Einstellungen → Erweitert → Entwickler*). 2. Auf der Seite [Releases](https://github.com/PBuchmann/AndiGenerator.NET/releases) das passende Paket herunterladen: `andigenerator-net__amd64.deb` für Chromebooks mit Intel- oder AMD-Prozessor, `…_arm64.deb` für Chromebooks mit ARM-Prozessor (z. B. MediaTek oder Qualcomm). Welcher Prozessor eingebaut ist, steht unter *Einstellungen → Info zu ChromeOS → Weitere Details*, oder im Linux-Terminal mit `dpkg --print-architecture`. -3. In der App *Dateien* doppelt auf die heruntergeladene Datei klicken und **Installieren** wählen. Das Programm erscheint danach im Launcher im Ordner *Linux-Apps*. -4. Die click-TT-Dateien müssen für Linux sichtbar sein: entweder in den Ordner *Linux-Dateien* legen oder einen Ordner in *Dateien* mit der rechten Maustaste **Mit Linux teilen**. +3. Die Datei in der App *Dateien* in den Ordner *Linux-Dateien* ziehen. +4. Das *Terminal* öffnen (im Launcher unter *Linux-Apps*) und eingeben – mit dem Dateinamen der heruntergeladenen Datei: + `sudo apt install ./andigenerator-net__amd64.deb` + ChromeOS bietet die Installation per Doppelklick nicht mehr an. Das Programm erscheint danach im Launcher im Ordner *Linux-Apps*. +5. Die click-TT-Dateien müssen für Linux sichtbar sein: entweder in den Ordner *Linux-Dateien* legen oder einen Ordner in *Dateien* mit der rechten Maustaste **Mit Linux teilen**. Ohne Installation geht es mit `AndiGeneratorNET--linux-x64.tar.gz` bzw. `…-linux-arm64.tar.gz`: entpacken und `./AndiGenerator.NET` starten. Unter Linux liegen die eigenen Daten im Ordner `~/.local/share/AndiGenerator.NET`. Neue Versionen werden hier nicht selbst gesucht – zum Aktualisieren das neue Paket genauso installieren. @@ -169,7 +180,7 @@ Im Automodus entfällt die Kachel *Pflichtregeln*; die Ergebniskachel nimmt ihre ![Ergebniskachel im Automodus](Anleitung/Bilder/18-automodus.png) -Den **Hauptbereich** füllen die Ansichten. Jede Ansicht öffnet sich als Reiter; Sie können mehrere öffnen, zwischen ihnen wechseln, sie per Maus nebeneinander anordnen und mit dem **×** am Reiter schließen. In vielen Ansichten vergrößert oder verkleinert **Strg + Mausrad** (oder der Zoomregler) die Darstellung. +Den **Hauptbereich** füllen die Ansichten. Jede Ansicht öffnet sich als Reiter; Sie können mehrere öffnen, zwischen ihnen wechseln, sie per Maus nebeneinander anordnen und mit dem **×** am Reiter schließen. In vielen Ansichten vergrößert oder verkleinert **Strg + Mausrad** (auf dem Mac auch **⌘ + Mausrad**, oder der Zoomregler) die Darstellung. Ganz unten zeigt die **Statuszeile** den Stand in einer Zeile. diff --git a/Doku/Anleitung.pdf b/Doku/Anleitung.pdf index aea64a2..2be5ec9 100644 Binary files a/Doku/Anleitung.pdf and b/Doku/Anleitung.pdf differ diff --git a/Doku/MIGRATIONSPLAN.md b/Doku/MIGRATIONSPLAN.md index f47f294..387a09a 100644 --- a/Doku/MIGRATIONSPLAN.md +++ b/Doku/MIGRATIONSPLAN.md @@ -735,3 +735,5 @@ Befund: Billigere Pläne nach der Kostenfunktion des Originals sind nicht automa | 05.10.2026 | Release: zusätzlich Linux-Pakete für Chromebooks (Linux-Entwicklungsumgebung) – eigenständig veröffentlicht für linux-x64 und linux-arm64, je Debian-Paket (`/opt/andigenerator-net`, Eintrag im Launcher) und portables tar.gz (`src/AndiGenerator.Desktop/Linux/paket-bauen.sh`, Job `linux` im Release-Workflow); ohne Selbst-Update | | 05.10.2026 | Bildschirmfotos der Anleitung automatisch: `bildschirmfotos.cmd` startet den UI-Test `Bildschirmfotos` (Avalonia.Headless mit Skia, 1400 × 860, 150 %), der mit der anonymisierten Staffel R2_4 Startseite, Einrichtung, Kostenoptimierung mit allen Ansichten, Automodus (neues Bild 18-automodus: Ergebniskachel) und die Dialoge aufnimmt; ohne Umgebungsvariable `ANDIGEN_BILDER` tut der Test nichts. | | 05.10.2026 | Anleitung: eigener Abschnitt 5.1 „Der Automodus“ (Phasen, Wertung des besten Plans, Eingreifen, Wahl des Verfahrens); Abschnitt 3.5 verweist darauf. Nach dem Start zeigen Ansichten, die „Start mit“ auf den Ausgangsplan gestellt hatte, wieder die laufende Generierung (vorher blieb dort der unveränderte Ausgangsplan stehen). Bildschirmfotos von Teilen des Fensters: ganzes Fenster zeichnen und zuschneiden (beim Zeichnen nur eines Teils zerfiel die Schrift). | +| 10.10.2026 | macOS (Weg zu 1.0, Vorgabe Peter): Release-Job `macos` baut für osx-arm64 und osx-x64 ein App-Paket (`src/AndiGenerator.Desktop/macOS`: Info.plist, Symbol .icns, `paket-bauen.sh`), signiert es ad hoc (ohne Apple-Entwicklerkonto keine Notarisierung, erster Start über „Dennoch öffnen“) und hängt je ein .dmg an das Release; ohne Selbst-Update wie unter Linux. CI baut, testet und startet die App zusätzlich auf macOS (Rauchtest mit Bildschirmfoto), da kein Test-Mac vorhanden ist. Oberfläche: Zoom auch mit ⌘ (Tasten und Mausrad), Programmmenü des Macs mit „Über“ und „Anleitung“. Anleitung: Abschnitt Mac; Chromebook-Installation per Terminal (`sudo apt install`), da ChromeOS .deb-Dateien nicht mehr per Doppelklick installiert. | +| 10.10.2026 | Windows auf ARM (Snapdragon-Laptops): Release veröffentlicht zusätzlich win-arm64 und packt es als eigenen Velopack-Kanal `win-arm64` (eigenes Setup und Portable-ZIP, Updates nur in diesem Kanal), hochgeladen mit `--merge` ins selbe Release. CI testet zusätzlich auf `windows-11-arm`. Anleitung und README nennen die ARM-Dateien. | diff --git a/README.md b/README.md index 392447d..76753c9 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ AndiGenerator.NET ist die C#/.NET-Portierung des **AndiGenerators** von **Andrea ## Installation -Die neueste Version gibt es unter [Releases](https://github.com/PBuchmann/AndiGenerator.NET/releases): `AndiGeneratorNET-win-Setup.exe` installiert das Programm für den eigenen Benutzer (ohne Administratorrechte) und hält es danach selbst aktuell; `AndiGeneratorNET-win-Portable.zip` läuft ohne Installation. Windows 10/11, 64 Bit. Für Chromebooks (Linux-Entwicklungsumgebung) und Linux gibt es Debian-Pakete `andigenerator-net__amd64.deb` bzw. `_arm64.deb` und portable `tar.gz`. Bis zur digitalen Signierung warnt Windows beim ersten Start – Einzelheiten in der [Anleitung](Doku/ANLEITUNG.md#2-installation). +Die neueste Version gibt es unter [Releases](https://github.com/PBuchmann/AndiGenerator.NET/releases): `AndiGeneratorNET-win-Setup.exe` installiert das Programm für den eigenen Benutzer (ohne Administratorrechte) und hält es danach selbst aktuell; `AndiGeneratorNET-win-Portable.zip` läuft ohne Installation. Windows 10/11, 64 Bit; für Windows-Laptops mit ARM-Prozessor (Snapdragon) `AndiGeneratorNET-win-arm64-Setup.exe` bzw. `-win-arm64-Portable.zip`. Für Macs (macOS 14 oder neuer) gibt es Disk-Images `AndiGeneratorNET--macos-arm64.dmg` (Apple-Chip) bzw. `-macos-x64.dmg` (Intel). Für Chromebooks (Linux-Entwicklungsumgebung) und Linux gibt es Debian-Pakete `andigenerator-net__amd64.deb` bzw. `_arm64.deb` und portable `tar.gz`. Bis zur digitalen Signierung warnt Windows beim ersten Start – Einzelheiten in der [Anleitung](Doku/ANLEITUNG.md#2-installation). ## Selbst bauen diff --git a/src/AndiGenerator.Desktop/macOS/AndiGenerator.NET.icns b/src/AndiGenerator.Desktop/macOS/AndiGenerator.NET.icns new file mode 100644 index 0000000..3d5175c Binary files /dev/null and b/src/AndiGenerator.Desktop/macOS/AndiGenerator.NET.icns differ diff --git a/src/AndiGenerator.Desktop/macOS/Info.plist b/src/AndiGenerator.Desktop/macOS/Info.plist new file mode 100644 index 0000000..d07a25e --- /dev/null +++ b/src/AndiGenerator.Desktop/macOS/Info.plist @@ -0,0 +1,35 @@ + + + + + + CFBundleName + AndiGenerator.NET + CFBundleDisplayName + AndiGenerator.NET + CFBundleIdentifier + io.github.pbuchmann.andigenerator-net + CFBundleExecutable + AndiGenerator.NET + CFBundleIconFile + AndiGenerator.NET.icns + CFBundlePackageType + APPL + CFBundleInfoDictionaryVersion + 6.0 + CFBundleDevelopmentRegion + de + CFBundleShortVersionString + @KURZVERSION@ + CFBundleVersion + @VERSION@ + LSMinimumSystemVersion + 14.0 + LSApplicationCategoryType + public.app-category.sports + NSHighResolutionCapable + + NSHumanReadableCopyright + © 2017 Andreas Hofmann, © 2026 Peter Buchmann · GPL-3.0 + + diff --git a/src/AndiGenerator.Desktop/macOS/paket-bauen.sh b/src/AndiGenerator.Desktop/macOS/paket-bauen.sh new file mode 100755 index 0000000..ff61820 --- /dev/null +++ b/src/AndiGenerator.Desktop/macOS/paket-bauen.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash +# macOS-Paket: App-Paket AndiGenerator.NET.app aus einer eigenständigen Veröffentlichung, ad hoc signiert, als +# Disk-Image (.dmg) mit Verknüpfung zum Ordner „Programme“. Läuft nur auf macOS (codesign, hdiutil). +# Aufruf (Release-Workflow): paket-bauen.sh +# rid: osx-arm64 (Macs mit Apple-Chip M1 …) oder osx-x64 (Macs mit Intel-Prozessor) +set -euo pipefail + +rid="$1" +version="$2" +publish="$(realpath "$3")" +ziel="$(realpath "$4")" +hier="$(dirname "$(realpath "$0")")" + +case "$rid" in + osx-arm64 | osx-x64) name="macos-${rid#osx-}" ;; + *) echo "Unbekannte Laufzeit: $rid" >&2; exit 1 ;; +esac + +arbeit="$(mktemp -d)" +inhalt="$arbeit/dmg" +app="$inhalt/AndiGenerator.NET.app" +mkdir -p "$app/Contents/MacOS" "$app/Contents/Resources" + +# Programm (mit .NET-Laufzeit und Anleitung) nach Contents/MacOS, Symbol nach Contents/Resources. +cp -R "$publish/." "$app/Contents/MacOS/" +cp "$hier/AndiGenerator.NET.icns" "$app/Contents/Resources/" +chmod 755 "$app/Contents/MacOS/AndiGenerator.NET" + +# Die Kurzversion muss rein numerisch sein (1.0.0-beta.1 → 1.0.0); die volle Version steht in CFBundleVersion. +sed -e "s/@VERSION@/$version/g" -e "s/@KURZVERSION@/${version%%-*}/g" "$hier/Info.plist" > "$app/Contents/Info.plist" +plutil -lint "$app/Contents/Info.plist" + +# Ad-hoc-Signatur: Ohne Signatur startet auf Macs mit Apple-Chip gar nichts. Sie ersetzt keine Beglaubigung durch +# Apple (Notarisierung) – beim ersten Start fragt macOS deshalb nach (Anleitung: „Dennoch öffnen“). +codesign --force --deep --sign - "$app" +codesign --verify --deep --strict "$app" + +# Disk-Image: App-Paket und Verknüpfung zu /Applications zum Hineinziehen. +ln -s /Applications "$inhalt/Programme" +hdiutil create -volname "AndiGenerator.NET" -srcfolder "$inhalt" -ov -format UDZO "$ziel/AndiGeneratorNET-$version-$name.dmg" +rm -rf "$arbeit" diff --git a/src/AndiGenerator.UI/App.axaml b/src/AndiGenerator.UI/App.axaml index 48a5876..8f9c79b 100644 --- a/src/AndiGenerator.UI/App.axaml +++ b/src/AndiGenerator.UI/App.axaml @@ -2,6 +2,7 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:ui="using:AndiGenerator.UI" x:Class="AndiGenerator.UI.App" + Name="AndiGenerator.NET" RequestedThemeVariant="Light"> diff --git a/src/AndiGenerator.UI/App.axaml.cs b/src/AndiGenerator.UI/App.axaml.cs index 056479d..3558921 100644 --- a/src/AndiGenerator.UI/App.axaml.cs +++ b/src/AndiGenerator.UI/App.axaml.cs @@ -33,8 +33,26 @@ public override void OnFrameworkInitializationCompleted() desktop.ShutdownMode = ShutdownMode.OnMainWindowClose; desktop.Exit += (_, _) => modell.Dispose(); fenster.Opened += (_, _) => Aktualisierung.Starten(oberflaeche); + if (OperatingSystem.IsMacOS()) + { + NativeMenu.SetMenu(this, Programmmenue(modell)); + } } base.OnFrameworkInitializationCompleted(); } + + /// + /// Programmmenü des Macs (oben links in der Menüleiste, unter dem Programmnamen): „Über“ und die Anleitung statt der + /// Vorgabe von Avalonia. Beenden, Ausblenden usw. ergänzt macOS selbst. + /// + /// Das Hauptfenster mit den Befehlen. + /// Das Menü. + private static NativeMenu Programmmenue(HauptfensterViewModel modell) + { + var menue = new NativeMenu(); + menue.Items.Add(new NativeMenuItem("Über AndiGenerator.NET") { Command = modell.UeberCommand }); + menue.Items.Add(new NativeMenuItem("Anleitung") { Command = modell.AnleitungCommand }); + return menue; + } } diff --git a/src/AndiGenerator.UI/HauptfensterView.axaml b/src/AndiGenerator.UI/HauptfensterView.axaml index 24c5a36..1ed393f 100644 --- a/src/AndiGenerator.UI/HauptfensterView.axaml +++ b/src/AndiGenerator.UI/HauptfensterView.axaml @@ -17,6 +17,13 @@ + + + + + + +