From aab5c7d039e8fe5e28b2279ece2de9210bfb3800 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20M=C3=BCllner?= Date: Wed, 4 Mar 2026 11:30:32 +0100 Subject: [PATCH] fix(storage): enforce strict <=500KB upload guarantee for private bucket - Harden compression pipeline with iterative quality + dimension reduction - Throw explicit error if final output still exceeds 500KB bucket limit - Keep 1080px cap while allowing progressive downscaling to fit constraints - Update login screen branding comment to car64 --- lib/screens/login_screen.dart | 2 +- lib/services/storage_service.dart | 22 ++++++++++++++-------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/lib/screens/login_screen.dart b/lib/screens/login_screen.dart index 44711d3..adf260f 100644 --- a/lib/screens/login_screen.dart +++ b/lib/screens/login_screen.dart @@ -4,7 +4,7 @@ import 'package:flutter/material.dart'; import '../main.dart'; import '../theme/app_colors.dart'; -/// Branded login screen matching the HW Collector Hub email style. +/// Branded login screen matching the car64 style. class LoginScreen extends StatefulWidget { const LoginScreen({super.key}); diff --git a/lib/services/storage_service.dart b/lib/services/storage_service.dart index d8b37ae..edd3951 100644 --- a/lib/services/storage_service.dart +++ b/lib/services/storage_service.dart @@ -78,24 +78,30 @@ class StorageService { throw Exception('Invalid image file.'); } - final resized = decoded.width > _maxWidth + img.Image working = decoded.width > _maxWidth ? img.copyResize(decoded, width: _maxWidth) : decoded; var quality = 85; - Uint8List out = Uint8List.fromList(img.encodeJpg(resized, quality: quality)); + Uint8List out = Uint8List.fromList(img.encodeJpg(working, quality: quality)); + // First pass: reduce JPEG quality. while (out.lengthInBytes > _maxImageBytes && quality > 35) { - quality -= 10; - out = Uint8List.fromList(img.encodeJpg(resized, quality: quality)); + quality -= 5; + out = Uint8List.fromList(img.encodeJpg(working, quality: quality)); + } + + // Second pass: reduce dimensions progressively if still above the limit. + while (out.lengthInBytes > _maxImageBytes && working.width > 320) { + final nextWidth = (working.width * 0.85).round(); + working = img.copyResize(working, width: nextWidth); + out = Uint8List.fromList(img.encodeJpg(working, quality: quality)); } if (out.lengthInBytes > _maxImageBytes) { - final reduced = img.copyResize( - resized, - width: (resized.width * 0.8).round(), + throw Exception( + 'Image is too large after compression (${out.lengthInBytes} bytes).', ); - out = Uint8List.fromList(img.encodeJpg(reduced, quality: 45)); } return out;