avoid loading images of unsupported types
This commit is contained in:
parent
0e9be74e3a
commit
87dc1768dd
5 changed files with 63 additions and 17 deletions
|
@ -56,6 +56,8 @@ class ImageEntry {
|
|||
this.dateModifiedSecs = dateModifiedSecs;
|
||||
}
|
||||
|
||||
bool get canDecode => !MimeTypes.undecodable.contains(mimeType);
|
||||
|
||||
ImageEntry copyWith({
|
||||
@required String uri,
|
||||
@required String path,
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
24
lib/widgets/collection/thumbnail/error.dart
Normal file
24
lib/widgets/collection/thumbnail/error.dart
Normal 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,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue