68 lines
1.7 KiB
Dart
68 lines
1.7 KiB
Dart
// Author: fruit.com.cn
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
import '../config/app_config.dart';
|
|
import '../theme/app_colors.dart';
|
|
|
|
/// 封面图统一入口:后端给的是相对路径,这里补服务地址并处理加载失败。
|
|
class RemoteImage extends StatelessWidget {
|
|
const RemoteImage(
|
|
this.path, {
|
|
super.key,
|
|
this.width,
|
|
this.height,
|
|
this.fit = BoxFit.cover,
|
|
this.showFallbackIcon = false,
|
|
this.fallbackIconKey,
|
|
this.fallbackAspectRatio,
|
|
this.fallbackColor = AppColors.raised,
|
|
});
|
|
|
|
final String path;
|
|
final double? width;
|
|
final double? height;
|
|
final BoxFit fit;
|
|
final bool showFallbackIcon;
|
|
final Key? fallbackIconKey;
|
|
final double? fallbackAspectRatio;
|
|
final Color fallbackColor;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final url = AppConfig.mediaUrl(path);
|
|
if (url.isEmpty) return _fallback();
|
|
return Image.network(
|
|
url,
|
|
width: width,
|
|
height: height,
|
|
fit: fit,
|
|
errorBuilder: (_, _, _) => _fallback(),
|
|
frameBuilder: (context, child, frame, wasSynchronouslyLoaded) {
|
|
if (wasSynchronouslyLoaded || frame != null) return child;
|
|
return _fallback();
|
|
},
|
|
);
|
|
}
|
|
|
|
Widget _fallback() {
|
|
final fallback = Container(
|
|
width: width,
|
|
height: height,
|
|
color: fallbackColor,
|
|
alignment: Alignment.center,
|
|
child: showFallbackIcon
|
|
? Icon(
|
|
Icons.image_not_supported_outlined,
|
|
key: fallbackIconKey,
|
|
color: AppColors.muted,
|
|
size: 32,
|
|
)
|
|
: null,
|
|
);
|
|
final ratio = fallbackAspectRatio;
|
|
if (ratio == null) return fallback;
|
|
return AspectRatio(aspectRatio: ratio, child: fallback);
|
|
}
|
|
}
|