feat : Map Widget
This commit is contained in:
@@ -1,10 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:latlong2/latlong.dart';
|
|
||||||
|
|
||||||
class CustomMarker {
|
|
||||||
final LatLng point;
|
|
||||||
final VoidCallback? onTap;
|
|
||||||
final int? id;
|
|
||||||
|
|
||||||
CustomMarker({ this.id, required this.point, this.onTap});
|
|
||||||
}
|
|
||||||
@@ -1,207 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_map/flutter_map.dart';
|
|
||||||
import 'package:geolocator/geolocator.dart';
|
|
||||||
import 'package:get/get.dart';
|
|
||||||
import 'package:rasadyar_core/presentation/common/app_color.dart';
|
|
||||||
import 'package:rasadyar_core/presentation/common/app_fonts.dart';
|
|
||||||
import 'package:rasadyar_core/presentation/common/assets.gen.dart';
|
|
||||||
import 'package:rasadyar_core/presentation/widget/buttons/elevated.dart';
|
|
||||||
import 'package:rasadyar_core/presentation/widget/buttons/fab.dart';
|
|
||||||
import 'package:rasadyar_core/presentation/widget/buttons/outline_elevated.dart';
|
|
||||||
|
|
||||||
import 'logic.dart';
|
|
||||||
|
|
||||||
class MapWidget extends GetView<MapWidgetLogic> {
|
|
||||||
final VoidCallback? initOnTap;
|
|
||||||
final Widget? initMarkerWidget;
|
|
||||||
final Widget markerWidget;
|
|
||||||
|
|
||||||
const MapWidget({
|
|
||||||
this.initOnTap,
|
|
||||||
this.initMarkerWidget,
|
|
||||||
required this.markerWidget,
|
|
||||||
super.key,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Stack(
|
|
||||||
children: [
|
|
||||||
ObxValue((errorType) {
|
|
||||||
if (errorType.isNotEmpty) {
|
|
||||||
if (errorType.contains(ErrorLocationType.serviceDisabled)) {
|
|
||||||
Future.microtask(() {
|
|
||||||
Get.defaultDialog(
|
|
||||||
title: 'خطا',
|
|
||||||
content: const Text('سرویس مکانیابی غیرفعال است'),
|
|
||||||
cancel: ROutlinedElevated(
|
|
||||||
text: 'بررسی مجدد',
|
|
||||||
width: 120,
|
|
||||||
textStyle: AppFonts.yekan16,
|
|
||||||
onPressed: () async {
|
|
||||||
var service = await controller.locationServiceEnabled();
|
|
||||||
if (service) {
|
|
||||||
controller.errorLocationType.remove(
|
|
||||||
ErrorLocationType.serviceDisabled,
|
|
||||||
);
|
|
||||||
Get.back();
|
|
||||||
}
|
|
||||||
// Don't call Get.back() if service is still disabled
|
|
||||||
},
|
|
||||||
),
|
|
||||||
confirm: RElevated(
|
|
||||||
text: 'روشن کردن',
|
|
||||||
textStyle: AppFonts.yekan16,
|
|
||||||
width: 120,
|
|
||||||
onPressed: () async {
|
|
||||||
var res = await Geolocator.openLocationSettings();
|
|
||||||
if (res) {
|
|
||||||
var service = await controller.locationServiceEnabled();
|
|
||||||
if (service) {
|
|
||||||
controller.errorLocationType.remove(
|
|
||||||
ErrorLocationType.serviceDisabled,
|
|
||||||
);
|
|
||||||
Get.back();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
contentPadding: EdgeInsets.all(8),
|
|
||||||
onWillPop: () async {
|
|
||||||
return controller.errorLocationType.isEmpty;
|
|
||||||
},
|
|
||||||
barrierDismissible: false,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
Future.microtask(() {
|
|
||||||
Get.defaultDialog(
|
|
||||||
title: 'خطا',
|
|
||||||
content: const Text(' دسترسی به سرویس مکانیابی غیرفعال است'),
|
|
||||||
cancel: ROutlinedElevated(
|
|
||||||
text: 'بررسی مجدد',
|
|
||||||
width: 120,
|
|
||||||
textStyle: AppFonts.yekan16,
|
|
||||||
onPressed: () async {
|
|
||||||
await controller.checkPermission();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
confirm: RElevated(
|
|
||||||
text: 'اجازه دادن',
|
|
||||||
textStyle: AppFonts.yekan16,
|
|
||||||
width: 120,
|
|
||||||
onPressed: () async {
|
|
||||||
var res = await controller.checkPermission(request: true);
|
|
||||||
if (res) {
|
|
||||||
controller.errorLocationType.remove(
|
|
||||||
ErrorLocationType.permissionDenied,
|
|
||||||
);
|
|
||||||
Get.back();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
|
|
||||||
contentPadding: EdgeInsets.all(8),
|
|
||||||
onWillPop: () async {
|
|
||||||
return controller.errorLocationType.isEmpty;
|
|
||||||
},
|
|
||||||
barrierDismissible: false,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return const SizedBox.shrink();
|
|
||||||
}, controller.errorLocationType),
|
|
||||||
_buildMap(),
|
|
||||||
_buildGpsButton(),
|
|
||||||
_buildFilterButton(),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildMap() {
|
|
||||||
return ObxValue((currentLocation) {
|
|
||||||
return FlutterMap(
|
|
||||||
mapController: controller.animatedMapController.mapController,
|
|
||||||
options: MapOptions(
|
|
||||||
initialCenter: currentLocation.value,
|
|
||||||
initialZoom: 18,
|
|
||||||
onPositionChanged: (camera, hasGesture) {
|
|
||||||
if (hasGesture) {
|
|
||||||
controller.debouncedUpdateVisibleMarkers(center: camera.center);
|
|
||||||
}
|
|
||||||
//controller.debouncedUpdateVisibleMarkers(center: camera.center);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
children: [
|
|
||||||
TileLayer(urlTemplate: controller.tileType),
|
|
||||||
ObxValue((markers) {
|
|
||||||
return MarkerLayer(
|
|
||||||
markers:
|
|
||||||
markers
|
|
||||||
.map(
|
|
||||||
(e) => Marker(
|
|
||||||
point: e.point,
|
|
||||||
child: GestureDetector(
|
|
||||||
onTap: e.id != -1 ? e.onTap : initOnTap,
|
|
||||||
child:
|
|
||||||
e.id != -1
|
|
||||||
? markerWidget
|
|
||||||
: initMarkerWidget ?? SizedBox.shrink(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.toList(),
|
|
||||||
);
|
|
||||||
}, controller.markers),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}, controller.currentLocation);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildGpsButton() {
|
|
||||||
return Positioned(
|
|
||||||
right: 10,
|
|
||||||
bottom: 83,
|
|
||||||
child: ObxValue((data) {
|
|
||||||
return RFab.small(
|
|
||||||
backgroundColor: AppColor.greenNormal,
|
|
||||||
isLoading: data.value,
|
|
||||||
icon: Assets.vec.gpsSvg.svg(),
|
|
||||||
onPressed: () async {
|
|
||||||
controller.isLoading.value = true;
|
|
||||||
await controller.determineCurrentPosition();
|
|
||||||
controller.isLoading.value = false;
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}, controller.isLoading),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildFilterButton() {
|
|
||||||
return Positioned(
|
|
||||||
right: 10,
|
|
||||||
bottom: 30,
|
|
||||||
child: RFab.small(
|
|
||||||
backgroundColor: AppColor.blueNormal,
|
|
||||||
icon: Assets.vec.filterSvg.svg(width: 24, height: 24),
|
|
||||||
onPressed: () {},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Marker markerWidget({required LatLng marker, required VoidCallback onTap}) {
|
|
||||||
return Marker(
|
|
||||||
point: marker,
|
|
||||||
child: GestureDetector(
|
|
||||||
onTap: onTap,
|
|
||||||
behavior: HitTestBehavior.opaque,
|
|
||||||
child: SizedBox(
|
|
||||||
width: 36,
|
|
||||||
height: 36,
|
|
||||||
child: Assets.vec.mapMarkerSvg.svg(width: 30, height: 30),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
@@ -2,24 +2,40 @@ import 'package:rasadyar_core/core.dart';
|
|||||||
import 'package:rasadyar_livestock/data/common/dio_exception_handeler.dart';
|
import 'package:rasadyar_livestock/data/common/dio_exception_handeler.dart';
|
||||||
import 'package:rasadyar_livestock/data/data_source/remote/auth/auth_remote.dart';
|
import 'package:rasadyar_livestock/data/data_source/remote/auth/auth_remote.dart';
|
||||||
import 'package:rasadyar_livestock/data/data_source/remote/auth/auth_remote_imp.dart';
|
import 'package:rasadyar_livestock/data/data_source/remote/auth/auth_remote_imp.dart';
|
||||||
|
import 'package:rasadyar_livestock/data/repository/auth/auth_repository.dart';
|
||||||
import 'package:rasadyar_livestock/data/repository/auth/auth_repository_imp.dart';
|
import 'package:rasadyar_livestock/data/repository/auth/auth_repository_imp.dart';
|
||||||
import 'package:rasadyar_livestock/presentation/routes/app_pages.dart';
|
import 'package:rasadyar_livestock/presentation/routes/app_pages.dart';
|
||||||
|
|
||||||
GetIt get diLiveStock => GetIt.instance;
|
GetIt get diLiveStock => GetIt.instance;
|
||||||
|
|
||||||
Future setupLiveStockDI() async {
|
Future<void> setupLiveStockDI() async {
|
||||||
diLiveStock.registerSingleton(DioErrorHandler());
|
diLiveStock.registerSingleton(DioErrorHandler());
|
||||||
var tokenService = Get.find<TokenStorageService>();
|
|
||||||
|
|
||||||
|
final tokenService = Get.find<TokenStorageService>();
|
||||||
|
|
||||||
|
|
||||||
if (tokenService.baseurl.value == null) {
|
if (tokenService.baseurl.value == null) {
|
||||||
await tokenService.saveBaseUrl('https://api.dam.rasadyar.net/');
|
await tokenService.saveBaseUrl('https://api.dam.rasadyar.net/');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
diLiveStock.registerLazySingleton<AuthRemoteDataSource>(
|
||||||
|
() => AuthRemoteDataSourceImp(diLiveStock.get<DioRemote>()),
|
||||||
|
);
|
||||||
|
|
||||||
|
diLiveStock.registerLazySingleton<AuthRepository>(
|
||||||
|
() => AuthRepositoryImp(diLiveStock.get<AuthRemoteDataSource>()),
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
diLiveStock.registerLazySingleton<AppInterceptor>(
|
diLiveStock.registerLazySingleton<AppInterceptor>(
|
||||||
() => AppInterceptor(
|
() => AppInterceptor(
|
||||||
refreshTokenCallback: () async {
|
refreshTokenCallback: () async {
|
||||||
var authRepository = diLiveStock.get<AuthRepositoryImp>();
|
final authRepository = diLiveStock.get<AuthRepository>();
|
||||||
var hasAuthenticated = await authRepository.hasAuthenticated();
|
final hasAuthenticated = await authRepository.hasAuthenticated();
|
||||||
if (hasAuthenticated) {
|
if (hasAuthenticated) {
|
||||||
var newToken = await authRepository.loginWithRefreshToken(
|
final newToken = await authRepository.loginWithRefreshToken(
|
||||||
authRequest: {'refresh': tokenService.refreshToken.value},
|
authRequest: {'refresh': tokenService.refreshToken.value},
|
||||||
);
|
);
|
||||||
return newToken?.access;
|
return newToken?.access;
|
||||||
@@ -37,23 +53,13 @@ Future setupLiveStockDI() async {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Register the DioRemote client
|
|
||||||
diLiveStock.registerLazySingleton<DioRemote>(
|
diLiveStock.registerLazySingleton<DioRemote>(
|
||||||
() => DioRemote(
|
() => DioRemote(
|
||||||
baseUrl: tokenService.baseurl.value,
|
baseUrl: tokenService.baseurl.value,
|
||||||
interceptors: diLiveStock.get<AppInterceptor>(),
|
interceptors: diLiveStock.get<AppInterceptor>(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
var dioRemoteClient = diLiveStock.get<DioRemote>();
|
|
||||||
await dioRemoteClient.init();
|
|
||||||
|
|
||||||
// Register the AuthRemote data source implementation
|
await diLiveStock.get<DioRemote>().init();
|
||||||
diLiveStock.registerLazySingleton<AuthRemoteDataSource>(
|
|
||||||
() => AuthRemoteDataSourceImp(diLiveStock.get<DioRemote>()),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Register the AuthRepository implementation
|
|
||||||
diLiveStock.registerLazySingleton<AuthRepositoryImp>(
|
|
||||||
() => AuthRepositoryImp(diLiveStock.get<AuthRemoteDataSource>()),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import 'package:rasadyar_core/core.dart';
|
|||||||
import 'package:rasadyar_livestock/data/common/dio_exception_handeler.dart';
|
import 'package:rasadyar_livestock/data/common/dio_exception_handeler.dart';
|
||||||
import 'package:rasadyar_livestock/data/model/request/login_request/login_request_model.dart';
|
import 'package:rasadyar_livestock/data/model/request/login_request/login_request_model.dart';
|
||||||
import 'package:rasadyar_livestock/data/model/response/auth/auth_response_model.dart';
|
import 'package:rasadyar_livestock/data/model/response/auth/auth_response_model.dart';
|
||||||
import 'package:rasadyar_livestock/data/repository/auth/auth_repository_imp.dart';
|
import 'package:rasadyar_livestock/data/repository/auth/auth_repository.dart' show AuthRepository;
|
||||||
import 'package:rasadyar_livestock/injection/live_stock_di.dart';
|
import 'package:rasadyar_livestock/injection/live_stock_di.dart';
|
||||||
import 'package:rasadyar_livestock/presentation/routes/app_pages.dart';
|
import 'package:rasadyar_livestock/presentation/routes/app_pages.dart';
|
||||||
import 'package:rasadyar_livestock/presentation/widgets/captcha/logic.dart';
|
import 'package:rasadyar_livestock/presentation/widgets/captcha/logic.dart';
|
||||||
@@ -44,7 +44,7 @@ class AuthLogic extends GetxController with GetTickerProviderStateMixin {
|
|||||||
RxInt secondsRemaining = 120.obs;
|
RxInt secondsRemaining = 120.obs;
|
||||||
Timer? _timer;
|
Timer? _timer;
|
||||||
|
|
||||||
AuthRepositoryImp authRepository = diLiveStock.get<AuthRepositoryImp>();
|
AuthRepository authRepository = diLiveStock.get<AuthRepository>();
|
||||||
|
|
||||||
final Module _module = Get.arguments;
|
final Module _module = Get.arguments;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:rasadyar_core/core.dart';
|
import 'package:rasadyar_core/core.dart';
|
||||||
import 'package:rasadyar_core/presentation/widget/map/view.dart';
|
import 'package:rasadyar_livestock/presentation/page/map/widget/map_widget/view.dart';
|
||||||
|
|
||||||
import 'logic.dart';
|
import 'logic.dart';
|
||||||
|
|
||||||
class MapPage extends GetView<MapLogic> {
|
class MapPage extends GetView<MapLogic> {
|
||||||
@@ -8,23 +9,6 @@ class MapPage extends GetView<MapLogic> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(body: Stack(children: [MapWidget()]));
|
||||||
body: Stack(
|
|
||||||
children: [
|
|
||||||
MapWidget(
|
|
||||||
markerWidget: Icon(Icons.pin_drop_rounded),
|
|
||||||
initOnTap: () {
|
|
||||||
|
|
||||||
},
|
|
||||||
initMarkerWidget: Assets.vec.mapMarkerSvg.svg(
|
|
||||||
width: 30,
|
|
||||||
height: 30,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,23 +1,17 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_map/flutter_map.dart';
|
import 'package:rasadyar_core/core.dart';
|
||||||
import 'package:flutter_map_animations/flutter_map_animations.dart';
|
|
||||||
import 'package:geolocator/geolocator.dart';
|
|
||||||
import 'package:get/get.dart';
|
|
||||||
import 'package:latlong2/latlong.dart';
|
|
||||||
import 'package:rasadyar_core/utils/logger_utils.dart';
|
|
||||||
|
|
||||||
import 'custom_marker.dart';
|
|
||||||
|
|
||||||
enum ErrorLocationType { serviceDisabled, permissionDenied, none }
|
enum ErrorLocationType { serviceDisabled, permissionDenied, none }
|
||||||
|
|
||||||
class MapWidgetLogic extends GetxController with GetTickerProviderStateMixin {
|
class MapWidgetLogic extends GetxController with GetTickerProviderStateMixin {
|
||||||
Rx<LatLng> currentLocation = LatLng(35.824891, 50.948025).obs;
|
Rx<LatLng> currentLocation = LatLng(35.824891, 50.948025).obs;
|
||||||
String tileType = 'https://tile.openstreetmap.org/{z}/{x}/{y}.png';
|
String tileType = 'https://tile.openstreetmap.org/{z}/{x}/{y}.png';
|
||||||
|
RxDouble currentZoom = 15.0.obs;
|
||||||
|
|
||||||
|
|
||||||
RxList<CustomMarker> markers = <CustomMarker>[].obs;
|
|
||||||
RxList<LatLng> allMarkers = <LatLng>[].obs;
|
RxList<LatLng> allMarkers = <LatLng>[].obs;
|
||||||
Rx<MapController> mapController = MapController().obs;
|
Rx<MapController> mapController = MapController().obs;
|
||||||
RxList<ErrorLocationType> errorLocationType = RxList();
|
RxList<ErrorLocationType> errorLocationType = RxList();
|
||||||
@@ -25,6 +19,20 @@ class MapWidgetLogic extends GetxController with GetTickerProviderStateMixin {
|
|||||||
Timer? _debounceTimer;
|
Timer? _debounceTimer;
|
||||||
RxBool isLoading = false.obs;
|
RxBool isLoading = false.obs;
|
||||||
|
|
||||||
|
RxList<LatLng> markerLocations = <LatLng>[
|
||||||
|
LatLng(35.824891, 50.948025),
|
||||||
|
LatLng(35.825000, 50.949000),
|
||||||
|
LatLng(35.823000, 50.947000),
|
||||||
|
LatLng(35.826000, 50.950000),
|
||||||
|
LatLng(35.827000, 50.951000),
|
||||||
|
LatLng(35.828000, 50.952000),
|
||||||
|
LatLng(35.829000, 50.953000),
|
||||||
|
LatLng(35.830000, 50.954000),
|
||||||
|
LatLng(35.831000, 50.955000),
|
||||||
|
LatLng(35.832000, 50.956000),
|
||||||
|
LatLng(35.832000, 50.956055),
|
||||||
|
].obs;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onInit() {
|
void onInit() {
|
||||||
super.onInit();
|
super.onInit();
|
||||||
@@ -89,8 +97,7 @@ class MapWidgetLogic extends GetxController with GetTickerProviderStateMixin {
|
|||||||
|
|
||||||
switch (permission) {
|
switch (permission) {
|
||||||
case LocationPermission.denied:
|
case LocationPermission.denied:
|
||||||
final LocationPermission requestResult =
|
final LocationPermission requestResult = await Geolocator.requestPermission();
|
||||||
await Geolocator.requestPermission();
|
|
||||||
return requestResult != LocationPermission.denied &&
|
return requestResult != LocationPermission.denied &&
|
||||||
requestResult != LocationPermission.deniedForever;
|
requestResult != LocationPermission.deniedForever;
|
||||||
|
|
||||||
@@ -117,9 +124,7 @@ class MapWidgetLogic extends GetxController with GetTickerProviderStateMixin {
|
|||||||
final latLng = LatLng(position.latitude, position.longitude);
|
final latLng = LatLng(position.latitude, position.longitude);
|
||||||
|
|
||||||
currentLocation.value = latLng;
|
currentLocation.value = latLng;
|
||||||
markers.add(
|
|
||||||
CustomMarker(id: -1, point: latLng, ),
|
|
||||||
);
|
|
||||||
animatedMapController.animateTo(
|
animatedMapController.animateTo(
|
||||||
dest: latLng,
|
dest: latLng,
|
||||||
zoom: 18,
|
zoom: 18,
|
||||||
@@ -138,7 +143,7 @@ class MapWidgetLogic extends GetxController with GetTickerProviderStateMixin {
|
|||||||
'radius': 1000.0,
|
'radius': 1000.0,
|
||||||
});
|
});
|
||||||
|
|
||||||
// markers.addAll(filtered);
|
// markers.addAll(filtered);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,21 +155,8 @@ class MapWidgetLogic extends GetxController with GetTickerProviderStateMixin {
|
|||||||
final center = LatLng(centerLat, centerLng);
|
final center = LatLng(centerLat, centerLng);
|
||||||
final distance = Distance();
|
final distance = Distance();
|
||||||
|
|
||||||
return rawMarkers
|
return rawMarkers.where((marker) => distance(center, marker) <= radiusInMeters).toList();
|
||||||
.where((marker) => distance(center, marker) <= radiusInMeters)
|
|
||||||
.toList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void addMarker(CustomMarker marker) {
|
|
||||||
markers.add(marker);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setMarkers(List<CustomMarker> newMarkers) {
|
|
||||||
markers.value = newMarkers;
|
|
||||||
}
|
|
||||||
|
|
||||||
void clearMarkers() {
|
|
||||||
markers.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,179 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:rasadyar_core/core.dart';
|
||||||
|
|
||||||
|
import 'logic.dart';
|
||||||
|
|
||||||
|
class MapWidget extends GetView<MapWidgetLogic> {
|
||||||
|
const MapWidget({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Expanded(
|
||||||
|
child: Stack(
|
||||||
|
fit: StackFit.expand,
|
||||||
|
children: [
|
||||||
|
ObxValue((errorType) {
|
||||||
|
if (errorType.isNotEmpty) {
|
||||||
|
if (errorType.contains(ErrorLocationType.serviceDisabled)) {
|
||||||
|
Future.microtask(() {
|
||||||
|
Get.defaultDialog(
|
||||||
|
title: 'خطا',
|
||||||
|
content: const Text('سرویس مکانیابی غیرفعال است'),
|
||||||
|
cancel: ROutlinedElevated(
|
||||||
|
text: 'بررسی مجدد',
|
||||||
|
width: 120,
|
||||||
|
textStyle: AppFonts.yekan16,
|
||||||
|
onPressed: () async {
|
||||||
|
var service = await controller.locationServiceEnabled();
|
||||||
|
if (service) {
|
||||||
|
controller.errorLocationType.remove(ErrorLocationType.serviceDisabled);
|
||||||
|
Get.back();
|
||||||
|
}
|
||||||
|
// Don't call Get.back() if service is still disabled
|
||||||
|
},
|
||||||
|
),
|
||||||
|
confirm: RElevated(
|
||||||
|
text: 'روشن کردن',
|
||||||
|
textStyle: AppFonts.yekan16,
|
||||||
|
width: 120,
|
||||||
|
onPressed: () async {
|
||||||
|
var res = await Geolocator.openLocationSettings();
|
||||||
|
if (res) {
|
||||||
|
var service = await controller.locationServiceEnabled();
|
||||||
|
if (service) {
|
||||||
|
controller.errorLocationType.remove(ErrorLocationType.serviceDisabled);
|
||||||
|
Get.back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
contentPadding: EdgeInsets.all(8),
|
||||||
|
onWillPop: () async {
|
||||||
|
return controller.errorLocationType.isEmpty;
|
||||||
|
},
|
||||||
|
barrierDismissible: false,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
Future.microtask(() {
|
||||||
|
Get.defaultDialog(
|
||||||
|
title: 'خطا',
|
||||||
|
content: const Text(' دسترسی به سرویس مکانیابی غیرفعال است'),
|
||||||
|
cancel: ROutlinedElevated(
|
||||||
|
text: 'بررسی مجدد',
|
||||||
|
width: 120,
|
||||||
|
textStyle: AppFonts.yekan16,
|
||||||
|
onPressed: () async {
|
||||||
|
await controller.checkPermission();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
confirm: RElevated(
|
||||||
|
text: 'اجازه دادن',
|
||||||
|
textStyle: AppFonts.yekan16,
|
||||||
|
width: 120,
|
||||||
|
onPressed: () async {
|
||||||
|
var res = await controller.checkPermission(request: true);
|
||||||
|
if (res) {
|
||||||
|
controller.errorLocationType.remove(ErrorLocationType.permissionDenied);
|
||||||
|
Get.back();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
|
contentPadding: EdgeInsets.all(8),
|
||||||
|
onWillPop: () async {
|
||||||
|
return controller.errorLocationType.isEmpty;
|
||||||
|
},
|
||||||
|
barrierDismissible: false,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return const SizedBox.shrink();
|
||||||
|
}, controller.errorLocationType),
|
||||||
|
|
||||||
|
ObxValue((currentLocation) {
|
||||||
|
return FlutterMap(
|
||||||
|
mapController: controller.animatedMapController.mapController,
|
||||||
|
options: MapOptions(
|
||||||
|
initialCenter: currentLocation.value,
|
||||||
|
interactionOptions: const InteractionOptions(
|
||||||
|
flags: InteractiveFlag.all & ~InteractiveFlag.rotate,
|
||||||
|
),
|
||||||
|
initialZoom: 15,
|
||||||
|
onPositionChanged: (camera, hasGesture) {
|
||||||
|
controller.currentZoom.value = camera.zoom;
|
||||||
|
/* controller.debouncedUpdateVisibleMarkers(
|
||||||
|
center: camera.center,
|
||||||
|
zoom: camera.zoom,
|
||||||
|
);*/
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
|
children: [
|
||||||
|
TileLayer(
|
||||||
|
urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
|
||||||
|
userAgentPackageName: 'ir.mnpc.rasadyar',
|
||||||
|
),
|
||||||
|
|
||||||
|
ObxValue((markers) {
|
||||||
|
return MarkerClusterLayerWidget(
|
||||||
|
options: MarkerClusterLayerOptions(
|
||||||
|
maxClusterRadius: 80,
|
||||||
|
size: const Size(40, 40),
|
||||||
|
alignment: Alignment.center,
|
||||||
|
padding: const EdgeInsets.all(50),
|
||||||
|
maxZoom: 18,
|
||||||
|
markers: buildMarkers(markers),
|
||||||
|
builder: (context, clusterMarkers) {
|
||||||
|
return Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(20),
|
||||||
|
color: Colors.blue,
|
||||||
|
),
|
||||||
|
child: Center(
|
||||||
|
child: Text(
|
||||||
|
clusterMarkers.length.toString(),
|
||||||
|
style: const TextStyle(color: Colors.white),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}, controller.markerLocations),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}, controller.currentLocation),
|
||||||
|
|
||||||
|
// Uncomment the following lines to enable the search widget
|
||||||
|
/* Positioned(
|
||||||
|
top: 10,
|
||||||
|
left: 20,
|
||||||
|
right: 20,
|
||||||
|
child: ObxValue((data) {
|
||||||
|
if (data.value) {
|
||||||
|
return SearchWidget(
|
||||||
|
onSearchChanged: (data) {
|
||||||
|
controller.baseLogic.searchValue.value = data;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return SizedBox.shrink();
|
||||||
|
}
|
||||||
|
}, controller.baseLogic.isSearchSelected),
|
||||||
|
),*/
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Marker> buildMarkers(RxList<LatLng> latLng) => latLng
|
||||||
|
.map(
|
||||||
|
(element) => Marker(
|
||||||
|
point: element,
|
||||||
|
child: FaIcon(FontAwesomeIcons.locationPin, color: AppColor.error),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
import 'package:rasadyar_core/core.dart';
|
import 'package:rasadyar_core/core.dart';
|
||||||
import 'package:rasadyar_core/presentation/widget/map/logic.dart';
|
|
||||||
import 'package:rasadyar_livestock/presentation/page/auth/logic.dart';
|
import 'package:rasadyar_livestock/presentation/page/auth/logic.dart';
|
||||||
import 'package:rasadyar_livestock/presentation/page/auth/view.dart';
|
import 'package:rasadyar_livestock/presentation/page/auth/view.dart';
|
||||||
import 'package:rasadyar_livestock/presentation/page/map/logic.dart';
|
import 'package:rasadyar_livestock/presentation/page/map/logic.dart';
|
||||||
|
import 'package:rasadyar_livestock/presentation/page/map/widget/map_widget/logic.dart';
|
||||||
import 'package:rasadyar_livestock/presentation/page/profile/logic.dart';
|
import 'package:rasadyar_livestock/presentation/page/profile/logic.dart';
|
||||||
import 'package:rasadyar_livestock/presentation/page/request_tagging/logic.dart';
|
import 'package:rasadyar_livestock/presentation/page/request_tagging/logic.dart';
|
||||||
import 'package:rasadyar_livestock/presentation/page/request_tagging/view.dart';
|
import 'package:rasadyar_livestock/presentation/page/request_tagging/view.dart';
|
||||||
@@ -38,7 +38,6 @@ sealed class LiveStockPages {
|
|||||||
Get.lazyPut(() => ProfileLogic());
|
Get.lazyPut(() => ProfileLogic());
|
||||||
Get.lazyPut(() => ProfileLogic());
|
Get.lazyPut(() => ProfileLogic());
|
||||||
Get.lazyPut(() => MapWidgetLogic());
|
Get.lazyPut(() => MapWidgetLogic());
|
||||||
Get.lazyPut(() => DraggableBottomSheetController());
|
|
||||||
}),
|
}),
|
||||||
children: [
|
children: [
|
||||||
/*GetPage(
|
/*GetPage(
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:rasadyar_core/core.dart';
|
import 'package:rasadyar_core/core.dart';
|
||||||
import 'package:rasadyar_livestock/data/model/response/captcha/captcha_response_model.dart';
|
import 'package:rasadyar_livestock/data/model/response/captcha/captcha_response_model.dart';
|
||||||
import 'package:rasadyar_livestock/data/repository/auth/auth_repository_imp.dart';
|
import 'package:rasadyar_livestock/data/repository/auth/auth_repository.dart';
|
||||||
import 'package:rasadyar_livestock/injection/live_stock_di.dart';
|
import 'package:rasadyar_livestock/injection/live_stock_di.dart';
|
||||||
|
|
||||||
class CaptchaWidgetLogic extends GetxController with StateMixin<CaptchaResponseModel> {
|
class CaptchaWidgetLogic extends GetxController with StateMixin<CaptchaResponseModel> {
|
||||||
TextEditingController textController = TextEditingController();
|
TextEditingController textController = TextEditingController();
|
||||||
RxnString captchaKey = RxnString();
|
RxnString captchaKey = RxnString();
|
||||||
GlobalKey<FormState> formKey = GlobalKey<FormState>();
|
GlobalKey<FormState> formKey = GlobalKey<FormState>();
|
||||||
AuthRepositoryImp authRepository = diLiveStock.get<AuthRepositoryImp>();
|
AuthRepository authRepository = diLiveStock.get<AuthRepository>();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onInit() {
|
void onInit() {
|
||||||
|
|||||||
Reference in New Issue
Block a user