feat: sort places by distance
This commit is contained in:
@@ -13,19 +13,27 @@ import 'package:immich_mobile/pages/common/large_leading_tile.dart';
|
||||
import 'package:immich_mobile/providers/search/search_page_state.provider.dart';
|
||||
import 'package:immich_mobile/routing/router.dart';
|
||||
import 'package:immich_mobile/services/api.service.dart';
|
||||
import 'package:immich_mobile/utils/calculate_distance.dart';
|
||||
import 'package:immich_mobile/widgets/common/search_field.dart';
|
||||
import 'package:immich_mobile/widgets/map/map_thumbnail.dart';
|
||||
import 'package:maplibre_gl/maplibre_gl.dart';
|
||||
|
||||
enum FilterType {
|
||||
name,
|
||||
distance,
|
||||
}
|
||||
|
||||
@RoutePage()
|
||||
class PlacesCollectionPage extends HookConsumerWidget {
|
||||
const PlacesCollectionPage({super.key, this.currentLocation});
|
||||
final LatLng? currentLocation;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final places = ref.watch(getAllPlacesProvider);
|
||||
final formFocus = useFocusNode();
|
||||
final ValueNotifier<String?> search = useState(null);
|
||||
final filterType = useState(FilterType.name);
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
@@ -52,12 +60,11 @@ class PlacesCollectionPage extends HookConsumerWidget {
|
||||
body: ListView(
|
||||
shrinkWrap: true,
|
||||
children: [
|
||||
if (search.value == null)
|
||||
if (search.value == null) ...[
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: SizedBox(
|
||||
height: 200,
|
||||
width: context.width,
|
||||
child: MapThumbnail(
|
||||
onTap: (_, __) => context
|
||||
.pushRoute(MapRoute(initialLocation: currentLocation)),
|
||||
@@ -73,6 +80,51 @@ class PlacesCollectionPage extends HookConsumerWidget {
|
||||
),
|
||||
),
|
||||
),
|
||||
if (currentLocation != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12.0),
|
||||
child: Row(
|
||||
spacing: 8.0,
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
Text('sort_places_by'.tr()),
|
||||
Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8.0),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.surfaceContainerHighest,
|
||||
width: 1.5,
|
||||
),
|
||||
borderRadius: BorderRadius.circular(8.0),
|
||||
),
|
||||
child: DropdownButton(
|
||||
value: filterType.value,
|
||||
items: [
|
||||
DropdownMenuItem(
|
||||
value: FilterType.name,
|
||||
child: Text('name'.tr()),
|
||||
),
|
||||
DropdownMenuItem(
|
||||
value: FilterType.distance,
|
||||
child: Text('distance'.tr()),
|
||||
),
|
||||
],
|
||||
onChanged: (e) {
|
||||
filterType.value = e!;
|
||||
},
|
||||
isExpanded: false,
|
||||
underline: const SizedBox(),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
places.when(
|
||||
data: (places) {
|
||||
if (search.value != null) {
|
||||
@@ -81,6 +133,26 @@ class PlacesCollectionPage extends HookConsumerWidget {
|
||||
.toLowerCase()
|
||||
.contains(search.value!.toLowerCase());
|
||||
}).toList();
|
||||
} else if (filterType.value == FilterType.distance &&
|
||||
currentLocation != null) {
|
||||
// Sort places by distance when filterType is distance and search is null
|
||||
places = List.from(places);
|
||||
places.sort((a, b) {
|
||||
final double distanceA = calculateDistance(
|
||||
currentLocation!.latitude,
|
||||
currentLocation!.longitude,
|
||||
a.latitude,
|
||||
a.longitude,
|
||||
);
|
||||
final double distanceB = calculateDistance(
|
||||
currentLocation!.latitude,
|
||||
currentLocation!.longitude,
|
||||
b.latitude,
|
||||
b.longitude,
|
||||
);
|
||||
|
||||
return distanceA.compareTo(distanceB);
|
||||
});
|
||||
}
|
||||
return ListView.builder(
|
||||
shrinkWrap: true,
|
||||
|
||||
Reference in New Issue
Block a user