Update: 2026-07-30 02:27:45
This commit is contained in:
@@ -17,8 +17,11 @@ class MainShellView extends StatefulWidget {
|
||||
|
||||
class _MainShellViewState extends State<MainShellView> {
|
||||
final MainShellController _shellController = Get.find<MainShellController>();
|
||||
// Must be find(), not put(): main.dart already registers the permanent
|
||||
// instance. Re-putting it here swapped in a second, empty instance that other
|
||||
// controllers were no longer holding, so progress updates went nowhere.
|
||||
final UploadProgressService _progressService =
|
||||
Get.put(UploadProgressService());
|
||||
Get.find<UploadProgressService>();
|
||||
|
||||
// 5 pages: Home(0), Invoices(1), [Scanner FAB](2), Notifications(3), Settings(4)
|
||||
final List<Widget> _pages = const [
|
||||
@@ -179,13 +182,37 @@ class _MainShellViewState extends State<MainShellView> {
|
||||
final status = _progressService.status.value;
|
||||
final progress = _progressService.progress.value;
|
||||
|
||||
Color accentColor =
|
||||
status == 'done' ? const Color(0xFF10B981) : const Color(0xFF0F4C81);
|
||||
String statusText = status == 'uploading'
|
||||
? 'جاري رفع الصور...'
|
||||
: (status == 'processing'
|
||||
? 'جاري استخراج البيانات...'
|
||||
: 'اكتملت المعالجة ✓');
|
||||
// Terminal states must look different from in-progress ones, otherwise a
|
||||
// failed or partially failed batch is indistinguishable from a success.
|
||||
final bool isTerminal =
|
||||
status == 'done' || status == 'partial' || status == 'failed';
|
||||
|
||||
final Color accentColor = switch (status) {
|
||||
'done' => const Color(0xFF10B981),
|
||||
'partial' => const Color(0xFFF59E0B),
|
||||
'failed' => const Color(0xFFEF4444),
|
||||
_ => const Color(0xFF0F4C81),
|
||||
};
|
||||
|
||||
final String statusText = switch (status) {
|
||||
'uploading' => 'جاري رفع الصور...',
|
||||
'processing' => 'جاري استخراج البيانات...',
|
||||
'done' => 'اكتملت المعالجة ✓',
|
||||
'partial' => 'اكتملت المعالجة مع أخطاء',
|
||||
'failed' => 'فشلت العملية',
|
||||
_ => 'جاري المعالجة...',
|
||||
};
|
||||
|
||||
final IconData? terminalIcon = switch (status) {
|
||||
'done' => Icons.check_circle,
|
||||
'partial' => Icons.warning_amber_rounded,
|
||||
'failed' => Icons.error_outline,
|
||||
_ => null,
|
||||
};
|
||||
|
||||
final String detailText = _progressService.errorMessage.value.isNotEmpty
|
||||
? _progressService.errorMessage.value
|
||||
: '${_progressService.companyName.value} • ${_progressService.currentImageIndex.value}/${_progressService.totalImages.value}';
|
||||
|
||||
return Card(
|
||||
elevation: 8,
|
||||
@@ -199,9 +226,8 @@ class _MainShellViewState extends State<MainShellView> {
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
status == 'done'
|
||||
? const Icon(Icons.check_circle,
|
||||
color: Color(0xFF10B981), size: 24)
|
||||
terminalIcon != null
|
||||
? Icon(terminalIcon, color: accentColor, size: 24)
|
||||
: const SizedBox(
|
||||
width: 24,
|
||||
height: 24,
|
||||
@@ -213,10 +239,14 @@ class _MainShellViewState extends State<MainShellView> {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(statusText,
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold, fontSize: 13)),
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 13,
|
||||
color: status == 'failed' ? accentColor : null)),
|
||||
Text(
|
||||
'${_progressService.companyName.value} • ${_progressService.currentImageIndex.value}/${_progressService.totalImages.value}',
|
||||
detailText,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
color: isDark ? Colors.white38 : Colors.grey),
|
||||
@@ -224,13 +254,23 @@ class _MainShellViewState extends State<MainShellView> {
|
||||
],
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'${(progress * 100).toInt()}%',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 14,
|
||||
color: accentColor),
|
||||
),
|
||||
if (isTerminal)
|
||||
// A terminal card no longer moves on its own, so give the user
|
||||
// a way to clear it instead of waiting out a timer.
|
||||
IconButton(
|
||||
icon: const Icon(Icons.close, size: 18),
|
||||
color: isDark ? Colors.white38 : Colors.grey,
|
||||
onPressed: _progressService.dismiss,
|
||||
tooltip: 'إخفاء',
|
||||
)
|
||||
else
|
||||
Text(
|
||||
'${(progress * 100).toInt()}%',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 14,
|
||||
color: accentColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
|
||||
Reference in New Issue
Block a user