- HTML 76.8%
- JavaScript 11.7%
- Python 10.5%
- Shell 1%
| .gitignore | ||
| app.html | ||
| COPYRIGHT | ||
| desktop_ui.js | ||
| finanzplan-desktop | ||
| finanzplan_desktop.py | ||
| fpsync.py | ||
| icon.svg | ||
| install.sh | ||
| LICENSE | ||
| README.md | ||
| requirements.txt | ||
| test_fpsync.py | ||
Finanzplan — Desktop-Client (Linux)
Ein Desktop-Client für die Finanzplan-App, der dieselbe app.html wie die
Android-App in einem nativen Fenster (WebKitGTK via pywebview) laufen lässt und
sich per Partner-Sync direkt im WLAN mit dem Handy abgleicht.
- Kein Server, keine Cloud. Der Abgleich geht ausschließlich direkt
Desktop ↔ Handy im lokalen Netz, jede Nachricht AES-256-GCM-verschlüsselt.
Das ist exakt dasselbe Protokoll wie zwischen zwei Telefonen (
SyncManager.kt), nur in Python nachgebaut (fpsync.py). - Daten liegen lokal im WebView-Speicher unter
~/.local/share/finanzplan. - Kein Codewechsel an der App.
app.htmlist unverändert übernommen; sie blendet ihren eigenen Sync-Knopf aus, wenn keine Android-Bridge da ist – der Sync läuft hier stattdessen über das Fenstermenü.
Einrichten (Fedora / Hyprland)
Einmalig die System-Bausteine für WebKitGTK installieren (die kommen nicht aus pip):
sudo dnf install python3-gobject gtk3 webkit2gtk4.1
Dann starten – der erste Start legt automatisch eine .venv an und installiert
die Python-Pakete hinein:
./finanzplan-desktop
Die venv wird mit
--system-site-packageserstellt, damit sie das per dnf installierte PyGObject/WebKitGTK mitbenutzt; nur die reinen Python-Pakete (pywebview,cryptography,zeroconf,qrcode,secretstorage) landen in der venv.
In den App-Launcher / dmenu eintragen
Damit finanzplan-desktop überall aufrufbar ist und als Eintrag „Finanzplan"
im App-Launcher (dmenu, dank shell, Wofi, …) auftaucht:
./install.sh
Das legt an:
- einen Symlink
~/.local/bin/finanzplan-desktop→ Start-Skript (der Ordner liegt im PATH), - einen
.desktop-Eintrag~/.local/share/applications/finanzplan-desktop.desktop, - das Icon unter
~/.local/share/icons/hicolor/scalable/apps/.
Rückgängig: ./install.sh --uninstall.
Warum nicht einfach den Ordner in den PATH legen? Dann kollidiert der Verzeichnisname
finanzplan-desktopmit dem gleichnamigen Kommando – die Shell findet zuerst das Verzeichnis und meldet „keine Berechtigung". Der Symlink in~/.local/binlöst genau das (das Start-Skript nutztreadlink -fund findet seinen Ordner auch über den Symlink).
In Hyprland alternativ per Keybind (hyprland.conf):
bind = $mainMod, F, exec, finanzplan-desktop
Skalierung & Diagramme (nur Desktop)
Auf dem großen Bildschirm blendet der Client eine kleine Leiste unten links ein:
-
Zoom – Knöpfe
−/ Prozent /+, oder per Tastatur Strg + / Strg − / Strg 0 (zurücksetzen), oder Strg + Mausrad. Die Stufe wird gemerkt (localStorage, nur auf diesem Rechner – wandert nicht in den Sync). Skaliert wird über WebKit selbst, genau wie der Zoom eines Browsers. -
📊 Diagramme – ein Overlay in zwei Abschnitten (Esc schließt):
- Anteile (Ringe): anstehende Ausgaben nach Kategorie, Nötig/Optional,
laufende Kosten pro Monat, Ausgegeben-Log des laufenden Jahres. Kategorien
zählen auf ihrer obersten Ebene (
Freizeit/Kino→Freizeit), wie in der App; hineindrillen kann man dort. - Verlauf: Balken für Monatsportionen — Ausgegeben/Erhalten je Monat und Bleibt übrig je Monat (dieselbe Zahl wie die Monatssaldo-Karte, ohne Projektion). Linien für Stände und Entwicklungen — Kontostand (die eingetragenen Überträge über zwei Jahre), Laufende Kosten je Monat (macht schleichende Erhöhungen sichtbar) und der Jahresvergleich (aufgelaufene Ausgaben, laufendes Jahr gegen Vorjahr). Zum Schluss die Budget-Stände. Ohne Werteachse, dafür Werte im Tooltip und die Eckwerte in der Legende.
Beim Kontostand gilt: gemessen ist nur, was eingetragen wurde. Monate ohne Übertrag bekommen keinen Punkt, die Überbrückung ist gestrichelt, und der fortgeschriebene „heute"-Punkt ist hohl statt gefüllt. Die Linien-Achse beginnt bei null – sähe eine Kurve sonst dramatisch aus, wäre das nur der Maßstab, nicht die Sache.
Karten ohne Daten fallen weg. Gerechnet wird mit den Funktionen der App (
monatSaldo,currentRecs,spentSum, …), nicht mit Nachbauten – ein eigener Nachbau wird beim nächsten Schema-Schritt still falsch. - Anteile (Ringe): anstehende Ausgaben nach Kategorie, Nötig/Optional,
laufende Kosten pro Monat, Ausgegeben-Log des laufenden Jahres. Kategorien
zählen auf ihrer obersten Ebene (
Diese Extras stecken in desktop_ui.js und werden nach dem Laden in die
unveränderte app.html injiziert – die App-Datei selbst bleibt also byteidentisch
zur Android-Version und kann bei einem Update weiter einfach überkopiert werden.
Injiziert wird als
new Function("…")mit dem Quelltext als JSON-Zeichenkette. Das ist nötig, weil pywebview WebKit die Skriptlänge in Zeichen meldet, WebKit aber in Bytes rechnet: mit Umlauten oder Emoji im Skript schneidet WebKit hinten ab und wirftSyntaxError: Unexpected end of script– dann fehlt die Leiste ersatzlos. Als JSON ist die Zusendung reines ASCII.
Beenden
Fenster zu, Menü „Programm“ → Beenden, Strg + Q, oder Strg + C im Terminal – alles vier beendet den Client.
Früher ging keins davon: der Client las das Erscheinungsbild erst beim Schließen per
evaluate_jsaus der Seite. Dieser Aufruf läuft im GTK-Haupt- faden und wartet dort auf eine Antwort, die nur derselbe – gerade blockierte – Faden liefern könnte. Das Fenster blieb hängen und half nur nochkill. Heute meldet die Seite jede Änderung sofort (desktop_ui.js→pywebview.api.theme), und Strg + C hängt überGLib.unix_signal_addin der GTK-Schleife.
Wenn das Fenster zäh wirkt
WebKitGTK ist nicht auf jeder Treiber-/Compositor-Kombination gleich flott. Zum Eingrenzen:
FP_KEIN_DMABUF=1 finanzplan-desktop # ohne DMABUF-Pfad (setzt WEBKIT_DISABLE_DMABUF_RENDERER)
FP_DEBUG=1 finanzplan-desktop # Rechtsklick → „Element untersuchen“ zum Nachmessen
Der Client selbst schaltet enable-smooth-scrolling ein (WebKit hat das ab Werk
aus, das Mausrad springt sonst in groben Stufen) und hängt den wheel-Horcher
fürs Strg-Zoomen nur an, solange Strg gedrückt ist – ein dauerhaft nicht-passiver
Horcher nimmt WebKit das nebenläufige Scrollen weg.
Dunkelmodus
Der Dunkelmodus kommt aus der App selbst (ab v2.9.0): Menü → Erscheinungsbild
schaltet durch Folgt dem System · Immer hell · Immer dunkel, die Wahl liegt im
localStorage dieses Rechners. Zwei Dinge macht nur der Desktop-Client:
- die Ring-Diagramme lesen die Wahl am
data-themedes<html>ab (statt das System zu fragen) und wechseln damit auf die dunkle Palette, - die Wahl wird bei jedem Umschalten nach
~/.local/share/finanzplan/themegeschrieben (die Seite meldet sie überpywebview.api.theme); daraus setzt der nächste Start die Fensterfarbe, sonst blitzt ein weißes Fenster auf, bevor die Seite steht. Ohne diese Datei entscheidetgsettings … color-scheme.
Koppeln & Synchronisieren
Alles im Menü „Partner-Sync“ des Fensters:
- Koppeln — Code zeigen → ein QR erscheint. Am Handy „Mit Partner teilen“ → „Code scannen“ wählen und den QR scannen. Der 32-Byte-Schlüssel wandert nur über den Bildschirm, nie über ein Netz. (Genauso funktioniert es zwischen zwei Handys – nur zeigt hier der Desktop den Code und das Handy scannt.)
- Danach im selben WLAN abgleichen:
- Ein Gerät wählt Empfangen, das andere Senden.
- Beim Senden werden wartende Partner automatisch gefunden (mDNS) – oder man tippt die IP:Port ein, die das empfangende Gerät anzeigt.
- Nach einem Round-Trip haben beide Seiten denselben, gemergten Stand (Last-Write-Wins pro Eintrag + Tombstones – dieselbe Logik wie in der App).
Schlüssel-Ablage
Der Sync-Schlüssel wird bevorzugt im Secret Service (GNOME-Keyring/KWallet
über D-Bus) abgelegt, sofern unter der Sitzung erreichbar; sonst in einer Datei
~/.local/share/finanzplan/sync_key.bin mit Rechten 0600. Kein
Passphrase-Prompt beim Start. Welche Ablage aktiv ist, steht im Kopplungs-Dialog.
Unter Hyprland läuft nicht immer ein Secret Service. Wer den Keyring will, startet z. B.
gnome-keyring-daemonmit; ansonsten greift automatisch der Datei-Fallback. Der Schlüssel erlaubt einem Mitleser im selben WLAN höchstens, die Ausgabenliste zu lesen.
Daten sichern
- Im Fenstermenü „Daten“: Backup exportieren / Backup einlesen (native Dateidialoge).
- Oder in der App selbst über ⋯ → Sichern/Einlesen – der In-App-Export nutzt den Browser-Download (landet im Download-Ordner) und kann das Backup passphrase-verschlüsseln.
Dateien
| Datei | Zweck |
|---|---|
finanzplan-desktop |
Start-Skript (venv-Einrichtung + Start) |
finanzplan_desktop.py |
pywebview-Fenster, Menü, QR-/Sende-/Empfangs-Dialoge |
desktop_ui.js |
Desktop-Extras (Zoom + Diagramme), in app.html injiziert |
fpsync.py |
Krypto, Frame-Protokoll, Client/Server, mDNS, Schlüssel |
app.html |
die unveränderte App-Oberfläche (aus dem Finanzplan-Repo) |
install.sh |
Symlink + .desktop-Eintrag + Icon für den App-Launcher |
icon.svg |
App-Icon |
test_fpsync.py |
Selbsttest für Krypto/Protokoll (ohne GUI) |
Test: python3 test_fpsync.py
Grenzen / Hinweise
- Getestet sind der Sync-/Krypto-Kern (per Loopback, siehe
test_fpsync.py) und das Fenster selbst unter Xvfb (Injektion der Extras, Zoom-Brücke, Theme-Meldung, Beenden per Strg+C/Strg+Q). Der echte Abgleich mit dem Handy muss auf dem Zielrechner im WLAN ausprobiert werden. app.htmlist eine Kopie. Bei einem App-Update die Datei neu ausFinanzplan/app/src/main/assets/app.htmlherüberkopieren.- Falls die pywebview-Version das Fenstermenü nicht darstellt: bitte melden – dann rüsten wir einen In-App-Sync-Knopf nach.