813 lines
31 KiB
Dart
813 lines
31 KiB
Dart
import 'dart:async';
|
|
import 'dart:developer';
|
|
import 'dart:io';
|
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
|
import 'package:flutter/cupertino.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
import 'package:flutter_polyline_points/flutter_polyline_points.dart';
|
|
import 'package:geocoding/geocoding.dart';
|
|
import 'package:geolocator/geolocator.dart';
|
|
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
|
import 'package:injector/injector.dart';
|
|
import 'package:intl/intl.dart';
|
|
import 'package:package_info_plus/package_info_plus.dart';
|
|
import 'package:professional_repository/professional_repository.dart';
|
|
import 'package:prosappco/blocs/my_user_bloc/my_user_bloc.dart';
|
|
import 'package:prosappco/blocs/notification_bloc/notification_bloc.dart';
|
|
import 'package:prosappco/blocs/professional_list_bloc/professional_list_bloc.dart';
|
|
import 'package:prosappco/blocs/service_bloc/service_bloc.dart';
|
|
import 'package:prosappco/constansts.dart';
|
|
import 'package:prosappco/local_notifications/local_notifications.dart';
|
|
import 'package:prosappco/screens/lists/professional_list_screen.dart';
|
|
import 'package:prosappco/screens/user/user_service_screen.dart';
|
|
import 'package:prosappco/utils/time_of_day_extension.dart';
|
|
import 'package:service_repository/service_repository.dart';
|
|
import 'package:setting_repository/setting_repository.dart';
|
|
import 'package:url_launcher/url_launcher.dart';
|
|
|
|
class UserMapScreen extends StatefulWidget {
|
|
const UserMapScreen({super.key});
|
|
|
|
@override
|
|
State<UserMapScreen> createState() => _UserMapScreenState();
|
|
}
|
|
|
|
class _UserMapScreenState extends State<UserMapScreen> {
|
|
final Completer<GoogleMapController> _mapController =
|
|
Completer<GoogleMapController>();
|
|
LatLng? _currentP;
|
|
|
|
final TextEditingController _addressController = TextEditingController();
|
|
final TextEditingController _observationController = TextEditingController();
|
|
|
|
final settingRepository = Injector.appInstance.get<SettingRepository>();
|
|
SettingEntity? settings;
|
|
late String appVersion;
|
|
|
|
final DateFormat formatter = DateFormat('dd/MM/yyyy');
|
|
|
|
LatLng coordenadas = const LatLng(7.1253900, -73.1198000);
|
|
DateTime? fechaSeleccionada;
|
|
TimeOfDay? horaSeleccionada;
|
|
ServiceLocationPreferences? serviceLocationPreference;
|
|
UserProfessional? profesionalSeleccionado;
|
|
|
|
Map<PolylineId, Polyline> polylines = {};
|
|
|
|
bool isClearButtonVisible = false;
|
|
|
|
bool isLoading = false;
|
|
|
|
Set<Marker> markers = {};
|
|
BitmapDescriptor? _markerIcon;
|
|
|
|
final Uri _urlIos =
|
|
Uri.parse('https://apps.apple.com/co/app/prosapp/id6469028900');
|
|
final Uri _urlAndroid = Uri.parse(
|
|
'https://play.google.com/store/apps/details?id=com.prosapp.prosapp');
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
|
|
_loadSettings();
|
|
|
|
getLocation();
|
|
|
|
if (Platform.isAndroid) {
|
|
BitmapDescriptor.fromAssetImage(
|
|
const ImageConfiguration(size: Size(2, 2)),
|
|
'images/pro_marke_android.png',
|
|
).then((icon) {
|
|
setState(() {
|
|
_markerIcon = icon;
|
|
});
|
|
});
|
|
} else {
|
|
BitmapDescriptor.fromAssetImage(
|
|
const ImageConfiguration(size: Size(1, 1)),
|
|
'images/pro_marke.png',
|
|
).then((icon) {
|
|
setState(() {
|
|
_markerIcon = icon;
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
// void requestNotificationPermission() async {
|
|
// context.read<NotificationBloc>().requestPermission();
|
|
// }
|
|
|
|
_loadSettings() {
|
|
settingRepository.getSettings().then(
|
|
(value) => setState(() {
|
|
settings = value;
|
|
_getAppVersion();
|
|
}),
|
|
);
|
|
}
|
|
|
|
void _getAppVersion() async {
|
|
PackageInfo packageInfo = await PackageInfo.fromPlatform();
|
|
String version = packageInfo.version;
|
|
|
|
if (mounted) {
|
|
setState(() {
|
|
appVersion = version;
|
|
});
|
|
}
|
|
|
|
if (settings != null) {
|
|
_checkForUpdate(settings!);
|
|
}
|
|
}
|
|
|
|
void _checkForUpdate(SettingEntity settings) {
|
|
if (Platform.isAndroid) {
|
|
if (appVersion != settings.versionAndroid) {
|
|
showDialog(
|
|
context: context,
|
|
builder: (context) {
|
|
return WillPopScope(
|
|
onWillPop: () async {
|
|
return false;
|
|
},
|
|
child: Center(
|
|
child: AlertDialog(
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(16.0),
|
|
),
|
|
title: const Text(
|
|
"Debes Actualizar la Aplicación",
|
|
style: TextStyle(fontWeight: FontWeight.bold),
|
|
),
|
|
content: const Text(
|
|
"Tienes una versión desactualizada de nuestra aplicación. Te recomendamos actualizarla para disfrutar de las últimas características y mejoras.",
|
|
),
|
|
actions: [
|
|
TextButton(
|
|
child: const Text(
|
|
"Actualizar",
|
|
style: TextStyle(
|
|
fontWeight: FontWeight.w600, fontSize: 20),
|
|
),
|
|
onPressed: () {
|
|
launchUrl(_urlAndroid);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
},
|
|
);
|
|
}
|
|
}
|
|
if (Platform.isIOS) {
|
|
if (appVersion != settings.versionIos) {
|
|
showDialog(
|
|
context: context,
|
|
builder: (context) {
|
|
return WillPopScope(
|
|
onWillPop: () async {
|
|
return false;
|
|
},
|
|
child: Center(
|
|
child: AlertDialog(
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(16.0),
|
|
),
|
|
title: const Text(
|
|
"Debes Actualizar la Aplicación",
|
|
style: TextStyle(fontWeight: FontWeight.bold),
|
|
),
|
|
content: const Text(
|
|
"Tienes una versión desactualizada de nuestra aplicación. Te recomendamos actualizarla para disfrutar de las últimas características y mejoras.",
|
|
),
|
|
actions: [
|
|
TextButton(
|
|
child: const Text(
|
|
"Actualizar",
|
|
style: TextStyle(
|
|
fontWeight: FontWeight.w600, fontSize: 20),
|
|
),
|
|
onPressed: () {
|
|
launchUrl(_urlIos);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
},
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return BlocProvider<ServiceBloc>(
|
|
create: (context) => Injector.appInstance.get<ServiceBloc>(),
|
|
child: BlocConsumer<ServiceBloc, ServiceState>(
|
|
listener: (context, serviceState) {
|
|
if (serviceState is CreateServiceLoading) {
|
|
isLoading = true;
|
|
}
|
|
if (serviceState is CreateServiceFailure) {
|
|
isLoading = false;
|
|
}
|
|
|
|
if (serviceState is CreateServiceSuccess) {
|
|
isLoading = false;
|
|
|
|
Navigator.push(
|
|
context,
|
|
CupertinoPageRoute(
|
|
builder: (BuildContext context) {
|
|
return UserServiceScreen(serviceId: serviceState.serviceId);
|
|
},
|
|
),
|
|
);
|
|
}
|
|
},
|
|
builder: (context, state) {
|
|
return BlocBuilder<MyUserBloc, MyUserState>(
|
|
builder: (context, myUserState) {
|
|
return Column(
|
|
children: [
|
|
Expanded(
|
|
child: Stack(
|
|
children: [
|
|
GoogleMap(
|
|
myLocationEnabled: true,
|
|
polylines: Set<Polyline>.of(polylines.values),
|
|
onMapCreated: (GoogleMapController controller) {
|
|
_mapController.complete(controller);
|
|
},
|
|
markers: {
|
|
...markers,
|
|
Marker(
|
|
markerId: const MarkerId('currentLocation'),
|
|
position: _currentP ?? const LatLng(0, 0),
|
|
),
|
|
},
|
|
onCameraIdle: () {
|
|
getLocationName(
|
|
coordenadas.latitude, coordenadas.longitude)
|
|
.then((value) => setState(() {
|
|
_addressController.text = value;
|
|
}));
|
|
},
|
|
onCameraMove: (position) {
|
|
if (serviceLocationPreference !=
|
|
ServiceLocationPreferences.office) {
|
|
coordenadas = position.target;
|
|
}
|
|
},
|
|
initialCameraPosition: const CameraPosition(
|
|
target: LatLng(7.1253900, -73.1198000),
|
|
zoom: 16,
|
|
),
|
|
myLocationButtonEnabled: false,
|
|
),
|
|
Positioned(
|
|
top: 10,
|
|
left: 0,
|
|
child: Builder(
|
|
builder: (context) {
|
|
return ElevatedButton(
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: Colors.white,
|
|
shape: const CircleBorder(),
|
|
elevation: 3,
|
|
minimumSize: const Size(50, 50),
|
|
),
|
|
child: Icon(
|
|
Icons.menu,
|
|
color: Colors.black,
|
|
size: context.select(
|
|
(NotificationBloc bloc) =>
|
|
bloc.state.status.index > 0 ? 35 : 35,
|
|
),
|
|
),
|
|
onPressed: () {
|
|
Scaffold.of(context).openDrawer();
|
|
},
|
|
);
|
|
},
|
|
),
|
|
),
|
|
const Positioned(
|
|
bottom: 30,
|
|
right: 0,
|
|
left: 0,
|
|
top: 0,
|
|
child: Icon(
|
|
Icons.location_on,
|
|
size: 40,
|
|
color: Color(0xFFFF0000),
|
|
),
|
|
),
|
|
Positioned(
|
|
top: 10,
|
|
right: 10,
|
|
child: FloatingActionButton(
|
|
onPressed: () async {
|
|
try {
|
|
Position position = await _determinePosition();
|
|
|
|
setState(() {
|
|
_currentP = LatLng(
|
|
position.latitude,
|
|
position.longitude,
|
|
);
|
|
});
|
|
|
|
_animateCameraToPosition(_currentP!);
|
|
} catch (e) {
|
|
ScaffoldMessenger.of(context).clearSnackBars();
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
const SnackBar(
|
|
content:
|
|
Text('Por favor activa la ubicacion'),
|
|
),
|
|
);
|
|
}
|
|
},
|
|
elevation: 0,
|
|
child: const Icon(
|
|
Icons.gps_fixed,
|
|
size: 30,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
buildBottom(context, myUserState),
|
|
],
|
|
);
|
|
},
|
|
);
|
|
},
|
|
),
|
|
);
|
|
}
|
|
|
|
Container buildBottom(BuildContext context, MyUserState state) {
|
|
return Container(
|
|
padding: const EdgeInsets.symmetric(horizontal: 30, vertical: 10),
|
|
color: Colors.white,
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
TextField(
|
|
controller: TextEditingController(
|
|
text: profesionalSeleccionado == null
|
|
? ''
|
|
: '${profesionalSeleccionado?.myUser.name ?? ''} - ${profesionalSeleccionado?.professionalInfo.profession ?? ''}',
|
|
),
|
|
readOnly: true,
|
|
onTap: () async {
|
|
if (state.user?.name == null ||
|
|
state.user?.name == '' ||
|
|
state.user?.phone == '' ||
|
|
state.user?.phone == null) {
|
|
ScaffoldMessenger.of(context).clearSnackBars();
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
const SnackBar(
|
|
content: Text(
|
|
'Por favor completa tu perfil y agrega tu celular'),
|
|
),
|
|
);
|
|
return;
|
|
}
|
|
|
|
var datos = await Navigator.push(context,
|
|
CupertinoPageRoute(builder: (context) {
|
|
return const ProfessionalListScreen();
|
|
}));
|
|
|
|
if (datos != null) {
|
|
polylines.clear();
|
|
|
|
fechaSeleccionada = datos[0];
|
|
horaSeleccionada = datos[1];
|
|
serviceLocationPreference = datos[2];
|
|
profesionalSeleccionado = datos[3];
|
|
|
|
setState(() {});
|
|
if (serviceLocationPreference ==
|
|
ServiceLocationPreferences.office) {
|
|
_addressController.text =
|
|
profesionalSeleccionado?.professionalInfo.address ?? '';
|
|
|
|
_animateCameraToPosition(
|
|
LatLng(
|
|
profesionalSeleccionado!.professionalInfo.latitude,
|
|
profesionalSeleccionado!.professionalInfo.longitude,
|
|
),
|
|
);
|
|
coordenadas = LatLng(
|
|
profesionalSeleccionado!.professionalInfo.latitude,
|
|
profesionalSeleccionado!.professionalInfo.longitude,
|
|
);
|
|
|
|
if (_currentP != null) {
|
|
getPolylinePoints(
|
|
_currentP!,
|
|
LatLng(
|
|
profesionalSeleccionado!.professionalInfo.latitude,
|
|
profesionalSeleccionado!.professionalInfo.longitude,
|
|
)).then(
|
|
(coordinates) => {
|
|
generatePolyLineFromPoints(coordinates),
|
|
},
|
|
);
|
|
}
|
|
|
|
markers.add(
|
|
Marker(
|
|
icon: _markerIcon!,
|
|
markerId: MarkerId(
|
|
profesionalSeleccionado!.professionalInfo.id),
|
|
position: LatLng(
|
|
profesionalSeleccionado!.professionalInfo.latitude,
|
|
profesionalSeleccionado!.professionalInfo.longitude,
|
|
),
|
|
),
|
|
);
|
|
} else {}
|
|
|
|
isClearButtonVisible = true;
|
|
}
|
|
},
|
|
decoration: const InputDecoration(
|
|
prefixIcon: Icon(Icons.assignment_ind_rounded),
|
|
suffixIcon: Icon(Icons.arrow_drop_down),
|
|
hintText: 'Selecciona un profesional',
|
|
),
|
|
),
|
|
const SizedBox(height: 15),
|
|
TextField(
|
|
readOnly: true,
|
|
controller: _addressController,
|
|
decoration: const InputDecoration(
|
|
prefixIcon: Icon(Icons.location_on),
|
|
hintText: 'Dirección',
|
|
),
|
|
),
|
|
Visibility(
|
|
visible: fechaSeleccionada != null && horaSeleccionada != null,
|
|
child: Column(
|
|
children: [
|
|
const SizedBox(height: 15),
|
|
Row(
|
|
children: [
|
|
Expanded(
|
|
child: TextField(
|
|
readOnly: true,
|
|
controller: TextEditingController(
|
|
text: fechaSeleccionada == null
|
|
? ''
|
|
: formatter.format(fechaSeleccionada!),
|
|
),
|
|
decoration: const InputDecoration(
|
|
prefixIcon: Icon(Icons.calendar_month),
|
|
hintText: 'Fecha',
|
|
),
|
|
),
|
|
),
|
|
Expanded(
|
|
child: TextField(
|
|
readOnly: true,
|
|
controller: TextEditingController(
|
|
text: horaSeleccionada == null
|
|
? ''
|
|
: ScheduleEntity.getFormatTime(horaSeleccionada),
|
|
),
|
|
decoration: const InputDecoration(
|
|
prefixIcon: Icon(Icons.watch_later_outlined),
|
|
hintText: 'Hora',
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
const SizedBox(height: 15),
|
|
TextField(
|
|
controller: _observationController,
|
|
decoration: const InputDecoration(
|
|
prefixIcon: Icon(Icons.message_outlined),
|
|
hintText: 'Observaciones',
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
const SizedBox(height: 15),
|
|
Row(
|
|
children: [
|
|
Expanded(
|
|
child: FilledButton(
|
|
onPressed: isLoading
|
|
? null
|
|
: () {
|
|
if (profesionalSeleccionado == null) return;
|
|
|
|
if (state.user?.name == null ||
|
|
state.user?.name == '' ||
|
|
state.user?.phone == '' ||
|
|
state.user?.phone == null) {
|
|
ScaffoldMessenger.of(context).clearSnackBars();
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
const SnackBar(
|
|
content: Text(
|
|
'Por favor completa tu perfil y agrega tu celular'),
|
|
),
|
|
);
|
|
return;
|
|
}
|
|
|
|
if (serviceLocationPreference ==
|
|
ServiceLocationPreferences.office) {
|
|
if (settings?.tarifas == true) {
|
|
context.read<ServiceBloc>().add(
|
|
CreateService(
|
|
professionalId: profesionalSeleccionado!
|
|
.professionalInfo.id,
|
|
userId: state.user!.id,
|
|
address: profesionalSeleccionado!
|
|
.professionalInfo.address,
|
|
aditionalAddress: profesionalSeleccionado!
|
|
.professionalInfo.aditionalAddress,
|
|
latitude: profesionalSeleccionado!
|
|
.professionalInfo.latitude,
|
|
longitude: profesionalSeleccionado!
|
|
.professionalInfo.longitude,
|
|
day: fechaSeleccionada.toString(),
|
|
createdAt: Timestamp.now(),
|
|
description: _observationController.text,
|
|
range1Hour1: horaSeleccionada!,
|
|
range1Hour2:
|
|
horaSeleccionada!.add(hour: 2),
|
|
rate: profesionalSeleccionado!
|
|
.professionalInfo.rate,
|
|
location: serviceLocationPreference!,
|
|
),
|
|
);
|
|
} else {
|
|
context.read<ServiceBloc>().add(
|
|
CreateService(
|
|
professionalId: profesionalSeleccionado!
|
|
.professionalInfo.id,
|
|
userId: state.user!.id,
|
|
address: profesionalSeleccionado!
|
|
.professionalInfo.address,
|
|
aditionalAddress: profesionalSeleccionado!
|
|
.professionalInfo.aditionalAddress,
|
|
latitude: profesionalSeleccionado!
|
|
.professionalInfo.latitude,
|
|
longitude: profesionalSeleccionado!
|
|
.professionalInfo.longitude,
|
|
day: fechaSeleccionada.toString(),
|
|
createdAt: Timestamp.now(),
|
|
description: _observationController.text,
|
|
range1Hour1: horaSeleccionada!,
|
|
range1Hour2:
|
|
horaSeleccionada!.add(hour: 2),
|
|
rate: '0',
|
|
location: serviceLocationPreference!,
|
|
),
|
|
);
|
|
}
|
|
} else if (serviceLocationPreference ==
|
|
ServiceLocationPreferences.delivery) {
|
|
if (settings?.tarifas == true) {
|
|
context.read<ServiceBloc>().add(
|
|
CreateService(
|
|
professionalId: profesionalSeleccionado!
|
|
.professionalInfo.id,
|
|
userId: state.user!.id,
|
|
address: _addressController.text,
|
|
aditionalAddress: '',
|
|
latitude: 0,
|
|
longitude: 0,
|
|
day: fechaSeleccionada.toString(),
|
|
createdAt: Timestamp.now(),
|
|
description: _observationController.text,
|
|
range1Hour1: horaSeleccionada!,
|
|
range1Hour2:
|
|
horaSeleccionada!.add(hour: 2),
|
|
rate: profesionalSeleccionado!
|
|
.professionalInfo.rate,
|
|
location: serviceLocationPreference!,
|
|
),
|
|
);
|
|
} else {
|
|
context.read<ServiceBloc>().add(
|
|
CreateService(
|
|
professionalId: profesionalSeleccionado!
|
|
.professionalInfo.id,
|
|
userId: state.user!.id,
|
|
address: _addressController.text,
|
|
aditionalAddress: '',
|
|
latitude: 0,
|
|
longitude: 0,
|
|
day: fechaSeleccionada.toString(),
|
|
createdAt: Timestamp.now(),
|
|
description: _observationController.text,
|
|
range1Hour1: horaSeleccionada!,
|
|
range1Hour2:
|
|
horaSeleccionada!.add(hour: 2),
|
|
rate: '0',
|
|
location: serviceLocationPreference!,
|
|
),
|
|
);
|
|
}
|
|
} else {
|
|
// TODO: error inesperado
|
|
}
|
|
|
|
if (profesionalSeleccionado!.myUser.token != null) {
|
|
LocalNotifications.sendPushNotification(
|
|
profesionalSeleccionado!.myUser.token!,
|
|
'Nuevo servicio',
|
|
'Tienes una nueva solicitud de servicio pendiente',
|
|
);
|
|
}
|
|
|
|
fechaSeleccionada = null;
|
|
horaSeleccionada = null;
|
|
profesionalSeleccionado = null;
|
|
isClearButtonVisible = false;
|
|
_observationController.text = '';
|
|
serviceLocationPreference = null;
|
|
|
|
polylines.clear();
|
|
markers.clear();
|
|
setState(() {});
|
|
},
|
|
style: FilledButton.styleFrom(
|
|
backgroundColor: Theme.of(context).colorScheme.primary,
|
|
padding: const EdgeInsets.symmetric(vertical: 15),
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(10),
|
|
),
|
|
),
|
|
child: const Text(
|
|
'Pedir cita',
|
|
style: TextStyle(color: Colors.white, fontSize: 18),
|
|
),
|
|
),
|
|
),
|
|
Visibility(
|
|
visible: isClearButtonVisible,
|
|
child: const SizedBox(width: 10),
|
|
),
|
|
Visibility(
|
|
visible: isClearButtonVisible,
|
|
child: FilledButton(
|
|
onPressed: () {
|
|
fechaSeleccionada = null;
|
|
horaSeleccionada = null;
|
|
profesionalSeleccionado = null;
|
|
isClearButtonVisible = false;
|
|
_observationController.text = '';
|
|
serviceLocationPreference = null;
|
|
|
|
polylines.clear();
|
|
markers.clear();
|
|
setState(() {});
|
|
},
|
|
style: FilledButton.styleFrom(
|
|
backgroundColor: Colors.red,
|
|
padding: const EdgeInsets.symmetric(vertical: 15),
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(10),
|
|
),
|
|
),
|
|
child: const Icon(
|
|
CupertinoIcons.xmark,
|
|
color: Colors.white,
|
|
size: 30,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
)
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Future<void> _animateCameraToPosition(LatLng position) async {
|
|
final GoogleMapController controller = await _mapController.future;
|
|
controller.animateCamera(
|
|
CameraUpdate.newCameraPosition(
|
|
CameraPosition(
|
|
target: position,
|
|
zoom: 17.5,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Future<List<LatLng>> getPolylinePoints(
|
|
LatLng originP, LatLng destinationP) async {
|
|
List<LatLng> polylineCoordinates = [];
|
|
PolylinePoints polylinePoints = PolylinePoints();
|
|
PolylineResult result = await polylinePoints.getRouteBetweenCoordinates(
|
|
GOOGLE_MAPS_API_KEY,
|
|
PointLatLng(originP.latitude, originP.longitude),
|
|
PointLatLng(destinationP.latitude, destinationP.longitude),
|
|
travelMode: TravelMode.driving,
|
|
);
|
|
if (result.points.isNotEmpty) {
|
|
for (var point in result.points) {
|
|
polylineCoordinates.add(LatLng(point.latitude, point.longitude));
|
|
}
|
|
} else {
|
|
print(result.errorMessage);
|
|
}
|
|
return polylineCoordinates;
|
|
}
|
|
|
|
void getLocation() async {
|
|
try {
|
|
Position position = await _determinePosition();
|
|
|
|
setState(() {
|
|
_currentP = LatLng(
|
|
position.latitude,
|
|
position.longitude,
|
|
);
|
|
});
|
|
|
|
_animateCameraToPosition(_currentP!);
|
|
} catch (e) {
|
|
log(e.toString());
|
|
}
|
|
}
|
|
|
|
void generatePolyLineFromPoints(List<LatLng> polylineCoordinates) async {
|
|
PolylineId id = const PolylineId("poly");
|
|
Polyline polyline = Polyline(
|
|
polylineId: id,
|
|
color: Colors.blue,
|
|
points: polylineCoordinates,
|
|
width: 6,
|
|
);
|
|
setState(() {
|
|
polylines[id] = polyline;
|
|
});
|
|
}
|
|
|
|
Future<String> getLocationName(double latitude, double longitude) async {
|
|
String address;
|
|
List<Placemark> placemarks =
|
|
await placemarkFromCoordinates(latitude, longitude);
|
|
Placemark place = placemarks[0];
|
|
|
|
if (place.thoroughfare != '' || place.subThoroughfare != '') {
|
|
address =
|
|
"${place.thoroughfare} ${place.subThoroughfare} ${place.subLocality}, ${place.locality}, ${place.administrativeArea}";
|
|
} else {
|
|
address = '';
|
|
}
|
|
return address;
|
|
}
|
|
|
|
Future<Position> _determinePosition() async {
|
|
bool serviceEnabled;
|
|
LocationPermission permission;
|
|
|
|
serviceEnabled = await Geolocator.isLocationServiceEnabled();
|
|
|
|
if (!serviceEnabled) {
|
|
return Future.error('Location services are disabled');
|
|
}
|
|
|
|
permission = await Geolocator.checkPermission();
|
|
|
|
if (permission == LocationPermission.denied) {
|
|
permission = await Geolocator.requestPermission();
|
|
|
|
if (permission == LocationPermission.denied) {
|
|
return Future.error('Location permission denied');
|
|
}
|
|
}
|
|
|
|
if (permission == LocationPermission.deniedForever) {
|
|
return Future.error('Location permissions are permanently denied');
|
|
}
|
|
|
|
Position position = await Geolocator.getCurrentPosition();
|
|
|
|
return position;
|
|
}
|
|
}
|