catalog & locate all entries on start

This commit is contained in:
Thibault Deckers 2019-08-11 00:23:08 +09:00
parent fac80d98b9
commit 21539b97bb
12 changed files with 113 additions and 60 deletions

View file

@ -183,6 +183,8 @@ public class MetadataHandler implements MethodChannel.MethodCallHandler {
}
}
result.success(metadataMap);
} catch (ImageProcessingException e) {
result.error("getCatalogMetadata-imageprocessing", "failed to get metadata for path=" + path + " (" + e.getMessage() + ")", null);
} catch (FileNotFoundException e) {
result.error("getCatalogMetadata-filenotfound", "failed to get metadata for path=" + path + " (" + e.getMessage() + ")", null);
} catch (Exception e) {

View file

@ -1,6 +1,6 @@
import 'package:aves/model/image_decode_service.dart';
import 'package:aves/model/image_entry.dart';
import 'package:aves/model/metadata_storage_service.dart';
import 'package:aves/model/metadata_db.dart';
import 'package:aves/widgets/album/all_collection_page.dart';
import 'package:aves/widgets/common/fake_app_bar.dart';
import 'package:flutter/material.dart';
@ -50,6 +50,7 @@ class _HomePageState extends State<HomePage> {
onDone: () {
debugPrint('mediastore stream done');
setState(() {});
catalogEntries();
},
onError: (error) => debugPrint('mediastore stream error=$error'),
);
@ -65,4 +66,22 @@ class _HomePageState extends State<HomePage> {
resizeToAvoidBottomInset: false,
);
}
catalogEntries() async {
debugPrint('$runtimeType catalogEntries cataloging start');
await Future.forEach<ImageEntry>(entries, (entry) async {
await entry.catalog();
});
debugPrint('$runtimeType catalogEntries cataloging complete');
// sort with more accurate date
entries.sort((a,b) => b.bestDate.compareTo(a.bestDate));
setState(() {});
debugPrint('$runtimeType catalogEntries locating start');
await Future.forEach<ImageEntry>(entries, (entry) async {
await entry.locate();
});
debugPrint('$runtimeType catalogEntries locating done');
}
}

View file

@ -1,36 +0,0 @@
import 'package:geocoder/model.dart';
class CatalogMetadata {
final int contentId, dateMillis;
final String xmpSubjects;
final double latitude, longitude;
Address address;
CatalogMetadata({this.contentId, this.dateMillis, this.xmpSubjects, double latitude, double longitude})
// Geocoder throws an IllegalArgumentException when a coordinate has a funky values like 1.7056881853375E7
: this.latitude = latitude == null || latitude < -90.0 || latitude > 90.0 ? null : latitude,
this.longitude = longitude == null || longitude < -180.0 || longitude > 180.0 ? null : longitude;
factory CatalogMetadata.fromMap(Map map) {
return CatalogMetadata(
contentId: map['contentId'],
dateMillis: map['dateMillis'],
xmpSubjects: map['xmpSubjects'],
latitude: map['latitude'],
longitude: map['longitude'],
);
}
Map<String, dynamic> toMap() => {
'contentId': contentId,
'dateMillis': dateMillis,
'xmpSubjects': xmpSubjects,
'latitude': latitude,
'longitude': longitude,
};
@override
String toString() {
return 'CatalogMetadata{contentId=$contentId, dateMillis=$dateMillis, latitude=$latitude, longitude=$longitude, xmpSubjects=$xmpSubjects}';
}
}

View file

