From cc4f3bb22511bc6d8da3a9c0741503b7879bfbbf Mon Sep 17 00:00:00 2001 From: karim Date: Sat, 16 May 2026 01:29:49 +0200 Subject: [PATCH] =?UTF-8?q?Einstellungen:=20Tab=20=C2=ABUpdates=20&=20Supp?= =?UTF-8?q?ort=C2=BB=20+=20Bump=20auf=200.7.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Neuer Settings-Tab mit manueller Update-Suche (ignoriert die Skip- Markierung), Zeitstempel der letzten Prüfung, Link zur Dokumentation auf rapport.kgva.ch. Update-Helper sind in src/utils/updater.js zentralisiert; UpdateNotifier schreibt jetzt auch beim Auto-Check das Datum der letzten Prüfung mit. Version 0.6.0 → 0.7.0 in package.json, tauri.conf.json, Cargo.toml und allen UI-Referenzen. Changelog-Eintrag 0.7 mit den drei Highlights dieses Releases ergänzt. Co-Authored-By: Claude Opus 4.7 --- README.md | 4 +- package.json | 2 +- src-tauri/Cargo.lock | 2 +- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- src/App.jsx | 23 ++-- src/components/UpdatesSupport.jsx | 197 ++++++++++++++++++++++++++++++ src/views/Settings.jsx | 5 + 8 files changed, 223 insertions(+), 14 deletions(-) create mode 100644 src/components/UpdatesSupport.jsx diff --git a/README.md b/README.md index 73e4342..fe6aad1 100755 --- a/README.md +++ b/README.md @@ -121,8 +121,8 @@ Zusätzlich im UI-Changelog: [`src/App.jsx`](src/App.jsx) — Konstante `CHANGEL # 1. Versionen anheben (package.json, tauri.conf.json, Cargo.toml) # 2. Changelog in src/App.jsx ergänzen # 3. Commit + Tag -git tag -a v0.6.0 -m "Rapport 0.6" -git push origin main v0.6.0 +git tag -a v0.7.0 -m "Rapport 0.7" +git push origin main v0.7.0 # 4. Bundle bauen npx tauri build diff --git a/package.json b/package.json index eff4667..55206c0 100755 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "rapport", "private": true, - "version": "0.6.0", + "version": "0.7.0", "type": "module", "scripts": { "dev": "vite", diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index a8fc76a..df7a671 100755 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2880,7 +2880,7 @@ dependencies = [ [[package]] name = "rapport" -version = "0.6.0" +version = "0.7.0" dependencies = [ "log", "serde", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index ae4887b..bbeb0ff 100755 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rapport" -version = "0.6.0" +version = "0.7.0" description = "Rapport — Studio-Management für Architekturbüros" authors = ["Karim Gabriele Varano "] license = "AGPL-3.0-or-later" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index f45d61e..31d9fde 100755 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "../node_modules/@tauri-apps/cli/config.schema.json", "productName": "RAPPORT PRE-RELEASE", - "version": "0.6.0", + "version": "0.7.0", "identifier": "com.karimgabrielevarano.rapport", "build": { "frontendDist": "../dist", diff --git a/src/App.jsx b/src/App.jsx index ccc1c99..6c753b2 100755 --- a/src/App.jsx +++ b/src/App.jsx @@ -231,8 +231,8 @@ export default function App() { const [modal, setModal] = useState(null); const [printContent, setPrintContent] = useState(null); const [darkMode, setDarkMode] = useState(() => localStorage.getItem("rapport_dark") === "1"); - const [showChangelog, setShowChangelog] = useState(() => localStorage.getItem("rapport_changelog_seen") !== "0.6"); - const [changelogVersion, setChangelogVersion] = useState("0.6"); + const [showChangelog, setShowChangelog] = useState(() => localStorage.getItem("rapport_changelog_seen") !== "0.7"); + const [changelogVersion, setChangelogVersion] = useState("0.7"); const [showAbout, setShowAbout] = useState(false); const [navOpen, setNavOpen] = useState(false); const [expandedNav, setExpandedNav] = useState(new Set(["buchhaltung"])); @@ -334,7 +334,7 @@ export default function App() { } if (!currentUser) { - return ; + return ; } if (printContent) { @@ -607,8 +607,8 @@ export default function App() {
- +
} @@ -673,6 +673,13 @@ export default function App() { {showChangelog && (() => { const CHANGELOGS = { + "0.7": { + items: [ + ["Automatische Updates", "Rapport prüft beim Start, ob eine neue Version unter git.kgva.ch verfügbar ist, und installiert sie auf Knopfdruck — kein manuelles DMG-Download mehr nötig. Updates lassen sich überspringen oder verschieben; Pakete werden vor der Installation per Signaturprüfung verifiziert."], + ["System-Tray-Icon", "Rapport läuft im Hintergrund weiter, wenn das Fenster geschlossen wird, und ist über ein Menüleisten-Icon erreichbar. Schnellzugriff auf Dashboard, Zeiterfassung, Projekte und Buchhaltung; Cmd+Q beendet die App vollständig."], + ["Einstellungen: Updates & Support", "Neuer Tab «Updates & Support» mit manueller Update-Suche, Zeitstempel der letzten Prüfung und Link zur Dokumentation auf rapport.kgva.ch."], + ], + }, "0.6": { items: [ ["Sicherheit: Passwort-Hashing", "Passwörter werden jetzt mit PBKDF2 (SHA-256, 100 000 Iterationen) und einem zufälligen Salt gespeichert. Bestehende Klartext-Passwörter werden beim ersten erfolgreichen Login transparent migriert."], @@ -730,7 +737,7 @@ export default function App() { }, }; const versions = Object.keys(CHANGELOGS); - const current = CHANGELOGS[changelogVersion] || CHANGELOGS["0.6"]; + const current = CHANGELOGS[changelogVersion] || CHANGELOGS["0.7"]; return (
@@ -759,7 +766,7 @@ export default function App() { ))}
-
@@ -774,7 +781,7 @@ export default function App() {
ÜBER RAPPORT
Rapport
-
Alpha 0.6 · Studio-Management für Architekturbüros
+
Alpha 0.7 · Studio-Management für Architekturbüros
LIZENZ
diff --git a/src/components/UpdatesSupport.jsx b/src/components/UpdatesSupport.jsx new file mode 100644 index 0000000..66e10f8 --- /dev/null +++ b/src/components/UpdatesSupport.jsx @@ -0,0 +1,197 @@ +import { useEffect, useState, useCallback } from "react"; +import { + checkForAppUpdate, + installAppUpdate, + skipUpdateVersion, + getLastUpdateCheck, + formatLastCheck, + isTauri, +} from "../utils/updater.js"; + +function Section({ title, children }) { + return ( +
+
{title}
+ {children} +
+ ); +} + +export default function UpdatesSupport({ fallbackVersion }) { + const [version, setVersion] = useState(fallbackVersion || ""); + const [lastCheck, setLastCheck] = useState(() => getLastUpdateCheck()); + const [state, setState] = useState("idle"); + const [update, setUpdate] = useState(null); + const [error, setError] = useState(null); + const [downloaded, setDownloaded] = useState(0); + const [total, setTotal] = useState(0); + + useEffect(() => { + if (!isTauri()) return; + import("@tauri-apps/api/app").then(({ getVersion }) => { + getVersion().then(setVersion).catch(() => {}); + }); + }, []); + + const runCheck = useCallback(async () => { + setError(null); + if (!isTauri()) { + setState("not-tauri"); + return; + } + setState("checking"); + try { + const res = await checkForAppUpdate({ respectSkip: false }); + setLastCheck(getLastUpdateCheck()); + if (res.available) { + setUpdate(res.update); + setState("available"); + } else { + setUpdate(null); + setState("no-update"); + } + } catch (e) { + console.error("Update-Check fehlgeschlagen:", e); + setError(String(e?.message || e)); + setState("idle"); + } + }, []); + + const install = async () => { + if (!update) return; + setError(null); + try { + setState("downloading"); + setDownloaded(0); + setTotal(0); + await installAppUpdate(update, (event) => { + if (event.event === "Started") { + setTotal(event.data.contentLength || 0); + } else if (event.event === "Progress") { + setDownloaded((d) => d + (event.data.chunkLength || 0)); + } else if (event.event === "Finished") { + setState("installing"); + } + }); + } catch (e) { + console.error("Update-Installation fehlgeschlagen:", e); + setError(String(e?.message || e)); + setState("available"); + } + }; + + const skipVersion = () => { + skipUpdateVersion(update?.version); + setUpdate(null); + setState("idle"); + }; + + const isBusy = state === "downloading" || state === "installing"; + const pct = total > 0 ? Math.min(100, Math.round((downloaded / total) * 100)) : null; + + return ( +
+
+
+
+ Aktuelle Version + {version || "—"} +
+
+ Letzte Prüfung + {formatLastCheck(lastCheck)} +
+ + + + {state === "no-update" && ( +
+ ✓ Rapport ist auf dem neuesten Stand. +
+ )} + + {state === "available" && update && ( +
+
UPDATE VERFÜGBAR
+
Rapport {update.version}
+ {update.body && ( +
+ {update.body} +
+ )} + + +
+ )} + + {isBusy && ( +
+
+ {state === "downloading" + ? (pct !== null ? `Wird heruntergeladen … ${pct}%` : "Wird heruntergeladen …") + : "Wird installiert …"} +
+
+
+
+ +
+ )} + + {state === "not-tauri" && ( +
+ Updates sind nur in der Desktop-App verfügbar. +
+ )} + + {error && ( +
+ {error} +
+ )} + +

+ Updates werden automatisch beim Start der App geprüft. Hier kannst du manuell suchen — z.B. wenn die App selten geschlossen wird. +

+
+
+ +
+
+

+ Anleitungen, Dokumentation und Support findest du auf der offiziellen Website: +

+ + rapport.kgva.ch ↗ + +

+ Dort findest du auch das Changelog, Fehlerberichte und Kontaktmöglichkeiten für direkten Support. +

+
+
+
+ ); +} diff --git a/src/views/Settings.jsx b/src/views/Settings.jsx index 8d21f0b..1cee7e9 100755 --- a/src/views/Settings.jsx +++ b/src/views/Settings.jsx @@ -2,6 +2,7 @@ import React, { useState } from "react"; import { STORAGE_KEY, DEFAULT_ABSENZ_TYPES } from "../constants.js"; import { formatIban, isQRIban, applyProjectNumberFormat, applyProtoNumberFormat, generateId, getFeiertageForYear, getAbsenzTypes } from "../utils.js"; import { Header, FormField, Modal, DateInput, useConfirm } from "../components/UI.jsx"; +import UpdatesSupport from "../components/UpdatesSupport.jsx"; const PERMISSION_GROUPS = [ { label: "Grundmodule", items: [ @@ -37,6 +38,7 @@ const TABS = [ { id: "team", label: "Team & Rollen" }, { id: "kalender", label: "Feiertage & Absenzen" }, { id: "system", label: "System" }, + { id: "support", label: "Updates & Support" }, { id: "profil", label: "Mein Profil" }, ]; @@ -858,6 +860,9 @@ export default function Settings({ data, update, currentUser, uiZoom, setUiZoom
)} + + {/* ── Tab: Updates & Support ── */} + {tab === "support" && } } );