2026-04-03-maplibra primary succsess

This commit is contained in:
Hamza-Ayed
2026-04-04 14:08:07 +03:00
parent e325405dff
commit 8d5fefc9e3
23 changed files with 2331 additions and 947 deletions

View File

@@ -1,6 +1,6 @@
// في ملف: constant/country_polygons.dart
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:maplibre_gl/maplibre_gl.dart';
class CountryPolygons {
// ==========================================================

View File

@@ -11,7 +11,7 @@ class AppLink {
/// هذا الرابط خاص برحلات الركاب، ويستخدمه السيرفر الجانبي للرحلات (Ride Server Side) للتعامل مع عمليات إلغاء الرحلات وتحديث حالة الرحلات وغيرها من العمليات المتعلقة بالرحلات.
/// https://routesy.intaleq.xyz for syria
/// for jordan https://routesjo.intaleq.xyz
static String routesOsm = 'https://routesy.intaleq.xyz';
static String routesOsm = 'https://routesjo.intaleq.xyz';
///https://location.intaleq.xyz/intaleq/ride/location
///locationServerSide هو السيرفر الجانبي الخاص بموقع السائقين، حيث يتم إرسال تحديثات الموقع من التطبيق إلى هذا السيرفر، ومن ثم يقوم هذا السيرفر بتوزيع هذه التحديثات إلى الركاب المتصلين الذين يتابعون السائق في الوقت الحقيقي.
@@ -42,7 +42,7 @@ class AppLink {
static String test = "$server/test.php";
//===============firebase==========================
static String getTokens = "$server/ride/firebase/getTokensPassenger.php.php";
static String getTokens = "$server/ride/firebase/getTokensPassenger.php";
static String getTokenParent = "$server/ride/firebase/getTokenParent.php";
static String addTokens = "$server/ride/firebase/add.php";
static String addFingerPrint = "$paymentServer/ride/firebase/add.php";

View File

@@ -1,4 +1,4 @@
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:maplibre_gl/maplibre_gl.dart';
class UniversitiesPolygons {
// AUC polygon points

View File

@@ -1,7 +1,6 @@
// import 'dart:async';
// import 'package:get/get.dart';
// import 'package:google_maps_flutter/google_maps_flutter.dart';
// import 'package:location/location.dart';
// import 'package:Intaleq/constant/box_name.dart';
// import 'package:Intaleq/constant/links.dart';

View File

@@ -1,4 +1,4 @@
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:maplibre_gl/maplibre_gl.dart';
List<LatLng> decodePolylineIsolate(String encoded) {
List<LatLng> points = [];

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:maplibre_gl/maplibre_gl.dart';
import 'package:Intaleq/constant/style.dart';
import 'package:Intaleq/controller/home/map_passenger_controller.dart';

View File

@@ -4,23 +4,25 @@ import 'dart:convert';
import 'package:Intaleq/constant/links.dart';
import 'package:Intaleq/controller/functions/crud.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:maplibre_gl/maplibre_gl.dart';
class TripMonitorController extends GetxController {
bool isLoading = false;
Map tripData = {};
late String rideId;
late String driverId;
GoogleMapController? mapController;
MapLibreMapController? mapController;
List myListString = [];
late Timer timer;
late LatLng parentLocation;
BitmapDescriptor carIcon = BitmapDescriptor.defaultMarker;
BitmapDescriptor motoIcon = BitmapDescriptor.defaultMarker;
BitmapDescriptor ladyIcon = BitmapDescriptor.defaultMarker;
String carIcon = 'car';
String motoIcon = 'moto';
String ladyIcon = 'lady';
double rotation = 0;
double speed = 0;
bool isStyleLoaded = false;
getLocationParent() async {
var res = await CRUD().get(
@@ -36,21 +38,65 @@ class TripMonitorController extends GetxController {
}
}
void onMapCreated(GoogleMapController controller) async {
void onMapCreated(MapLibreMapController controller) async {
mapController = controller;
controller.getVisibleRegion();
controller.animateCamera(
update();
}
void onStyleLoaded() async {
isStyleLoaded = true;
await _loadMapIcons();
mapController?.animateCamera(
CameraUpdate.newLatLng(parentLocation),
);
update();
// Set up a timer or interval to trigger the marker update every 3 seconds.
refreshMapElements();
// Set up a timer or interval to trigger the marker update every 10 seconds.
timer = Timer.periodic(const Duration(seconds: 10), (_) async {
await getLocationParent();
mapController?.animateCamera(CameraUpdate.newLatLng(parentLocation));
refreshMapElements();
update();
});
}
Future<void> _loadMapIcons() async {
if (mapController == null) return;
final icons = {
'car': 'assets/images/car.png',
'moto': 'assets/images/moto1.png',
'lady': 'assets/images/lady1.png',
};
for (var entry in icons.entries) {
final bytes = await rootBundle.load(entry.value);
await mapController!.addImage(entry.key, bytes.buffer.asUint8List());
}
}
void refreshMapElements() async {
if (!isStyleLoaded || mapController == null) return;
await mapController!.clearSymbols();
String iconToUse = carIcon;
if (tripData['message'] != null && tripData['message'].isNotEmpty) {
final model = tripData['message'][0]['model'].toString();
final gender = tripData['message'][0]['gender'].toString();
if (model.contains('دراجة')) {
iconToUse = motoIcon;
} else if (gender == 'Female') {
iconToUse = ladyIcon;
}
}
await mapController!.addSymbol(SymbolOptions(
geometry: parentLocation,
iconImage: iconToUse,
iconRotate: rotation,
textField: 'driver',
textOpacity: 0,
));
}
// init() async {
// final arguments = Get.arguments;
// driverId = arguments['driverId'];
@@ -65,41 +111,8 @@ class TripMonitorController extends GetxController {
update();
}
void addCustomCarIcon() {
ImageConfiguration config = ImageConfiguration(
size: const Size(30, 30), devicePixelRatio: Get.pixelRatio);
BitmapDescriptor.fromAssetImage(config, 'assets/images/car.png',
mipmaps: false)
.then((value) {
carIcon = value;
update();
});
void addCustomMotoIcon() {
ImageConfiguration config = ImageConfiguration(
size: const Size(30, 30), devicePixelRatio: Get.pixelRatio);
BitmapDescriptor.fromAssetImage(config, 'assets/images/moto1.png',
mipmaps: false)
.then((value) {
motoIcon = value;
update();
});
}
void addCustomLadyIcon() {
ImageConfiguration config = ImageConfiguration(
size: const Size(30, 30), devicePixelRatio: Get.pixelRatio);
BitmapDescriptor.fromAssetImage(config, 'assets/images/lady1.png',
mipmaps: false)
.then((value) {
ladyIcon = value;
update();
});
}
}
@override
void onInit() {
addCustomCarIcon();
super.onInit();
}

View File

@@ -4,7 +4,7 @@ class Log {
Log._();
static void print(String value, {StackTrace? stackTrace}) {
// developer.log(value, name: 'LOG', stackTrace: stackTrace);
developer.log(value, name: 'LOG', stackTrace: stackTrace);
}
static Object? inspect(Object? object) {

View File

@@ -1,11 +1,10 @@
import 'dart:io';
import 'package:Intaleq/controller/home/trip_monitor_controller.dart';
import 'package:Intaleq/views/widgets/my_scafold.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:maplibre_gl/maplibre_gl.dart';
import 'package:vibration/vibration.dart';
import '../../../../constant/colors.dart';
@@ -24,31 +23,15 @@ class TripMonitor extends StatelessWidget {
return MyScafolld(
title: 'Trip Monitor'.tr,
body: [
GoogleMap(
MapLibreMap(
onMapCreated: tripMonitorController.onMapCreated,
onStyleLoadedCallback: tripMonitorController.onStyleLoaded,
initialCameraPosition: CameraPosition(
// bearing: 45,
target: tripMonitorController.parentLocation,
zoom: 16,
tilt: 40,
),
// onCameraMove: (position) {},
markers: {
Marker(
markerId: MarkerId('start'.tr),
position: tripMonitorController.parentLocation,
draggable: true,
icon: tripMonitorController.tripData['message'][0]['model']
.contains('دراجة')
? tripMonitorController.motoIcon
: tripMonitorController.tripData['message'][0]['model']
['gender'] ==
'Male'
? tripMonitorController.carIcon
: tripMonitorController.ladyIcon,
rotation: tripMonitorController.rotation,
),
},
styleString: "assets/style.json",
),
speedCircle()
],

View File

@@ -5,7 +5,7 @@ import 'package:Intaleq/views/widgets/my_scafold.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:maplibre_gl/maplibre_gl.dart';
import 'package:vibration/vibration.dart';
import '../../../../constant/colors.dart';
@@ -30,31 +30,15 @@ class TripMonitor extends StatelessWidget {
return MyScafolld(
title: 'Trip Monitor'.tr,
body: [
GoogleMap(
MapLibreMap(
onMapCreated: tripMonitorController.onMapCreated,
onStyleLoadedCallback: tripMonitorController.onStyleLoaded,
initialCameraPosition: CameraPosition(
// bearing: 45,
target: tripMonitorController.parentLocation,
zoom: 16,
tilt: 40,
),
// onCameraMove: (position) {},
markers: {
Marker(
markerId: MarkerId('start'.tr),
position: tripMonitorController.parentLocation,
draggable: true,
icon: tripMonitorController.tripData['message'][0]['model']
.contains('دراجة')
? tripMonitorController.motoIcon
: tripMonitorController.tripData['message'][0]['model']
['gender'] ==
'Male'
? tripMonitorController.carIcon
: tripMonitorController.ladyIcon,
rotation: tripMonitorController.rotation,
),
},
styleString: "assets/style.json",
),
speedCircle()
],

View File

@@ -2,7 +2,7 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:maplibre_gl/maplibre_gl.dart';
import 'package:Intaleq/constant/box_name.dart';
import 'package:Intaleq/constant/table_names.dart';
import 'package:Intaleq/views/widgets/elevated_btn.dart';

View File

@@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:maplibre_gl/maplibre_gl.dart';
import '../../../constant/colors.dart';
import '../../../constant/style.dart';

View File

@@ -1,14 +1,11 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:maplibre_gl/maplibre_gl.dart';
import 'package:Intaleq/controller/home/points_for_rider_controller.dart';
import '../../../constant/colors.dart';
import '../../../constant/style.dart';
// import '../../../controller/functions/location_controller.dart'; // Un-comment if needed
// import '../../../controller/home/device_tier.dart'; // Removed to rely on Controller logic
import '../../../controller/home/map_passenger_controller.dart';
import '../../widgets/mycircular.dart';
import '../../widgets/mydialoug.dart';
@@ -28,29 +25,46 @@ class GoogleMapPassengerWidget extends StatelessWidget {
top: 0,
left: 0,
right: 0,
child: GoogleMap(
child: MapLibreMap(
onMapCreated: controller.onMapCreated,
// ✅ Camera Bounds
cameraTargetBounds: CameraTargetBounds(controller.boundsdata),
onStyleLoadedCallback: () => controller.onStyleLoaded(),
styleString: "assets/style.json",
// ✅ Performance: Smoother zoom limits for low-end devices
minMaxZoomPreference: controller.lowPerf
? const MinMaxZoomPreference(6, 17)
: const MinMaxZoomPreference(6, 18),
// ✅ Destination Selection on Long Press
onLongPress: (LatLng argument) {
initialCameraPosition: CameraPosition(
target: controller.passengerLocation,
zoom: controller.lowPerf ? 14.5 : 15,
),
// ✅ Map Settings
myLocationEnabled: true,
trackCameraPosition: true,
// ✅ Camera Movement Logic
onCameraIdle: () {
if (controller.mapController != null) {
final position = controller.mapController!.cameraPosition;
if (position != null) {
print('✅ onCameraIdle targeted: ${position.target}');
// 1. Always update current view target (for pickers)
controller
.updateCurrentLocationFromCamera(position.target);
}
}
},
onMapLongClick: (point, latlng) {
MyDialog().getDialog('Are you want to go to this site'.tr, '',
() async {
controller.clearPolyline();
// Ensure we have car data available before routing
// if (controller.dataCarsLocationByPassenger != null) {
// i use this check if needed
if (controller.carsLocationByPassenger.isNotEmpty) {
await controller.getDirectionMap(
'${controller.passengerLocation.latitude},${controller.passengerLocation.longitude}',
'${argument.latitude},${argument.longitude}',
'${latlng.latitude},${latlng.longitude}',
);
Get.back(); // Close Dialog
await controller.bottomSheet();
@@ -76,80 +90,9 @@ class GoogleMapPassengerWidget extends StatelessWidget {
});
},
// ✅ Hide UI elements on tap
onTap: (argument) {
onMapClick: (point, latlng) {
controller.hidePlaces();
},
initialCameraPosition: CameraPosition(
target: controller.passengerLocation,
zoom: controller.lowPerf ? 14.5 : 15,
),
// ✅ Markers
markers: controller.markers.toSet(),
// ✅ Polygons (e.g., University/Country borders)
polygons: controller.polygons,
// ✅ Polylines: Switch to lighter version if lowPerf is detected
polylines: controller.lowPerf
? controller.polyLinesLight.toSet()
: controller.polyLines.toSet(),
// ✅ Map Type: Switch to Normal map on low-end devices to save RAM
mapType: controller.lowPerf
? MapType.normal
: (controller.mapType
? MapType.satellite
: MapType
.normal), // Changed terrain default to normal for better performance
// ✅ UI Settings for Performance
myLocationButtonEnabled: false,
mapToolbarEnabled: false,
tiltGesturesEnabled:
false, // Disable tilt to save GPU resources
// Lite Mode (Static image) only on very low-end Androids if needed,
// but usually handled by lowPerf logic in mapType/Traffic
liteModeEnabled: Platform.isAndroid && controller.lowPerf,
trafficEnabled: controller.mapTrafficON && !controller.lowPerf,
buildingsEnabled: !controller.lowPerf,
rotateGesturesEnabled:
!controller.lowPerf, // Disable rotation on low-end
// ✅ Camera Movement Logic
onCameraMove: (CameraPosition position) {
// 1. Always update current view target (for pickers)
controller.newMyLocation = position.target;
// 2. Handle Drag-to-Select for specific states
if (controller.startLocationFromMap == true) {
controller.newStartPointLocation = position.target;
} else if (controller.passengerStartLocationFromMap == true) {
controller.newStartPointLocation = position.target;
}
// 3. Handle Waypoints Dragging
int waypointsLength =
Get.find<WayPointController>().wayPoints.length;
if (waypointsLength > 0 &&
controller.wayPointIndex >= 0 &&
controller.wayPointIndex <
controller.placesCoordinate.length) {
controller.placesCoordinate[controller.wayPointIndex] =
'${position.target.latitude},${position.target.longitude}';
}
// 4. Throttle heavy calculations (Reverse Geocoding / API calls)
if (controller.lowPerf) {
controller.onCameraMoveThrottled(position);
}
},
myLocationEnabled: false,
),
),
);

View File

@@ -3,7 +3,7 @@ import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter_font_icons/flutter_font_icons.dart';
import 'package:get/get.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:maplibre_gl/maplibre_gl.dart';
import 'dart:ui'; // مهم لإضافة تأثير الضبابية
import '../../../constant/colors.dart';

View File

@@ -8,7 +8,7 @@ import 'package:Intaleq/controller/home/map_passenger_controller.dart';
import 'package:Intaleq/main.dart';
import 'package:Intaleq/views/home/map_widget.dart/form_search_places_destenation.dart';
import 'package:Intaleq/views/widgets/elevated_btn.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:maplibre_gl/maplibre_gl.dart';
import '../../../constant/colors.dart';
import '../../../constant/table_names.dart';
import '../../../controller/functions/toast.dart';
@@ -760,6 +760,8 @@ class _MapPickerOverlay extends StatelessWidget {
controller.newMyLocation.latitude,
controller.newMyLocation.longitude,
);
print('🌐 MAP PICKER CENTER: ${currentCameraPosition.latitude}, ${currentCameraPosition.longitude}');
print('✅ _onConfirmTap confirmed coordinates: ${currentCameraPosition.latitude}, ${currentCameraPosition.longitude}');
// ── CASE 0: Waypoint picker mode ──────────────────────────────────────
if (controller.isPickingWaypoint && controller.pickingWaypointIndex >= 0) {

View File

@@ -3,7 +3,7 @@ import 'package:get/get.dart';
import 'package:Intaleq/constant/style.dart';
import 'package:Intaleq/views/widgets/my_scafold.dart';
import 'package:Intaleq/views/widgets/mycircular.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:maplibre_gl/maplibre_gl.dart';
import '../../../constant/colors.dart';
import '../../../controller/functions/launch.dart';
@@ -72,6 +72,7 @@ class OrderHistory extends StatelessWidget {
double.parse(ride['end_location'].toString().split(',')[0]),
double.parse(ride['end_location'].toString().split(',')[1]),
);
final LatLngBounds bounds = LatLngBounds(
northeast: LatLng(
startLocation.latitude > endLocation.latitude
@@ -124,32 +125,34 @@ class OrderHistory extends StatelessWidget {
height: 150, // ارتفاع ثابت للخريطة
child: AbsorbPointer(
// لمنع التفاعل المباشر مع الخريطة داخل القائمة
child: GoogleMap(
child: MapLibreMap(
styleString: "assets/style.json",
initialCameraPosition:
CameraPosition(target: startLocation, zoom: 12),
// --- نفس منطق الخريطة والخطوط ---
onMapCreated: (GoogleMapController controller) {
onStyleLoadedCallback: () async {
// This is a bit tricky in a list, but we can do it:
// Since we don't have the controller here easily without state,
// we'll rely on the simple map view or use a stateful widget for each card.
// For now, let's keep it simple.
},
onMapCreated: (MapLibreMapController controller) async {
await controller.addSymbol(SymbolOptions(
geometry: startLocation,
iconImage: 'start_icon',
));
await controller.addSymbol(SymbolOptions(
geometry: endLocation,
iconImage: 'end_icon',
));
await controller.addLine(LineOptions(
geometry: [startLocation, endLocation],
lineColor: '#${AppColor.primaryColor.value.toRadixString(16).substring(2)}',
lineWidth: 4,
));
controller.animateCamera(
CameraUpdate.newLatLngBounds(bounds, 60));
CameraUpdate.newLatLngBounds(bounds, left: 20, top: 20, right: 20, bottom: 20));
},
polylines: {
Polyline(
polylineId: const PolylineId('route'),
points: [startLocation, endLocation],
color: AppColor.primaryColor,
width: 4,
),
},
markers: {
Marker(
markerId: const MarkerId('start'),
position: startLocation),
Marker(
markerId: const MarkerId('end'),
position: endLocation),
},
mapToolbarEnabled: false,
zoomControlsEnabled: false,
),
),
),