feat: v0.8.3 — PWA-Support, Desktop-Verhalten, Testmodus-Kennzeichnung
- PWA: manifest.webmanifest + Icons (192/512/180px) + Apple-Touch-Meta-Tags → Web-App lässt sich auf Homebildschirm hinzufügen (iOS/Android) - Desktop: user-select:none global + contextmenu blockiert - BackendChoice: lokaler Modus als Testmodus mit TEST-Badge und Warnung Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -3,8 +3,15 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||||
|
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
|
||||||
|
<link rel="manifest" href="/manifest.webmanifest" />
|
||||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet" />
|
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<meta name="theme-color" content="#1a1a18" />
|
||||||
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||||
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
||||||
|
<meta name="apple-mobile-web-app-title" content="Rapport" />
|
||||||
|
<meta name="description" content="Studio-Management für Architekturbüros" />
|
||||||
<title>Rapport</title>
|
<title>Rapport</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "rapport",
|
"name": "rapport",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.8.2",
|
"version": "0.8.3",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
@@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"name": "Rapport",
|
||||||
|
"short_name": "Rapport",
|
||||||
|
"description": "Studio-Management für Architekturbüros",
|
||||||
|
"start_url": "/",
|
||||||
|
"scope": "/",
|
||||||
|
"display": "standalone",
|
||||||
|
"orientation": "portrait",
|
||||||
|
"background_color": "#ebe7e1",
|
||||||
|
"theme_color": "#1a1a18",
|
||||||
|
"lang": "de-CH",
|
||||||
|
"categories": ["business", "productivity"],
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"src": "/pwa-192.png",
|
||||||
|
"sizes": "192x192",
|
||||||
|
"type": "image/png",
|
||||||
|
"purpose": "any maskable"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/pwa-512.png",
|
||||||
|
"sizes": "512x512",
|
||||||
|
"type": "image/png",
|
||||||
|
"purpose": "any maskable"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 49 KiB |
Generated
+1
-1
@@ -2880,7 +2880,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rapport"
|
name = "rapport"
|
||||||
version = "0.8.1"
|
version = "0.8.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"serde",
|
"serde",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "rapport"
|
name = "rapport"
|
||||||
version = "0.8.2"
|
version = "0.8.3"
|
||||||
description = "Rapport — Studio-Management für Architekturbüros"
|
description = "Rapport — Studio-Management für Architekturbüros"
|
||||||
authors = ["Karim Gabriele Varano <karim@gabrielevarano.ch>"]
|
authors = ["Karim Gabriele Varano <karim@gabrielevarano.ch>"]
|
||||||
license = "AGPL-3.0-or-later"
|
license = "AGPL-3.0-or-later"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "../node_modules/@tauri-apps/cli/config.schema.json",
|
"$schema": "../node_modules/@tauri-apps/cli/config.schema.json",
|
||||||
"productName": "RAPPORT PRE-RELEASE",
|
"productName": "RAPPORT PRE-RELEASE",
|
||||||
"version": "0.8.2",
|
"version": "0.8.3",
|
||||||
"identifier": "com.karimgabrielevarano.rapport",
|
"identifier": "com.karimgabrielevarano.rapport",
|
||||||
"build": {
|
"build": {
|
||||||
"frontendDist": "../dist",
|
"frontendDist": "../dist",
|
||||||
|
|||||||
+15
-8
@@ -303,8 +303,8 @@ export default function App() {
|
|||||||
const [modal, setModal] = useState(null);
|
const [modal, setModal] = useState(null);
|
||||||
const [printContent, setPrintContent] = useState(null);
|
const [printContent, setPrintContent] = useState(null);
|
||||||
const [darkMode, setDarkMode] = useState(() => localStorage.getItem("rapport_dark") === "1");
|
const [darkMode, setDarkMode] = useState(() => localStorage.getItem("rapport_dark") === "1");
|
||||||
const [showChangelog, setShowChangelog] = useState(() => localStorage.getItem("rapport_changelog_seen") !== "0.8.2");
|
const [showChangelog, setShowChangelog] = useState(() => localStorage.getItem("rapport_changelog_seen") !== "0.8.3");
|
||||||
const [changelogVersion, setChangelogVersion] = useState("0.8.2");
|
const [changelogVersion, setChangelogVersion] = useState("0.8.3");
|
||||||
const [showAbout, setShowAbout] = useState(false);
|
const [showAbout, setShowAbout] = useState(false);
|
||||||
const [navOpen, setNavOpen] = useState(false);
|
const [navOpen, setNavOpen] = useState(false);
|
||||||
const [expandedNav, setExpandedNav] = useState(new Set(["buchhaltung"]));
|
const [expandedNav, setExpandedNav] = useState(new Set(["buchhaltung"]));
|
||||||
@@ -518,7 +518,7 @@ export default function App() {
|
|||||||
</>;
|
</>;
|
||||||
}
|
}
|
||||||
return <>
|
return <>
|
||||||
<Login verifyLogin={verifyLogin} settings={data.settings} version="0.8.2" cloudUnreachable={cloudUnreachable} />
|
<Login verifyLogin={verifyLogin} settings={data.settings} version="0.8.3" cloudUnreachable={cloudUnreachable} />
|
||||||
<UpdateNotifier />
|
<UpdateNotifier />
|
||||||
</>;
|
</>;
|
||||||
}
|
}
|
||||||
@@ -793,8 +793,8 @@ export default function App() {
|
|||||||
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
|
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
|
||||||
<button onClick={() => setShowAbout(true)} style={{ background: "none", border: "none", padding: 0, color: "#555", fontSize: 10, letterSpacing: "0.08em", cursor: "pointer", fontFamily: "inherit", textAlign: "left" }}
|
<button onClick={() => setShowAbout(true)} style={{ background: "none", border: "none", padding: 0, color: "#555", fontSize: 10, letterSpacing: "0.08em", cursor: "pointer", fontFamily: "inherit", textAlign: "left" }}
|
||||||
onMouseEnter={e => e.currentTarget.style.color = "#aaa"} onMouseLeave={e => e.currentTarget.style.color = "#555"}>ÜBER RAPPORT</button>
|
onMouseEnter={e => e.currentTarget.style.color = "#aaa"} onMouseLeave={e => e.currentTarget.style.color = "#555"}>ÜBER RAPPORT</button>
|
||||||
<button onClick={() => { setChangelogVersion("0.8.2"); setShowChangelog(true); }} style={{ background: "none", border: "none", padding: 0, color: "#aaa", fontSize: 10, letterSpacing: "0.08em", cursor: "pointer", fontFamily: "inherit" }}
|
<button onClick={() => { setChangelogVersion("0.8.3"); setShowChangelog(true); }} style={{ background: "none", border: "none", padding: 0, color: "#aaa", fontSize: 10, letterSpacing: "0.08em", cursor: "pointer", fontFamily: "inherit" }}
|
||||||
onMouseEnter={e => e.currentTarget.style.color = "#f0ede8"} onMouseLeave={e => e.currentTarget.style.color = "#aaa"}>0.8.2</button>
|
onMouseEnter={e => e.currentTarget.style.color = "#f0ede8"} onMouseLeave={e => e.currentTarget.style.color = "#aaa"}>0.8.3</button>
|
||||||
</div>
|
</div>
|
||||||
</div>}
|
</div>}
|
||||||
|
|
||||||
@@ -859,6 +859,13 @@ export default function App() {
|
|||||||
|
|
||||||
{showChangelog && (() => {
|
{showChangelog && (() => {
|
||||||
const CHANGELOGS = {
|
const CHANGELOGS = {
|
||||||
|
"0.8.3": {
|
||||||
|
items: [
|
||||||
|
["Desktop-App-Verhalten", "Kein Text mehr markierbar, kein Rechtsklick-Menü — die App verhält sich jetzt wie eine native Desktop-Applikation. Eingabefelder sind weiterhin voll benutzbar."],
|
||||||
|
["PWA-Support", "Die Web-Version lässt sich auf dem Homebildschirm von iPhone/iPad und Android hinzufügen. Nach dem Hinzufügen öffnet sie sich vollbild ohne Browser-Chrome — mit eigenem App-Icon und Name."],
|
||||||
|
["Testmodus klar gekennzeichnet", "Wer Rapport ohne Server ausprobiert, sieht jetzt explizit, dass es sich um einen Testmodus mit Einschränkungen handelt (5 MB Limit, kein Backup, kein Mehrbenutzer)."],
|
||||||
|
],
|
||||||
|
},
|
||||||
"0.8.2": {
|
"0.8.2": {
|
||||||
items: [
|
items: [
|
||||||
["Selbstheilung für hängende 0.8.0-Installationen", "Wer von 0.7 auf 0.8 geupdated hat und in den Cloud-Setup-Wizard geschoben wurde, kommt mit 0.8.2 automatisch zurück in seinen Lokal-Modus. Der Auto-Recovery-Code erkennt: Cloud-Modus gesetzt + lokale Daten vorhanden + keine Cloud-Anmeldung → Cloud-Konfiguration wird zurückgenommen, alle Daten bleiben erhalten."],
|
["Selbstheilung für hängende 0.8.0-Installationen", "Wer von 0.7 auf 0.8 geupdated hat und in den Cloud-Setup-Wizard geschoben wurde, kommt mit 0.8.2 automatisch zurück in seinen Lokal-Modus. Der Auto-Recovery-Code erkennt: Cloud-Modus gesetzt + lokale Daten vorhanden + keine Cloud-Anmeldung → Cloud-Konfiguration wird zurückgenommen, alle Daten bleiben erhalten."],
|
||||||
@@ -948,7 +955,7 @@ export default function App() {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
const versions = Object.keys(CHANGELOGS);
|
const versions = Object.keys(CHANGELOGS);
|
||||||
const current = CHANGELOGS[changelogVersion] || CHANGELOGS["0.8.2"];
|
const current = CHANGELOGS[changelogVersion] || CHANGELOGS["0.8.3"];
|
||||||
return (
|
return (
|
||||||
<div style={{ position: "fixed", inset: 0, background: "rgba(0,0,0,0.55)", zIndex: 200, display: "flex", alignItems: "center", justifyContent: "center", padding: 24 }}>
|
<div style={{ position: "fixed", inset: 0, background: "rgba(0,0,0,0.55)", zIndex: 200, display: "flex", alignItems: "center", justifyContent: "center", padding: 24 }}>
|
||||||
<div style={{ background: "#fff", borderRadius: 10, width: "100%", maxWidth: 480, boxShadow: "0 8px 40px rgba(0,0,0,0.18)", overflow: "hidden" }}>
|
<div style={{ background: "#fff", borderRadius: 10, width: "100%", maxWidth: 480, boxShadow: "0 8px 40px rgba(0,0,0,0.18)", overflow: "hidden" }}>
|
||||||
@@ -977,7 +984,7 @@ export default function App() {
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
<div style={{ padding: "12px 32px 24px" }}>
|
<div style={{ padding: "12px 32px 24px" }}>
|
||||||
<button className="btn btn-primary" style={{ width: "100%", fontSize: 13 }} onClick={() => { setShowChangelog(false); localStorage.setItem("rapport_changelog_seen", "0.8.2"); }}>
|
<button className="btn btn-primary" style={{ width: "100%", fontSize: 13 }} onClick={() => { setShowChangelog(false); localStorage.setItem("rapport_changelog_seen", "0.8.3"); }}>
|
||||||
Schliessen
|
Schliessen
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -992,7 +999,7 @@ export default function App() {
|
|||||||
<div style={{ background: "#1a1a18", padding: "28px 32px 24px" }}>
|
<div style={{ background: "#1a1a18", padding: "28px 32px 24px" }}>
|
||||||
<div style={{ fontSize: 10, letterSpacing: "0.18em", color: "#b07848", marginBottom: 8, fontWeight: 600 }}>ÜBER RAPPORT</div>
|
<div style={{ fontSize: 10, letterSpacing: "0.18em", color: "#b07848", marginBottom: 8, fontWeight: 600 }}>ÜBER RAPPORT</div>
|
||||||
<div style={{ fontFamily: "'Playfair Display', serif", fontSize: 28, color: "#f0ede8", fontWeight: 400, lineHeight: 1.1 }}>Rapport</div>
|
<div style={{ fontFamily: "'Playfair Display', serif", fontSize: 28, color: "#f0ede8", fontWeight: 400, lineHeight: 1.1 }}>Rapport</div>
|
||||||
<div style={{ fontSize: 11, color: "#888", marginTop: 6, letterSpacing: "0.04em" }}>Alpha 0.8.2 · Studio-Management für Architekturbüros</div>
|
<div style={{ fontSize: 11, color: "#888", marginTop: 6, letterSpacing: "0.04em" }}>Alpha 0.8.3 · Studio-Management für Architekturbüros</div>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ padding: "20px 32px 8px" }}>
|
<div style={{ padding: "20px 32px 8px" }}>
|
||||||
<div style={{ fontSize: 11, fontWeight: 600, color: "#888", letterSpacing: "0.1em", marginBottom: 12 }}>LIZENZ</div>
|
<div style={{ fontSize: 11, fontWeight: 600, color: "#888", letterSpacing: "0.1em", marginBottom: 12 }}>LIZENZ</div>
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
*, *::before, *::after { box-sizing: border-box; }
|
*, *::before, *::after { box-sizing: border-box; }
|
||||||
html, body { margin: 0; padding: 0; height: 100%; }
|
html, body { margin: 0; padding: 0; height: 100%; }
|
||||||
#root { height: 100%; }
|
#root { height: 100%; }
|
||||||
|
|
||||||
|
/* Desktop-App-Verhalten: kein Textmarkieren, kein Drag */
|
||||||
|
* { user-select: none; -webkit-user-drag: none; }
|
||||||
|
input, textarea, [contenteditable] { user-select: text; }
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ import { createRoot } from 'react-dom/client'
|
|||||||
import './index.css'
|
import './index.css'
|
||||||
import App from './App.jsx'
|
import App from './App.jsx'
|
||||||
|
|
||||||
|
document.addEventListener('contextmenu', e => e.preventDefault())
|
||||||
|
|
||||||
createRoot(document.getElementById('root')).render(
|
createRoot(document.getElementById('root')).render(
|
||||||
<StrictMode>
|
<StrictMode>
|
||||||
<App />
|
<App />
|
||||||
|
|||||||
@@ -82,10 +82,13 @@ export default function BackendChoice() {
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<button className="bc-option" onClick={() => pick("local")}>
|
<button className="bc-option" onClick={() => pick("local")}>
|
||||||
<div className="bc-title">Lokal auf diesem Gerät</div>
|
<div className="bc-title" style={{ display: "flex", alignItems: "center", gap: 8 }}>
|
||||||
|
Testmodus (lokal)
|
||||||
|
<span style={{ fontSize: 10, fontWeight: 600, letterSpacing: "0.08em", color: "#9a7858", background: "rgba(154,120,88,0.10)", borderRadius: 4, padding: "2px 6px" }}>TEST</span>
|
||||||
|
</div>
|
||||||
<div className="bc-desc">
|
<div className="bc-desc">
|
||||||
Daten liegen ausschliesslich in diesem Browser / dieser App. Kein Server nötig.
|
Daten liegen nur in diesem Browser. Kein Backup, kein Mehrbenutzer, begrenzt auf ~5 MB.
|
||||||
Ideal zum Ausprobieren oder als Solo-Setup.
|
Nur zum Ausprobieren — für den produktiven Einsatz einen Server verbinden.
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user