300 lines
12 KiB
Dart
300 lines
12 KiB
Dart
import 'dart:async';
|
|
import 'dart:convert';
|
|
import 'dart:developer';
|
|
import 'package:http/http.dart' as http;
|
|
|
|
import 'package:flutter/material.dart';
|
|
import 'package:google_maps_flutter/google_maps_flutter.dart' ;
|
|
import '../../../bloc/device_update_bloc.dart';
|
|
import '../../../product/constant/app/app_constants.dart';
|
|
import '../../../product/extension/context_extension.dart';
|
|
import '../../../product/services/language_services.dart';
|
|
import '../../../product/shared/find_location_maps/shared_map_search_location.dart';
|
|
|
|
import '../../../product/shared/find_location_maps/model/prediction_model.dart';
|
|
import '../../../product/shared/shared_transition.dart';
|
|
import 'geocode_model.dart';
|
|
|
|
showMapDialog(
|
|
BuildContext context,
|
|
DeviceUpdateBloc deviceUpdateBloc,
|
|
TextEditingController latitudeController,
|
|
TextEditingController longitudeController) async {
|
|
const CameraPosition defaultPosition = CameraPosition(
|
|
target: LatLng(20.985424, 105.738354),
|
|
zoom: 12,
|
|
);
|
|
TextEditingController searchLocationController = TextEditingController();
|
|
TextEditingController mapDialogLatitudeController = TextEditingController();
|
|
TextEditingController mapDialogLongitudeController = TextEditingController();
|
|
Completer<GoogleMapController> ggmapController = Completer();
|
|
final streamController = StreamController<GoogleMapController>.broadcast();
|
|
|
|
showGeneralDialog(
|
|
barrierDismissible: false,
|
|
transitionDuration: context.normalDuration,
|
|
transitionBuilder: transitionsLeftToRight,
|
|
context: context,
|
|
pageBuilder: (context, animation, secondaryAnimation) {
|
|
return StreamBuilder<Set<Marker>>(
|
|
stream: deviceUpdateBloc.streamMarkers,
|
|
builder: (context, markerSnapshot) {
|
|
if (!markerSnapshot.hasData) {
|
|
if (latitudeController.value.text != "" &&
|
|
longitudeController.value.text != "") {
|
|
double latitude = double.parse(latitudeController.text);
|
|
double longitude = double.parse(longitudeController.text);
|
|
addMarker(
|
|
LatLng(latitude, longitude),
|
|
ggmapController,
|
|
deviceUpdateBloc,
|
|
mapDialogLatitudeController,
|
|
mapDialogLongitudeController,
|
|
);
|
|
}
|
|
}
|
|
return Scaffold(
|
|
appBar: AppBar(
|
|
title: Text(appLocalization(context)
|
|
.update_device_dialog_maps_dialog_title),
|
|
centerTitle: true,
|
|
actions: [
|
|
IconButton(
|
|
onPressed: () async {
|
|
String latitude = mapDialogLatitudeController.text;
|
|
String longitude = mapDialogLongitudeController.text;
|
|
log("Finish -- Latitude: $latitude, longitude: $longitude --");
|
|
getDataFromApi(latitude, longitude, deviceUpdateBloc);
|
|
latitudeController.text =
|
|
mapDialogLatitudeController.text;
|
|
longitudeController.text =
|
|
mapDialogLongitudeController.text;
|
|
bool isChange = true;
|
|
deviceUpdateBloc.sinkIsChanged.add(isChange);
|
|
Navigator.of(context).pop();
|
|
},
|
|
icon: const Icon(Icons.check))
|
|
],
|
|
),
|
|
body: Stack(
|
|
children: [
|
|
GoogleMap(
|
|
onTap: (location) async {
|
|
addMarker(
|
|
location,
|
|
ggmapController,
|
|
deviceUpdateBloc,
|
|
mapDialogLatitudeController,
|
|
mapDialogLongitudeController,
|
|
);
|
|
},
|
|
markers: markerSnapshot.data ?? {},
|
|
onMapCreated: (GoogleMapController mapController) {
|
|
ggmapController.complete(mapController);
|
|
streamController.add(mapController);
|
|
},
|
|
initialCameraPosition: defaultPosition,
|
|
),
|
|
Container(
|
|
// color: Colors.white,
|
|
height: 80,
|
|
alignment: Alignment.topCenter,
|
|
padding: const EdgeInsets.all(10),
|
|
child: StreamBuilder<TextEditingController>(
|
|
stream: deviceUpdateBloc.streamSearchLocation,
|
|
builder: (context, searchLocation) {
|
|
return NearBySearchSFM(
|
|
textInputAction: TextInputAction.done,
|
|
textEditingController:
|
|
searchLocation.data ?? searchLocationController,
|
|
googleAPIKey: ApplicationConstants.MAP_KEY,
|
|
locationLatitude: 20.985424,
|
|
locationLongitude: 105.738354,
|
|
radius: 50000,
|
|
inputDecoration: InputDecoration(
|
|
hintText: appLocalization(context)
|
|
.update_device_dialog_search_location_hint,
|
|
border: InputBorder.none),
|
|
debounceTime: 600,
|
|
isLatLngRequired: true,
|
|
getPlaceDetailWithLatLng: (Prediction prediction) {
|
|
FocusScope.of(context).unfocus();
|
|
addMarker(
|
|
LatLng(double.parse(prediction.lat!),
|
|
double.parse(prediction.lng!)),
|
|
ggmapController,
|
|
deviceUpdateBloc,
|
|
mapDialogLatitudeController,
|
|
mapDialogLongitudeController);
|
|
},
|
|
itemClick: (Prediction prediction) {
|
|
searchLocationController.text =
|
|
prediction.structuredFormatting!.mainText!;
|
|
deviceUpdateBloc.sinkSearchLocation
|
|
.add(searchLocationController);
|
|
searchLocationController.selection =
|
|
TextSelection.fromPosition(TextPosition(
|
|
offset: prediction.structuredFormatting!
|
|
.mainText!.length));
|
|
},
|
|
boxDecoration: BoxDecoration(
|
|
color: Colors.white,
|
|
border: Border.all(
|
|
color: Colors.grey,
|
|
width: 0.5,
|
|
),
|
|
borderRadius: const BorderRadius.all(
|
|
Radius.circular(20))),
|
|
);
|
|
}),
|
|
)
|
|
],
|
|
),
|
|
);
|
|
});
|
|
},
|
|
);
|
|
}
|
|
|
|
addMarker(
|
|
LatLng position,
|
|
Completer<GoogleMapController> mapController,
|
|
DeviceUpdateBloc deviceUpdateBloc,
|
|
TextEditingController mapDialogLatitudeController,
|
|
TextEditingController mapDialogLongitudeController,
|
|
) async {
|
|
log("AddMarker -- Latitude: ${position.latitude}, longitude: ${position.longitude} --");
|
|
|
|
Set<Marker> marker = {};
|
|
deviceUpdateBloc.sinkMarkers.add(marker);
|
|
Marker newMarker = Marker(
|
|
markerId: const MarkerId('value'),
|
|
position: LatLng(position.latitude, position.longitude),
|
|
icon: BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueGreen),
|
|
draggable: true,
|
|
onDragEnd: (position) {
|
|
mapDialogLatitudeController.text = position.latitude.toString();
|
|
mapDialogLongitudeController.text = position.longitude.toString();
|
|
},
|
|
);
|
|
marker.add(newMarker);
|
|
deviceUpdateBloc.sinkMarkers.add(marker);
|
|
mapDialogLatitudeController.text = position.latitude.toString();
|
|
mapDialogLongitudeController.text = position.longitude.toString();
|
|
updateCameraPosition(position, 14, mapController);
|
|
}
|
|
|
|
void getDataFromApi(String latitude, String longitude,
|
|
DeviceUpdateBloc deviceUpdateBloc) async {
|
|
String path =
|
|
"maps/api/geocode/json?latlng=$latitude,$longitude&language=vi&result_type=political&key=${ApplicationConstants.MAP_KEY}";
|
|
var url = Uri.parse('https://maps.googleapis.com/$path');
|
|
|
|
final response = await http.get(url);
|
|
|
|
if (response.statusCode != 200) {
|
|
log("Loi: ${response.statusCode}");
|
|
return;
|
|
}
|
|
|
|
Map<String, dynamic> data = jsonDecode(response.body);
|
|
if (!data.containsKey('results') || data['results'].isEmpty) {
|
|
log("Khong co result");
|
|
return;
|
|
}
|
|
|
|
List<dynamic> results = data['results'];
|
|
List<Geocode> geocodes =
|
|
results.map((result) => Geocode.fromJson(result)).toList();
|
|
|
|
Map<String, String> locations =
|
|
_extractLocationComponents(geocodes[0].addressComponents!);
|
|
|
|
// In ra thông tin của các location
|
|
locations.forEach((key, value) {
|
|
log("$key: $value");
|
|
});
|
|
|
|
await _processLocations(locations, deviceUpdateBloc);
|
|
}
|
|
|
|
Map<String, String> _extractLocationComponents(
|
|
List<AddressComponent> addressComponents) {
|
|
Map<String, String> locations = {};
|
|
|
|
for (var addressComponent in addressComponents) {
|
|
String longName = addressComponent.longName ?? "";
|
|
if (addressComponent.types!.contains('administrative_area_level_3') ||
|
|
addressComponent.types!.contains('sublocality_level_1')) {
|
|
locations['wardkey'] = longName;
|
|
} else if (addressComponent.types!
|
|
.contains('administrative_area_level_2') ||
|
|
addressComponent.types!.contains('sublocality_level_2') ||
|
|
addressComponent.types!.contains('locality')) {
|
|
locations['districtkey'] = longName;
|
|
} else if (addressComponent.types!
|
|
.contains('administrative_area_level_1')) {
|
|
locations['provincekey'] = longName;
|
|
}
|
|
}
|
|
|
|
return locations;
|
|
}
|
|
|
|
Future<void> _processLocations(
|
|
Map<String, String> locations, DeviceUpdateBloc deviceUpdateBloc) async {
|
|
String provinceNameFromAPI = locations['provincekey'] ?? "";
|
|
String districtNameFromAPI = locations['districtkey'] ?? "";
|
|
String wardNameFromAPI = locations['wardkey'] ?? "";
|
|
|
|
final province =
|
|
await deviceUpdateBloc.getProvinceByName(provinceNameFromAPI);
|
|
if (province.name != "null") {
|
|
log("Province: ${province.fullName}, ProvinceCode: ${province.code}");
|
|
deviceUpdateBloc.sinkProvinceData
|
|
.add({"code": province.code!, "name": province.fullName!});
|
|
deviceUpdateBloc.getAllProvinces();
|
|
|
|
final district = await deviceUpdateBloc.getDistrictByName(
|
|
districtNameFromAPI, province.code!);
|
|
log("Districtname: ${district.fullName}, districtCode: ${district.code}");
|
|
deviceUpdateBloc.getAllDistricts(province.code!);
|
|
if (district.name != "null") {
|
|
deviceUpdateBloc.sinkDistrictData
|
|
.add({"code": district.code!, "name": district.fullName!});
|
|
final ward =
|
|
await deviceUpdateBloc.getWardByName(wardNameFromAPI, district.code!);
|
|
log("Wardname: ${ward.fullName}, WardCode: ${ward.code}");
|
|
deviceUpdateBloc.getAllWards(district.code!);
|
|
if (ward.name != "null") {
|
|
log("Xac dinh duoc het thong tin tu toa do");
|
|
deviceUpdateBloc.sinkWardData
|
|
.add({"code": ward.code!, "name": ward.fullName!});
|
|
} else {
|
|
deviceUpdateBloc.sinkWardData.add({});
|
|
}
|
|
} else {
|
|
deviceUpdateBloc.sinkDistrictData.add({});
|
|
}
|
|
} else {
|
|
deviceUpdateBloc.sinkProvinceData.add({});
|
|
}
|
|
}
|
|
|
|
Future<void> updateCameraPosition(LatLng location, double zoom,
|
|
Completer<GoogleMapController> mapController) async {
|
|
final CameraPosition cameraPosition = CameraPosition(
|
|
target: LatLng(
|
|
location.latitude,
|
|
location.longitude,
|
|
),
|
|
zoom: zoom,
|
|
);
|
|
final GoogleMapController mapControllerNew = await mapController.future;
|
|
mapControllerNew.animateCamera(
|
|
CameraUpdate.newCameraPosition(
|
|
cameraPosition,
|
|
),
|
|
);
|
|
}
|