Complete refactoring SFM App Source Code
This commit is contained in:
298
lib/feature/devices/device_update/map_dialog.dart
Normal file
298
lib/feature/devices/device_update/map_dialog.dart
Normal file
@@ -0,0 +1,298 @@
|
||||
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 'device_update_bloc.dart';
|
||||
import '../../../product/constant/app/app_constants.dart';
|
||||
import '../../../product/extention/context_extention.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,
|
||||
),
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user