From a2fc8bfd2fb98e3f29cd51ce8d82d96804151b35 Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Tue, 7 Apr 2020 17:46:23 +0900 Subject: [PATCH] various fixes --- .../aves/channelhandlers/ImageDecodeTask.java | 71 ++++++++++--------- .../aves/decoder/VideoThumbnailFetcher.java | 6 +- lib/model/filters/mime.dart | 4 +- lib/model/image_entry.dart | 6 +- lib/model/mime_types.dart | 14 ++-- lib/widgets/album/collection_drawer.dart | 4 +- lib/widgets/album/search/search_delegate.dart | 2 +- lib/widgets/album/thumbnail_collection.dart | 2 +- lib/widgets/fullscreen/fullscreen_body.dart | 1 + .../fullscreen/info/basic_section.dart | 4 +- 10 files changed, 63 insertions(+), 51 deletions(-) diff --git a/android/app/src/main/java/deckers/thibault/aves/channelhandlers/ImageDecodeTask.java b/android/app/src/main/java/deckers/thibault/aves/channelhandlers/ImageDecodeTask.java index 27cd31d94..203705860 100644 --- a/android/app/src/main/java/deckers/thibault/aves/channelhandlers/ImageDecodeTask.java +++ b/android/app/src/main/java/deckers/thibault/aves/channelhandlers/ImageDecodeTask.java @@ -22,6 +22,7 @@ import com.bumptech.glide.signature.ObjectKey; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.util.concurrent.ExecutionException; import java.util.function.Consumer; import deckers.thibault.aves.decoder.VideoThumbnail; @@ -69,10 +70,28 @@ public class ImageDecodeTask extends AsyncTask= Build.VERSION_CODES.Q) { - bitmap = getThumbnailBytesByResolver(p); - } else { - bitmap = getThumbnailBytesByMediaStore(p); + Exception exception = null; + try { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + bitmap = getThumbnailBytesByResolver(p); + } else { + bitmap = getThumbnailBytesByMediaStore(p); + } + } catch (Exception e) { + exception = e; + } + + // fallback if the native methods failed + try { + if (bitmap == null) { + bitmap = getThumbnailByGlide(p); + } + } catch (Exception e) { + exception = e; + } + + if (bitmap == null) { + Log.e(LOG_TAG, "failed to load thumbnail for uri=" + p.entry.uri + ", path=" + p.entry.path, exception); } } else { Log.d(LOG_TAG, "getThumbnail with uri=" + p.entry.uri + " cancelled"); @@ -89,18 +108,13 @@ public class ImageDecodeTask extends AsyncTask { } else { // not ideal: bitmap -> byte[] -> bitmap // but simple fallback and we cache result - Bitmap bitmap = retriever.getFrameAtTime(); ByteArrayOutputStream bos = new ByteArrayOutputStream(); - bitmap.compress(Bitmap.CompressFormat.PNG, 0, bos); + Bitmap bitmap = retriever.getFrameAtTime(); + if (bitmap != null) { + bitmap.compress(Bitmap.CompressFormat.PNG, 0, bos); + } callback.onDataReady(new ByteArrayInputStream(bos.toByteArray())); } } catch (Exception ex) { diff --git a/lib/model/filters/mime.dart b/lib/model/filters/mime.dart index 8c5668b75..a94e0a797 100644 --- a/lib/model/filters/mime.dart +++ b/lib/model/filters/mime.dart @@ -24,9 +24,9 @@ class MimeFilter extends CollectionFilter { _label ??= lowMime.split('/')[0].toUpperCase(); } else { _filter = (entry) => entry.mimeType == lowMime; - if (lowMime == MimeTypes.MIME_GIF) { + if (lowMime == MimeTypes.GIF) { _icon = OMIcons.gif; - } else if (lowMime == MimeTypes.MIME_SVG) { + } else if (lowMime == MimeTypes.SVG) { _label = 'SVG'; } _label ??= lowMime.split('/')[1].toUpperCase(); diff --git a/lib/model/image_entry.dart b/lib/model/image_entry.dart index 49a8cc175..48f62c85d 100644 --- a/lib/model/image_entry.dart +++ b/lib/model/image_entry.dart @@ -105,9 +105,9 @@ class ImageEntry { bool get isFavourite => favourites.isFavourite(this); - bool get isGif => mimeType == MimeTypes.MIME_GIF; + bool get isGif => mimeType == MimeTypes.GIF; - bool get isSvg => mimeType == MimeTypes.MIME_SVG; + bool get isSvg => mimeType == MimeTypes.SVG; bool get isVideo => mimeType.startsWith('video'); @@ -117,7 +117,7 @@ class ImageEntry { bool get canPrint => !isVideo; - bool get canRotate => canEdit && (mimeType == MimeTypes.MIME_JPEG || mimeType == MimeTypes.MIME_PNG); + bool get canRotate => canEdit && (mimeType == MimeTypes.JPEG || mimeType == MimeTypes.PNG); bool get rotated => ((isVideo && isCatalogued) ? _catalogMetadata.videoRotation : orientationDegrees) % 180 == 90; diff --git a/lib/model/mime_types.dart b/lib/model/mime_types.dart index af4f2bdfa..eb2d2ed7b 100644 --- a/lib/model/mime_types.dart +++ b/lib/model/mime_types.dart @@ -1,7 +1,11 @@ class MimeTypes { - static const String MIME_GIF = 'image/gif'; - static const String MIME_JPEG = 'image/jpeg'; - static const String MIME_PNG = 'image/png'; - static const String MIME_SVG = 'image/svg+xml'; - static const String MIME_VIDEO = 'video/*'; + static const String GIF = 'image/gif'; + static const String JPEG = 'image/jpeg'; + static const String PNG = 'image/png'; + static const String SVG = 'image/svg+xml'; + + static const String ANY_VIDEO = 'video/*'; + static const String AVI = 'video/avi'; + static const String MP2T = 'video/mp2t'; // .m2ts + static const String MP4 = 'video/mp4'; } diff --git a/lib/widgets/album/collection_drawer.dart b/lib/widgets/album/collection_drawer.dart index 7c9b1a990..f2ee703a6 100644 --- a/lib/widgets/album/collection_drawer.dart +++ b/lib/widgets/album/collection_drawer.dart @@ -79,13 +79,13 @@ class _CollectionDrawerState extends State { source: source, leading: const Icon(OMIcons.movie), title: 'Videos', - filter: MimeFilter(MimeTypes.MIME_VIDEO), + filter: MimeFilter(MimeTypes.ANY_VIDEO), ); final gifEntry = _FilteredCollectionNavTile( source: source, leading: const Icon(OMIcons.gif), title: 'GIFs', - filter: MimeFilter(MimeTypes.MIME_GIF), + filter: MimeFilter(MimeTypes.GIF), ); final favouriteEntry = _FilteredCollectionNavTile( source: source, diff --git a/lib/widgets/album/search/search_delegate.dart b/lib/widgets/album/search/search_delegate.dart index 771664ff1..b3ae3c208 100644 --- a/lib/widgets/album/search/search_delegate.dart +++ b/lib/widgets/album/search/search_delegate.dart @@ -63,7 +63,7 @@ class ImageSearchDelegate extends SearchDelegate { children: [ _buildFilterRow( context: context, - filters: [FavouriteFilter(), MimeFilter(MimeTypes.MIME_VIDEO), MimeFilter(MimeTypes.MIME_GIF), MimeFilter(MimeTypes.MIME_SVG)].where((f) => containQuery(f.label)), + filters: [FavouriteFilter(), MimeFilter(MimeTypes.ANY_VIDEO), MimeFilter(MimeTypes.GIF), MimeFilter(MimeTypes.SVG)].where((f) => containQuery(f.label)), ), _buildFilterRow( context: context, diff --git a/lib/widgets/album/thumbnail_collection.dart b/lib/widgets/album/thumbnail_collection.dart index 06ebeb0bf..956f47e26 100644 --- a/lib/widgets/album/thumbnail_collection.dart +++ b/lib/widgets/album/thumbnail_collection.dart @@ -114,7 +114,7 @@ class ThumbnailCollection extends StatelessWidget { icon: OMIcons.favoriteBorder, text: 'No favourites!', ) - : collection.filters.any((filter) => filter is MimeFilter && filter.mime == MimeTypes.MIME_VIDEO) + : collection.filters.any((filter) => filter is MimeFilter && filter.mime == MimeTypes.ANY_VIDEO) ? const EmptyContent( icon: OMIcons.movie, ) diff --git a/lib/widgets/fullscreen/fullscreen_body.dart b/lib/widgets/fullscreen/fullscreen_body.dart index c010279c5..bd3c980c3 100644 --- a/lib/widgets/fullscreen/fullscreen_body.dart +++ b/lib/widgets/fullscreen/fullscreen_body.dart @@ -319,6 +319,7 @@ class FullscreenBodyState extends State with SingleTickerProvide if (controllerEntry != null) { _videoControllers.remove(controllerEntry); } else { + // unsupported by video_player 0.10.8+2 (backed by ExoPlayer): AVI final controller = VideoPlayerController.uri(uri)..initialize(); controllerEntry = Tuple2(uri, controller); } diff --git a/lib/widgets/fullscreen/info/basic_section.dart b/lib/widgets/fullscreen/info/basic_section.dart index 3c46c0347..8aad7f114 100644 --- a/lib/widgets/fullscreen/info/basic_section.dart +++ b/lib/widgets/fullscreen/info/basic_section.dart @@ -50,8 +50,8 @@ class BasicSection extends StatelessWidget { builder: (context, isFavourite, child) { final album = entry.directory; final filters = [ - if (entry.isVideo) MimeFilter(MimeTypes.MIME_VIDEO), - if (entry.isGif) MimeFilter(MimeTypes.MIME_GIF), + if (entry.isVideo) MimeFilter(MimeTypes.ANY_VIDEO), + if (entry.isGif) MimeFilter(MimeTypes.GIF), if (isFavourite) FavouriteFilter(), if (album != null) AlbumFilter(album, CollectionSource.getUniqueAlbumName(album, collection?.source?.sortedAlbums)), ...tags.map((tag) => TagFilter(tag)),