135 lines
3.4 KiB
Dart
135 lines
3.4 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:wisata_app/widgets/platform_network_image.dart';
|
|
|
|
class DestinationImage extends StatelessWidget {
|
|
const DestinationImage({
|
|
super.key,
|
|
required this.path,
|
|
this.fit = BoxFit.cover,
|
|
this.width,
|
|
this.height,
|
|
this.fallbackMessage = 'Gambar gagal dimuat',
|
|
});
|
|
|
|
final String path;
|
|
final BoxFit fit;
|
|
final double? width;
|
|
final double? height;
|
|
final String fallbackMessage;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final normalizedPath = path.trim().replaceAll('\\', '/');
|
|
|
|
if (normalizedPath.isEmpty) {
|
|
return _DestinationImageFallback(
|
|
message: fallbackMessage,
|
|
detail: 'URL gambar kosong',
|
|
);
|
|
}
|
|
|
|
if (normalizedPath.startsWith('assets/')) {
|
|
return Image.asset(
|
|
normalizedPath,
|
|
fit: fit,
|
|
width: width,
|
|
height: height,
|
|
errorBuilder: (context, error, stackTrace) {
|
|
debugPrint('ERROR ASSET IMAGE: $error');
|
|
debugPrint('FAILED ASSET: $normalizedPath');
|
|
return _DestinationImageFallback(
|
|
message: fallbackMessage,
|
|
detail: normalizedPath,
|
|
);
|
|
},
|
|
);
|
|
}
|
|
|
|
final uri = Uri.tryParse(normalizedPath);
|
|
if (uri == null || !uri.hasScheme || uri.host.isEmpty) {
|
|
debugPrint('INVALID IMAGE URL: $normalizedPath');
|
|
return _DestinationImageFallback(
|
|
message: fallbackMessage,
|
|
detail: normalizedPath,
|
|
);
|
|
}
|
|
|
|
return buildPlatformNetworkImage(
|
|
uri: uri,
|
|
fit: fit,
|
|
width: width,
|
|
height: height,
|
|
loadingBuilder: () => const ColoredBox(
|
|
color: Color(0xFFE5E7EB),
|
|
child: Center(
|
|
child: SizedBox.square(
|
|
dimension: 28,
|
|
child: CircularProgressIndicator(strokeWidth: 2.4),
|
|
),
|
|
),
|
|
),
|
|
errorBuilder: (error) {
|
|
debugPrint('ERROR IMAGE: $error');
|
|
debugPrint('FAILED URL: ${uri.toString()}');
|
|
return _DestinationImageFallback(
|
|
message: fallbackMessage,
|
|
detail: uri.toString(),
|
|
);
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
class _DestinationImageFallback extends StatelessWidget {
|
|
const _DestinationImageFallback({
|
|
required this.message,
|
|
required this.detail,
|
|
});
|
|
|
|
final String message;
|
|
final String detail;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return DecoratedBox(
|
|
decoration: const BoxDecoration(
|
|
gradient: LinearGradient(
|
|
begin: Alignment.topLeft,
|
|
end: Alignment.bottomRight,
|
|
colors: [
|
|
Color(0xFF083A63),
|
|
Color(0xFF0F4C81),
|
|
Color(0xFF2563EB),
|
|
],
|
|
),
|
|
),
|
|
child: Center(
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(18),
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
const Icon(
|
|
Icons.broken_image_rounded,
|
|
color: Colors.white,
|
|
size: 54,
|
|
),
|
|
const SizedBox(height: 10),
|
|
Text(
|
|
'$message\n$detail',
|
|
textAlign: TextAlign.center,
|
|
maxLines: 4,
|
|
overflow: TextOverflow.ellipsis,
|
|
style: const TextStyle(
|
|
color: Colors.white,
|
|
fontWeight: FontWeight.w800,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|