avoid loading images of unsupported types

This commit is contained in:
Thibault Deckers 2020-10-21 12:16:27 +09:00
parent 0e9be74e3a
commit 87dc1768dd
5 changed files with 63 additions and 17 deletions

View file

@ -56,6 +56,8 @@ class ImageEntry {
this.dateModifiedSecs = dateModifiedSecs;
}
bool get canDecode => !MimeTypes.undecodable.contains(mimeType);
ImageEntry copyWith({
@required String uri,
@required String path,

View file

@ -9,6 +9,9 @@ class MimeTypes {
static const String svg = 'image/svg+xml';
static const String webp = 'image/webp';
static const String tiff = 'image/tiff';
static const String psd = 'image/vnd.adobe.photoshop';
static const String arw = 'image/x-sony-arw';
static const String cr2 = 'image/x-canon-cr2';
static const String crw = 'image/x-canon-crw';
@ -38,4 +41,5 @@ class MimeTypes {
// groups
static const List<String> rawImages = [arw, cr2, crw, dcr, dng, erf, k25, kdc, mrw, nef, nrw, orf, pef, raf, raw, rw2, sr2, srf, srw, x3f];
static const List<String> undecodable = [crw, psd, tiff]; // TODO TLAD make it dynamic if it depends on OS/lib versions
}

View file

@ -0,0 +1,24 @@
import 'package:aves/widgets/common/icons.dart';
import 'package:flutter/material.dart';
class ErrorThumbnail extends StatelessWidget {
final double extent;
final String tooltip;
const ErrorThumbnail({@required this.extent, @required this.tooltip});
@override
Widget build(BuildContext context) {
return Center(
child: Tooltip(
message: tooltip,
preferBelow: false,
child: Icon(
AIcons.error,
size: extent / 2,
color: Colors.blueGrey,
),
),
);
}
}

View file

@ -2,7 +2,7 @@ import 'dart:math';
import 'package:aves/model/image_entry.dart';
import 'package:aves/utils/durations.dart';
import 'package:aves/widgets/common/icons.dart';
import 'package:aves/widgets/collection/thumbnail/error.dart';
import 'package:aves/widgets/common/image_providers/thumbnail_provider.dart';
import 'package:aves/widgets/common/image_providers/uri_image_provider.dart';
import 'package:aves/widgets/common/transition_image.dart';
@ -71,7 +71,11 @@ class _ThumbnailRasterImageState extends State<ThumbnailRasterImage> {
_pauseProvider();
}
bool get isSupported => entry.canDecode;
void _initProvider() {
if (!entry.canDecode) return;
_fastThumbnailProvider = ThumbnailProvider(
ThumbnailProviderKey.fromEntry(entry),
);
@ -95,6 +99,13 @@ class _ThumbnailRasterImageState extends State<ThumbnailRasterImage> {
@override
Widget build(BuildContext context) {
if (!entry.canDecode) {
return ErrorThumbnail(
extent: extent,
tooltip: '${entry.mimeType} not supported',
);
}
final fastImage = Image(
key: ValueKey('LQ'),
image: _fastThumbnailProvider,
@ -127,16 +138,9 @@ class _ThumbnailRasterImageState extends State<ThumbnailRasterImage> {
child: frame == null ? fastImage : child,
);
},
errorBuilder: (context, error, stackTrace) => Center(
child: Tooltip(
message: error.toString(),
preferBelow: false,
child: Icon(
AIcons.error,
size: extent / 2,
color: Colors.blueGrey,
),
),
errorBuilder: (context, error, stackTrace) => ErrorThumbnail(
extent: extent,
tooltip: error.toString(),
),
width: extent,
height: extent,

View file

@ -93,7 +93,7 @@ class ImageView extends StatelessWidget {
initialScale: PhotoViewComputedScale.contained,
onTapUp: (tapContext, details, value) => onTap?.call(),
);
} else {
} else if (entry.canDecode) {
final uriImage = UriImage(
uri: entry.uri,
mimeType: entry.mimeType,
@ -111,11 +111,7 @@ class ImageView extends StatelessWidget {
context,
imageCache.statusForKey(uriImage).keepAlive ? uriImage : fastThumbnailProvider,
),
loadFailedChild: EmptyContent(
icon: AIcons.error,
text: 'Oops!',
alignment: Alignment.center,
),
loadFailedChild: _buildError(),
backgroundDecoration: backgroundDecoration,
scaleStateChangedCallback: onScaleChanged,
minScale: PhotoViewComputedScale.contained,
@ -123,6 +119,8 @@ class ImageView extends StatelessWidget {
onTapUp: (tapContext, details, value) => onTap?.call(),
filterQuality: FilterQuality.low,
);
} else {
child = _buildError();
}
return heroTag != null
@ -133,4 +131,18 @@ class ImageView extends StatelessWidget {
)
: child;
}
Widget _buildError() => GestureDetector(
onTap: () => onTap?.call(),
// use a `Container` with a dummy color to make it expand
// so that we can also detect taps around the title `Text`
child: Container(
color: Colors.transparent,
child: EmptyContent(
icon: AIcons.error,
text: 'Oops!',
alignment: Alignment.center,
),
),
);
}