diff --git a/lib/model/entry.dart b/lib/model/entry.dart index 8071699f1..45eb405f8 100644 --- a/lib/model/entry.dart +++ b/lib/model/entry.dart @@ -249,7 +249,9 @@ class AvesEntry { bool get is360 => _catalogMetadata?.is360 ?? false; - bool get canEdit => path != null && !trashed; + bool get isMediaStoreContentUri => uri.startsWith('content://media/'); + + bool get canEdit => path != null && !trashed && isMediaStoreContentUri; bool get canEditDate => canEdit && (canEditExif || canEditXmp); diff --git a/lib/model/entry_dirs.dart b/lib/model/entry_dirs.dart index d18ff2dd8..73c206a6b 100644 --- a/lib/model/entry_dirs.dart +++ b/lib/model/entry_dirs.dart @@ -58,9 +58,13 @@ class EntryDir { var resolved = vrl.volumePath; final parts = pContext.split(vrl.relativeDir); for (final part in parts) { - final partLower = part.toLowerCase(); - final childrenDirs = Directory(resolved).listSync().where((v) => v.absolute is Directory).toSet(); - final found = childrenDirs.firstWhereOrNull((v) => pContext.basename(v.path).toLowerCase() == partLower); + FileSystemEntity? found; + final dir = Directory(resolved); + if (dir.existsSync()) { + final partLower = part.toLowerCase(); + final childrenDirs = dir.listSync().where((v) => v.absolute is Directory).toSet(); + found = childrenDirs.firstWhereOrNull((v) => pContext.basename(v.path).toLowerCase() == partLower); + } resolved = found?.path ?? '$resolved${pContext.separator}$part'; } return resolved; diff --git a/lib/ref/mime_types.dart b/lib/ref/mime_types.dart index 9a300c3ce..72ce54e7c 100644 --- a/lib/ref/mime_types.dart +++ b/lib/ref/mime_types.dart @@ -18,6 +18,8 @@ class MimeTypes { static const cdr = 'image/x-coreldraw'; static const djvu = 'image/vnd.djvu'; static const jxl = 'image/jxl'; + static const pat = 'image/x-coreldrawpattern'; + static const pnm = 'image/x-portable-anymap'; static const psdVnd = 'image/vnd.adobe.photoshop'; static const psdX = 'image/x-photoshop'; @@ -25,7 +27,8 @@ class MimeTypes { static const cr2 = 'image/x-canon-cr2'; static const crw = 'image/x-canon-crw'; static const dcr = 'image/x-kodak-dcr'; - static const dng = 'image/x-adobe-dng'; + static const dng = 'image/dng'; + static const dngX = 'image/x-adobe-dng'; static const erf = 'image/x-epson-erf'; static const k25 = 'image/x-kodak-k25'; static const kdc = 'image/x-kodak-kdc'; @@ -53,11 +56,13 @@ class MimeTypes { static const mkv = 'video/mkv'; static const mkvX = 'video/x-matroska'; static const mov = 'video/quicktime'; + static const mp2p = 'video/mp2p'; static const mp2t = 'video/mp2t'; // .m2ts, .ts static const mp2ts = 'video/mp2ts'; // .ts (prefer `mp2t` when possible) static const mp4 = 'video/mp4'; static const mpeg = 'video/mpeg'; static const ogv = 'video/ogg'; + static const realVideo = 'video/x-pn-realvideo'; static const webm = 'video/webm'; static const wmv = 'video/x-ms-wmv'; @@ -73,14 +78,14 @@ class MimeTypes { // formats that support transparency static const Set alphaImages = {avif, bmp, bmpX, gif, heic, heif, ico, png, svg, tiff, webp}; - static const Set rawImages = {arw, cr2, crw, dcr, dng, erf, k25, kdc, mrw, nef, nrw, orf, pef, raf, raw, rw2, sr2, srf, srw, x3f}; + static const Set rawImages = {arw, cr2, crw, dcr, dng, dngX, erf, k25, kdc, mrw, nef, nrw, orf, pef, raf, raw, rw2, sr2, srf, srw, x3f}; // TODO TLAD [codec] make it dynamic if it depends on OS/lib versions - static const Set undecodableImages = {art, cdr, crw, djvu, jxl, psdVnd, psdX, octetStream, zip}; + static const Set undecodableImages = {art, cdr, crw, djvu, jxl, pat, pnm, psdVnd, psdX, octetStream, zip}; static const Set _knownOpaqueImages = {jpeg}; - static const Set _knownVideos = {v3gpp, asf, avi, aviVnd, flv, flvX, mkv, mkvX, mov, mp2t, mp2ts, mp4, mpeg, ogv, webm, wmv}; + static const Set _knownVideos = {v3gpp, asf, avi, aviVnd, flv, flvX, mkv, mkvX, mov, mp2p, mp2t, mp2ts, mp4, mpeg, ogv, realVideo, webm, wmv}; static final Set knownMediaTypes = { anyImage, diff --git a/lib/services/media/media_file_service.dart b/lib/services/media/media_file_service.dart index 2b21d702a..ecae724f3 100644 --- a/lib/services/media/media_file_service.dart +++ b/lib/services/media/media_file_service.dart @@ -144,7 +144,7 @@ class PlatformMediaFileService implements MediaFileService { } on PlatformException catch (e, stack) { // do not report issues with simple parameter-less media content // as it is likely an obsolete Media Store entry - if (!uri.startsWith('content://media/external/') || uri.contains('?')) { + if (!uri.startsWith('content://media/') || uri.contains('?')) { await reportService.recordError(e, stack); } } diff --git a/lib/widgets/common/grid/item_tracker.dart b/lib/widgets/common/grid/item_tracker.dart index 8f5755999..f9b07c896 100644 --- a/lib/widgets/common/grid/item_tracker.dart +++ b/lib/widgets/common/grid/item_tracker.dart @@ -169,6 +169,7 @@ class _GridItemTrackerState extends State> with WidgetsBin if (pivotItem != null) { WidgetsBinding.instance.addPostFrameCallback((_) { + if (!mounted) return; context.read().trackItem(pivotItem, animate: false); }); } diff --git a/lib/widgets/common/magnifier/core/core.dart b/lib/widgets/common/magnifier/core/core.dart index 9364dcbc2..aa259d35a 100644 --- a/lib/widgets/common/magnifier/core/core.dart +++ b/lib/widgets/common/magnifier/core/core.dart @@ -169,12 +169,14 @@ class _MagnifierCoreState extends State with TickerProviderStateM final pps = details.velocity.pixelsPerSecond; if (pps != Offset.zero) { final newPosition = clampPosition(position: _position + pps * widget.panInertia); - final tween = Tween(begin: _position, end: newPosition); - const curve = Curves.easeOutCubic; - _positionAnimation = tween.animate(CurvedAnimation(parent: _positionAnimationController, curve: curve)); - _positionAnimationController - ..duration = _getAnimationDurationForVelocity(curve: curve, tween: tween, targetPixelPerSecond: pps) - ..forward(from: 0.0); + if (_position != newPosition) { + final tween = Tween(begin: _position, end: newPosition); + const curve = Curves.easeOutCubic; + _positionAnimation = tween.animate(CurvedAnimation(parent: _positionAnimationController, curve: curve)); + _positionAnimationController + ..duration = _getAnimationDurationForVelocity(curve: curve, tween: tween, targetPixelPerSecond: pps) + ..forward(from: 0.0); + } } }