polish nouri 0.6.0 startup and desktop header
This commit is contained in:
@@ -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
@@ -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
|
||||||
|
|||||||
@@ -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
@@ -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"
|
||||||
|
|||||||
Reference in New Issue
Block a user