import 'dart:async'; import 'package:get/get.dart'; import 'package:get/get_rx/src/rx_types/rx_types.dart'; import 'package:injectable/injectable.dart'; import 'package:location/base/base_controller.dart'; import 'package:location/data/bean/location_info.dart'; import 'package:location/data/bean/user_info.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:flutter_map/flutter_map.dart'; import 'package:location/handler/error_handler.dart'; import 'package:location/module/friend/friend_page.dart'; import 'package:location/resource/string.gen.dart'; import 'package:location/sdk/map/map_helper.dart'; import 'package:location/utils/base_expand.dart'; import 'package:location/utils/toast_util.dart'; import '../../data/repositories/config_repository.dart'; import '../../socket/atmob_location_client.dart'; import '../../dialog/add_friend_dialog.dart'; import '../../dialog/check_loation_permission_dialog.dart'; import '../../dialog/location_permission_dialog.dart'; import '../../utils/location_convert_marker_util.dart'; import '../../utils/location_permission_util.dart'; import '../add_friend/add_friend_page.dart'; import '../mine/mine_page.dart'; @injectable class MainController extends BaseController { final FriendsRepository friendsRepository; final AccountRepository accountRepository; RxList get _friendsList => friendsRepository.friendsList; RxList integrateList = RxList(); UserInfo get mineUserInfo => accountRepository.mineUserInfo.value; MainController(this.friendsRepository, this.accountRepository, AtmobLocationClient atmobLocationClient, ConfigRepository configRepository); final Rxn _selectedFriend = Rxn(); UserInfo? get selectedFriend => _selectedFriend.value; final MapController mapController = MapController(); StreamSubscription? mineLocationSubscription; StreamSubscription? friendsListSubscription; StreamSubscription? loginSubscription; bool isFirstShowMineLocation = true; DateTime _lastRefreshTime = DateTime.fromMillisecondsSinceEpoch(0); @override void onReady() { super.onReady(); AddFriendDialog.show( onAddClick: () async { await onAddFriendClick(); checkLocationPermissionCallback(); }, onNotAddDismiss: checkLocationPermissionCallback); loginSubscription = accountRepository.isLogin.listen((isLogin) { if (isLogin == false) { _selectedFriend.value = null; } }); friendsListSubscription = _friendsList.listen((list) { integrateList.assignAll(list); integrateList.insert(0, mineUserInfo); mapController.replaceAllMarkers( Location2MarkerUtil.userInfoList2MarkerList(list, selectedFriend)); }); mineLocationSubscription = accountRepository.mineUserInfo.value.lastLocation.listen((location) { final mineInfo = accountRepository.mineUserInfo.value; mapController.updateOrAddMarker(Location2MarkerUtil.userInfo2Marker( mineInfo, selectedFriend?.id == mineInfo.id)); if (isFirstShowMineLocation && location != null) { isFirstShowMineLocation = false; animateCameraToUser(mineInfo); } }); } Future onAddFriendClick() { return AddFriendPage.show(); } void onMineClick() { MinePage.start(); } void checkLocationPermissionCallback() async { bool isGranted = await LocationPermissionUtil.checkLocationPermission(); if (!isGranted) { CheckLocationPermissionDialog.show( onRequestPermissionClick: _requestLocationPermission); } } void onSelectClick(UserInfo userInfo) { UserInfo? oldInfo = _selectedFriend.value; _selectedFriend.value = userInfo; //修改地图选中 _updateMapSelected(oldInfo, userInfo); //移动到选中的位置 animateCameraToUser(userInfo); } void _updateMapSelected(UserInfo? oldInfo, UserInfo newInfo) { List markers = []; if (oldInfo != null) { markers.add(oldInfo); } markers.add(newInfo); mapController.updateOrAddMarkers( Location2MarkerUtil.userInfoList2MarkerList(markers, selectedFriend)); } void animateCameraToUser(UserInfo userInfo) { LocationInfo? locationInfo = userInfo.lastLocation.value; if (locationInfo == null || locationInfo.longitude == null || locationInfo.latitude == null || locationInfo.longitude == 0 || locationInfo.latitude == 0) { return; } animateCamera( latitude: locationInfo.latitude, longitude: locationInfo.longitude); } void animateCamera({required double? latitude, required double? longitude}) { mapController.animateCamera( CameraPosition(longitude: longitude, latitude: latitude, zoom: 18)); } void onMarkerTap(Marker marker) { String id = marker.id; if (id == Constants.mineLocationId) { onSelectClick(mineUserInfo); return; } UserInfo? userInfo = integrateList.firstWhereOrNull((element) => element.id == id); if (userInfo == null) { return; } onSelectClick(userInfo); } void onCurrentLocationClick() async { //权限检查 bool isGranted = await LocationPermissionUtil.checkLocationPermission(); if (!isGranted) { LocationPermissionDialog.show(onNextStep: _requestLocationPermission); } else { _updateCurrentLocation(); } } void onRefreshFriendLocationClick() { final now = DateTime.now(); final secondsSinceLastRefresh = now.difference(_lastRefreshTime).inSeconds; if (secondsSinceLastRefresh < 10) { final remainingSeconds = 10 - secondsSinceLastRefresh; ToastUtil.show('请等待 $remainingSeconds 秒后重试'); return; } _lastRefreshTime = now; friendsRepository.refreshFriends().then((_) { ToastUtil.show(StringName.refreshFriendDataSuccess); }).catchError((error) { ErrorHandler.toastError(error); _lastRefreshTime = DateTime.fromMillisecondsSinceEpoch(0); }); } void _requestLocationPermission() async { bool isGranted = await LocationPermissionUtil.requestLocationPermission(); _showLocationAlways(); if (isGranted) { _updateCurrentLocation(); } } void _showLocationAlways() async { bool isGranted = await LocationPermissionUtil.checkShowLocationAlways(); if (!isGranted) { LocationAlwaysPermissionDialog.show(onNextStep: () async { isGranted = await LocationPermissionUtil.requestShowLocationAlways(); if (isGranted) { _updateCurrentLocation(); } }); } } void _updateCurrentLocation() { MapHelper.getLastLocation()?.let((it) { animateCamera(latitude: it.latitude, longitude: it.longitude); }); } onFriendClick() { FriendPage.start(); } @override void onClose() { mineLocationSubscription?.cancel(); friendsListSubscription?.cancel(); loginSubscription?.cancel(); } }