various fixes
This commit is contained in:
parent
1a17f9546c
commit
862a8003fa
7 changed files with 51 additions and 18 deletions
|
@ -49,6 +49,7 @@ class RegionProvider extends ImageProvider<RegionProviderKey> {
|
|||
}
|
||||
return await decode(bytes);
|
||||
} catch (error) {
|
||||
// loading may fail if the provided MIME type is incorrect (e.g. the Media Store may report a JPEG as a TIFF)
|
||||
debugPrint('$runtimeType _loadAsync failed with mimeType=$mimeType, uri=$uri, error=$error');
|
||||
throw StateError('$mimeType region decoding failed (page $pageId)');
|
||||
}
|
||||
|
|
|
@ -50,7 +50,8 @@ class ThumbnailProvider extends ImageProvider<ThumbnailProviderKey> {
|
|||
}
|
||||
return await decode(bytes);
|
||||
} catch (error) {
|
||||
debugPrint('$runtimeType _loadAsync failed with uri=$uri, error=$error');
|
||||
// loading may fail if the provided MIME type is incorrect (e.g. the Media Store may report a JPEG as a TIFF)
|
||||
debugPrint('$runtimeType _loadAsync failed with mimeType=$mimeType, uri=$uri, error=$error');
|
||||
throw StateError('$mimeType decoding failed (page $pageId)');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,6 +68,7 @@ class UriImage extends ImageProvider<UriImage> with EquatableMixin {
|
|||
}
|
||||
return await decode(bytes);
|
||||
} catch (error) {
|
||||
// loading may fail if the provided MIME type is incorrect (e.g. the Media Store may report a JPEG as a TIFF)
|
||||
debugPrint('$runtimeType _loadAsync failed with mimeType=$mimeType, uri=$uri, error=$error');
|
||||
throw StateError('$mimeType decoding failed (page $pageId)');
|
||||
} finally {
|
||||
|
|
|
@ -449,6 +449,7 @@ class AvesEntry {
|
|||
CatalogMetadata? get catalogMetadata => _catalogMetadata;
|
||||
|
||||
set catalogMetadata(CatalogMetadata? newMetadata) {
|
||||
final oldMimeType = mimeType;
|
||||
final oldDateModifiedSecs = dateModifiedSecs;
|
||||
final oldRotationDegrees = rotationDegrees;
|
||||
final oldIsFlipped = isFlipped;
|
||||
|
@ -459,7 +460,7 @@ class AvesEntry {
|
|||
_tags = null;
|
||||
metadataChangeNotifier.notify();
|
||||
|
||||
_onVisualFieldChanged(oldDateModifiedSecs, oldRotationDegrees, oldIsFlipped);
|
||||
_onVisualFieldChanged(oldMimeType, oldDateModifiedSecs, oldRotationDegrees, oldIsFlipped);
|
||||
}
|
||||
|
||||
void clearMetadata() {
|
||||
|
@ -583,6 +584,7 @@ class AvesEntry {
|
|||
}
|
||||
|
||||
Future<void> applyNewFields(Map newFields, {required bool persist}) async {
|
||||
final oldMimeType = mimeType;
|
||||
final oldDateModifiedSecs = this.dateModifiedSecs;
|
||||
final oldRotationDegrees = this.rotationDegrees;
|
||||
final oldIsFlipped = this.isFlipped;
|
||||
|
@ -622,7 +624,7 @@ class AvesEntry {
|
|||
if (catalogMetadata != null) await metadataDb.saveMetadata({catalogMetadata!});
|
||||
}
|
||||
|
||||
await _onVisualFieldChanged(oldDateModifiedSecs, oldRotationDegrees, oldIsFlipped);
|
||||
await _onVisualFieldChanged(oldMimeType, oldDateModifiedSecs, oldRotationDegrees, oldIsFlipped);
|
||||
metadataChangeNotifier.notify();
|
||||
}
|
||||
|
||||
|
@ -663,10 +665,10 @@ class AvesEntry {
|
|||
return completer.future;
|
||||
}
|
||||
|
||||
// when the entry image itself changed (e.g. after rotation)
|
||||
Future<void> _onVisualFieldChanged(int? oldDateModifiedSecs, int oldRotationDegrees, bool oldIsFlipped) async {
|
||||
if (oldDateModifiedSecs != dateModifiedSecs || oldRotationDegrees != rotationDegrees || oldIsFlipped != isFlipped) {
|
||||
await EntryCache.evict(uri, mimeType, oldDateModifiedSecs, oldRotationDegrees, oldIsFlipped);
|
||||
// when the MIME type or the image itself changed (e.g. after rotation)
|
||||
Future<void> _onVisualFieldChanged(String oldMimeType, int? oldDateModifiedSecs, int oldRotationDegrees, bool oldIsFlipped) async {
|
||||
if ((!MimeTypes.refersToSameType(oldMimeType, mimeType) && !MimeTypes.isVideo(oldMimeType)) || oldDateModifiedSecs != dateModifiedSecs || oldRotationDegrees != rotationDegrees || oldIsFlipped != isFlipped) {
|
||||
await EntryCache.evict(uri, oldMimeType, oldDateModifiedSecs, oldRotationDegrees, oldIsFlipped);
|
||||
imageChangeNotifier.notify();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ import 'dart:async';
|
|||
|
||||
import 'package:aves/image_providers/thumbnail_provider.dart';
|
||||
import 'package:aves/image_providers/uri_image_provider.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
class EntryCache {
|
||||
// ordered descending
|
||||
|
@ -19,9 +20,11 @@ class EntryCache {
|
|||
String uri,
|
||||
String mimeType,
|
||||
int? dateModifiedSecs,
|
||||
int oldRotationDegrees,
|
||||
bool oldIsFlipped,
|
||||
int rotationDegrees,
|
||||
bool isFlipped,
|
||||
) async {
|
||||
debugPrint('Evict cached images for uri=$uri, mimeType=$mimeType, dateModifiedSecs=$dateModifiedSecs, rotationDegrees=$rotationDegrees, isFlipped=$isFlipped');
|
||||
|
||||
// TODO TLAD provide pageId parameter for multi page items, if someday image editing features are added for them
|
||||
int? pageId;
|
||||
|
||||
|
@ -30,8 +33,8 @@ class EntryCache {
|
|||
uri: uri,
|
||||
mimeType: mimeType,
|
||||
pageId: pageId,
|
||||
rotationDegrees: oldRotationDegrees,
|
||||
isFlipped: oldIsFlipped,
|
||||
rotationDegrees: rotationDegrees,
|
||||
isFlipped: isFlipped,
|
||||
).evict();
|
||||
|
||||
// evict low quality thumbnail (without specified extents)
|
||||
|
@ -40,8 +43,8 @@ class EntryCache {
|
|||
mimeType: mimeType,
|
||||
pageId: pageId,
|
||||
dateModifiedSecs: dateModifiedSecs ?? 0,
|
||||
rotationDegrees: oldRotationDegrees,
|
||||
isFlipped: oldIsFlipped,
|
||||
rotationDegrees: rotationDegrees,
|
||||
isFlipped: isFlipped,
|
||||
)).evict();
|
||||
|
||||
await Future.forEach<double>(
|
||||
|
@ -51,8 +54,8 @@ class EntryCache {
|
|||
mimeType: mimeType,
|
||||
pageId: pageId,
|
||||
dateModifiedSecs: dateModifiedSecs ?? 0,
|
||||
rotationDegrees: oldRotationDegrees,
|
||||
isFlipped: oldIsFlipped,
|
||||
rotationDegrees: rotationDegrees,
|
||||
isFlipped: isFlipped,
|
||||
extent: extent,
|
||||
)).evict());
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ class MimeTypes {
|
|||
static const anyImage = 'image/*';
|
||||
|
||||
static const bmp = 'image/bmp';
|
||||
static const bmpX = 'image/x-ms-bmp';
|
||||
static const gif = 'image/gif';
|
||||
static const heic = 'image/heic';
|
||||
static const heif = 'image/heif';
|
||||
|
@ -43,6 +44,8 @@ class MimeTypes {
|
|||
|
||||
static const avi = 'video/avi';
|
||||
static const aviVnd = 'video/vnd.avi';
|
||||
static const flv = 'video/flv';
|
||||
static const flvX = 'video/x-flv';
|
||||
static const mkv = 'video/x-matroska';
|
||||
static const mov = 'video/quicktime';
|
||||
static const mp2t = 'video/mp2t'; // .m2ts, .ts
|
||||
|
@ -62,7 +65,7 @@ class MimeTypes {
|
|||
// groups
|
||||
|
||||
// formats that support transparency
|
||||
static const Set<String> alphaImages = {bmp, gif, ico, png, svg, tiff, webp};
|
||||
static const Set<String> alphaImages = {bmp, bmpX, gif, ico, png, svg, tiff, webp};
|
||||
|
||||
static const Set<String> rawImages = {arw, cr2, crw, dcr, dng, erf, k25, kdc, mrw, nef, nrw, orf, pef, raf, raw, rw2, sr2, srf, srw, x3f};
|
||||
|
||||
|
@ -71,11 +74,33 @@ class MimeTypes {
|
|||
|
||||
static const Set<String> _knownOpaqueImages = {heic, heif, jpeg};
|
||||
|
||||
static const Set<String> _knownVideos = {avi, aviVnd, mkv, mov, mp2t, mp2ts, mp4, mpeg, ogv, webm};
|
||||
static const Set<String> _knownVideos = {avi, aviVnd, flv, flvX, mkv, mov, mp2t, mp2ts, mp4, mpeg, ogv, webm};
|
||||
|
||||
static final Set<String> knownMediaTypes = {..._knownOpaqueImages, ...alphaImages, ...rawImages, ...undecodableImages, ..._knownVideos};
|
||||
|
||||
static bool isImage(String mimeType) => mimeType.startsWith('image');
|
||||
|
||||
static bool isVideo(String mimeType) => mimeType.startsWith('video');
|
||||
|
||||
static bool refersToSameType(String a, b) {
|
||||
switch (a) {
|
||||
case avi:
|
||||
case aviVnd:
|
||||
return [avi, aviVnd].contains(b);
|
||||
case bmp:
|
||||
case bmpX:
|
||||
return [bmp, bmpX].contains(b);
|
||||
case flv:
|
||||
case flvX:
|
||||
return [flv, flvX].contains(b);
|
||||
case heic:
|
||||
case heif:
|
||||
return [heic, heif].contains(b);
|
||||
case psdVnd:
|
||||
case psdX:
|
||||
return [psdVnd, psdX].contains(b);
|
||||
default:
|
||||
return a == b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ class InfoSearchDelegate extends SearchDelegate {
|
|||
final l10n = context.l10n;
|
||||
final suggestions = {
|
||||
l10n.viewerInfoSearchSuggestionDate: 'date or time or when -timer -uptime -exposure -timeline -verbatim',
|
||||
l10n.viewerInfoSearchSuggestionDescription: 'abstract or description or comment or textual or title',
|
||||
l10n.viewerInfoSearchSuggestionDescription: 'abstract or description or comment or textual or title -line',
|
||||
l10n.viewerInfoSearchSuggestionDimensions: 'width or height or dimension or framesize or imagelength',
|
||||
l10n.viewerInfoSearchSuggestionResolution: 'resolution',
|
||||
l10n.viewerInfoSearchSuggestionRights: 'rights or copyright or attribution or license or artist or creator or by-line or credit -tool',
|
||||
|
|
Loading…
Reference in a new issue