Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 101 additions & 18 deletions lib/app/map/_lib/managers/report.dart
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,79 @@ class ReportMapLayerSheet extends StatefulWidget {
State<ReportMapLayerSheet> createState() => _ReportMapLayerSheetState();
}

class SafeImageSection extends StatefulWidget {
final Widget Function(VoidCallback onError) builder;

const SafeImageSection({
super.key,
required this.builder,
});

@override
State<SafeImageSection> createState() => _SafeImageSectionState();
}

class _SafeImageSectionState extends State<SafeImageSection> {
bool _hasError = false;
int _retryKey = 0;

void _onImageError() {
if (_hasError) return;
_hasError = true;

WidgetsBinding.instance.addPostFrameCallback((_) {
if (!mounted) return;
setState(() {});
});
}

void _retry() {
setState(() {
_hasError = false;
_retryKey++;
});
}

@override
Widget build(BuildContext context) {
if (_hasError) {
return _GeneratingView(onRetry: _retry);
}

return KeyedSubtree(
key: ValueKey(_retryKey),
child: widget.builder(_onImageError),
);
}
}

class _GeneratingView extends StatelessWidget {
final VoidCallback onRetry;

const _GeneratingView({
required this.onRetry,
});

@override
Widget build(BuildContext context) {
return AspectRatio(
aspectRatio: 2334 / 2977,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('CWA 正在製圖中'.i18n),
const SizedBox(height: 12),
TextButton.icon(
onPressed: onRetry,
icon: const Icon(Icons.refresh),
label: Text('重新載入'.i18n),
),
],
),
);
}
}

class _ReportMapLayerSheetState extends State<ReportMapLayerSheet> {
final morphingSheetController = MorphingSheetController();

Expand Down Expand Up @@ -982,47 +1055,57 @@ class _ReportMapLayerSheetState extends State<ReportMapLayerSheet> {
),
],
),
if (report.hasNumber)
if (report.hasNumber &&
report.intensityMapImageUrl != null)
Section(
label: Text('震度圖'.i18n),
children: [
Padding(
padding: .symmetric(horizontal: 8),
child: EnlargeableImage(
aspectRatio: 2334 / 2977,
heroTag: 'intensity-image-${report.id}',
imageUrl: report.intensityMapImageUrl!,
imageName: report.intensityMapImageName!,
child: SafeImageSection(
builder: (onError) => EnlargeableImage(
aspectRatio: 2334 / 2977,
heroTag: 'intensity-image-${report.id}',
imageUrl: report.intensityMapImageUrl!,
imageName: report.intensityMapImageName!,
onLoadFailed: onError,
),
),
),
],
),
if (report.hasNumber)
if (report.hasNumber && report.pgaMapImageUrl != null)
Section(
label: Text('最大地動加速度圖'.i18n),
children: [
Padding(
padding: .symmetric(horizontal: 8),
child: EnlargeableImage(
aspectRatio: 2334 / 2977,
heroTag: 'pga-image-${report.id}',
imageUrl: report.pgaMapImageUrl!,
imageName: report.pgaMapImageName!,
child: SafeImageSection(
builder: (onError) => EnlargeableImage(
aspectRatio: 2334 / 2977,
heroTag: 'pga-image-${report.id}',
imageUrl: report.pgaMapImageUrl!,
imageName: report.pgaMapImageName!,
onLoadFailed: onError,
),
),
),
],
),
if (report.hasNumber)
if (report.hasNumber && report.pgvMapImageUrl != null)
Section(
label: Text('最大地動速度圖'.i18n),
children: [
Padding(
padding: .symmetric(horizontal: 8),
child: EnlargeableImage(
aspectRatio: 2334 / 2977,
heroTag: 'pgv-image-${report.id}',
imageUrl: report.pgvMapImageUrl!,
imageName: report.pgvMapImageName!,
child: SafeImageSection(
builder: (onError) => EnlargeableImage(
aspectRatio: 2334 / 2977,
heroTag: 'pgv-image-${report.id}',
imageUrl: report.pgvMapImageUrl!,
imageName: report.pgvMapImageName!,
onLoadFailed: onError,
),
),
),
],
Expand Down
10 changes: 9 additions & 1 deletion lib/widgets/report/enlargeable_image.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ class EnlargeableImage extends StatelessWidget {
final String heroTag;
final String imageUrl;
final String imageName;
final VoidCallback? onLoadFailed;

const EnlargeableImage({
super.key,
required this.aspectRatio,
required this.heroTag,
required this.imageUrl,
required this.imageName,
this.onLoadFailed,
});

@override
Expand All @@ -28,7 +30,13 @@ class EnlargeableImage extends StatelessWidget {
children: [
Hero(
tag: heroTag,
child: CachedNetworkImage(imageUrl: imageUrl),
child: CachedNetworkImage(imageUrl: imageUrl,
fit: BoxFit.cover,
errorWidget: (context, url, error) {
onLoadFailed?.call();
return const SizedBox.shrink();
},
),
),
Positioned.fill(
child: Material(
Expand Down
Loading