From 23f878b962b05d0f47c6423a5f2aa81049e90bdc Mon Sep 17 00:00:00 2001 From: ashilkn Date: Wed, 15 Mar 2023 16:17:12 +0530 Subject: [PATCH 01/11] Created InfoItem for locationTags in file details --- lib/ui/viewer/file/file_details_widget.dart | 7 +++ .../file_details/location_tags_widget.dart | 54 +++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 lib/ui/viewer/file_details/location_tags_widget.dart diff --git a/lib/ui/viewer/file/file_details_widget.dart b/lib/ui/viewer/file/file_details_widget.dart index 12c9a4b58..041698694 100644 --- a/lib/ui/viewer/file/file_details_widget.dart +++ b/lib/ui/viewer/file/file_details_widget.dart @@ -16,6 +16,7 @@ import 'package:photos/ui/viewer/file_details/backed_up_time_item_widget.dart'; import "package:photos/ui/viewer/file_details/creation_time_item_widget.dart"; import 'package:photos/ui/viewer/file_details/exif_item_widgets.dart'; import "package:photos/ui/viewer/file_details/file_properties_item_widget.dart"; +import "package:photos/ui/viewer/file_details/location_tags_widget.dart"; import "package:photos/ui/viewer/file_details/objects_item_widget.dart"; import "package:photos/utils/exif_util.dart"; @@ -125,6 +126,12 @@ class _FileDetailsWidgetState extends State { }, ), ); + if (FeatureFlagService.instance.isInternalUserOrDebugBuild()) { + fileDetailsTiles.addAll([ + LocationTagsWidget(widget.file), + const FileDetailsDivider(), + ]); + } if (_isImage) { fileDetailsTiles.addAll([ ValueListenableBuilder( diff --git a/lib/ui/viewer/file_details/location_tags_widget.dart b/lib/ui/viewer/file_details/location_tags_widget.dart new file mode 100644 index 000000000..d26ae0bf4 --- /dev/null +++ b/lib/ui/viewer/file_details/location_tags_widget.dart @@ -0,0 +1,54 @@ +import "dart:async"; + +import "package:flutter/material.dart"; +import "package:photos/models/file.dart"; +import "package:photos/services/location_service.dart"; +import "package:photos/ui/components/buttons/chip_button_widget.dart"; +import "package:photos/ui/components/buttons/inline_button_widget.dart"; +import "package:photos/ui/components/info_item_widget.dart"; + +class LocationTagsWidget extends StatefulWidget { + final File file; + const LocationTagsWidget(this.file, {super.key}); + + @override + State createState() => _LocationTagsWidgetState(); +} + +class _LocationTagsWidgetState extends State { + String title = "Add location"; + IconData leadingIcon = Icons.add_location_alt_outlined; + bool hasChipButtons = false; + late final Future> locationTagChips; + @override + void initState() { + locationTagChips = _getLocationTags(); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return InfoItemWidget( + leadingIcon: Icons.add_location_alt_outlined, + title: "Add location", + subtitleSection: locationTagChips, + hasChipButtons: hasChipButtons, + ); + } + + Future> _getLocationTags() async { + final locationTags = + LocationService.instance.getLocationsByFileID(widget.file.generatedID!); + if (locationTags.isEmpty) { + return [ + InlineButtonWidget("Group nearby photos", () {}), + ]; + } + setState(() { + title = "Location"; + leadingIcon = Icons.pin_drop_outlined; + hasChipButtons = true; + }); + return locationTags.map((e) => ChipButtonWidget(e)).toList(); + } +} From 828f2e5a83a7524c4d8bd86d531be4a15a47757b Mon Sep 17 00:00:00 2001 From: ashilkn Date: Wed, 15 Mar 2023 16:30:21 +0530 Subject: [PATCH 02/11] Added animation when locationTag InfoItem rebuilds --- .../file_details/location_tags_widget.dart | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/ui/viewer/file_details/location_tags_widget.dart b/lib/ui/viewer/file_details/location_tags_widget.dart index d26ae0bf4..352583441 100644 --- a/lib/ui/viewer/file_details/location_tags_widget.dart +++ b/lib/ui/viewer/file_details/location_tags_widget.dart @@ -28,11 +28,17 @@ class _LocationTagsWidgetState extends State { @override Widget build(BuildContext context) { - return InfoItemWidget( - leadingIcon: Icons.add_location_alt_outlined, - title: "Add location", - subtitleSection: locationTagChips, - hasChipButtons: hasChipButtons, + return AnimatedSwitcher( + duration: const Duration(milliseconds: 500), + switchInCurve: Curves.easeInOutExpo, + switchOutCurve: Curves.easeInOutExpo, + child: InfoItemWidget( + key: ValueKey(title), + leadingIcon: Icons.add_location_alt_outlined, + title: title, + subtitleSection: locationTagChips, + hasChipButtons: hasChipButtons, + ), ); } From 595e0e1149d8710ab12affd7331901de4926d0fb Mon Sep 17 00:00:00 2001 From: ashilkn Date: Fri, 17 Mar 2023 10:12:47 +0530 Subject: [PATCH 03/11] Store loactionTag data with name, raduis & properites of the ellipse --- lib/core/constants.dart | 2 ++ lib/services/location_service.dart | 26 ++++++++++++++++++++++---- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/lib/core/constants.dart b/lib/core/constants.dart index 236419b4d..469170f7b 100644 --- a/lib/core/constants.dart +++ b/lib/core/constants.dart @@ -57,3 +57,5 @@ const double restrictedMaxWidth = 430; const double mobileSmallThreshold = 336; const publicLinkDeviceLimits = [50, 25, 10, 5, 2, 1]; + +const kilometersPerDegree = 111.16; diff --git a/lib/services/location_service.dart b/lib/services/location_service.dart index 7815b355c..7b8a53430 100644 --- a/lib/services/location_service.dart +++ b/lib/services/location_service.dart @@ -1,6 +1,8 @@ import "dart:collection"; import "dart:convert"; +import "dart:math"; +import "package:photos/core/constants.dart"; import "package:shared_preferences/shared_preferences.dart"; class LocationService { @@ -22,22 +24,38 @@ class LocationService { Future addLocation( String location, double lat, - double lon, + double long, int radius, ) async { final list = getLocations(); + //The area enclosed by the location tag will be a circle on a 3D spherical + //globe and an ellipse on a 2D Mercator projection (2D map) + //a & b are the semi-major and semi-minor axes of the ellipse + //Converting the unit from kilometers to degrees for a and b as that is + //the unit on the caritesian plane + final a = (radius * _scaleFactor(lat)) / kilometersPerDegree; + final b = radius / kilometersPerDegree; + final center = [lat, long]; final data = { - "id": list.length, "name": location, - "lat": lat, - "lon": lon, "radius": radius, + "a": a, + "b": b, + "center": center, }; final encodedMap = json.encode(data); list.add(encodedMap); await prefs!.setStringList('locations', list); } + ///The area bounded by the location tag becomes more elliptical with increase + ///in the magnitude of the latitude on the caritesian plane. When latitude is + ///0 degrees, the ellipse is a circle with a = b = r. When latitude incrases, + ///the major axis (a) has to be scaled by the secant of the latitude. + double _scaleFactor(double lat) { + return 1 / cos(lat * (pi / 180)); + } + Future addFileToLocation(int locationId, int fileId) async { final list = getFilesByLocation(locationId.toString()); list.add(fileId.toString()); From 9963e9a19411241c6daf84601c4352a86a763c82 Mon Sep 17 00:00:00 2001 From: ashilkn Date: Fri, 17 Mar 2023 16:23:22 +0530 Subject: [PATCH 04/11] Show location tag infoItem in file details only if file has GPS data --- lib/services/location_service.dart | 9 +++++ lib/ui/viewer/file/file_details_widget.dart | 38 ++++++++++++++++++--- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/lib/services/location_service.dart b/lib/services/location_service.dart index 7b8a53430..6f966c24e 100644 --- a/lib/services/location_service.dart +++ b/lib/services/location_service.dart @@ -99,3 +99,12 @@ class LocationService { return map; } } + +class GPSData { + String latRef; + List lat; + String longRef; + List long; + + GPSData(this.latRef, this.lat, this.longRef, this.long); +} diff --git a/lib/ui/viewer/file/file_details_widget.dart b/lib/ui/viewer/file/file_details_widget.dart index 041698694..ee71e7706 100644 --- a/lib/ui/viewer/file/file_details_widget.dart +++ b/lib/ui/viewer/file/file_details_widget.dart @@ -46,6 +46,7 @@ class _FileDetailsWidgetState extends State { bool _isImage = false; late int _currentUserID; bool showExifListTile = false; + bool hasGPSData = false; @override void initState() { @@ -53,6 +54,11 @@ class _FileDetailsWidgetState extends State { _currentUserID = Configuration.instance.getUserID()!; _isImage = widget.file.fileType == FileType.image || widget.file.fileType == FileType.livePhoto; + _exifNotifier.addListener(() { + if (_exifNotifier.value != null) { + hasGPSData = _haGPSData(_exifNotifier.value!); + } + }); if (_isImage) { _exifNotifier.addListener(() { if (_exifNotifier.value != null) { @@ -64,10 +70,10 @@ class _FileDetailsWidgetState extends State { _exifData["exposureTime"] != null || _exifData["ISO"] != null; }); - getExif(widget.file).then((exif) { - _exifNotifier.value = exif; - }); } + getExif(widget.file).then((exif) { + _exifNotifier.value = exif; + }); super.initState(); } @@ -128,8 +134,19 @@ class _FileDetailsWidgetState extends State { ); if (FeatureFlagService.instance.isInternalUserOrDebugBuild()) { fileDetailsTiles.addAll([ - LocationTagsWidget(widget.file), - const FileDetailsDivider(), + ValueListenableBuilder( + valueListenable: _exifNotifier, + builder: (context, _, __) { + return hasGPSData + ? Column( + children: [ + LocationTagsWidget(widget.file), + const FileDetailsDivider(), + ], + ) + : const SizedBox.shrink(); + }, + ) ]); } if (_isImage) { @@ -207,6 +224,17 @@ class _FileDetailsWidgetState extends State { ); } + bool _haGPSData(Map exif) { + return exif["GPS GPSLatitude"] != null && + exif["GPS GPSLongitude"] != null && + exif["GPS GPSLatitudeRef"] != null && + exif["GPS GPSLongitudeRef"] != null && + exif["GPS GPSLatitude"].toString() != "" && + exif["GPS GPSLongitude"].toString() != "" && + exif["GPS GPSLatitudeRef"].toString() != "" && + exif["GPS GPSLongitudeRef"].toString() != ""; + } + _generateExifForDetails(Map exif) { if (exif["EXIF FocalLength"] != null) { _exifData["focalLength"] = From d2b2a8f59575f24ac9e8c837594d96567192af92 Mon Sep 17 00:00:00 2001 From: ashilkn Date: Fri, 17 Mar 2023 17:30:39 +0530 Subject: [PATCH 05/11] Modify code for hasGPSData + pass signedDecimalDegree coordinates to LocationTagsWidget --- lib/services/location_service.dart | 9 +++ lib/ui/viewer/file/file_details_widget.dart | 56 +++++++++++++++---- .../file_details/location_tags_widget.dart | 10 ++-- 3 files changed, 57 insertions(+), 18 deletions(-) diff --git a/lib/services/location_service.dart b/lib/services/location_service.dart index 6f966c24e..ce8c5266c 100644 --- a/lib/services/location_service.dart +++ b/lib/services/location_service.dart @@ -107,4 +107,13 @@ class GPSData { List long; GPSData(this.latRef, this.lat, this.longRef, this.long); + + List toSignedDecimalDegreeCoordinates() { + final latSign = latRef == "N" ? 1 : -1; + final longSign = longRef == "E" ? 1 : -1; + return [ + latSign * lat[0] + lat[1] / 60 + lat[2] / 3600, + longSign * long[0] + long[1] / 60 + long[2] / 3600 + ]; + } } diff --git a/lib/ui/viewer/file/file_details_widget.dart b/lib/ui/viewer/file/file_details_widget.dart index ee71e7706..e525a69fb 100644 --- a/lib/ui/viewer/file/file_details_widget.dart +++ b/lib/ui/viewer/file/file_details_widget.dart @@ -5,6 +5,7 @@ import "package:photos/core/configuration.dart"; import "package:photos/models/file.dart"; import "package:photos/models/file_type.dart"; import "package:photos/services/feature_flag_service.dart"; +import "package:photos/services/location_service.dart"; import 'package:photos/theme/ente_theme.dart'; import 'package:photos/ui/components/buttons/icon_button_widget.dart'; import "package:photos/ui/components/divider_widget.dart"; @@ -40,7 +41,11 @@ class _FileDetailsWidgetState extends State { "takenOnDevice": null, "exposureTime": null, "ISO": null, - "megaPixels": null + "megaPixels": null, + "lat": null, + "long": null, + "latRef": null, + "longRef": null, }; bool _isImage = false; @@ -56,7 +61,8 @@ class _FileDetailsWidgetState extends State { widget.file.fileType == FileType.livePhoto; _exifNotifier.addListener(() { if (_exifNotifier.value != null) { - hasGPSData = _haGPSData(_exifNotifier.value!); + _generateExifForLocation(_exifNotifier.value!); + hasGPSData = _haGPSData(); } }); if (_isImage) { @@ -140,7 +146,14 @@ class _FileDetailsWidgetState extends State { return hasGPSData ? Column( children: [ - LocationTagsWidget(widget.file), + LocationTagsWidget( + GPSData( + _exifData["latRef"], + _exifData["lat"], + _exifData["longRef"], + _exifData["long"], + ).toSignedDecimalDegreeCoordinates(), + ), const FileDetailsDivider(), ], ) @@ -224,15 +237,34 @@ class _FileDetailsWidgetState extends State { ); } - bool _haGPSData(Map exif) { - return exif["GPS GPSLatitude"] != null && - exif["GPS GPSLongitude"] != null && - exif["GPS GPSLatitudeRef"] != null && - exif["GPS GPSLongitudeRef"] != null && - exif["GPS GPSLatitude"].toString() != "" && - exif["GPS GPSLongitude"].toString() != "" && - exif["GPS GPSLatitudeRef"].toString() != "" && - exif["GPS GPSLongitudeRef"].toString() != ""; + bool _haGPSData() { + return _exifData["lat"] != null && + _exifData["long"] != null && + _exifData["latRef"] != null && + _exifData["longRef"] != null; + } + + _generateExifForLocation(Map exif) { + if (exif["GPS GPSLatitude"] != null) { + _exifData["lat"] = exif["GPS GPSLatitude"]! + .values + .toList() + .map((e) => ((e as Ratio).numerator / e.denominator)) + .toList(); + } + if (exif["GPS GPSLongitude"] != null) { + _exifData["long"] = exif["GPS GPSLongitude"]! + .values + .toList() + .map((e) => ((e as Ratio).numerator / e.denominator)) + .toList(); + } + if (exif["GPS GPSLatitudeRef"] != null) { + _exifData["latRef"] = exif["GPS GPSLatitudeRef"].toString(); + } + if (exif["GPS GPSLongitudeRef"] != null) { + _exifData["longRef"] = exif["GPS GPSLongitudeRef"].toString(); + } } _generateExifForDetails(Map exif) { diff --git a/lib/ui/viewer/file_details/location_tags_widget.dart b/lib/ui/viewer/file_details/location_tags_widget.dart index 352583441..80d4de29c 100644 --- a/lib/ui/viewer/file_details/location_tags_widget.dart +++ b/lib/ui/viewer/file_details/location_tags_widget.dart @@ -1,15 +1,13 @@ import "dart:async"; import "package:flutter/material.dart"; -import "package:photos/models/file.dart"; -import "package:photos/services/location_service.dart"; import "package:photos/ui/components/buttons/chip_button_widget.dart"; import "package:photos/ui/components/buttons/inline_button_widget.dart"; import "package:photos/ui/components/info_item_widget.dart"; class LocationTagsWidget extends StatefulWidget { - final File file; - const LocationTagsWidget(this.file, {super.key}); + final List coordinates; + const LocationTagsWidget(this.coordinates, {super.key}); @override State createState() => _LocationTagsWidgetState(); @@ -43,8 +41,8 @@ class _LocationTagsWidgetState extends State { } Future> _getLocationTags() async { - final locationTags = - LocationService.instance.getLocationsByFileID(widget.file.generatedID!); + final locationTags = []; + // LocationService.instance.getLocationsByFileID(widget.file.generatedID!); if (locationTags.isEmpty) { return [ InlineButtonWidget("Group nearby photos", () {}), From d412a8cd90a4185e3c029583623f9cd0c4a21066 Mon Sep 17 00:00:00 2001 From: ashilkn Date: Fri, 17 Mar 2023 19:21:53 +0530 Subject: [PATCH 06/11] Wrote service method to return the location tags for a given coordinate and used it in file details --- lib/services/location_service.dart | 23 ++++++++++++++++--- lib/services/search_service.dart | 2 +- .../file_details/location_tags_widget.dart | 5 ++-- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/lib/services/location_service.dart b/lib/services/location_service.dart index ce8c5266c..294e3dafe 100644 --- a/lib/services/location_service.dart +++ b/lib/services/location_service.dart @@ -15,7 +15,7 @@ class LocationService { prefs ??= await SharedPreferences.getInstance(); } - List getLocations() { + List getAllLocationTags() { var list = prefs!.getStringList('locations'); list ??= []; return list; @@ -27,7 +27,7 @@ class LocationService { double long, int radius, ) async { - final list = getLocations(); + final list = getAllLocationTags(); //The area enclosed by the location tag will be a circle on a 3D spherical //globe and an ellipse on a 2D Mercator projection (2D map) //a & b are the semi-major and semi-minor axes of the ellipse @@ -56,6 +56,23 @@ class LocationService { return 1 / cos(lat * (pi / 180)); } + List enclosingLocationTags(List coordinates) { + final result = List.of([]); + final allLocationTags = getAllLocationTags(); + for (var locationTag in allLocationTags) { + final locationJson = json.decode(locationTag); + final a = locationJson["a"]; + final b = locationJson["b"]; + final center = locationJson["center"]; + final x = coordinates[0] - center[0]; + final y = coordinates[1] - center[1]; + if ((x * x) / (a * a) + (y * y) / (b * b) <= 1) { + result.add(locationJson["name"]); + } + } + return result; + } + Future addFileToLocation(int locationId, int fileId) async { final list = getFilesByLocation(locationId.toString()); list.add(fileId.toString()); @@ -69,7 +86,7 @@ class LocationService { } List getLocationsByFileID(int fileId) { - final locationList = getLocations(); + final locationList = getAllLocationTags(); final locations = List.of([]); for (String locationString in locationList) { final locationJson = json.decode(locationString); diff --git a/lib/services/search_service.dart b/lib/services/search_service.dart index c9209e91f..eb8436766 100644 --- a/lib/services/search_service.dart +++ b/lib/services/search_service.dart @@ -272,7 +272,7 @@ class SearchService { String query, ) async { final List searchResults = []; - final locations = LocationService.instance.getLocations(); + final locations = LocationService.instance.getAllLocationTags(); for (String location in locations) { final locationJson = json.decode(location); final locationName = locationJson["name"].toString(); diff --git a/lib/ui/viewer/file_details/location_tags_widget.dart b/lib/ui/viewer/file_details/location_tags_widget.dart index 80d4de29c..23c504912 100644 --- a/lib/ui/viewer/file_details/location_tags_widget.dart +++ b/lib/ui/viewer/file_details/location_tags_widget.dart @@ -1,6 +1,7 @@ import "dart:async"; import "package:flutter/material.dart"; +import "package:photos/services/location_service.dart"; import "package:photos/ui/components/buttons/chip_button_widget.dart"; import "package:photos/ui/components/buttons/inline_button_widget.dart"; import "package:photos/ui/components/info_item_widget.dart"; @@ -41,8 +42,8 @@ class _LocationTagsWidgetState extends State { } Future> _getLocationTags() async { - final locationTags = []; - // LocationService.instance.getLocationsByFileID(widget.file.generatedID!); + final locationTags = + LocationService.instance.enclosingLocationTags(widget.coordinates); if (locationTags.isEmpty) { return [ InlineButtonWidget("Group nearby photos", () {}), From fa913b243c9ac9b6a5e442327e4edd393bbd26fd Mon Sep 17 00:00:00 2001 From: ashilkn Date: Mon, 20 Mar 2023 10:45:20 +0530 Subject: [PATCH 07/11] Optimised by storing square of semi major and minor axes of ellipse with location data --- lib/services/location_service.dart | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/services/location_service.dart b/lib/services/location_service.dart index 294e3dafe..d170f1466 100644 --- a/lib/services/location_service.dart +++ b/lib/services/location_service.dart @@ -39,8 +39,8 @@ class LocationService { final data = { "name": location, "radius": radius, - "a": a, - "b": b, + "aSquare": a * a, + "bSquare": b * b, "center": center, }; final encodedMap = json.encode(data); @@ -61,12 +61,12 @@ class LocationService { final allLocationTags = getAllLocationTags(); for (var locationTag in allLocationTags) { final locationJson = json.decode(locationTag); - final a = locationJson["a"]; - final b = locationJson["b"]; + final aSquare = locationJson["aSquare"]; + final bSquare = locationJson["bSquare"]; final center = locationJson["center"]; final x = coordinates[0] - center[0]; final y = coordinates[1] - center[1]; - if ((x * x) / (a * a) + (y * y) / (b * b) <= 1) { + if ((x * x) / (aSquare) + (y * y) / (bSquare) <= 1) { result.add(locationJson["name"]); } } From 573ee901c849fbb7bfff22fe00ab8d7433e41290 Mon Sep 17 00:00:00 2001 From: ashilkn Date: Mon, 20 Mar 2023 11:05:25 +0530 Subject: [PATCH 08/11] Layout fixes for ChipButtonWidget --- .../components/buttons/chip_button_widget.dart | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/lib/ui/components/buttons/chip_button_widget.dart b/lib/ui/components/buttons/chip_button_widget.dart index 20c492737..27d9d2b19 100644 --- a/lib/ui/components/buttons/chip_button_widget.dart +++ b/lib/ui/components/buttons/chip_button_widget.dart @@ -37,14 +37,16 @@ class ChipButtonWidget extends StatelessWidget { size: 17, ) : const SizedBox.shrink(), - const SizedBox(width: 4), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 4), - child: Text( - label ?? "", - style: getEnteTextTheme(context).smallBold, - ), - ) + if (label != null && leadingIcon != null) + const SizedBox(width: 4), + if (label != null) + Padding( + padding: const EdgeInsets.symmetric(horizontal: 4), + child: Text( + label!, + style: getEnteTextTheme(context).smallBold, + ), + ) ], ), ), From aa7cb83f9a5c5ddbaf5c9b84d5f53b5fb7cdeed4 Mon Sep 17 00:00:00 2001 From: ashilkn Date: Mon, 27 Mar 2023 16:33:46 +0530 Subject: [PATCH 09/11] Make final --- lib/services/location_service.dart | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/services/location_service.dart b/lib/services/location_service.dart index d170f1466..57f7059a3 100644 --- a/lib/services/location_service.dart +++ b/lib/services/location_service.dart @@ -118,10 +118,10 @@ class LocationService { } class GPSData { - String latRef; - List lat; - String longRef; - List long; + final String latRef; + final List lat; + final String longRef; + final List long; GPSData(this.latRef, this.lat, this.longRef, this.long); From f3ef3bfe25d4dd5d383caf5d90bb6f6434ef1ade Mon Sep 17 00:00:00 2001 From: ashilkn Date: Mon, 27 Mar 2023 16:35:06 +0530 Subject: [PATCH 10/11] Define return type as void --- lib/ui/viewer/file/file_details_widget.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ui/viewer/file/file_details_widget.dart b/lib/ui/viewer/file/file_details_widget.dart index e525a69fb..ecd6dba4d 100644 --- a/lib/ui/viewer/file/file_details_widget.dart +++ b/lib/ui/viewer/file/file_details_widget.dart @@ -244,7 +244,7 @@ class _FileDetailsWidgetState extends State { _exifData["longRef"] != null; } - _generateExifForLocation(Map exif) { + void _generateExifForLocation(Map exif) { if (exif["GPS GPSLatitude"] != null) { _exifData["lat"] = exif["GPS GPSLatitude"]! .values From 6cdc8d6783efd219d403814df94fd97d42126002 Mon Sep 17 00:00:00 2001 From: vishnukvmd Date: Mon, 27 Mar 2023 18:07:10 +0530 Subject: [PATCH 11/11] v0.7.38 --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 16b2a754e..37414178d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -12,7 +12,7 @@ description: ente photos application # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 0.7.37+437 +version: 0.7.38+438 environment: sdk: '>=2.17.0 <3.0.0'