This commit is contained in:
2025-10-21 15:48:26 +07:00
parent 1cda00c0bf
commit b94a19dd3f

View File

@@ -1,5 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:cached_network_image/cached_network_image.dart';
import '../../../products/presentation/providers/products_provider.dart'; import '../../../products/presentation/providers/products_provider.dart';
import '../../../products/presentation/providers/selected_category_provider.dart'; import '../../../products/presentation/providers/selected_category_provider.dart';
import '../../../categories/presentation/providers/categories_provider.dart'; import '../../../categories/presentation/providers/categories_provider.dart';
@@ -9,7 +10,7 @@ import '../../domain/entities/cart_item.dart';
import '../../../../core/widgets/loading_indicator.dart'; import '../../../../core/widgets/loading_indicator.dart';
import '../../../../core/widgets/error_widget.dart'; import '../../../../core/widgets/error_widget.dart';
import '../../../../core/widgets/empty_state.dart'; import '../../../../core/widgets/empty_state.dart';
import '../../../../core/widgets/optimized_cached_image.dart'; import '../../../../core/config/image_cache_config.dart';
import '../../../../shared/widgets/price_display.dart'; import '../../../../shared/widgets/price_display.dart';
/// Home page - Quick sale POS interface /// Home page - Quick sale POS interface
@@ -407,6 +408,65 @@ class _CategoryButton extends StatelessWidget {
} }
} }
/// Immutable product image widget that won't rebuild
class _ProductImage extends StatelessWidget {
final String productId;
final String? imageUrl;
const _ProductImage({
required this.productId,
required this.imageUrl,
});
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return ClipRRect(
borderRadius: BorderRadius.circular(12),
child: imageUrl != null && imageUrl!.isNotEmpty
? CachedNetworkImage(
key: ValueKey('product_img_$productId'),
imageUrl: imageUrl!,
width: 60,
height: 60,
fit: BoxFit.cover,
cacheManager: ProductImageCacheManager(),
memCacheWidth: 120,
memCacheHeight: 120,
maxWidthDiskCache: 240,
maxHeightDiskCache: 240,
fadeInDuration: Duration.zero, // No fade animation
fadeOutDuration: Duration.zero, // No fade animation
placeholder: (context, url) => Container(
width: 60,
height: 60,
color: theme.colorScheme.surfaceContainerHighest,
),
errorWidget: (context, url, error) => Container(
width: 60,
height: 60,
color: theme.colorScheme.surfaceContainerHighest,
child: Icon(
Icons.image_not_supported,
color: theme.colorScheme.onSurfaceVariant,
size: 24,
),
),
)
: Container(
width: 60,
height: 60,
color: theme.colorScheme.surfaceContainerHighest,
child: Icon(
Icons.inventory_2,
color: theme.colorScheme.onSurfaceVariant,
),
),
);
}
}
/// Product list item /// Product list item
class _ProductListItem extends StatelessWidget { class _ProductListItem extends StatelessWidget {
final dynamic product; final dynamic product;
@@ -444,28 +504,10 @@ class _ProductListItem extends StatelessWidget {
padding: const EdgeInsets.all(12), padding: const EdgeInsets.all(12),
child: Row( child: Row(
children: [ children: [
// Product image // Product image - separated into its own widget
RepaintBoundary( _ProductImage(
child: ClipRRect( productId: product.id,
borderRadius: BorderRadius.circular(12), imageUrl: product.imageUrl,
child: product.imageUrl != null
? OptimizedCachedImage(
key: ValueKey('product_img_${product.id}'),
imageUrl: product.imageUrl!,
width: 60,
height: 60,
fit: BoxFit.cover,
)
: Container(
width: 60,
height: 60,
color: theme.colorScheme.surfaceContainerHighest,
child: Icon(
Icons.inventory_2,
color: theme.colorScheme.onSurfaceVariant,
),
),
),
), ),
const SizedBox(width: 12), const SizedBox(width: 12),
// Product info // Product info