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
This commit is contained in:
Lukas Müllner 2026-03-04 11:30:32 +01:00
parent 13114bd63f
commit aab5c7d039
2 changed files with 15 additions and 9 deletions

View file

@ -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});

View file

@ -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;