change to map-saas api key and env - 2026-04-12
This commit is contained in:
@@ -12,7 +12,8 @@ class ContactUsController extends GetxController {
|
||||
final TimeOfDay workStartTime = const TimeOfDay(hour: 10, minute: 0);
|
||||
final TimeOfDay workEndTime = const TimeOfDay(hour: 16, minute: 0);
|
||||
|
||||
bool _isWithinWorkTime(TimeOfDay now) {
|
||||
bool get isWorkTime {
|
||||
final now = TimeOfDay.now();
|
||||
return (now.hour > workStartTime.hour ||
|
||||
(now.hour == workStartTime.hour &&
|
||||
now.minute >= workStartTime.minute)) &&
|
||||
@@ -20,6 +21,11 @@ class ContactUsController extends GetxController {
|
||||
(now.hour == workEndTime.hour && now.minute <= workEndTime.minute));
|
||||
}
|
||||
|
||||
/// Helper to format working hours for UI
|
||||
String get workHoursString =>
|
||||
'${workStartTime.hour.toString().padLeft(2, '0')}:${workStartTime.minute.toString().padLeft(2, '0')} - '
|
||||
'${workEndTime.hour.toString().padLeft(2, '0')}:${workEndTime.minute.toString().padLeft(2, '0')}';
|
||||
|
||||
/// PHONE LIST (USED FOR CALLS + WHATSAPP)
|
||||
final List<String> phoneNumbers = [
|
||||
'+963952475734',
|
||||
@@ -33,10 +39,24 @@ class ContactUsController extends GetxController {
|
||||
return phoneNumbers[random.nextInt(phoneNumbers.length)];
|
||||
}
|
||||
|
||||
/// SHOW DIALOG
|
||||
/// DIRECT ACTIONS
|
||||
void makeCall() {
|
||||
if (isWorkTime) {
|
||||
makePhoneCall(getRandomPhone());
|
||||
}
|
||||
}
|
||||
|
||||
void sendWhatsApp() {
|
||||
launchCommunication('whatsapp', getRandomPhone(), 'Hello'.tr);
|
||||
}
|
||||
|
||||
void sendEmail() {
|
||||
launchCommunication('email', 'support@intaleqapp.com', 'Hello'.tr);
|
||||
}
|
||||
|
||||
/// SHOW DIALOG (Optional legacy support)
|
||||
void showContactDialog(BuildContext context) {
|
||||
TimeOfDay now = TimeOfDay.now();
|
||||
bool withinHours = _isWithinWorkTime(now);
|
||||
bool withinHours = isWorkTime;
|
||||
|
||||
showCupertinoModalPopup(
|
||||
context: context,
|
||||
@@ -44,7 +64,6 @@ class ContactUsController extends GetxController {
|
||||
title: Text('Contact Us'.tr),
|
||||
message: Text('Choose a contact option'.tr),
|
||||
actions: <Widget>[
|
||||
/// 📞 CALL (RANDOM) — ONLY DURING WORK HOURS
|
||||
if (withinHours)
|
||||
CupertinoActionSheetAction(
|
||||
child: Row(
|
||||
@@ -55,12 +74,10 @@ class ContactUsController extends GetxController {
|
||||
],
|
||||
),
|
||||
onPressed: () {
|
||||
final phone = getRandomPhone();
|
||||
makePhoneCall(phone);
|
||||
Navigator.pop(context);
|
||||
makeCall();
|
||||
},
|
||||
),
|
||||
|
||||
/// ⛔ OUTSIDE WORK HOURS — SHOW INFO
|
||||
if (!withinHours)
|
||||
CupertinoActionSheetAction(
|
||||
child: Text(
|
||||
@@ -70,8 +87,6 @@ class ContactUsController extends GetxController {
|
||||
),
|
||||
onPressed: () => Navigator.pop(context),
|
||||
),
|
||||
|
||||
/// 💬 WHATSAPP (RANDOM)
|
||||
CupertinoActionSheetAction(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
@@ -84,20 +99,18 @@ class ContactUsController extends GetxController {
|
||||
],
|
||||
),
|
||||
onPressed: () {
|
||||
final phone = getRandomPhone();
|
||||
launchCommunication('whatsapp', phone, 'Hello'.tr);
|
||||
Navigator.pop(context);
|
||||
sendWhatsApp();
|
||||
},
|
||||
),
|
||||
|
||||
/// 📧 EMAIL
|
||||
CupertinoActionSheetAction(
|
||||
child: Text('Send Email'.tr),
|
||||
onPressed: () => launchCommunication(
|
||||
'email', 'support@intaleqapp.com', 'Hello'.tr),
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
sendEmail();
|
||||
},
|
||||
),
|
||||
],
|
||||
|
||||
/// ❌ CANCEL BUTTON
|
||||
cancelButton: CupertinoActionSheetAction(
|
||||
child: Text('Cancel'.tr),
|
||||
onPressed: () => Navigator.pop(context),
|
||||
|
||||
@@ -611,53 +611,56 @@ class MapPassengerController extends GetxController {
|
||||
if (response.statusCode == 200) {
|
||||
final responseData = json.decode(response.body);
|
||||
|
||||
if (responseData['code'] == 'Ok' || responseData['routes'] != null) {
|
||||
var routeData = responseData['routes'][0];
|
||||
// Support both old format (routes[0]) and new SaaS format (top-level)
|
||||
var routeData = responseData['routes'] != null
|
||||
? responseData['routes'][0]
|
||||
: responseData;
|
||||
|
||||
// 2. تحديث المتغيرات (المسافة والوقت)
|
||||
double durationSecondsRaw = (routeData['duration'] as num).toDouble();
|
||||
int finalDurationSeconds =
|
||||
(durationSecondsRaw * kDurationScalar).toInt();
|
||||
double distanceMeters = (routeData['distance'] as num).toDouble();
|
||||
// 2. تحديث المتغيرات (المسافة والوقت)
|
||||
double durationSecondsRaw = (routeData['duration'] as num).toDouble();
|
||||
int finalDurationSeconds =
|
||||
(durationSecondsRaw * kDurationScalar).toInt();
|
||||
double distanceMeters = (routeData['distance'] as num).toDouble();
|
||||
|
||||
timeToPassengerFromDriverAfterApplied = finalDurationSeconds;
|
||||
remainingTimeToPassengerFromDriverAfterApplied = finalDurationSeconds;
|
||||
distanceByPassenger = distanceMeters.toStringAsFixed(0);
|
||||
timeToPassengerFromDriverAfterApplied = finalDurationSeconds;
|
||||
remainingTimeToPassengerFromDriverAfterApplied = finalDurationSeconds;
|
||||
distanceByPassenger = distanceMeters.toStringAsFixed(0);
|
||||
|
||||
// تحديث نصوص الواجهة
|
||||
int minutes = (finalDurationSeconds / 60).floor();
|
||||
int seconds = finalDurationSeconds % 60;
|
||||
stringRemainingTimeToPassenger =
|
||||
'$minutes:${seconds.toString().padLeft(2, '0')}';
|
||||
// تحديث نصوص الواجهة
|
||||
int minutes = (finalDurationSeconds / 60).floor();
|
||||
int seconds = finalDurationSeconds % 60;
|
||||
stringRemainingTimeToPassenger =
|
||||
'$minutes:${seconds.toString().padLeft(2, '0')}';
|
||||
|
||||
Log.print(
|
||||
'✅ Driver Route Info: $minutes min, ${distanceMeters.toInt()} m');
|
||||
Log.print(
|
||||
'✅ Driver Route Info: $minutes min, ${distanceMeters.toInt()} m');
|
||||
|
||||
// 3. معالجة الرسم (Polyline)
|
||||
String pointsString = routeData['geometry'] ?? "";
|
||||
if (pointsString.isNotEmpty) {
|
||||
List<LatLng> decodedPoints =
|
||||
await compute(decodePolylineIsolate, pointsString);
|
||||
// حفظ نسخة للمقارنة
|
||||
_currentDriverRoutePoints = decodedPoints;
|
||||
// إزالة خط مسار السائق القديم فقط
|
||||
polyLines = polyLines.where((p) => p.lineOpacity != 0.999).toList();
|
||||
// 3. معالجة الرسم (Polyline)
|
||||
// SaaS uses 'points', OSRM uses 'geometry'
|
||||
String pointsString =
|
||||
routeData['points'] ?? routeData['geometry'] ?? "";
|
||||
if (pointsString.isNotEmpty) {
|
||||
List<LatLng> decodedPoints =
|
||||
await compute(decodePolylineIsolate, pointsString);
|
||||
// حفظ نسخة للمقارنة
|
||||
_currentDriverRoutePoints = decodedPoints;
|
||||
// إزالة خط مسار السائق القديم فقط
|
||||
polyLines = polyLines.where((p) => p.lineOpacity != 0.999).toList();
|
||||
|
||||
// إضافة الخط الجديد (بستايل مميز للسائق)
|
||||
polyLines.add(LineOptions(
|
||||
geometry: decodedPoints,
|
||||
lineColor: '#333333', // لون مختلف عن مسار الرحلة الأساسي
|
||||
lineWidth: 5,
|
||||
lineOpacity: 0.999, // acting as ID
|
||||
));
|
||||
refreshMapElements();
|
||||
}
|
||||
|
||||
// 4. ضبط الكاميرا لتشمل السائق والراكب
|
||||
_fitCameraToPoints(driverPos, passengerPos);
|
||||
|
||||
update(); // تحديث واحد للكل
|
||||
// إضافة الخط الجديد (بستايل مميز للسائق)
|
||||
polyLines.add(LineOptions(
|
||||
geometry: decodedPoints,
|
||||
lineColor: '#333333', // لون مختلف عن مسار الرحلة الأساسي
|
||||
lineWidth: 5,
|
||||
lineOpacity: 0.999, // acting as ID
|
||||
));
|
||||
refreshMapElements();
|
||||
}
|
||||
|
||||
// 4. ضبط الكاميرا لتشمل السائق والراكب
|
||||
_fitCameraToPoints(driverPos, passengerPos);
|
||||
|
||||
update(); // تحديث واحد للكل
|
||||
}
|
||||
} catch (e) {
|
||||
Log.print('❌ Error calculating driver route: $e');
|
||||
@@ -6478,30 +6481,29 @@ Intaleq Team''';
|
||||
double lngDest = double.parse(coordDestination[1]);
|
||||
myDestination = LatLng(latDest, lngDest);
|
||||
|
||||
// ── 2. Routing Decision: Hybrid Strategy ───────────────────────────
|
||||
final bool isSaaSRequest = activeMenuWaypointCount == 0;
|
||||
// ── 2. Unified SaaS Routing Strategy ──────────────────────────
|
||||
final bool isSaaSRequest = true;
|
||||
Uri uri;
|
||||
|
||||
if (isSaaSRequest) {
|
||||
// Mapping SaaS format: Query Parameters
|
||||
var originCoords = origin.split(',');
|
||||
final Map<String, String> queryParams = {
|
||||
'fromLat': originCoords[0].trim(),
|
||||
'fromLng': originCoords[1].trim(),
|
||||
'toLat': latDest.toString(),
|
||||
'toLng': lngDest.toString(),
|
||||
};
|
||||
uri =
|
||||
Uri.parse(AppLink.mapSaasRoute).replace(queryParameters: queryParams);
|
||||
} else {
|
||||
// Legacy OSRM format for multi-waypoint support
|
||||
var originCoords = origin.split(',');
|
||||
String waypointCoords = _buildOsrmWaypointCoords();
|
||||
String osrmUrl =
|
||||
'${AppLink.routesOsm}/route/v1/driving/${originCoords[1]},${originCoords[0]}$waypointCoords;$lngDest,$latDest';
|
||||
uri = Uri.parse('$osrmUrl?steps=false&overview=full');
|
||||
var originCoords = origin.split(',');
|
||||
final Map<String, String> queryParams = {
|
||||
'fromLat': originCoords[0].trim(),
|
||||
'fromLng': originCoords[1].trim(),
|
||||
'toLat': latDest.toString(),
|
||||
'toLng': lngDest.toString(),
|
||||
};
|
||||
|
||||
// Add multi-stop waypoints to the query parameters
|
||||
for (int i = 0; i < activeMenuWaypointCount; i++) {
|
||||
final wp = menuWaypoints[i];
|
||||
if (wp != null) {
|
||||
queryParams['stop${i + 1}Lat'] = wp.latitude.toString();
|
||||
queryParams['stop${i + 1}Lng'] = wp.longitude.toString();
|
||||
}
|
||||
}
|
||||
|
||||
uri = Uri.parse(AppLink.mapSaasRoute).replace(queryParameters: queryParams);
|
||||
|
||||
Log.print(
|
||||
'Requesting Route URI (${isSaaSRequest ? "SaaS" : "OSRM"}, Attempt: ${attemptCount + 1}): $uri');
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import 'package:Intaleq/controller/functions/crud.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_contacts/flutter_contacts.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
import 'package:share_plus/share_plus.dart';
|
||||
|
||||
import '../../../main.dart';
|
||||
@@ -107,7 +108,37 @@ ${'Download the Intaleq app now and enjoy your ride!'.tr}
|
||||
/// tried to access the first phone number of a contact that had none.
|
||||
Future<void> pickContacts() async {
|
||||
try {
|
||||
if (await FlutterContacts.requestPermission(readonly: true)) {
|
||||
// 1. Check current permission status using permission_handler for better control
|
||||
PermissionStatus status = await Permission.contacts.status;
|
||||
|
||||
// 2. If status is permanently denied, direct user to settings
|
||||
if (status.isPermanentlyDenied) {
|
||||
Get.defaultDialog(
|
||||
title: 'Permission Required'.tr,
|
||||
middleText:
|
||||
'Contact permission is permanently denied. Please enable it in settings to continue.'
|
||||
.tr,
|
||||
textConfirm: 'Settings'.tr,
|
||||
textCancel: 'Cancel'.tr,
|
||||
confirmTextColor: Colors.white,
|
||||
onConfirm: () {
|
||||
openAppSettings();
|
||||
Get.back();
|
||||
},
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. Request permission if not already granted
|
||||
if (!status.isGranted) {
|
||||
status = await Permission.contacts.request();
|
||||
}
|
||||
|
||||
// 4. Proceed if granted
|
||||
if (status.isGranted) {
|
||||
// Also call flutter_contacts requestPermission to ensure it's synced (internal state)
|
||||
await FlutterContacts.requestPermission(readonly: true);
|
||||
|
||||
final List<Contact> allContacts =
|
||||
await FlutterContacts.getContacts(withProperties: true);
|
||||
final int totalContactsOnDevice = allContacts.length;
|
||||
|
||||
@@ -4,6 +4,18 @@ class MyTranslation extends Translations {
|
||||
@override
|
||||
Map<String, Map<String, String>> get keys => {
|
||||
"ar": {
|
||||
"About Intaleq": "حول انطلق",
|
||||
"Chat with us anytime": "دردش معنا في أي وقت",
|
||||
"Direct talk with our team": "تحدث مباشرة مع فريقنا",
|
||||
"Email Support": "الدعم عبر البريد الإلكتروني",
|
||||
"For official inquiries": "للاستفسارات الرسمية",
|
||||
"Intaleq Support": "دعم انطلق",
|
||||
"Reach out to us via": "تواصل معنا عبر",
|
||||
"Support is Away": "الدعم غير متاح حالياً",
|
||||
"Support is currently Online": "الدعم متاح حالياً",
|
||||
"Voice Call": "اتصال صوتي",
|
||||
"We're here to help you 24/7": "نحن هنا لمساعدتكم على مدار الساعة",
|
||||
"Working Hours:": "ساعات العمل:",
|
||||
"1 Passenger": "راكب واحد",
|
||||
"2 Passengers": "راكبين",
|
||||
"3 Passengers": "٣ ركاب",
|
||||
@@ -7263,6 +7275,18 @@ class MyTranslation extends Translations {
|
||||
"Change Country": "تبديل الدولة",
|
||||
},
|
||||
"tr": {
|
||||
"About Intaleq": "Intaleq Hakkında",
|
||||
"Chat with us anytime": "İstediğiniz zaman bizimle sohbet edin",
|
||||
"Direct talk with our team": "Ekibimizle doğrudan görüşün",
|
||||
"Email Support": "E-posta Desteği",
|
||||
"For official inquiries": "Resmi sorular için",
|
||||
"Intaleq Support": "Intaleq Destek",
|
||||
"Reach out to us via": "Bize şuradan ulaşın",
|
||||
"Support is Away": "Destek şu an uzakta",
|
||||
"Support is currently Online": "Destek şu an çevrimiçi",
|
||||
"Voice Call": "Sesli Arama",
|
||||
"We're here to help you 24/7": "7/24 size yardımcı olmaya hazırız",
|
||||
"Working Hours:": "Çalışma Saatleri:",
|
||||
"1 Passenger": "1 Passenger",
|
||||
"2 Passengers": "2 Passengers",
|
||||
"3 Passengers": "3 Passengers",
|
||||
@@ -13840,6 +13864,18 @@ class MyTranslation extends Translations {
|
||||
"Change Country": "Cambiar país",
|
||||
},
|
||||
"fa": {
|
||||
"About Intaleq": "درباره انطلق",
|
||||
"Chat with us anytime": "هر زمان با ما چت کنید",
|
||||
"Direct talk with our team": "صحبت مستقیم با تیم ما",
|
||||
"Email Support": "پشتیبانی ایمیلی",
|
||||
"For official inquiries": "برای استعلامهای رسمی",
|
||||
"Intaleq Support": "پشتیبانی انطلق",
|
||||
"Reach out to us via": "با ما در تماس باشید از طریق",
|
||||
"Support is Away": "پشتیبانی در حال حاضر در دسترس نیست",
|
||||
"Support is currently Online": "پشتیبانی در حال حاضر آنلاین است",
|
||||
"Voice Call": "تماس صوتی",
|
||||
"We're here to help you 24/7": "ما ۷/۲۴ برای کمک به شما آمادهایم",
|
||||
"Working Hours:": "ساعات کاری:",
|
||||
"1 Passenger": "1 Passenger",
|
||||
"2 Passengers": "2 Passengers",
|
||||
"3 Passengers": "3 Passengers",
|
||||
@@ -16826,6 +16862,18 @@ class MyTranslation extends Translations {
|
||||
"Change Country": "Αλλαγή Χώρας",
|
||||
},
|
||||
"ur": {
|
||||
"About Intaleq": "انطلق کے بارے میں",
|
||||
"Chat with us anytime": "کسی भी समय हमसे चैट करें",
|
||||
"Direct talk with our team": "ہماری ٹیم سے براہ راست بات کریں",
|
||||
"Email Support": "ای میل سپورٹ",
|
||||
"For official inquiries": "سرکاری استفسارات کے لیے",
|
||||
"Intaleq Support": "انطلق سپورٹ",
|
||||
"Reach out to us via": "ہم سے رابطہ کریں بذریعہ",
|
||||
"Support is Away": "سپورٹ اب دستیاب نہیں ہے",
|
||||
"Support is currently Online": "سپورٹ اب آن لائن ہے",
|
||||
"Voice Call": "صوتی کال",
|
||||
"We're here to help you 24/7": "ہم چوبیس گھنٹے آپ کی مدد کے لیے حاضر ہیں",
|
||||
"Working Hours:": "کام کے اوقات:",
|
||||
"1 Passenger": "1 Passenger",
|
||||
"2 Passengers": "2 Passengers",
|
||||
"3 Passengers": "3 Passengers",
|
||||
@@ -18375,6 +18423,18 @@ class MyTranslation extends Translations {
|
||||
"Change Country": "ملک تبدیل کریں",
|
||||
},
|
||||
"hi": {
|
||||
"About Intaleq": "Intaleq के बारे में",
|
||||
"Chat with us anytime": "हमसे कभी भी चैट करें",
|
||||
"Direct talk with our team": "हमारी टीम से सीधे बात करें",
|
||||
"Email Support": "ईमेल सहायता",
|
||||
"For official inquiries": "आधिकारिक पूछताछ के लिए",
|
||||
"Intaleq Support": "Intaleq सहायता",
|
||||
"Reach out to us via": "हमसे संपर्क करें",
|
||||
"Support is Away": "सहायता अभी उपलब्ध नहीं है",
|
||||
"Support is currently Online": "सहायता अभी ऑनलाइन है",
|
||||
"Voice Call": "वॉइस कॉल",
|
||||
"We're here to help you 24/7": "हम आपकी सहायता के लिए 24/7 उपलब्ध हैं",
|
||||
"Working Hours:": "कार्य समय:",
|
||||
"1 Passenger": "1 Passenger",
|
||||
"2 Passengers": "2 Passengers",
|
||||
"3 Passengers": "3 Passengers",
|
||||
@@ -19923,6 +19983,18 @@ class MyTranslation extends Translations {
|
||||
"Change Country": "देश बदलें",
|
||||
},
|
||||
"ru": {
|
||||
"About Intaleq": "Об Intaleq",
|
||||
"Chat with us anytime": "Пишите нам в любое время",
|
||||
"Direct talk with our team": "Прямой разговор с нашей командой",
|
||||
"Email Support": "Поддержка по электронной почте",
|
||||
"For official inquiries": "Для официальных запросов",
|
||||
"Intaleq Support": "Поддержка Intaleq",
|
||||
"Reach out to us via": "Свяжитесь с нами через",
|
||||
"Support is Away": "Поддержка сейчас недоступна",
|
||||
"Support is currently Online": "Поддержка сейчас онлайн",
|
||||
"Voice Call": "Голосовой звонок",
|
||||
"We're here to help you 24/7": "Мы готовы помочь вам 24/7",
|
||||
"Working Hours:": "Рабочие часы:",
|
||||
"1 Passenger": "1 Passenger",
|
||||
"2 Passengers": "2 Passengers",
|
||||
"3 Passengers": "3 Passengers",
|
||||
@@ -21375,6 +21447,18 @@ class MyTranslation extends Translations {
|
||||
"Change Country": "Сменить страну",
|
||||
},
|
||||
"it": {
|
||||
"About Intaleq": "Informazioni su Intaleq",
|
||||
"Chat with us anytime": "Chatta con noi in qualsiasi momento",
|
||||
"Direct talk with our team": "Parla direttamente con il nostro team",
|
||||
"Email Support": "Supporto via email",
|
||||
"For official inquiries": "Per richieste ufficiali",
|
||||
"Intaleq Support": "Supporto Intaleq",
|
||||
"Reach out to us via": "Contattaci tramite",
|
||||
"Support is Away": "Il supporto è attualmente assente",
|
||||
"Support is currently Online": "Il supporto è attualmente online",
|
||||
"Voice Call": "Chiamata vocale",
|
||||
"We're here to help you 24/7": "Siamo qui per aiutarti 24/7",
|
||||
"Working Hours:": "Orario di lavoro:",
|
||||
"1 Passenger": "1 Passenger",
|
||||
"2 Passengers": "2 Passengers",
|
||||
"3 Passengers": "3 Passengers",
|
||||
|
||||
Reference in New Issue
Block a user