various fixes
This commit is contained in:
parent
01d2d7ea2f
commit
a2fc8bfd2f
10 changed files with 63 additions and 51 deletions
|
@ -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,11 +70,29 @@ public class ImageDecodeTask extends AsyncTask<ImageDecodeTask.Params, Void, Ima
|
|||
Params p = params[0];
|
||||
Bitmap bitmap = null;
|
||||
if (!this.isCancelled()) {
|
||||
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<ImageDecodeTask.Params, Void, Ima
|
|||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.Q)
|
||||
private Bitmap getThumbnailBytesByResolver(Params params) {
|
||||
private Bitmap getThumbnailBytesByResolver(Params params) throws IOException {
|
||||
ImageEntry entry = params.entry;
|
||||
int width = params.width;
|
||||
int height = params.height;
|
||||
|
||||
ContentResolver resolver = activity.getContentResolver();
|
||||
try {
|
||||
return resolver.loadThumbnail(entry.uri, new Size(width, height), null);
|
||||
} catch (IOException e) {
|
||||
Log.e(LOG_TAG, "failed to load thumbnail for uri=" + entry.uri + ", path=" + entry.path + ", width=" + width + ", height=" + height, e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Bitmap getThumbnailBytesByMediaStore(Params params) {
|
||||
|
@ -108,7 +122,6 @@ public class ImageDecodeTask extends AsyncTask<ImageDecodeTask.Params, Void, Ima
|
|||
long contentId = ContentUris.parseId(entry.uri);
|
||||
|
||||
ContentResolver resolver = activity.getContentResolver();
|
||||
try {
|
||||
if (entry.isVideo()) {
|
||||
return MediaStore.Video.Thumbnails.getThumbnail(resolver, contentId, MediaStore.Video.Thumbnails.MINI_KIND, null);
|
||||
} else {
|
||||
|
@ -121,13 +134,9 @@ public class ImageDecodeTask extends AsyncTask<ImageDecodeTask.Params, Void, Ima
|
|||
}
|
||||
return bitmap;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(LOG_TAG, "failed to get thumbnail for uri=" + entry.uri, e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Bitmap getThumbnailByGlide(Params params) {
|
||||
private Bitmap getThumbnailByGlide(Params params) throws ExecutionException, InterruptedException {
|
||||
ImageEntry entry = params.entry;
|
||||
int width = params.width;
|
||||
int height = params.height;
|
||||
|
@ -158,13 +167,9 @@ public class ImageDecodeTask extends AsyncTask<ImageDecodeTask.Params, Void, Ima
|
|||
|
||||
try {
|
||||
return target.get();
|
||||
} catch (InterruptedException e) {
|
||||
Log.d(LOG_TAG, "getThumbnail with uri=" + entry.uri + " interrupted");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} finally {
|
||||
Glide.with(activity).clear(target);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -31,9 +31,11 @@ class VideoThumbnailFetcher implements DataFetcher<InputStream> {
|
|||
} else {
|
||||
// not ideal: bitmap -> byte[] -> bitmap
|
||||
// but simple fallback and we cache result
|
||||
Bitmap bitmap = retriever.getFrameAtTime();
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
Bitmap bitmap = retriever.getFrameAtTime();
|
||||
if (bitmap != null) {
|
||||
bitmap.compress(Bitmap.CompressFormat.PNG, 0, bos);
|
||||
}
|
||||
callback.onDataReady(new ByteArrayInputStream(bos.toByteArray()));
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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';
|
||||
}
|
||||
|
|
|
@ -79,13 +79,13 @@ class _CollectionDrawerState extends State<CollectionDrawer> {
|
|||
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,
|
||||
|
|
|
@ -63,7 +63,7 @@ class ImageSearchDelegate extends SearchDelegate<CollectionFilter> {
|
|||
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,
|
||||
|
|
|
@ -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,
|
||||
)
|
||||
|
|
|
@ -319,6 +319,7 @@ class FullscreenBodyState extends State<FullscreenBody> 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);
|
||||
}
|
||||
|
|
|
@ -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)),
|
||||
|
|
Loading…
Reference in a new issue