Move city search to a separate isolate
This commit is contained in:
parent
63cb04d4c1
commit
0645ff89f5
4 changed files with 76 additions and 65 deletions
|
@ -8,6 +8,7 @@ import "package:photos/core/constants.dart";
|
|||
import "package:photos/core/event_bus.dart";
|
||||
import "package:photos/events/location_tag_updated_event.dart";
|
||||
import "package:photos/models/api/entity/type.dart";
|
||||
import "package:photos/models/file/file.dart";
|
||||
import "package:photos/models/local_entity_data.dart";
|
||||
import "package:photos/models/location/location.dart";
|
||||
import 'package:photos/models/location_tag/location_tag.dart';
|
||||
|
@ -43,8 +44,19 @@ class LocationService {
|
|||
);
|
||||
}
|
||||
|
||||
List<City> getAllCities() {
|
||||
return _cities;
|
||||
Future<Map<City, List<EnteFile>>> getFilesInCity(
|
||||
List<EnteFile> allFiles,
|
||||
String query,
|
||||
) async {
|
||||
final result = await _computer.compute(
|
||||
getCityResults,
|
||||
param: {
|
||||
"query": query,
|
||||
"cities": _cities,
|
||||
"files": allFiles,
|
||||
},
|
||||
);
|
||||
return result;
|
||||
}
|
||||
|
||||
Future<Iterable<LocalEntity<LocationTag>>> getLocationTags() {
|
||||
|
@ -81,14 +93,6 @@ class LocationService {
|
|||
}
|
||||
}
|
||||
|
||||
///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<List<LocalEntity<LocationTag>>> enclosingLocationTags(
|
||||
Location fileCoordinates,
|
||||
) async {
|
||||
|
@ -114,22 +118,6 @@ class LocationService {
|
|||
}
|
||||
}
|
||||
|
||||
bool isFileInsideLocationTag(
|
||||
Location centerPoint,
|
||||
Location fileCoordinates,
|
||||
double radius,
|
||||
) {
|
||||
final a =
|
||||
(radius * _scaleFactor(centerPoint.latitude!)) / kilometersPerDegree;
|
||||
final b = radius / kilometersPerDegree;
|
||||
final x = centerPoint.latitude! - fileCoordinates.latitude!;
|
||||
final y = centerPoint.longitude! - fileCoordinates.longitude!;
|
||||
if ((x * x) / (a * a) + (y * y) / (b * b) <= 1) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// returns [lat, lng]
|
||||
List<String>? convertLocationToDMS(Location centerPoint) {
|
||||
if (centerPoint.latitude == null || centerPoint.longitude == null) {
|
||||
|
@ -248,6 +236,61 @@ Future<List<City>> parseCities(Map args) async {
|
|||
return cities;
|
||||
}
|
||||
|
||||
Map<City, List<EnteFile>> getCityResults(Map args) {
|
||||
final query = (args["query"] as String).toLowerCase();
|
||||
final cities = args["cities"] as List<City>;
|
||||
final files = args["files"] as List<EnteFile>;
|
||||
|
||||
final matchingCities = cities.where(
|
||||
(city) => city.city.toLowerCase().contains(query),
|
||||
);
|
||||
|
||||
final Map<City, List<EnteFile>> results = {};
|
||||
for (final city in matchingCities) {
|
||||
final List<EnteFile> matchingFiles = [];
|
||||
final cityLocation = Location(latitude: city.lat, longitude: city.lng);
|
||||
for (final file in files) {
|
||||
if (file.hasLocation) {
|
||||
if (isFileInsideLocationTag(
|
||||
cityLocation,
|
||||
file.location!,
|
||||
defaultCityRadius,
|
||||
)) {
|
||||
matchingFiles.add(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (matchingFiles.isNotEmpty) {
|
||||
results[city] = matchingFiles;
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
bool isFileInsideLocationTag(
|
||||
Location centerPoint,
|
||||
Location fileCoordinates,
|
||||
double radius,
|
||||
) {
|
||||
final a =
|
||||
(radius * _scaleFactor(centerPoint.latitude!)) / kilometersPerDegree;
|
||||
final b = radius / kilometersPerDegree;
|
||||
final x = centerPoint.latitude! - fileCoordinates.latitude!;
|
||||
final y = centerPoint.longitude! - fileCoordinates.longitude!;
|
||||
if ((x * x) / (a * a) + (y * y) / (b * b) <= 1) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
///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));
|
||||
}
|
||||
|
||||
class City {
|
||||
final String city;
|
||||
final String country;
|
||||
|
|
|
@ -3,7 +3,6 @@ import "dart:math";
|
|||
import "package:flutter/cupertino.dart";
|
||||
import "package:intl/intl.dart";
|
||||
import 'package:logging/logging.dart';
|
||||
import "package:photos/core/constants.dart";
|
||||
import 'package:photos/core/event_bus.dart';
|
||||
import 'package:photos/data/holidays.dart';
|
||||
import 'package:photos/data/months.dart';
|
||||
|
@ -18,7 +17,6 @@ import "package:photos/models/file/extensions/file_props.dart";
|
|||
import 'package:photos/models/file/file.dart';
|
||||
import 'package:photos/models/file/file_type.dart';
|
||||
import "package:photos/models/local_entity_data.dart";
|
||||
import "package:photos/models/location/location.dart";
|
||||
import "package:photos/models/location_tag/location_tag.dart";
|
||||
import 'package:photos/models/search/album_search_result.dart';
|
||||
import 'package:photos/models/search/generic_search_result.dart';
|
||||
|
@ -620,7 +618,7 @@ class SearchService {
|
|||
for (EnteFile file in allFiles) {
|
||||
if (file.hasLocation) {
|
||||
for (LocalEntity<LocationTag> tag in result.keys) {
|
||||
if (LocationService.instance.isFileInsideLocationTag(
|
||||
if (isFileInsideLocationTag(
|
||||
tag.item.centerPoint,
|
||||
file.location!,
|
||||
tag.item.radius,
|
||||
|
@ -639,7 +637,7 @@ class SearchService {
|
|||
return false;
|
||||
}
|
||||
for (LocalEntity<LocationTag> tag in locationTagEntities) {
|
||||
if (LocationService.instance.isFileInsideLocationTag(
|
||||
if (isFileInsideLocationTag(
|
||||
tag.item.centerPoint,
|
||||
file.location!,
|
||||
tag.item.radius,
|
||||
|
@ -684,36 +682,9 @@ class SearchService {
|
|||
}
|
||||
|
||||
Future<List<GenericSearchResult>> getCityResults(String query) async {
|
||||
final startTime = DateTime.now().microsecondsSinceEpoch;
|
||||
final List<GenericSearchResult> searchResults = [];
|
||||
final cities = LocationService.instance.getAllCities();
|
||||
final matchingCities = <City>[];
|
||||
final queryLower = query.toLowerCase();
|
||||
for (City city in cities) {
|
||||
if (city.city.toLowerCase().startsWith(queryLower)) {
|
||||
matchingCities.add(city);
|
||||
}
|
||||
}
|
||||
final files = await getAllFiles();
|
||||
final Map<City, List<EnteFile>> results = {};
|
||||
for (final city in matchingCities) {
|
||||
final List<EnteFile> matchingFiles = [];
|
||||
final cityLocation = Location(latitude: city.lat, longitude: city.lng);
|
||||
for (final file in files) {
|
||||
if (file.hasLocation) {
|
||||
if (LocationService.instance.isFileInsideLocationTag(
|
||||
cityLocation,
|
||||
file.location!,
|
||||
defaultCityRadius,
|
||||
)) {
|
||||
matchingFiles.add(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (matchingFiles.isNotEmpty) {
|
||||
results[city] = matchingFiles;
|
||||
}
|
||||
}
|
||||
final results = await LocationService.instance.getFilesInCity(files, query);
|
||||
final List<GenericSearchResult> searchResults = [];
|
||||
for (final entry in results.entries) {
|
||||
searchResults.add(
|
||||
GenericSearchResult(
|
||||
|
@ -723,9 +694,6 @@ class SearchService {
|
|||
),
|
||||
);
|
||||
}
|
||||
final endTime = DateTime.now().microsecondsSinceEpoch;
|
||||
_logger
|
||||
.info("Time taken " + ((endTime - startTime) / 1000).toString() + "ms");
|
||||
return searchResults;
|
||||
}
|
||||
|
||||
|
@ -745,7 +713,7 @@ class SearchService {
|
|||
for (EnteFile file in allFiles) {
|
||||
if (file.hasLocation) {
|
||||
for (LocalEntity<LocationTag> tag in tagToItemsMap.keys) {
|
||||
if (LocationService.instance.isFileInsideLocationTag(
|
||||
if (isFileInsideLocationTag(
|
||||
tag.item.centerPoint,
|
||||
file.location!,
|
||||
tag.item.radius,
|
||||
|
|
|
@ -62,7 +62,7 @@ class _DynamicLocationGalleryWidgetState
|
|||
final stopWatch = Stopwatch()..start();
|
||||
final copyOfFiles = List<EnteFile>.from(result.files);
|
||||
copyOfFiles.removeWhere((f) {
|
||||
return !LocationService.instance.isFileInsideLocationTag(
|
||||
return !isFileInsideLocationTag(
|
||||
InheritedLocationTagData.of(context).centerPoint,
|
||||
f.location!,
|
||||
selectedRadius,
|
||||
|
|
|
@ -205,7 +205,7 @@ class _LocationGalleryWidgetState extends State<LocationGalleryWidget> {
|
|||
final stopWatch = Stopwatch()..start();
|
||||
final filesInLocation = allFilesWithLocation;
|
||||
filesInLocation.removeWhere((f) {
|
||||
return !LocationService.instance.isFileInsideLocationTag(
|
||||
return !isFileInsideLocationTag(
|
||||
centerPoint,
|
||||
f.location!,
|
||||
selectedRadius,
|
||||
|
|
Loading…
Add table
Reference in a new issue