various null/default fixes
This commit is contained in:
parent
e9e48c37f4
commit
f0818066b5
10 changed files with 44 additions and 17 deletions
|
@ -21,9 +21,9 @@ public class AvesImageEntry {
|
||||||
this.uri = Uri.parse((String) map.get("uri"));
|
this.uri = Uri.parse((String) map.get("uri"));
|
||||||
this.path = (String) map.get("path");
|
this.path = (String) map.get("path");
|
||||||
this.mimeType = (String) map.get("mimeType");
|
this.mimeType = (String) map.get("mimeType");
|
||||||
this.width = (int) map.get("width");
|
this.width = (Integer) map.get("width");
|
||||||
this.height = (int) map.get("height");
|
this.height = (Integer) map.get("height");
|
||||||
this.orientationDegrees = (int) map.get("orientationDegrees");
|
this.orientationDegrees = (Integer) map.get("orientationDegrees");
|
||||||
this.dateModifiedSecs = toLong(map.get("dateModifiedSecs"));
|
this.dateModifiedSecs = toLong(map.get("dateModifiedSecs"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,15 +41,16 @@ class ImageEntry {
|
||||||
String path,
|
String path,
|
||||||
this.contentId,
|
this.contentId,
|
||||||
this.sourceMimeType,
|
this.sourceMimeType,
|
||||||
this.width,
|
@required this.width,
|
||||||
this.height,
|
@required this.height,
|
||||||
this.orientationDegrees,
|
this.orientationDegrees,
|
||||||
this.sizeBytes,
|
this.sizeBytes,
|
||||||
this.sourceTitle,
|
this.sourceTitle,
|
||||||
this.dateModifiedSecs,
|
this.dateModifiedSecs,
|
||||||
this.sourceDateTakenMillis,
|
this.sourceDateTakenMillis,
|
||||||
this.durationMillis,
|
this.durationMillis,
|
||||||
}) {
|
}) : assert(width != null),
|
||||||
|
assert(height != null) {
|
||||||
this.path = path;
|
this.path = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,8 +87,8 @@ class ImageEntry {
|
||||||
path: map['path'] as String,
|
path: map['path'] as String,
|
||||||
contentId: map['contentId'] as int,
|
contentId: map['contentId'] as int,
|
||||||
sourceMimeType: map['sourceMimeType'] as String,
|
sourceMimeType: map['sourceMimeType'] as String,
|
||||||
width: map['width'] as int,
|
width: map['width'] as int ?? 0,
|
||||||
height: map['height'] as int,
|
height: map['height'] as int ?? 0,
|
||||||
orientationDegrees: map['orientationDegrees'] as int,
|
orientationDegrees: map['orientationDegrees'] as int,
|
||||||
sizeBytes: map['sizeBytes'] as int,
|
sizeBytes: map['sizeBytes'] as int,
|
||||||
sourceTitle: map['title'] as String,
|
sourceTitle: map['title'] as String,
|
||||||
|
@ -210,7 +211,7 @@ class ImageEntry {
|
||||||
String _durationText;
|
String _durationText;
|
||||||
|
|
||||||
String get durationText {
|
String get durationText {
|
||||||
_durationText ??= formatDuration(Duration(milliseconds: durationMillis));
|
_durationText ??= formatDuration(Duration(milliseconds: durationMillis ?? 0));
|
||||||
return _durationText;
|
return _durationText;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,7 +269,7 @@ class ImageEntry {
|
||||||
await catalog(background: background);
|
await catalog(background: background);
|
||||||
final latitude = _catalogMetadata?.latitude;
|
final latitude = _catalogMetadata?.latitude;
|
||||||
final longitude = _catalogMetadata?.longitude;
|
final longitude = _catalogMetadata?.longitude;
|
||||||
if (latitude == null || longitude == null) return;
|
if (latitude == null || longitude == null || (latitude == 0 && longitude == 0)) return;
|
||||||
|
|
||||||
final coordinates = Coordinates(latitude, longitude);
|
final coordinates = Coordinates(latitude, longitude);
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -66,7 +66,7 @@ class ImageFileService {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<Uint8List> getImage(String uri, String mimeType, {int expectedContentLength, BytesReceivedCallback onBytesReceived}) {
|
static Future<Uint8List> getImage(String uri, String mimeType, {int orientationDegrees, int expectedContentLength, BytesReceivedCallback onBytesReceived}) {
|
||||||
try {
|
try {
|
||||||
final completer = Completer<Uint8List>.sync();
|
final completer = Completer<Uint8List>.sync();
|
||||||
final sink = _OutputBuffer();
|
final sink = _OutputBuffer();
|
||||||
|
@ -74,6 +74,7 @@ class ImageFileService {
|
||||||
byteChannel.receiveBroadcastStream(<String, dynamic>{
|
byteChannel.receiveBroadcastStream(<String, dynamic>{
|
||||||
'uri': uri,
|
'uri': uri,
|
||||||
'mimeType': mimeType,
|
'mimeType': mimeType,
|
||||||
|
'orientationDegrees': orientationDegrees ?? 0,
|
||||||
}).listen(
|
}).listen(
|
||||||
(data) {
|
(data) {
|
||||||
final chunk = data as Uint8List;
|
final chunk = data as Uint8List;
|
||||||
|
@ -103,6 +104,9 @@ class ImageFileService {
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<Uint8List> getThumbnail(ImageEntry entry, double width, double height, {Object taskKey, int priority}) {
|
static Future<Uint8List> getThumbnail(ImageEntry entry, double width, double height, {Object taskKey, int priority}) {
|
||||||
|
if (entry.isSvg) {
|
||||||
|
return Future.sync(() => Uint8List(0));
|
||||||
|
}
|
||||||
return servicePolicy.call(
|
return servicePolicy.call(
|
||||||
() async {
|
() async {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -126,6 +126,7 @@ class _ThumbnailRasterImageState extends State<ThumbnailRasterImage> {
|
||||||
final imageProvider = UriImage(
|
final imageProvider = UriImage(
|
||||||
uri: entry.uri,
|
uri: entry.uri,
|
||||||
mimeType: entry.mimeType,
|
mimeType: entry.mimeType,
|
||||||
|
orientationDegrees: entry.orientationDegrees,
|
||||||
expectedContentLength: entry.sizeBytes,
|
expectedContentLength: entry.sizeBytes,
|
||||||
);
|
);
|
||||||
if (imageCache.statusForKey(imageProvider).keepAlive) {
|
if (imageCache.statusForKey(imageProvider).keepAlive) {
|
||||||
|
|
|
@ -76,12 +76,13 @@ class EntryActionDelegate with FeedbackMixin, PermissionAwareMixin {
|
||||||
Future<void> _print(ImageEntry entry) async {
|
Future<void> _print(ImageEntry entry) async {
|
||||||
final uri = entry.uri;
|
final uri = entry.uri;
|
||||||
final mimeType = entry.mimeType;
|
final mimeType = entry.mimeType;
|
||||||
|
final orientationDegrees = entry.orientationDegrees;
|
||||||
final documentName = entry.bestTitle ?? 'Aves';
|
final documentName = entry.bestTitle ?? 'Aves';
|
||||||
final doc = pdf.Document(title: documentName);
|
final doc = pdf.Document(title: documentName);
|
||||||
|
|
||||||
PdfImage pdfImage;
|
PdfImage pdfImage;
|
||||||
if (entry.isSvg) {
|
if (entry.isSvg) {
|
||||||
final bytes = await ImageFileService.getImage(uri, mimeType);
|
final bytes = await ImageFileService.getImage(uri, mimeType, orientationDegrees: entry.orientationDegrees);
|
||||||
if (bytes != null && bytes.isNotEmpty) {
|
if (bytes != null && bytes.isNotEmpty) {
|
||||||
final svgRoot = await svg.fromSvgBytes(bytes, uri);
|
final svgRoot = await svg.fromSvgBytes(bytes, uri);
|
||||||
final viewBox = svgRoot.viewport.viewBox;
|
final viewBox = svgRoot.viewport.viewBox;
|
||||||
|
@ -97,7 +98,11 @@ class EntryActionDelegate with FeedbackMixin, PermissionAwareMixin {
|
||||||
} else {
|
} else {
|
||||||
pdfImage = await pdfImageFromImageProvider(
|
pdfImage = await pdfImageFromImageProvider(
|
||||||
pdf: doc.document,
|
pdf: doc.document,
|
||||||
image: UriImage(uri: uri, mimeType: mimeType),
|
image: UriImage(
|
||||||
|
uri: uri,
|
||||||
|
mimeType: mimeType,
|
||||||
|
orientationDegrees: orientationDegrees,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (pdfImage != null) {
|
if (pdfImage != null) {
|
||||||
|
|
|
@ -11,13 +11,14 @@ class UriImage extends ImageProvider<UriImage> {
|
||||||
const UriImage({
|
const UriImage({
|
||||||
@required this.uri,
|
@required this.uri,
|
||||||
@required this.mimeType,
|
@required this.mimeType,
|
||||||
|
@required this.orientationDegrees,
|
||||||
this.expectedContentLength,
|
this.expectedContentLength,
|
||||||
this.scale = 1.0,
|
this.scale = 1.0,
|
||||||
}) : assert(uri != null),
|
}) : assert(uri != null),
|
||||||
assert(scale != null);
|
assert(scale != null);
|
||||||
|
|
||||||
final String uri, mimeType;
|
final String uri, mimeType;
|
||||||
final int expectedContentLength;
|
final int orientationDegrees, expectedContentLength;
|
||||||
final double scale;
|
final double scale;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -46,6 +47,7 @@ class UriImage extends ImageProvider<UriImage> {
|
||||||
final bytes = await ImageFileService.getImage(
|
final bytes = await ImageFileService.getImage(
|
||||||
uri,
|
uri,
|
||||||
mimeType,
|
mimeType,
|
||||||
|
orientationDegrees: orientationDegrees,
|
||||||
expectedContentLength: expectedContentLength,
|
expectedContentLength: expectedContentLength,
|
||||||
onBytesReceived: (cumulative, total) {
|
onBytesReceived: (cumulative, total) {
|
||||||
chunkEvents.add(ImageChunkEvent(
|
chunkEvents.add(ImageChunkEvent(
|
||||||
|
|
|
@ -60,6 +60,14 @@ class _FullscreenDebugPageState extends State<FullscreenDebugPage> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildEntryTabView() {
|
Widget _buildEntryTabView() {
|
||||||
|
String toDateValue(int time, {int factor = 1}) {
|
||||||
|
var value = '$time';
|
||||||
|
if (time != null && time > 0) {
|
||||||
|
value += ' (${DateTime.fromMillisecondsSinceEpoch(time * factor)})';
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
return ListView(
|
return ListView(
|
||||||
padding: EdgeInsets.all(16),
|
padding: EdgeInsets.all(16),
|
||||||
children: [
|
children: [
|
||||||
|
@ -76,8 +84,8 @@ class _FullscreenDebugPageState extends State<FullscreenDebugPage> {
|
||||||
}),
|
}),
|
||||||
Divider(),
|
Divider(),
|
||||||
InfoRowGroup({
|
InfoRowGroup({
|
||||||
'dateModifiedSecs': '${entry.dateModifiedSecs} (${DateTime.fromMillisecondsSinceEpoch(entry.dateModifiedSecs * 1000)})',
|
'dateModifiedSecs': toDateValue(entry.dateModifiedSecs, factor: 1000),
|
||||||
'sourceDateTakenMillis': '${entry.sourceDateTakenMillis} (${DateTime.fromMillisecondsSinceEpoch(entry.sourceDateTakenMillis)})',
|
'sourceDateTakenMillis': toDateValue(entry.sourceDateTakenMillis),
|
||||||
'bestDate': '${entry.bestDate}',
|
'bestDate': '${entry.bestDate}',
|
||||||
'monthTaken': '${entry.monthTaken}',
|
'monthTaken': '${entry.monthTaken}',
|
||||||
'dayTaken': '${entry.dayTaken}',
|
'dayTaken': '${entry.dayTaken}',
|
||||||
|
|
|
@ -530,7 +530,11 @@ class _FullscreenVerticalPageViewState extends State<FullscreenVerticalPageView>
|
||||||
|
|
||||||
// when the entry image itself changed (e.g. after rotation)
|
// when the entry image itself changed (e.g. after rotation)
|
||||||
void _onImageChanged() async {
|
void _onImageChanged() async {
|
||||||
await UriImage(uri: entry.uri, mimeType: entry.mimeType).evict();
|
await UriImage(
|
||||||
|
uri: entry.uri,
|
||||||
|
mimeType: entry.mimeType,
|
||||||
|
orientationDegrees: entry.orientationDegrees,
|
||||||
|
).evict();
|
||||||
// evict low quality thumbnail (without specified extents)
|
// evict low quality thumbnail (without specified extents)
|
||||||
await ThumbnailProvider(entry: entry).evict();
|
await ThumbnailProvider(entry: entry).evict();
|
||||||
// evict higher quality thumbnails (with powers of 2 from 32 to 1024 as specified extents)
|
// evict higher quality thumbnails (with powers of 2 from 32 to 1024 as specified extents)
|
||||||
|
|
|
@ -96,6 +96,7 @@ class ImageView extends StatelessWidget {
|
||||||
final uriImage = UriImage(
|
final uriImage = UriImage(
|
||||||
uri: entry.uri,
|
uri: entry.uri,
|
||||||
mimeType: entry.mimeType,
|
mimeType: entry.mimeType,
|
||||||
|
orientationDegrees: entry.orientationDegrees,
|
||||||
expectedContentLength: entry.sizeBytes,
|
expectedContentLength: entry.sizeBytes,
|
||||||
);
|
);
|
||||||
child = PhotoView(
|
child = PhotoView(
|
||||||
|
|
|
@ -101,6 +101,7 @@ class AvesVideoState extends State<AvesVideo> {
|
||||||
image: UriImage(
|
image: UriImage(
|
||||||
uri: entry.uri,
|
uri: entry.uri,
|
||||||
mimeType: entry.mimeType,
|
mimeType: entry.mimeType,
|
||||||
|
orientationDegrees: entry.orientationDegrees,
|
||||||
expectedContentLength: entry.sizeBytes,
|
expectedContentLength: entry.sizeBytes,
|
||||||
),
|
),
|
||||||
width: entry.width.toDouble(),
|
width: entry.width.toDouble(),
|
||||||
|
|
Loading…
Reference in a new issue