RemminaMac 0.1.0: SSH/RDP-Client für macOS (SwiftUI, Remmina-Layout, Profile, SSH-Keys, Docs, Release-Skripte)
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
# Architektur
|
||||
|
||||
```
|
||||
Sources/RemminaMac/
|
||||
RemminaMacApp.swift # @main, WindowGroup, lädt ProfileStore
|
||||
Models/ConnectionProfile.swift # ProtocolType + ConnectionProfile + StoredSSHKey (Codable)
|
||||
Stores/ProfileStore.swift # ObservableObject, JSON-Persistenz, Filter/Suche/Gruppen
|
||||
Security/KeychainHelper.swift# SecItemAdd/Copy/Delete Wrapper
|
||||
Services/ConnectionServices.swift # SSHService (ssh-Befehl) + RDPService (freerdp/rdc/vnc)
|
||||
Views/ContentView.swift # NavigationSplitView: Sidebar + Tabs + Statusbar
|
||||
Views/SessionView.swift # Detail pro Sitzung
|
||||
Views/ProfileEditorView.swift# Formular Neu/Bearbeiten + Keychain-Anbindung
|
||||
Views/SSHKeysView.swift # Key-Liste, Import, ssh-keygen
|
||||
```
|
||||
|
||||
## Datenfluss
|
||||
1. `RemminaMacApp` erstellt `ProfileStore` als `@StateObject`, injiziert als `environmentObject`.
|
||||
2. `ProfileStore.load()` liest `profiles.json` + `sshkeys.json`, sonst Sample-Daten.
|
||||
3. `ContentView` filtert via `searchText`/`selectedGroup`, `selection` steuert Detail.
|
||||
4. `connect(_:)` setzt `lastConnected`, öffnet Tab, delegiert an `SSHService`/`RDPService`.
|
||||
5. Secrets nur via `KeychainHelper`, JSON enthält nur Account-Referenzen.
|
||||
|
||||
## Wichtige Dateien
|
||||
- `Stores/ProfileStore.swift:13` — Pfade + `load()`/`save()`
|
||||
- `Models/ConnectionProfile.swift:3` — Protokoll-Defaults (Ports, Icons)
|
||||
- `Services/ConnectionServices.swift:6` — `sshArguments(for:key:)`
|
||||
- `Views/ContentView.swift` — Remmina-Layout
|
||||
|
||||
## Nächste Ausbaustufen
|
||||
1. SwiftTerm-View statt externem Terminal + `swift-nio-ssh` für echte SSH-Sessions.
|
||||
2. FreeRDP als XPC-Service einbetten statt `Process`.
|
||||
3. SFTP-Browser (NIO SFTP oder libssh2-Bridge).
|
||||
4. Export/Import-Buttons + Drag&Drop für Keys.
|
||||
@@ -0,0 +1,77 @@
|
||||
# Fehlerprotokoll (ERRORS.md)
|
||||
|
||||
Alle Fehler, die beim Erstellen / Bauen / Releasen von RemminaMac aufgetreten sind — mit Ursache, Fix und Status. Wird bei jedem Build fortgeschrieben.
|
||||
|
||||
Stand: 2026-09-21 · Version 0.1.0 · macOS arm64 · Swift 5.9+ · Xcode 15+
|
||||
|
||||
## Übersicht
|
||||
| # | Zeitpunkt | Phase | Fehler | Schwere | Status |
|
||||
|---|-----------|-------|--------|---------|--------|
|
||||
| 1 | 2026-09-21 | `swift build` (debug) | `WindowGroup<some View> has no member 'windowTitle'` | blockierend | ✅ behoben |
|
||||
| 2 | 2026-09-21 | `swift build -c release` | keine Fehler, nur lange Link-Zeit (~40 s) | Info | ✅ ok |
|
||||
| 3 | 2026-09-21 | Release-Skript | `dist/` war nicht in `.gitignore` → Binary drohte committet zu werden | mittel | ✅ behoben (ignoriert) |
|
||||
|
||||
---
|
||||
|
||||
## #1 — `windowTitle` existiert nicht auf `WindowGroup`
|
||||
**Phase:** erster `swift build`
|
||||
**Log (gekürzt):**
|
||||
```
|
||||
Sources/RemminaMac/RemminaMacApp.swift:14:10: error: value of type 'WindowGroup<some View>' has no member 'windowTitle'
|
||||
14 | .windowTitle("RemminaMac")
|
||||
```
|
||||
**Ursache:** `windowTitle(_:)` ist kein Modifier für `WindowGroup`. Der Fenstertitel wird im `WindowGroup`-Init übergeben.
|
||||
**Fix:** `Sources/RemminaMac/RemminaMacApp.swift`:
|
||||
```swift
|
||||
// vorher (falsch):
|
||||
WindowGroup { ... }.windowTitle("RemminaMac")
|
||||
// nachher (korrekt):
|
||||
WindowGroup("RemminaMac") { ... }
|
||||
```
|
||||
**Verifikation:** `swift build` → `Build complete! (1.31s)`.
|
||||
**Status:** ✅ behoben, kein Re-Check offen.
|
||||
|
||||
## #2 — Release-Build langsam, aber fehlerfrei
|
||||
**Phase:** `bash scripts/build-release.sh 0.1.0` → `swift build -c release`
|
||||
**Log:**
|
||||
```
|
||||
Building for production...
|
||||
[4/5] Linking RemminaMac
|
||||
Build complete! (40.54s)
|
||||
```
|
||||
**Ursache:** keine — Release-Optimierung + Link brauchen beim ersten Mal ~40 s.
|
||||
**Fix:** keiner nötig. Bei wiederholten Builds ist es schneller (Cache in `.build/`).
|
||||
**Artefakte:**
|
||||
```
|
||||
dist/RemminaMac-0.1.0-macos-arm64.zip (186K)
|
||||
dist/RemminaMac-0.1.0-macos-arm64.zip.sha256 (c476bb3c…)
|
||||
```
|
||||
**Status:** ✅ ok.
|
||||
|
||||
## #3 — `dist/` fast committet
|
||||
**Phase:** Release-Vorbereitung
|
||||
**Ursache:** `dist/` enthielt ZIP + entpacktes Binary, `.gitignore` kannte es noch nicht.
|
||||
**Fix:** `.gitignore` ergänzt:
|
||||
```
|
||||
.build/
|
||||
dist/
|
||||
*.zip
|
||||
*.sha256
|
||||
```
|
||||
**Verifikation:** `git status --short` zeigt kein `dist/` mehr.
|
||||
**Status:** ✅ behoben.
|
||||
|
||||
## Vorlage für neue Fehler
|
||||
```markdown
|
||||
## #N — Titel
|
||||
**Phase:** ...
|
||||
**Log:** ...
|
||||
**Ursache:** ...
|
||||
**Fix:** ...
|
||||
**Verifikation:** ...
|
||||
**Status:** ⬜ offen / ✅ behoben
|
||||
```
|
||||
|
||||
## Wie Fehler hierher kommen
|
||||
- Jeder `swift build` / `swift build -c release` / Skript-Lauf mit Fehler → Log-Ausschnitt + Exit-Code hier eintragen.
|
||||
- Gitea-Push/Release-Fehler (z. B. 401, Repo existiert schon, Asset-Upload schlägt fehl) ebenfalls hier dokumentieren.
|
||||
@@ -0,0 +1,40 @@
|
||||
# Installation
|
||||
|
||||
## Voraussetzungen
|
||||
- macOS 14+
|
||||
- Xcode 15+ (für GUI-Run) oder nur Swift-Toolchain 5.9+ (für CLI-Build)
|
||||
|
||||
## Variante A: Xcode (empfohlen für GUI)
|
||||
1. `open Package.swift` in `RemminaMac/`
|
||||
2. Target `RemminaMac` wählen, Destination `My Mac`
|
||||
3. `Cmd+R` → App startet
|
||||
4. Erster Start legt an:
|
||||
- `~/Library/Application Support/RemminaMac/profiles.json`
|
||||
- `~/Library/Application Support/RemminaMac/sshkeys.json`
|
||||
|
||||
## Variante B: Swift CLI
|
||||
```bash
|
||||
cd RemminaMac
|
||||
swift build
|
||||
.build/debug/RemminaMac
|
||||
```
|
||||
|
||||
## Variante C: Release-Binary (ohne Xcode)
|
||||
```bash
|
||||
./scripts/build-release.sh
|
||||
unzip dist/RemminaMac-*-macos-arm64.zip -d /tmp/rmm
|
||||
/tmp/rmm/RemminaMac
|
||||
```
|
||||
|
||||
## RDP-Voraussetzungen
|
||||
```bash
|
||||
# Für volle RDP-Unterstützung:
|
||||
brew install freerdp
|
||||
which xfreerdp
|
||||
# Ohne FreeRDP: Microsoft Remote Desktop aus dem App Store installieren
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
- `swift build` schlägt fehl → `swift --version` prüfen (>= 5.9), Xcode Command Line Tools: `xcode-select --install`
|
||||
- Keychain-Prompt → einmal erlauben, Service `RemminaMac`
|
||||
- `xfreerdp` nicht gefunden → Fallback nutzt `rdc://`, braucht MS Remote Desktop
|
||||
@@ -0,0 +1,36 @@
|
||||
# Releasing
|
||||
|
||||
## Lokal bauen
|
||||
```bash
|
||||
./scripts/build-release.sh [version]
|
||||
# Beispiel:
|
||||
./scripts/build-release.sh 0.1.0
|
||||
# Output:
|
||||
# dist/RemminaMac-0.1.0-macos-arm64.zip
|
||||
# dist/RemminaMac-0.1.0-macos-arm64.zip.sha256
|
||||
# dist/RemminaMac-0.1.0-macos-arm64/RemminaMac (Binary)
|
||||
```
|
||||
|
||||
## Was das Skript macht
|
||||
1. `swift build -c release`
|
||||
2. Binary nach `dist/RemminaMac-<ver>-macos-arm64/` kopieren
|
||||
3. `README.md` + `docs/` + `LICENSE` dazulegen
|
||||
4. ZIP + SHA256 erzeugen
|
||||
|
||||
## Gitea-Release erstellen
|
||||
```bash
|
||||
export GITEA_HOST="https://git.sysdaemon.xyz"
|
||||
export GITEA_OWNER="<owner>"
|
||||
export GITEA_REPO="remmina-mac"
|
||||
export GITEA_TOKEN="<token>" # statt Passwort: User → Settings → Applications → Token
|
||||
export VERSION="0.1.0"
|
||||
./scripts/publish-gitea-release.sh
|
||||
```
|
||||
Das Skript erstellt (falls nötig) das Release `v0.1.0` und lädt ZIP + SHA256 als Attachments hoch.
|
||||
|
||||
## Manuell via API
|
||||
```bash
|
||||
curl -u "user:pass" -H "Content-Type: application/json" \
|
||||
-d '{"tag_name":"v0.1.0","name":"v0.1.0","body":"Erstes Release"}' \
|
||||
"$GITEA_HOST/api/v1/repos/$OWNER/$REPO/releases"
|
||||
```
|
||||
@@ -0,0 +1,36 @@
|
||||
# Benutzung
|
||||
|
||||
## Layout (wie Remmina)
|
||||
- **Links:** Gruppen-Dropdown, Suche, Profil-Liste. Rechtsklick: Verbinden / Duplizieren / Bearbeiten / Löschen. Doppelklick verbindet.
|
||||
- **Rechts:** Tabs aller offenen Sitzungen + Verbindungsdetails (kopierbarer Befehl) + Hinweis-Box.
|
||||
- **Unten:** Statusbar mit Profil-/Sitzungs-Zähler.
|
||||
- **Toolbar:** `+` Neu, Stift Bearbeiten, Kopie-Symbol Duplizieren, Schlüssel Keys, `▶` Verbinden, `⚡` Quick-Connect.
|
||||
|
||||
## Profil anlegen
|
||||
1. `+` → Name, Gruppe, Protokoll (SSH/SFTP/RDP/VNC), Host, Port, User ausfüllen.
|
||||
2. SSH-Key wählen (vorher unter Schlüssel-Icon importieren).
|
||||
3. Optional Passwort → Haken „in Keychain speichern“.
|
||||
4. Speichern → liegt sofort in `profiles.json`.
|
||||
|
||||
## Verbinden
|
||||
- Profil wählen → `▶ Verbinden` oder Doppelklick.
|
||||
- SSH/SFTP: öffnet Terminal.app mit `ssh -p PORT -i KEY user@host`. Befehl steht zusätzlich kopierbar in der Detailansicht.
|
||||
- RDP: startet `xfreerdp` (falls vorhanden) oder öffnet MS Remote Desktop.
|
||||
- VNC: öffnet `vnc://host:port`.
|
||||
|
||||
## SSH-Keys verwalten (Schlüssel-Icon)
|
||||
- `Import aus ~/.ssh`: übernimmt alle privaten Keys (ohne `*.pub`, `known_hosts`, `config`).
|
||||
- `Wählen…`: Picker für Key-Datei.
|
||||
- `Neuen Key generieren`: ruft `/usr/bin/ssh-keygen -t ed25519 -f ~/.ssh/remminamac_<timestamp>` auf.
|
||||
- Passphrase → Keychain (`sshkey-<UUID>`).
|
||||
|
||||
## Quick-Connect
|
||||
- Mit Auswahl: verbindet direkt. Ohne Auswahl: öffnet Editor mit „Quick-Connect“-Vorlage.
|
||||
|
||||
## Export / Import (manuell, bis GUI-Buttons kommen)
|
||||
```bash
|
||||
PROFILE_DIR=~/Library/Application\ Support/RemminaMac
|
||||
cp "$PROFILE_DIR/profiles.json" ~/Desktop/remminamac-backup.json
|
||||
# Import:
|
||||
cp ~/Desktop/remminamac-backup.json "$PROFILE_DIR/profiles.json"
|
||||
```
|
||||
Reference in New Issue
Block a user