aves/lib/model/entry/extensions/props.dart
Thibault Deckers 5784607130 refactor
2023-03-14 20:31:18 +01:00

119 lines
3.8 KiB
Dart

import 'dart:ui';
import 'package:aves/model/entry/entry.dart';
import 'package:aves/model/settings/settings.dart';
import 'package:aves/ref/mime_types.dart';
import 'package:aves/utils/android_file_utils.dart';
extension ExtraAvesEntryProps on AvesEntry {
String get mimeTypeAnySubtype => mimeType.replaceAll(RegExp('/.*'), '/*');
bool get isSvg => mimeType == MimeTypes.svg;
// guess whether this is a photo, according to file type (used as a hint to e.g. display megapixels)
bool get isPhoto => [MimeTypes.heic, MimeTypes.heif, MimeTypes.jpeg, MimeTypes.tiff].contains(mimeType) || isRaw;
// Android's `BitmapRegionDecoder` documentation states that "only the JPEG and PNG formats are supported"
// but in practice (tested on API 25, 27, 29), it successfully decodes the formats listed below,
// and it actually fails to decode GIF, DNG and animated WEBP. Other formats were not tested.
bool get _supportedByBitmapRegionDecoder =>
[
MimeTypes.heic,
MimeTypes.heif,
MimeTypes.jpeg,
MimeTypes.png,
MimeTypes.webp,
MimeTypes.arw,
MimeTypes.cr2,
MimeTypes.nef,
MimeTypes.nrw,
MimeTypes.orf,
MimeTypes.pef,
MimeTypes.raf,
MimeTypes.rw2,
MimeTypes.srw,
].contains(mimeType) &&
!isAnimated;
bool get supportTiling => _supportedByBitmapRegionDecoder || mimeType == MimeTypes.tiff;
bool get useTiles => supportTiling && (width > 4096 || height > 4096);
bool get isRaw => MimeTypes.rawImages.contains(mimeType);
bool get isImage => MimeTypes.isImage(mimeType);
bool get isVideo => MimeTypes.isVideo(mimeType);
bool get isAnimated => catalogMetadata?.isAnimated ?? false;
bool get isGeotiff => catalogMetadata?.isGeotiff ?? false;
bool get is360 => catalogMetadata?.is360 ?? false;
bool get isMediaStoreContent => uri.startsWith('content://media/');
bool get isMediaStoreMediaContent => isMediaStoreContent && {'/external/images/', '/external/video/'}.any(uri.contains);
bool get isVaultContent => path?.startsWith(androidFileUtils.vaultRoot) ?? false;
bool get canEdit => !settings.isReadOnly && path != null && !trashed && (isMediaStoreContent || isVaultContent);
bool get canEditDate => canEdit && (canEditExif || canEditXmp);
bool get canEditLocation => canEdit && (canEditExif || mimeType == MimeTypes.mp4);
bool get canEditTitleDescription => canEdit && canEditXmp;
bool get canEditRating => canEdit && canEditXmp;
bool get canEditTags => canEdit && canEditXmp;
bool get canRotate => canEdit && (canEditExif || mimeType == MimeTypes.mp4);
bool get canFlip => canEdit && canEditExif;
bool get canEditExif => MimeTypes.canEditExif(mimeType);
bool get canEditIptc => MimeTypes.canEditIptc(mimeType);
bool get canEditXmp => MimeTypes.canEditXmp(mimeType);
bool get canRemoveMetadata => MimeTypes.canRemoveMetadata(mimeType);
static const ratioSeparator = '\u2236';
static const resolutionSeparator = ' \u00D7 ';
bool get isSized => width > 0 && height > 0;
String get resolutionText {
final ws = width;
final hs = height;
return isRotated ? '$hs$resolutionSeparator$ws' : '$ws$resolutionSeparator$hs';
}
String get aspectRatioText {
if (width > 0 && height > 0) {
final gcd = width.gcd(height);
final w = width ~/ gcd;
final h = height ~/ gcd;
return isRotated ? '$h$ratioSeparator$w' : '$w$ratioSeparator$h';
} else {
return '?$ratioSeparator?';
}
}
Size videoDisplaySize(double sar) {
final size = displaySize;
if (sar != 1) {
final dar = displayAspectRatio * sar;
final w = size.width;
final h = size.height;
if (w >= h) return Size(w, w / dar);
if (h > w) return Size(h * dar, h);
}
return size;
}
int get megaPixels => (width * height / 1000000).round();
}