import 'package:flutter/material.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/api/response/track_daily_summary_response.dart'; import 'package:location/data/bean/track_days.dart'; import 'package:location/data/consts/constants.dart'; import 'package:location/data/repositories/account_repository.dart'; import 'package:location/data/repositories/friends_repository.dart'; import 'package:location/data/repositories/track_repository.dart'; import 'package:location/handler/error_handler.dart'; import 'package:location/resource/string.gen.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:sliding_sheet2/sliding_sheet2.dart'; import '../../data/bean/track_daily_bean.dart'; import '../../data/bean/user_info.dart'; import '../../dialog/common_confirm_dialog_impl.dart'; import '../../dialog/loading_dialog.dart'; import '../../dialog/location_permission_dialog.dart'; import '../../sdk/map/map_helper.dart'; import '../../sdk/wechat/wechat_share_util.dart'; import '../../utils/permission_util.dart'; import '../../utils/toast_util.dart'; @injectable class TrackController extends BaseController with GetSingleTickerProviderStateMixin { final Rxn _userInfo = Rxn(); UserInfo? get userInfo => _userInfo.value; final MapController mapController = MapController(); SheetController sheetController = SheetController(); final RxList daysList = RxList(); final Rxn _tabController = Rxn(); TabController? get tabController => _tabController.value; final Rxn currentTrackDay = Rxn(); final GlobalKey shareGlobalKey = GlobalKey(); final RxDouble _sheetProgress = 0.0.obs; double get sheetProgress => _sheetProgress.value; final mapPadding = MapPadding(left: 50.w, top: 100.w, right: 50.w, bottom: Get.height / 2); final selectPadding = MapPadding(left: 80.w, top: 150.w, right: 80.w, bottom: Get.height / 2); final RxDouble trackBottomHeight = RxDouble(330.w); final Rxn _shareTrackData = Rxn(); TrackDailySummaryResponse? get shareTrackData => _shareTrackData.value; TrackDailyBean? selectedTrackDailyBean; final TrackRepository trackRepository; final FriendsRepository friendsRepository; final AccountRepository accountRepository; TrackController( this.trackRepository, this.friendsRepository, this.accountRepository); @override void onInit() { final param = Get.arguments; if (param is UserInfo) { _userInfo.value = param; } _onRequestTrackDateList(); } @override void onReady() { super.onReady(); sheetController.expand(); } void _onRequestTrackDateList() { trackRepository.getLocationTrackDays().then((list) { daysList.assignAll(list); _createTabController(); }).catchError((error) { ErrorHandler.toastError(error); }); } void _createTabController() { tabController?.dispose(); var inintIndex = 0; if (_userInfo.value?.isShowYesterday ?? false) { //控制请求当前页数据或者数据已有时跟换数据 inintIndex = 1; } final tab = TabController( length: daysList.length, vsync: this, initialIndex: inintIndex, ); _tabController.value = tab; tab.addListener(() { if (tab.indexIsChanging == false) { //控制请求当前页数据或者数据已有时跟换数据 mapController.clear(); selectedTrackDailyBean = null; currentTrackDay.value = daysList[tab.index]; } }); Future.delayed(Duration(milliseconds: 100), () { if (_userInfo.value?.isShowYesterday ?? false) { //控制请求当前页数据或者数据已有时跟换数据 if (daysList.length > 1) { currentTrackDay.value = daysList.isNotEmpty ? daysList[1] : null; } } else { currentTrackDay.value = daysList.isNotEmpty ? daysList[0] : null; } }); } ///显示轨迹以及标记点 void showMapTrack(List points, List markers) { mapController.clear(); //画折线 if (points.length > 1) { mapController.addPolyline( Polyline(lineId: Constants.traceNormalLineId, points: points), mapPadding: mapPadding); } //画标记点 if (markers.isNotEmpty) { mapController.updateOrAddMarkers(markers); } } void showSelectMarker(List points, Marker selectMarker) { clearSelectMapMarker(); mapController.updateOrAddMarker(selectMarker); mapController.moveToSuitableLocation(points, mapPadding: selectPadding); } void back() { Get.back(); } void showMovingTrack(List movingPoints) { clearSelectMapMarker(); mapController.addPolyline( Polyline( lineId: Constants.traceSelectLineId, points: movingPoints, lineType: PolylineType.selected), mapPadding: mapPadding); } void showTrackError(List errorPoints, Marker errorMarker) { clearSelectMapMarker(); mapController.updateOrAddMarker(errorMarker); mapController.addPolyline( Polyline( lineId: Constants.traceSelectLineId, points: errorPoints, lineType: PolylineType.error), mapPadding: mapPadding); } void clearSelectMapMarker() { mapController.removeMarker(Constants.mineLocationId); mapController.removePolyline(Constants.traceSelectLineId); mapController.removeMarker(Constants.tracePopupId); mapController.removeMarker(Constants.traceErrorId); } setSheetProgress(double progress) { _sheetProgress.value = progress; if (progress >= 1) { trackBottomHeight.value = 0; } else if (progress <= 0.45) { trackBottomHeight.value = 330.w; } else { double percent = (1 - progress) / (1 - 0.45); trackBottomHeight.value = 330.w * percent; } } void onCurrentLocationClick() 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); showMineLocationMarker(location); } MapHelper.addLocationListener(locationListener); } else { showMineLocationMarker(lastLocation); } } void showMineLocationMarker(MapLocation location) { clearSelectMapMarker(); Marker mineMarker = Marker( id: Constants.mineLocationId, latitude: location.latitude, longitude: location.longitude, isSelected: false, customAvatarUrl: accountRepository.mineUserInfo.value.avatar, markerName: StringName.locationMine, markerType: MarkerType.mine); mapController.updateOrAddMarker(mineMarker); animateCamera(latitude: location.latitude, longitude: location.longitude); } void animateCamera({required double? latitude, required double? longitude}) { mapController.animateCamera( CameraPosition(longitude: longitude, latitude: latitude, zoom: 18)); } 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(); } }); } } void shareTrack(TrackDailySummaryResponse summary) async { final day = currentTrackDay.value; final userInfo = _userInfo.value; if (day == null || userInfo == null) { return; } try { CustomLoadingDialog.show(); _shareTrackData.value = summary; await Future.delayed(Duration(milliseconds: 500)); await WechatShareUtil.shareWidgetToWeChat(shareGlobalKey); } catch (e) { print(e); } CustomLoadingDialog.hide(); _shareTrackData.value = null; } @override void onClose() { super.onClose(); tabController?.dispose(); } }