Commit afecc427 authored by Sai Srinivas's avatar Sai Srinivas
Browse files

20-11-2025 Poly Lines and technician tracking screen, and technician tracking...

20-11-2025 Poly Lines and technician tracking screen, and technician tracking in complaint details and service List screen and changes in Modal for serviceList Response
parent ec8a1705
...@@ -82,6 +82,8 @@ class TechDetails { ...@@ -82,6 +82,8 @@ class TechDetails {
class AllServiceList { class AllServiceList {
String? id; String? id;
String? lat;
String? lng;
String? empName; String? empName;
String? date; String? date;
String? techRoleName; String? techRoleName;
...@@ -92,12 +94,14 @@ class AllServiceList { ...@@ -92,12 +94,14 @@ class AllServiceList {
String? customerServiceRating; String? customerServiceRating;
String? inOrOutTime; String? inOrOutTime;
String? runningHrs; String? runningHrs;
String? fsrExt;
String? filePath; String? filePath;
String? fsrExt;
String? fsrNo; String? fsrNo;
AllServiceList( AllServiceList(
{this.id, {this.id,
this.lat,
this.lng,
this.empName, this.empName,
this.date, this.date,
this.techRoleName, this.techRoleName,
...@@ -108,12 +112,14 @@ class AllServiceList { ...@@ -108,12 +112,14 @@ class AllServiceList {
this.customerServiceRating, this.customerServiceRating,
this.inOrOutTime, this.inOrOutTime,
this.runningHrs, this.runningHrs,
this.fsrExt,
this.filePath, this.filePath,
this.fsrExt,
this.fsrNo}); this.fsrNo});
AllServiceList.fromJson(Map<String, dynamic> json) { AllServiceList.fromJson(Map<String, dynamic> json) {
id = json['id']; id = json['id'];
lat = json['lat'];
lng = json['lng'];
empName = json['emp_name']; empName = json['emp_name'];
date = json['date']; date = json['date'];
techRoleName = json['tech_role_name']; techRoleName = json['tech_role_name'];
...@@ -124,14 +130,16 @@ class AllServiceList { ...@@ -124,14 +130,16 @@ class AllServiceList {
customerServiceRating = json['customer_service_rating']; customerServiceRating = json['customer_service_rating'];
inOrOutTime = json['in_or_out_time']; inOrOutTime = json['in_or_out_time'];
runningHrs = json['running_hrs']; runningHrs = json['running_hrs'];
fsrExt = json['fsr_ext'];
filePath = json['file_path']; filePath = json['file_path'];
fsrExt = json['fsr_ext'];
fsrNo = json['fsr_no']; fsrNo = json['fsr_no'];
} }
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>(); final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id; data['id'] = this.id;
data['lat'] = this.lat;
data['lng'] = this.lng;
data['emp_name'] = this.empName; data['emp_name'] = this.empName;
data['date'] = this.date; data['date'] = this.date;
data['tech_role_name'] = this.techRoleName; data['tech_role_name'] = this.techRoleName;
...@@ -142,8 +150,8 @@ class AllServiceList { ...@@ -142,8 +150,8 @@ class AllServiceList {
data['customer_service_rating'] = this.customerServiceRating; data['customer_service_rating'] = this.customerServiceRating;
data['in_or_out_time'] = this.inOrOutTime; data['in_or_out_time'] = this.inOrOutTime;
data['running_hrs'] = this.runningHrs; data['running_hrs'] = this.runningHrs;
data['fsr_ext'] = this.fsrExt;
data['file_path'] = this.filePath; data['file_path'] = this.filePath;
data['fsr_ext'] = this.fsrExt;
data['fsr_no'] = this.fsrNo; data['fsr_no'] = this.fsrNo;
return data; return data;
} }
......
import 'dart:async';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:geolocator/geolocator.dart';
import 'package:location/location.dart' as LocationPlugin;
import 'package:flutter_polyline_points/flutter_polyline_points.dart';
class Techniciantrackingprovider extends ChangeNotifier {
final String _googleApikey = "AIzaSyBGzvgMMKwPBAANTwaoRsAnrCpiWCj8wVs";
GoogleMapController? _mapController;
LocationPlugin.LocationData? _currentLocation;
bool _isLoading = true;
bool _hasPermission = false;
final Set<Marker> _markers = {};
final Set<Polyline> _polylines = {};
final List<LatLng> _polylineCoordinates = [];
late PolylinePoints polylinePoints;
BitmapDescriptor? customerIcon;
BitmapDescriptor? technicianIcon;
LatLng get startLocation => const LatLng(17.439112226708446, 78.43292499146135);
GoogleMapController? get mapController => _mapController;
Set<Marker> get markers => _markers;
Set<Polyline> get polylines => _polylines;
LocationPlugin.LocationData? get currentLocation => _currentLocation;
bool get isLoading => _isLoading;
set mapController(GoogleMapController? controller) {
_mapController = controller;
notifyListeners();
}
Future<void> loadCustomIcons() async {
customerIcon ??= await BitmapDescriptor.fromAssetImage(
const ImageConfiguration(size: Size(80, 80)),
'assets/images/maps_ic.png',
);
technicianIcon ??= await BitmapDescriptor.fromAssetImage(
const ImageConfiguration(size: Size(80, 80)),
'assets/images/technician_marker.png',
);
notifyListeners();
}
Future<void> getLocationPermission(BuildContext context) async {
_isLoading = true;
notifyListeners();
bool serviceEnabled = await Geolocator.isLocationServiceEnabled();
if (!serviceEnabled) {
_isLoading = false;
notifyListeners();
return;
}
LocationPermission permission = await Geolocator.checkPermission();
if (permission == LocationPermission.denied) {
permission = await Geolocator.requestPermission();
if (permission == LocationPermission.denied) {
_isLoading = false;
notifyListeners();
return;
}
}
if (permission == LocationPermission.deniedForever) {
_isLoading = false;
notifyListeners();
return;
}
_hasPermission = true;
await loadCustomIcons();
final LocationPlugin.Location location = LocationPlugin.Location();
_currentLocation = await location.getLocation();
// Add customer marker
if (_currentLocation != null) {
_markers.add(Marker(
markerId: const MarkerId('customer'),
position: LatLng(_currentLocation!.latitude!, _currentLocation!.longitude!),
infoWindow: const InfoWindow(title: "You are here"),
icon: customerIcon ?? BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueGreen),
));
}
_isLoading = false;
notifyListeners();
}
void updateTechnicianLocation(double? lat, double? lng) {
if (lat == null || lng == null || lat == 0 || lng == 0) return;
final technicianLatLng = LatLng(lat, lng);
// Remove old technician marker
_markers.removeWhere((m) => m.markerId.value == 'technician');
_polylines.clear();
_polylineCoordinates.clear();
// Add new technician marker
_markers.add(Marker(
markerId: const MarkerId('technician'),
position: technicianLatLng,
infoWindow: const InfoWindow(title: "Technician"),
icon: technicianIcon ?? BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueBlue),
));
// Draw route if customer location exists
if (_currentLocation != null) {
_drawRoute(
LatLng(_currentLocation!.latitude!, _currentLocation!.longitude!),
technicianLatLng,
);
}
// Adjust camera
_fitBothMarkers();
setPolylines(lat,lng);
notifyListeners();
}
void setPolylines(double? lat, double? lng) async {
_polylineCoordinates.clear();
_polylines.clear();
PolylineResult result = await polylinePoints.getRouteBetweenCoordinates(
// googleApiKey: "AIzaSyAA2ukvrb1kWQZ2dttsNIMynLJqVCYYrhw",
request: PolylineRequest(
origin: await PointLatLng(
lat!,
lng!),
destination: await PointLatLng(
_currentLocation!.latitude!,
_currentLocation!.longitude!),
mode: TravelMode.driving),
// Example LatLng// Example LatLng
// Example LatLng
);
if (result.points.isNotEmpty) {
result.points.forEach((PointLatLng point) {
_polylineCoordinates.add(LatLng(point.latitude, point.longitude));
});
_polylines.add(Polyline(
width: 1,
polylineId: PolylineId("poly"),
color: Color(0xFF008CDE),
points: _polylineCoordinates,
));
notifyListeners();
}
}
Future<void> _drawRoute(LatLng origin, LatLng destination) async {
final polylinePoints = PolylinePoints(apiKey: _googleApikey);
try {
final result = await polylinePoints.getRouteBetweenCoordinates(
request: PolylineRequest(
origin: PointLatLng(origin.latitude, origin.longitude),
destination: PointLatLng(destination.latitude, destination.longitude),
mode: TravelMode.driving,
),
);
if (result.points.isNotEmpty) {
_polylineCoordinates.clear();
for (var point in result.points) {
_polylineCoordinates.add(LatLng(point.latitude, point.longitude));
}
_polylines.add(Polyline(
polylineId: const PolylineId('route'),
color: Colors.blue,
width: 5,
points: _polylineCoordinates,
patterns: [PatternItem.dash(20), PatternItem.gap(10)],
));
}
} catch (e) {
debugPrint("Polyline Error: $e");
}
notifyListeners();
}
void _fitBothMarkers() {
if (_markers.length < 2 || _mapController == null) return;
final positions = _markers.map((m) => m.position).toList();
double minLat = positions[0].latitude;
double maxLat = positions[0].latitude;
double minLng = positions[0].longitude;
double maxLng = positions[0].longitude;
for (var pos in positions) {
if (pos.latitude < minLat) minLat = pos.latitude;
if (pos.latitude > maxLat) maxLat = pos.latitude;
if (pos.longitude < minLng) minLng = pos.longitude;
if (pos.longitude > maxLng) maxLng = pos.longitude;
}
_mapController!.animateCamera(
CameraUpdate.newLatLngBounds(
LatLngBounds(
southwest: LatLng(minLat, minLng),
northeast: LatLng(maxLat, maxLng),
),
100,
),
);
}
Future<void> setMapStyle(GoogleMapController controller) async {
String mapStyle = '''
[
{
"featureType": "road",
"elementType": "geometry",
"stylers": [
{
"visibility": "on"
}
]
},
{
"featureType": "road.arterial",
"elementType": "geometry",
"stylers": [
{
"visibility": "on"
}
]
},
{
"featureType": "road.highway",
"elementType": "geometry",
"stylers": [
{
"visibility": "off"
}
]
},
{
"featureType": "road.local",
"elementType": "geometry",
"stylers": [
{
"visibility": "on"
}
]
},
{
"featureType": "poi",
"elementType": "labels",
"stylers": [
{
"visibility": "on"
}
]
},
{
"featureType": "poi.business",
"stylers": [
{
"visibility": "on"
}
]
},
{
"featureType": "transit",
"stylers": [
{
"visibility": "on"
}
]
},
{
"featureType": "road.local",
"elementType": "labels",
"stylers": [
{
"visibility": "on"
}
]
}
]
''';
await controller.setMapStyle(mapStyle);
}
void clearMap() {
_markers.clear();
_polylines.clear();
_polylineCoordinates.clear();
notifyListeners();
}
}
\ No newline at end of file
import 'dart:io';
import 'dart:ui';
import 'dart:async';
import 'dart:ui' as ui;
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/services.dart';
import 'package:flutter_svg/svg.dart';
import 'package:flutter/material.dart';
import 'package:gen_service/Models/HelpAndComplaintModels/allServiceListResponse.dart';
import 'package:gen_service/Notifiers/technicianTrackingProvider.dart';
import 'package:gen_service/Services/api_calling.dart';
import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:flutter_polyline_points/flutter_polyline_points.dart';
import '../../Models/HelpAndComplaintModels/complaintDetailsResponse.dart';
import '../../Utility/AppColors.dart';
class TechnicianTrackingScreen extends StatefulWidget {
final ServiceDetails? details;
final AllServiceList? allDet;
final String from;
final ComplaintDetails? complaintData;
const TechnicianTrackingScreen({
super.key,
this.details,
this.allDet,
required this.from,
required this.complaintData,
});
@override
_TechnicianTrackingScreenState createState() =>
_TechnicianTrackingScreenState();
}
class _TechnicianTrackingScreenState extends State<TechnicianTrackingScreen> {
var serviceData;
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
final mapProvider = Provider.of<Techniciantrackingprovider>(
context,
listen: false,
);
mapProvider.getLocationPermission(context);
mapProvider.polylinePoints = PolylinePoints(
apiKey: "AIzaSyAA2ukvrb1kWQZ2dttsNIMynLJqVCYYrhw",
);
if (widget.from == "All") {
serviceData = widget.allDet;
} else {
serviceData = widget.details;
}
});
// InitialPorterFunction();
}
@override
void dispose() {
// TODO: implement dispose
super.dispose();
}
@override
Widget build(BuildContext context) {
double screenWidth = MediaQuery.of(context).size.width;
double screenHeight = MediaQuery.of(context).size.height;
return SafeArea(
top: false,
bottom: Platform.isIOS ? false : true,
maintainBottomViewPadding: true,
child: Scaffold(
resizeToAvoidBottomInset: true,
backgroundColor: Color(0xFF4076FF),
body: Consumer<Techniciantrackingprovider>(
builder: (context, mapProvider, child) {
return CustomScrollView(
slivers: [
SliverAppBar(
automaticallyImplyLeading: false,
stretch: true,
onStretchTrigger: () async {},
stretchTriggerOffset: 300.0,
backgroundColor: Color(0xFF4076FF),
expandedHeight: screenHeight * 0.15,
flexibleSpace: FlexibleSpaceBar(
stretchModes: const [
StretchMode.zoomBackground,
StretchMode.blurBackground,
],
background: Container(
decoration: const BoxDecoration(
gradient: AppColors.commonAppBarGradient,
),
child: SafeArea(
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(width: 8),
InkResponse(
onTap: () {
HapticFeedback.selectionClick();
Navigator.pop(context, true);
},
child: SvgPicture.asset(
"assets/svg/appbar_back.svg",
height: 25,
),
),
SizedBox(width: 10),
Expanded(
flex: 4,
child: InkResponse(
onTap: () {
HapticFeedback.selectionClick();
Navigator.pop(context, true);
},
child: Text(
"Track Technician",
overflow: TextOverflow.ellipsis,
maxLines: 1,
style: TextStyle(
fontSize: 16,
color: Colors.white,
height: 1.1,
),
),
),
),
],
),
SizedBox(height: 10),
Container(
padding: const EdgeInsets.symmetric(
horizontal: 10,
vertical: 5,
),
child: Column(
children: [
// Product Info Row
Padding(
padding: const EdgeInsets.symmetric(
vertical: 4.0,
),
child: Row(
children: [
Expanded(
flex: 5,
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
RichText(
text: TextSpan(
style: const TextStyle(
fontFamily: 'Poppins',
color: Color(0xFF48F3FF),
fontSize: 12,
),
children: [
TextSpan(
text:
"#${widget.complaintData?.id!}",
),
TextSpan(
text:
(widget.complaintData?.complaintName ??
"")
.isNotEmpty
? " | ${widget.complaintData?.complaintName!}"
: "",
),
],
),
),
Text(
"${widget.complaintData?.registredDate ?? ""}",
maxLines: 2,
style: const TextStyle(
color: Colors.white,
fontSize: 14,
),
),
],
),
),
Expanded(
flex: 2,
child: Container(
padding: EdgeInsets.symmetric(
horizontal: 15,
vertical: 7,
),
decoration: BoxDecoration(
color:
widget
.complaintData
?.openStatus ==
"Open"
? AppColors.successBG
: AppColors.yellowBG,
borderRadius:
BorderRadius.circular(10),
),
child: Center(
child: Text(
"${widget.complaintData?.openStatus}",
style: TextStyle(
fontFamily: "Poppins",
fontSize: 14,
fontWeight: FontWeight.w400,
color:
widget
.complaintData
?.openStatus ==
"Open"
? AppColors.success
: AppColors
.normalText,
),
),
),
),
),
],
),
),
],
),
),
],
),
),
),
),
),
SliverFillRemaining(
hasScrollBody: false,
child: Container(
decoration: const BoxDecoration(
color: AppColors.backgroundRegular,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(30),
topRight: Radius.circular(30),
),
),
padding: const EdgeInsets.symmetric(
horizontal: 5,
vertical: 0,
),
child: Column(
children: [
Container(
margin: const EdgeInsets.symmetric(
horizontal: 0,
vertical: 5,
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(18),
),
height: screenHeight * 0.8,
child: ClipRRect(
borderRadius: BorderRadius.circular(18),
child: GoogleMap(
myLocationEnabled: true,
zoomGesturesEnabled: true,
zoomControlsEnabled: true,
scrollGesturesEnabled: false,
gestureRecognizers: {
Factory<OneSequenceGestureRecognizer>(
() => EagerGestureRecognizer(),
),
Factory<PanGestureRecognizer>(
() => PanGestureRecognizer(),
),
Factory<ScaleGestureRecognizer>(
() => ScaleGestureRecognizer(),
),
},
initialCameraPosition: CameraPosition(
target:
mapProvider.currentLocation != null
? LatLng(
mapProvider
.currentLocation!
.latitude!,
mapProvider
.currentLocation!
.longitude!,
)
: mapProvider.startLocation,
zoom: 15,
),
myLocationButtonEnabled: false,
mapType: MapType.normal,
markers: mapProvider.markers,
polylines: mapProvider.polylines,
onMapCreated: (GoogleMapController controller) {
mapProvider.mapController = controller;
mapProvider.setMapStyle(controller);
final double? techLat1 = 17.4484769;
final double? techLng1 = 78.3710461;
final double? techLat = double.tryParse(
serviceData?.lat?.trim() ?? '${techLat1}',
)??techLat1;
final double? techLng = double.tryParse(
serviceData?.lng?.trim() ?? '${techLng1}',
)??techLng1;
if (techLat != null &&
techLng != null &&
techLat != 0 &&
techLng != 0) {
mapProvider.updateTechnicianLocation(
techLat,
techLng,
);
}
},
),
),
),
],
),
),
),
],
);
},
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
floatingActionButton: Container(
alignment: Alignment.center,
height: 80,
width: screenWidth,
padding: EdgeInsets.symmetric(horizontal: 0, vertical: 10),
margin: EdgeInsets.symmetric(horizontal: 10),
decoration: BoxDecoration(
color: Color(0xFF008CDE),
borderRadius: BorderRadius.circular(50),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
flex: 1,
child: CircleAvatar(
radius: 25,
backgroundImage:
serviceData?.profileImg == "https://erp.gengroup.in/"
? AssetImage("assets/images/user_img.png")
: NetworkImage("${serviceData?.profileImg}"),
),
),
Expanded(
flex: 3,
child: SizedBox(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"${serviceData?.empName}",
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: TextStyle(
color: Colors.white,
fontSize: 14,
),
),
Text(
"${serviceData?.techRoleName}",
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
color: Colors.white,
fontSize: 12,
),
),
],
),
),
),
Expanded(
flex: 1,
child: SizedBox(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
InkResponse(
onTap: () async {
var url = "tel:${serviceData?.mobNum}";
if (await canLaunch(url)) {
await launch(url);
} else {
throw 'Could not launch $url';
}
},
child: Image.asset(
"assets/images/call_technicain_ic.png",
fit: BoxFit.cover,
height: 40,
width: 40,
),
),
],
),
),
),
],
),
),
),
);
}
}
...@@ -11,7 +11,7 @@ import 'package:gen_service/Screens/HelpAndComplaintScreens/SelectOrderHelpScree ...@@ -11,7 +11,7 @@ import 'package:gen_service/Screens/HelpAndComplaintScreens/SelectOrderHelpScree
import 'package:gen_service/Screens/HelpAndComplaintScreens/ComplaintListScreen.dart'; import 'package:gen_service/Screens/HelpAndComplaintScreens/ComplaintListScreen.dart';
import 'package:gen_service/Screens/ProfileScreen.dart'; import 'package:gen_service/Screens/ProfileScreen.dart';
import 'package:gen_service/Screens/TransactionScreens/TransactionListScreen.dart'; import 'package:gen_service/Screens/TransactionScreens/TransactionListScreen.dart';
import 'package:gen_service/Screens/TransactionScreens/contactMap.dart'; import 'package:gen_service/Screens/HelpAndComplaintScreens/contactMap.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:razorpay_flutter/razorpay_flutter.dart'; import 'package:razorpay_flutter/razorpay_flutter.dart';
......
...@@ -156,4 +156,15 @@ class AppColors { ...@@ -156,4 +156,15 @@ class AppColors {
Color(0xFF4076FF), Color(0xFF4076FF),
], ],
); );
static LinearGradient whiteGradient = LinearGradient(
colors: [
Color(0xFFFFFFFF).withOpacity(0.0),
Color(0xFFFFFFFF),
],
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
);
} }
\ No newline at end of file
...@@ -3,6 +3,7 @@ import 'package:gen_service/Notifiers/AuthProvider.dart'; ...@@ -3,6 +3,7 @@ import 'package:gen_service/Notifiers/AuthProvider.dart';
import 'package:gen_service/Notifiers/TransactionsProvider.dart'; import 'package:gen_service/Notifiers/TransactionsProvider.dart';
import 'package:gen_service/Notifiers/mapProvider.dart'; import 'package:gen_service/Notifiers/mapProvider.dart';
import 'package:gen_service/Notifiers/serviceAndJobCardListProvier.dart'; import 'package:gen_service/Notifiers/serviceAndJobCardListProvier.dart';
import 'package:gen_service/Notifiers/technicianTrackingProvider.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'Notifiers/ContactUsProvider.dart'; import 'Notifiers/ContactUsProvider.dart';
...@@ -35,8 +36,8 @@ class MyApp extends StatelessWidget { ...@@ -35,8 +36,8 @@ class MyApp extends StatelessWidget {
ChangeNotifierProvider(create: (_) => ContactUsProvider()), ChangeNotifierProvider(create: (_) => ContactUsProvider()),
ChangeNotifierProvider(create: (_) => ServiceAndJobCardListProvider()), ChangeNotifierProvider(create: (_) => ServiceAndJobCardListProvider()),
ChangeNotifierProvider(create: (_) => MapProvider()), ChangeNotifierProvider(create: (_) => MapProvider()),
ChangeNotifierProvider(create: (_) => PayAmountProvider()), ChangeNotifierProvider(create: (_) => PayAmountProvider()),
ChangeNotifierProvider(create: (_) => Techniciantrackingprovider()),
], ],
child: Consumer<ThemeProvider>( child: Consumer<ThemeProvider>(
builder: (context, themeProvider, child) { builder: (context, themeProvider, child) {
......
...@@ -358,6 +358,14 @@ packages: ...@@ -358,6 +358,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.31" version: "2.0.31"
flutter_polyline_points:
dependency: "direct main"
description:
name: flutter_polyline_points
sha256: c775fe59fbcf1f925d611c039555c7f58ed6d9411747b7a2915bbd9c5e730a51
url: "https://pub.dev"
source: hosted
version: "3.1.0"
flutter_svg: flutter_svg:
dependency: "direct main" dependency: "direct main"
description: description:
......
...@@ -61,6 +61,7 @@ dependencies: ...@@ -61,6 +61,7 @@ dependencies:
flutter_local_notifications: ^19.5.0 flutter_local_notifications: ^19.5.0
flutter_download_manager: ^0.5.5 flutter_download_manager: ^0.5.5
intl: ^0.20.2 intl: ^0.20.2
flutter_polyline_points: ^3.1.0
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment