import 'package:flutter/cupertino.dart'; import 'package:flutter_map/flutter_map.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import 'package:get/get_core/src/get_main.dart'; import 'package:injectable/injectable.dart'; import 'package:location/base/base_controller.dart'; import 'package:location/data/repositories/account_repository.dart'; import 'package:location/handler/error_handler.dart'; import 'package:location/sdk/map/map_helper.dart'; import 'package:location/utils/atmob_log.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:pull_to_refresh/pull_to_refresh.dart'; import 'package:sliding_sheet2/sliding_sheet2.dart'; import '../../../data/bean/user_info.dart'; import '../../../dialog/common_confirm_dialog_impl.dart'; import '../../../dialog/location_permission_dialog.dart'; import '../../../resource/string.gen.dart'; import '../../../utils/action_limiter.dart'; import '../../../utils/permission_util.dart'; import '../../../utils/toast_util.dart'; @injectable class CommonPointSelectAddressController extends BaseController { final TextEditingController searchEditController = TextEditingController(); final FocusNode searchFocusNode = FocusNode(); final mapController = MapController.create(); final SheetController sheetController = SheetController(); final RxDouble _commonPointRange = RxDouble(200); double get commonPointRange => _commonPointRange.value; final RxDouble _sheetProgress = 0.0.obs; double get sheetProgress => _sheetProgress.value; bool _isRangeChanging = false; bool _isFirstMoveCamera = true; UserInfo get mineUserInfo => accountRepository.mineUserInfo.value; RxList poiList = RxList(); final refreshController = RefreshController(initialRefresh: false); final Rxn _currentRangeCenterLocation = Rxn(); PoiItem? get currentRangeCenterLocation => _currentRangeCenterLocation.value; bool _isUserSelectLocation = false; final ActionLimiter _debounceLimiter = ActionLimiter(milliseconds: 300, mode: LimitMode.debounce); final AccountRepository accountRepository; CommonPointSelectAddressController(this.accountRepository); final MapPadding mapPadding = MapPadding(top: 80, left: 80, right: 80, bottom: 80); final CircleOptions circleOptions = CircleOptions( fillColor: '#4D7B7DFF', strokeWidth: 2.w, strokeColor: '#92AEE6'); final PoiQuery _poiQuery = PoiQuery(); final int _pageSize = 20; int _pageNum = 1; @override void onReady() { super.onReady(); circleOptions.radius = commonPointRange; _updateCurrentLocation(); mapController.setOnCameraChangeListener( (camera) { circleOptions ..longitude = camera.position.longitude ..latitude = camera.position.latitude; if (_isRangeChanging) { return; } if (camera.function == CameraChangeType.onCameraChangeFinish) { AtmobLog.d('zk', 'onCameraChangeFinish '); circleOptions.visible = true; if (!_isUserSelectLocation) { _currentRangeCenterLocation.value = null; } else { _isUserSelectLocation = false; } _updateOrAddCircle(); if (_isFirstMoveCamera) { _isFirstMoveCamera = false; _moveCameraToBounds(); } //重新还原数据 _resetPoiQuery(); _poiSearch(); } else { //暂时隐藏范围 if (circleOptions.visible == true) { circleOptions.visible = false; _updateOrAddCircle(); } } }, ); } void onSearchTextChange(String txt) { if (_poiQuery.keyWord == txt) { return; } _poiQuery.keyWord = txt; _resetPoiQuery(); _poiSearch(); } void _resetPoiQuery() { _pageNum = 1; } void _poiSearch() async { _debounceLimiter.run(() { AtmobLog.d('zk', '_poiSearch: $_poiQuery'); FlutterMap.paginatePoiSearch( pageNum: _pageNum, pageSize: _pageSize, query: _poiQuery, bound: PoiSearchBound.circle( center: LatLng( latitude: circleOptions.latitude, longitude: circleOptions.longitude), radius: circleOptions.radius?.toInt())) .then((list) { if (_pageNum == 1) { poiList.clear(); } if (list != null && list.isNotEmpty) { poiList.addAll(list); refreshController.loadComplete(); } if (list == null || list.length < _pageSize) { refreshController.loadNoData(); } }).catchError((error) { ErrorHandler.toastError(error); refreshController.loadFailed(); }); }); } void _updateOrAddCircle() { mapController.updateOrAddCircle('DC', circleOptions); } void backClick() { if (sheetController.state?.isExpanded == true) { sheetController.snapToExtent(0, duration: const Duration(milliseconds: 250)); return; } Get.back(); } _moveCameraToBounds() { final latLngBounds = CameraUpdateUtil.getBounds(circleOptions.latitude, circleOptions.longitude, circleOptions.radius ?? 0); if (latLngBounds != null) { mapController.moveCameraToBounds(latLngBounds, mapPadding: mapPadding); } } setSheetProgress(double progress) { _sheetProgress.value = progress; if (progress == 1) { // _requestFocus(); } } void onOpenSearchAddressModel() async { if (sheetProgress == 0) { _setExpand(); } } void _setExpand() async { await sheetController.snapToExtent(1, duration: const Duration(milliseconds: 250)); _requestFocus(); } void _requestFocus() async { if (searchFocusNode.hasFocus) { return; } //获取焦点 await Future.delayed(Duration(milliseconds: 150)); searchFocusNode.requestFocus(); } void setCommonPointRange(double value) { _commonPointRange.value = value; circleOptions.radius = value; if (circleOptions.visible == true) { _updateOrAddCircle(); _moveCameraToBounds(); } } void setCommonPointRangeStart() { _isRangeChanging = true; } void setCommonPointRangeEnd() { _isRangeChanging = false; _resetPoiQuery(); _poiSearch(); } void moveToCurrentLocation() async { //权限检查 bool isGranted = await PermissionUtil.checkLocationPermission(); if (!isGranted) { LocationPermissionDialog.show(onNextStep: _requestLocationPermission); } else { _updateCurrentLocation(); } } void _updateCurrentLocation() { var lastLocation = MapHelper.getLastLocation(); if (lastLocation == null) { locationListener(MapLocation location) { MapHelper.removeLocationListener(locationListener); _showCurrentRange(location); } MapHelper.addLocationListener(locationListener); } else { _showCurrentRange(lastLocation); } } void _showCurrentRange(MapLocation location) { circleOptions.latitude = location.latitude; circleOptions.longitude = location.longitude; _isUserSelectLocation = true; _currentRangeCenterLocation.value = PoiItem( latitude: location.latitude, longitude: location.longitude, address: location.address); _moveCameraToBounds(); } void _requestLocationPermission() async { bool isGranted = await PermissionUtil.requestLocationPermission(); if (isGranted) { _showLocationAlways(); _updateCurrentLocation(); } else { permissionRefuseDialog(settingClick: () { openAppSettings(); }); ToastUtil.show(StringName.permissionRequestFail); } } void _showLocationAlways() async { bool isGranted = await PermissionUtil.checkShowLocationAlways(); if (!isGranted) { LocationAlwaysPermissionDialog.show(onNextStep: () async { isGranted = await PermissionUtil.requestShowLocationAlways(); if (isGranted) { _updateCurrentLocation(); } }); } } onPoiItemClick(PoiItem item) async { _resetPoiQuery(); circleOptions ..longitude = item.longitude ..latitude = item.latitude; _currentRangeCenterLocation.value = item; _isUserSelectLocation = true; _moveCameraToBounds(); if (sheetController.state?.isExpanded == true) { await sheetController.scrollTo(0, duration: Duration(milliseconds: 1)); sheetController.snapToExtent(0, duration: const Duration(milliseconds: 250)); } } void onLoadMorePoiData() { _pageNum++; _poiSearch(); } void onSelectAddressDone() { if (currentRangeCenterLocation == null) { ToastUtil.show(StringName.selectAddressPlease); return; } Map backData = currentRangeCenterLocation!.toJson(); backData['radius'] = commonPointRange; Get.back(result: backData); } }