@ -16,7 +16,7 @@ class ImageDecodeService {
}
static Future<Uint8List> getImageBytes(ImageEntry entry, int width, int height) async {
debugPrint('getImageBytes with path=${entry.path} contentId=${entry.contentId}');
// debugPrint('getImageBytes with path=${entry.path} contentId=${entry.contentId}');
if (width > 0 && height > 0) {
try {
final result = await platform.invokeMethod('getImageBytes', <String, dynamic>{

View file

@ -1,4 +1,4 @@
import 'package:aves/model/catalog_metadata.dart';
import 'package:aves/model/image_metadata.dart';
import 'package:aves/model/metadata_service.dart';
import 'package:flutter/material.dart';
import 'package:geocoder/geocoder.dart';

View file

@ -0,0 +1,67 @@
import 'package:geocoder/model.dart';
class CatalogMetadata {
final int contentId, dateMillis;
final String xmpSubjects;
final double latitude, longitude;
Address address;
CatalogMetadata({
this.contentId,
this.dateMillis,
this.xmpSubjects,
double latitude,
double longitude,
})
// Geocoder throws an IllegalArgumentException when a coordinate has a funky values like 1.7056881853375E7
: this.latitude = latitude == null || latitude < -90.0 || latitude > 90.0 ? null : latitude,
this.longitude = longitude == null || longitude < -180.0 || longitude > 180.0 ? null : longitude;
factory CatalogMetadata.fromMap(Map map) {
return CatalogMetadata(
contentId: map['contentId'],
dateMillis: map['dateMillis'],
xmpSubjects: map['xmpSubjects'],
latitude: map['latitude'],
longitude: map['longitude'],
);
}
Map<String, dynamic> toMap() => {
'contentId': contentId,
'dateMillis': dateMillis,
'xmpSubjects': xmpSubjects,
'latitude': latitude,
'longitude': longitude,
};
@override
String toString() {
return 'CatalogMetadata{contentId=$contentId, dateMillis=$dateMillis, latitude=$latitude, longitude=$longitude, xmpSubjects=$xmpSubjects}';
}
}
class OverlayMetadata {
final String aperture, exposureTime, focalLength, iso;
OverlayMetadata({
String aperture,
this.exposureTime,
this.focalLength,
this.iso,
}) : this.aperture = aperture.replaceFirst('f', 'ƒ');
factory OverlayMetadata.fromMap(Map map) {
return OverlayMetadata(
aperture: map['aperture'],
exposureTime: map['exposureTime'],
focalLength: map['focalLength'],
iso: map['iso'],
);
}
@override
String toString() {
return 'OverlayMetadata{aperture=$aperture, exposureTime=$exposureTime, focalLength=$focalLength, iso=$iso}';
}
}

View file

@ -1,4 +1,4 @@
import 'package:aves/model/catalog_metadata.dart';
import 'package:aves/model/image_metadata.dart';
import 'package:flutter/foundation.dart';
import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
@ -52,7 +52,7 @@ class MetadataDb {
}
insert(CatalogMetadata metadata) async {
debugPrint('$runtimeType insert metadata=$metadata');
// debugPrint('$runtimeType insert metadata=$metadata');
final db = await _database;
await db.insert(
table,

View file

@ -1,5 +1,5 @@
import 'package:aves/model/catalog_metadata.dart';
import 'package:aves/model/metadata_storage_service.dart';
import 'package:aves/model/image_metadata.dart';
import 'package:aves/model/metadata_db.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
@ -40,16 +40,16 @@ class MetadataService {
return null;
}
// return map with string descriptions for: 'aperture' 'exposureTime' 'focalLength' 'iso'
static Future<Map> getOverlayMetadata(String path) async {
static Future<OverlayMetadata> getOverlayMetadata(String path) async {
try {
// return map with string descriptions for: 'aperture' 'exposureTime' 'focalLength' 'iso'
final result = await platform.invokeMethod('getOverlayMetadata', <String, dynamic>{
'path': path,
});
return result as Map;
}) as Map;
return OverlayMetadata.fromMap(result);
} on PlatformException catch (e) {
debugPrint('getOverlayMetadata failed with exception=${e.message}');
}
return Map();
return null;
}
}

View file

@ -1,5 +1,5 @@
import 'package:aves/model/catalog_metadata.dart';
import 'package:aves/model/metadata_storage_service.dart';
import 'package:aves/model/image_metadata.dart';
import 'package:aves/model/metadata_db.dart';
import 'package:flutter/material.dart';
class DebugPage extends StatefulWidget {

View file

@ -1,8 +1,8 @@
import 'dart:io';
import 'dart:math';
import 'package:aves/model/android_app_service.dart';
import 'package:aves/model/image_entry.dart';
import 'package:aves/utils/android_app_service.dart';
import 'package:aves/widgets/fullscreen/info/info_page.dart';
import 'package:aves/widgets/fullscreen/overlay_bottom.dart';
import 'package:aves/widgets/fullscreen/overlay_top.dart';

View file

@ -2,6 +2,7 @@ import 'dart:math';
import 'dart:ui';
import 'package:aves/model/image_entry.dart';
import 'package:aves/model/image_metadata.dart';
import 'package:aves/model/metadata_service.dart';
import 'package:aves/widgets/common/blurred.dart';
import 'package:flutter/material.dart';
@ -25,9 +26,9 @@ class FullscreenBottomOverlay extends StatefulWidget {
}
class _FullscreenBottomOverlayState extends State<FullscreenBottomOverlay> {
Future<Map> _detailLoader;
Future<OverlayMetadata> _detailLoader;
ImageEntry _lastEntry;
Map _lastDetails;
OverlayMetadata _lastDetails;
ImageEntry get entry => widget.entries[widget.index];
@ -63,7 +64,7 @@ class _FullscreenBottomOverlayState extends State<FullscreenBottomOverlay> {
padding: innerPadding,
child: FutureBuilder(
future: _detailLoader,
builder: (futureContext, AsyncSnapshot<Map> snapshot) {
builder: (futureContext, AsyncSnapshot<OverlayMetadata> snapshot) {
if (snapshot.connectionState == ConnectionState.done && !snapshot.hasError) {
_lastDetails = snapshot.data;
_lastEntry = entry;
@ -87,7 +88,7 @@ class _FullscreenBottomOverlayState extends State<FullscreenBottomOverlay> {
class _FullscreenBottomOverlayContent extends StatelessWidget {
final ImageEntry entry;
final Map details;
final OverlayMetadata details;
final String position;
final double maxWidth;
@ -129,7 +130,7 @@ class _FullscreenBottomOverlayContent extends StatelessWidget {
],
),
),
if (details != null && details.isNotEmpty) ...[
if (details != null) ...[
SizedBox(height: 4),
SizedBox(
width: subRowWidth,
@ -137,10 +138,10 @@ class _FullscreenBottomOverlayContent extends StatelessWidget {
children: [
Icon(Icons.camera, size: 16),
SizedBox(width: 8),
Expanded(child: Text((details['aperture'] as String).replaceAll('f', 'ƒ'))),
Expanded(child: Text(details['exposureTime'])),
Expanded(child: Text(details['focalLength'])),
Expanded(child: Text(details['iso'])),
Expanded(child: Text(details.aperture)),
Expanded(child: Text(details.exposureTime)),
Expanded(child: Text(details.focalLength)),
Expanded(child: Text(details.iso)),
],
),
),