upload z zjec z galerii + prettycode

This commit is contained in:
Mateusz Gruszczyński
2025-07-19 22:53:49 +02:00
parent d8233cb6e5
commit 114bf5c047
5 changed files with 39 additions and 24 deletions

18
app.py
View File

@@ -6,6 +6,7 @@ import mimetypes
import sys
import platform
import psutil
import pyheif # zdjecia heic
from datetime import datetime, timedelta, UTC, timezone
@@ -48,7 +49,7 @@ from functools import wraps
app = Flask(__name__)
app.config.from_object(Config)
ALLOWED_EXTENSIONS = {"png", "jpg", "jpeg", "gif", "webp"}
ALLOWED_EXTENSIONS = {"png", "jpg", "jpeg", "gif", "webp", "heic"}
SQLALCHEMY_ECHO = True
SYSTEM_PASSWORD = app.config.get("SYSTEM_PASSWORD", "changeme")
@@ -242,10 +243,17 @@ def enrich_list_data(l):
return l
def save_resized_image(file, path: str, max_size=(2000, 2000)):
img = Image.open(file)
img.thumbnail(max_size)
img.save(path)
def save_resized_image(file, path):
if file.filename.lower().endswith(".heic"):
heif_file = pyheif.read_heif(file.read())
image = Image.frombytes(
heif_file.mode, heif_file.size, heif_file.data, "raw"
)
image.save(path.replace(".heic", ".jpg"), format="JPEG")
else:
image = Image.open(file)
image.thumbnail((2000, 2000))
image.save(path)
def redirect_with_flash(

View File

@@ -6,4 +6,5 @@ Flask-Compress
eventlet
Werkzeug
Pillow
psutil
psutil
pyheif

View File

@@ -305,4 +305,10 @@ input.form-control {
.fade-out {
opacity: 0;
transition: opacity 0.5s ease;
}
@media (pointer: fine) {
.only-mobile {
display: none !important;
}
}

View File

@@ -5,12 +5,24 @@ if (!window.receiptUploaderInitialized) {
const form = document.getElementById("receiptForm");
const inputCamera = document.getElementById("cameraInput");
const inputGallery = document.getElementById("galleryInput");
const galleryBtn = document.getElementById("galleryBtn");
const galleryBtnText = document.getElementById("galleryBtnText");
const cameraBtn = document.getElementById("cameraBtn");
const progressContainer = document.getElementById("progressContainer");
const progressBar = document.getElementById("progressBar");
const gallery = document.getElementById("receiptGallery");
if (!form || !inputCamera || !inputGallery || !gallery) return;
const isDesktop = window.matchMedia("(pointer: fine)").matches;
// 🧼 Jedno miejsce, pełna logika desktopowa
if (isDesktop) {
if (cameraBtn) cameraBtn.remove(); // całkowicie usuń przycisk
if (inputCamera) inputCamera.remove(); // oraz input
if (galleryBtnText) galleryBtnText.textContent = " Dodaj paragon";
}
function handleFileUpload(inputElement) {
const file = inputElement.files[0];
if (!file) {
@@ -44,6 +56,7 @@ if (!window.receiptUploaderInitialized) {
progressBar.style.width = "0%";
progressBar.textContent = "";
inputElement.value = "";
window.receiptToastShown = false;
};
xhr.onreadystatechange = function () {
@@ -83,22 +96,9 @@ if (!window.receiptUploaderInitialized) {
xhr.send(formData);
}
inputCamera.addEventListener("change", () => handleFileUpload(inputCamera));
inputGallery.addEventListener("change", () => handleFileUpload(inputGallery));
inputCamera?.addEventListener("change", () => handleFileUpload(inputCamera));
inputGallery?.addEventListener("change", () => handleFileUpload(inputGallery));
});
window.receiptUploaderInitialized = true;
}
document.addEventListener("DOMContentLoaded", function () {
const galleryBtn = document.getElementById("galleryBtn");
const galleryInput = document.getElementById("galleryInput");
const isProbablyMobile =
window.matchMedia("(pointer: coarse)").matches || /Mobi|Android|iPhone|iPad/i.test(navigator.userAgent);
if (!isProbablyMobile && galleryBtn && galleryInput) {
galleryBtn.style.display = "none";
galleryInput.disabled = true;
}
});

View File

@@ -131,17 +131,17 @@
<form id="receiptForm" action="{{ url_for('upload_receipt', list_id=list.id) }}" method="post"
enctype="multipart/form-data" class="text-center">
<!-- Zrób zdjęcie -->
<!-- Zrób zdjęcie (tylko mobile) -->
<label for="cameraInput" id="cameraBtn"
class="btn btn-outline-light w-100 py-2 mb-2 d-flex align-items-center justify-content-center gap-2">
<i class="bi bi-camera"></i> 📸 Zrób zdjęcie
</label>
<input type="file" name="receipt" accept="image/*" capture="environment" class="d-none" id="cameraInput">
<!-- Z galerii -->
<!-- Z galerii / Dodaj paragon -->
<label for="galleryInput" id="galleryBtn"
class="btn btn-outline-light w-100 py-2 mb-2 d-flex align-items-center justify-content-center gap-2">
<i class="bi bi-image"></i> 🖼️ Z galerii
<i class="bi bi-image"></i> <span id="galleryBtnText">🖼️ Z galerii</span>
</label>
<input type="file" name="receipt" accept="image/*" class="d-none" id="galleryInput">