polish nouri 0.6.0 startup and desktop header

This commit is contained in:
2026-04-12 17:50:17 +02:00
parent 555fddab80
commit a26d519cf2
4 changed files with 23 additions and 6 deletions
+3 -1
View File
@@ -10,6 +10,7 @@ Nouri 0.6.0 bringt die App näher an einen stabilen 1.0-Stand. Der Schwerpunkt l
- Überarbeitete PWA-Icons inklusive zusätzlicher Größen und maskierbarer Variante - Überarbeitete PWA-Icons inklusive zusätzlicher Größen und maskierbarer Variante
- Ruhigeres visuelles Finish bei Karten, Fokuszuständen, Setup und leeren Bereichen - Ruhigeres visuelles Finish bei Karten, Fokuszuständen, Setup und leeren Bereichen
- Mobile Header-Logik bereinigt, damit der obere Bereich auf Smartphones nicht fest mitscrollt - Mobile Header-Logik bereinigt, damit der obere Bereich auf Smartphones nicht fest mitscrollt
- Desktop-Navigation wieder klarer als durchlaufende Leiste direkt neben dem Logo
### Bilder und Performance ### Bilder und Performance
@@ -32,6 +33,7 @@ Nouri 0.6.0 bringt die App näher an einen stabilen 1.0-Stand. Der Schwerpunkt l
- Restore mit klarer Bestätigung statt versehentlicher Überschreibung - Restore mit klarer Bestätigung statt versehentlicher Überschreibung
- Freundlichere Behandlung von zu großen Bild-Uploads - Freundlichere Behandlung von zu großen Bild-Uploads
- Robusterer Umgang mit vorhandenen älteren Datenstrukturen - Robusterer Umgang mit vorhandenen älteren Datenstrukturen
- Startet lokal jetzt auch ohne Pillow-Build auf Python 3.14, statt schon beim Import zu scheitern
### Planung und Vorschläge ### Planung und Vorschläge
@@ -46,7 +48,7 @@ Nouri 0.6.0 bringt die App näher an einen stabilen 1.0-Stand. Der Schwerpunkt l
- Neue Hilfsmodule für Bildverarbeitung und Backup/Restore - Neue Hilfsmodule für Bildverarbeitung und Backup/Restore
- App-Metadaten-Tabelle für robustere Schema-Verwaltung vorbereitet - App-Metadaten-Tabelle für robustere Schema-Verwaltung vorbereitet
- Cloudron-Version auf 0.6.0 angehoben - Cloudron-Version auf 0.6.0 angehoben
- Pillow als zusätzliche Abhängigkeit für lokale Bildverarbeitung ergänzt - Pillow für Bildverarbeitung ergänzt und auf Python 3.14 lokal als optionale Abhängigkeit abgefedert
## Hinweise zum Update ## Hinweise zum Update
+13 -1
View File
@@ -4,10 +4,18 @@ import os
import uuid import uuid
from pathlib import Path from pathlib import Path
from PIL import Image, ImageOps, UnidentifiedImageError
from werkzeug.datastructures import FileStorage from werkzeug.datastructures import FileStorage
from werkzeug.utils import secure_filename from werkzeug.utils import secure_filename
try:
from PIL import Image, ImageOps, UnidentifiedImageError
PILLOW_AVAILABLE = True
except ImportError: # pragma: no cover - local fallback when Pillow is unavailable
Image = None
ImageOps = None
UnidentifiedImageError = OSError
PILLOW_AVAILABLE = False
ALLOWED_IMAGE_EXTENSIONS = {"png", "jpg", "jpeg", "gif", "webp"} ALLOWED_IMAGE_EXTENSIONS = {"png", "jpg", "jpeg", "gif", "webp"}
IMAGE_VARIANTS = { IMAGE_VARIANTS = {
@@ -54,6 +62,8 @@ def remove_photo_assets(upload_folder: str | Path, filename: str | None) -> None
def _open_image(upload: FileStorage) -> Image.Image: def _open_image(upload: FileStorage) -> Image.Image:
if not PILLOW_AVAILABLE or Image is None or ImageOps is None:
raise OSError("Pillow ist nicht verfügbar.")
upload.stream.seek(0) upload.stream.seek(0)
image = Image.open(upload.stream) image = Image.open(upload.stream)
image.load() image.load()
@@ -61,6 +71,8 @@ def _open_image(upload: FileStorage) -> Image.Image:
def _prepare_image(image: Image.Image) -> Image.Image: def _prepare_image(image: Image.Image) -> Image.Image:
if not PILLOW_AVAILABLE:
return image
if image.mode not in {"RGB", "RGBA"}: if image.mode not in {"RGB", "RGBA"}:
image = image.convert("RGBA" if "A" in image.getbands() else "RGB") image = image.convert("RGBA" if "A" in image.getbands() else "RGB")
return image return image
+6 -3
View File
@@ -165,8 +165,8 @@ button.secondary:hover,
.site-header { .site-header {
position: static; position: static;
z-index: 10; z-index: 10;
display: grid; display: flex;
grid-template-columns: auto 1fr auto; flex-wrap: wrap;
gap: 1rem; gap: 1rem;
align-items: center; align-items: center;
padding: 1rem 1.2rem; padding: 1rem 1.2rem;
@@ -223,7 +223,8 @@ h3,
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
gap: 0.45rem; gap: 0.45rem;
justify-content: center; justify-content: flex-start;
flex: 1 1 32rem;
min-width: 0; min-width: 0;
} }
@@ -251,6 +252,8 @@ h3,
align-items: center; align-items: center;
gap: 0.75rem; gap: 0.75rem;
justify-content: flex-end; justify-content: flex-end;
margin-left: auto;
flex-wrap: wrap;
} }
.user-chip, .user-chip,
+1 -1
View File
@@ -1,4 +1,4 @@
Flask==3.1.1 Flask==3.1.1
gunicorn==23.0.0 gunicorn==23.0.0
pywebpush==2.3.0 pywebpush==2.3.0
Pillow==11.2.1 Pillow==11.2.1; python_version < "3.14"