import 'package:flutter/material.dart';
import '../core/theme/app_colors.dart';
/// Network image widget with a web fallback for cross-origin WordPress media.
class RemoteImage extends StatelessWidget {
const RemoteImage({
super.key,
required this.url,
this.fit = BoxFit.cover,
this.width,
this.height,
this.borderRadius,
this.fallbackIcon = Icons.image_not_supported_outlined,
this.fallbackIconSize = 42,
this.fallbackAsset,
this.backgroundColor = AppColors.softRed,
this.semanticLabel,
});
final String? url;
final BoxFit fit;
final double? width;
final double? height;
final BorderRadius? borderRadius;
final IconData fallbackIcon;
final double fallbackIconSize;
final String? fallbackAsset;
final Color backgroundColor;
final String? semanticLabel;
@override
Widget build(BuildContext context) {
final imageUrl = url?.trim();
Widget child;
if (imageUrl == null || imageUrl.isEmpty) {
child = _fallback();
} else {
child = Image.network(
imageUrl,
width: width,
height: height,
fit: fit,
semanticLabel: semanticLabel,
webHtmlElementStrategy: WebHtmlElementStrategy.fallback,
loadingBuilder: (context, image, progress) {
if (progress == null) return image;
return _loading();
},
errorBuilder: (context, error, stackTrace) => _fallback(),
);
}
if (borderRadius != null) {
child = ClipRRect(borderRadius: borderRadius!, child: child);
}
return SizedBox(
width: width,
height: height,
child: child,
);
}
Widget _loading() {
return ColoredBox(
color: backgroundColor,
child: const Center(
child: SizedBox(
width: 26,
height: 26,
child: CircularProgressIndicator(strokeWidth: 2.5),
),
),
);
}
Widget _fallback() {
if (fallbackAsset != null) {
return Image.asset(
fallbackAsset!,
width: width,
height: height,
fit: fit,
semanticLabel: semanticLabel,
);
}
return ColoredBox(
color: backgroundColor,
child: Center(
child: Icon(
fallbackIcon,
color: AppColors.heartRed,
size: fallbackIconSize,
),
),
);
}
}

