1 - search location and conditions
2 - parse list in isolate
This commit is contained in:
2025-08-02 11:10:22 +03:30
parent aaa69a94e9
commit 6040ca9f86
10 changed files with 695 additions and 375 deletions

View File

@@ -57,3 +57,5 @@ export 'utils/map_utils.dart';
export 'utils/network/network.dart'; export 'utils/network/network.dart';
export 'utils/route_utils.dart'; export 'utils/route_utils.dart';
export 'utils/separator_input_formatter.dart'; export 'utils/separator_input_formatter.dart';
export 'utils/utils.dart';

View File

@@ -37,6 +37,7 @@ class DioRemote implements IHttpClient {
ProgressCallback? onReceiveProgress, ProgressCallback? onReceiveProgress,
T Function(Map<String, dynamic> json)? fromJson, T Function(Map<String, dynamic> json)? fromJson,
T Function(List<dynamic> json)? fromJsonList, T Function(List<dynamic> json)? fromJsonList,
Future<T> Function(List<dynamic> json)? fromJsonListAsync,
}) async { }) async {
final response = await dio.get( final response = await dio.get(
path, path,
@@ -45,6 +46,10 @@ class DioRemote implements IHttpClient {
onReceiveProgress: onReceiveProgress, onReceiveProgress: onReceiveProgress,
cancelToken: ApiHandler.globalCancelToken, cancelToken: ApiHandler.globalCancelToken,
); );
if (fromJsonListAsync != null && response.data is List) {
response.data = await fromJsonListAsync(response.data);
return DioResponse<T>(response);
}
if (fromJsonList != null && response.data is List) { if (fromJsonList != null && response.data is List) {
response.data = fromJsonList(response.data); response.data = fromJsonList(response.data);
return DioResponse<T>(response); return DioResponse<T>(response);

View File

@@ -1,6 +1,5 @@
import 'dart:typed_data';
import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
import 'i_form_data.dart'; import 'i_form_data.dart';
import 'i_http_response.dart'; import 'i_http_response.dart';
@@ -8,12 +7,14 @@ abstract class IHttpClient {
Future<void> init(); Future<void> init();
Future<IHttpResponse<T>> get<T>( Future<IHttpResponse<T>> get<T>(
String path, { String path, {
Map<String, dynamic>? queryParameters, Map<String, dynamic>? queryParameters,
Map<String, String>? headers, Map<String, String>? headers,
ProgressCallback? onReceiveProgress, ProgressCallback? onReceiveProgress,
}); T Function(Map<String, dynamic> json)? fromJson,
T Function(List<dynamic> json)? fromJsonList,
Future<T> Function(List<dynamic> json)? fromJsonListAsync,
});
Future<IHttpResponse<T>> post<T>( Future<IHttpResponse<T>> post<T>(
String path, { String path, {
@@ -40,10 +41,7 @@ abstract class IHttpClient {
Map<String, String>? headers, Map<String, String>? headers,
}); });
Future<IHttpResponse<T>> download<T>( Future<IHttpResponse<T>> download<T>(String url, {ProgressCallback? onReceiveProgress});
String url, {
ProgressCallback? onReceiveProgress,
});
Future<IHttpResponse<T>> upload<T>( Future<IHttpResponse<T>> upload<T>(
String path, { String path, {

View File

@@ -0,0 +1,16 @@
import 'package:flutter/foundation.dart';
List<T> _parserList<T>(Map<String, dynamic> args) {
final list = args['list'] as List<dynamic>;
final T Function(Map<String, dynamic>) fromJson =
args['fromJson'] as T Function(Map<String, dynamic>);
return list.map<T>((e) => fromJson(e as Map<String, dynamic>)).toList();
}
Future<List<T>> parseListInIsolate<T>(
List<dynamic> list,
T Function(Map<String, dynamic>) fromJson,
) async {
return compute(_parserList<T>, {'list': list, 'fromJson': fromJson});
}

View File

@@ -1,17 +1,12 @@
export 'mixins/pagination_controller_mixin.dart'; export 'apk_updater.dart';
export 'network/network.dart';
export 'extension/date_time_utils.dart'; export 'extension/date_time_utils.dart';
export 'extension/num_utils.dart'; export 'extension/num_utils.dart';
export 'extension/string_utils.dart'; export 'extension/string_utils.dart';
export 'local/local_utils.dart';
export 'apk_updater.dart';
export 'logger_utils.dart'; export 'logger_utils.dart';
export 'map_utils.dart'; export 'map_utils.dart';
export 'mixins/pagination_controller_mixin.dart';
export 'network/network.dart';
export 'parser.dart';
export 'route_utils.dart'; export 'route_utils.dart';
export 'separator_input_formatter.dart'; export 'separator_input_formatter.dart';
export 'local/local_utils.dart';

View File

@@ -39,8 +39,8 @@ class InspectionRemoteDataSourceImp implements InspectionRemoteDataSource {
value: value, value: value,
), ),
headers: {'Content-Type': 'application/json'}, headers: {'Content-Type': 'application/json'},
fromJsonList: (json) => fromJsonListAsync: (json) async =>
json.map((item) => PoultryLocationModel.fromJson(item as Map<String, dynamic>)).toList(), parseListInIsolate(json, (json) => PoultryLocationModel.fromJson(json)),
); );
return res.data; return res.data;

View File

@@ -57,8 +57,9 @@ class InspectionMapLogic extends GetxController {
allPoultryLocation.value = Resource<List<PoultryLocationModel>>.loading(); allPoultryLocation.value = Resource<List<PoultryLocationModel>>.loading();
await safeCall( await safeCall(
call: () => inspectionRepository.getNearbyLocation(), call: () => inspectionRepository.getNearbyLocation(),
onSuccess: (result) { onSuccess: (result) async{
if (result != null) { if (result != null) {
allPoultryLocation.value = Resource<List<PoultryLocationModel>>.success(result); allPoultryLocation.value = Resource<List<PoultryLocationModel>>.success(result);
mapLogic.allLocations.value = Resource<List<PoultryLocationModel>>.success(result); mapLogic.allLocations.value = Resource<List<PoultryLocationModel>>.success(result);
} else { } else {

View File

@@ -20,7 +20,6 @@ class InspectionMapPage extends GetView<InspectionMapLogic> {
filteringWidget: filterWidget(showIndex: 3.obs, filterIndex: 5.obs), filteringWidget: filterWidget(showIndex: 3.obs, filterIndex: 5.obs),
widgets: [ widgets: [
MapPage(), MapPage(),
ObxValue((p0) => Text(p0.toString()), controller.showIndex),
ObxValue((data) { ObxValue((data) {
if (data.value) { if (data.value) {
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
@@ -66,7 +65,7 @@ class InspectionMapPage extends GetView<InspectionMapLogic> {
controller.baseLogic.searchTextController.clear(); controller.baseLogic.searchTextController.clear();
controller.baseLogic.searchValue.value = null; controller.baseLogic.searchValue.value = null;
controller.baseLogic.isSearchSelected.value = false; controller.baseLogic.isSearchSelected.value = false;
controller. mapLogic.hasFilterOrSearch.value = false; controller.mapLogic.hasFilterOrSearch.value = false;
controller.searchedPoultryLocation.value = Resource.initial(); controller.searchedPoultryLocation.value = Resource.initial();
}, },
enableFeedback: true, enableFeedback: true,
@@ -92,7 +91,6 @@ class InspectionMapPage extends GetView<InspectionMapLogic> {
), ),
GestureDetector( GestureDetector(
onTap: () { onTap: () {
Get.back(); Get.back();
}, },
child: Assets.vec.mapSvg.svg( child: Assets.vec.mapSvg.svg(

View File

@@ -74,6 +74,8 @@ class MapLogic extends GetxController with GetTickerProviderStateMixin {
super.onClose(); super.onClose();
} }
double _deg2rad(double deg) => deg * (pi / 180);
Future<void> determineCurrentPosition() async { Future<void> determineCurrentPosition() async {
isLoading.value = true; isLoading.value = true;
final position = await Geolocator.getCurrentPosition( final position = await Geolocator.getCurrentPosition(
@@ -95,7 +97,8 @@ class MapLogic extends GetxController with GetTickerProviderStateMixin {
isLoading.value = false; isLoading.value = false;
} }
/* void debouncedUpdateVisibleMarkers({required LatLng center, required double zoom}) { /*
void debouncedUpdateVisibleMarkers({required LatLng center, required double zoom}) {
_debounceTimer?.cancel(); _debounceTimer?.cancel();
_debounceTimer = Timer(const Duration(milliseconds: 300), () { _debounceTimer = Timer(const Duration(milliseconds: 300), () {
final radius = getVisibleRadiusKm( final radius = getVisibleRadiusKm(
@@ -105,7 +108,7 @@ class MapLogic extends GetxController with GetTickerProviderStateMixin {
); );
final filtered = filterNearbyMarkers( final filtered = filterNearbyMarkers(
allPoultryLocation.value.data ?? [], all.value.data ?? [],
center.latitude, center.latitude,
center.longitude, center.longitude,
radius, radius,
@@ -114,7 +117,8 @@ class MapLogic extends GetxController with GetTickerProviderStateMixin {
final uniqueFiltered = filtered.where((e) => !existingIds.contains(e.id)).toList(); final uniqueFiltered = filtered.where((e) => !existingIds.contains(e.id)).toList();
markers2.addAll(uniqueFiltered); markers2.addAll(uniqueFiltered);
}); });
}*/ }
*/
List<LatLng> filterNearbyMarkers( List<LatLng> filterNearbyMarkers(
List<LatLng> allMarkers, List<LatLng> allMarkers,
@@ -127,13 +131,27 @@ class MapLogic extends GetxController with GetTickerProviderStateMixin {
return allMarkers.where((marker) => distance(center, marker) <= radiusInMeters).toList(); return allMarkers.where((marker) => distance(center, marker) <= radiusInMeters).toList();
} }
double getVisibleRadiusKm({ double getVisibleRadiusKm({required LatLng center, required LatLng corner}) {
required double zoom, const earthRadius = 6371; // Km
required double screenWidthPx,
required double latitude, final dLat = _deg2rad(corner.latitude - center.latitude);
}) { final dLng = _deg2rad(corner.longitude - center.longitude);
double metersPerPixel = 156543.03392 * cos(latitude * pi / 180) / pow(2, zoom);
double visibleWidthInMeters = metersPerPixel * screenWidthPx; final a =
return (visibleWidthInMeters / 2); // radius in Meter sin(dLat / 2) * sin(dLat / 2) +
cos(_deg2rad(center.latitude)) *
cos(_deg2rad(corner.latitude)) *
sin(dLng / 2) *
sin(dLng / 2);
final c = 2 * atan2(sqrt(a), sqrt(1 - a));
return earthRadius * c;
}
bool isInVisibleBounds(LatLng point, LatLngBounds bounds) {
return point.latitude <= bounds.north &&
point.latitude >= bounds.south &&
point.longitude >= bounds.west &&
point.longitude <= bounds.east;
} }
} }