Food: single-source tracking, mode exclusivity, in-app navigation
This commit is contained in:
@@ -100,7 +100,9 @@ class FoodDeliveryHomePage extends StatelessWidget {
|
||||
Text(
|
||||
c.isDeliveryModeEnabled
|
||||
? (c.isSocketConnected
|
||||
? 'متصل — ستصلك عروض التوصيل فوراً'
|
||||
// صريح عمداً: الوضع استعداد لا حجز. أول مهمة تصل —
|
||||
// رحلة كانت أو توصيلاً — تجعله مشغولاً عن الأخرى.
|
||||
? 'متصل — ستصلك عروض التوصيل، وقد تصلك رحلة أيضاً'
|
||||
: 'إعادة الاتصال… العروض تصل بالتحديث الدوري')
|
||||
: 'فعّله لاستقبال عروض توصيل الطعام',
|
||||
style: AppStyle.subtitle,
|
||||
|
||||
@@ -7,6 +7,7 @@ import 'package:url_launcher/url_launcher.dart';
|
||||
import '../../constant/colors.dart';
|
||||
import '../../constant/style.dart';
|
||||
import '../../controller/food_delivery/food_delivery_controller.dart';
|
||||
import '../../controller/food_delivery/food_navigation.dart';
|
||||
import '../../controller/food_delivery/food_delivery_models.dart';
|
||||
import '../../controller/food_delivery/food_delivery_service.dart';
|
||||
import '../widgets/elevated_btn.dart';
|
||||
@@ -41,14 +42,13 @@ class _FoodTaskDetailsPageState extends State<FoodTaskDetailsPage> {
|
||||
if (!res.success) mySnackbarWarning(res.message);
|
||||
}
|
||||
|
||||
Future<void> _openMaps(double lat, double lng) async {
|
||||
// نفتح تطبيق الخرائط الافتراضي على الجهاز — لا نضمّن مفاتيح ولا نمرّر
|
||||
// بيانات الزبون في الرابط سوى الإحداثيات اللازمة للملاحة.
|
||||
final uri = Uri.parse('https://www.google.com/maps/dir/?api=1&destination=$lat,$lng');
|
||||
if (!await launchUrl(uri, mode: LaunchMode.externalApplication)) {
|
||||
mySnackbarWarning('تعذّر فتح تطبيق الخرائط');
|
||||
}
|
||||
}
|
||||
/// الملاحة الداخلية هي الافتراضي: تُبقي السائق داخل التطبيق فيظل موقعه
|
||||
/// مرصوداً ويستمر بثّه للزبون. جوجل يبقى خياراً ثانوياً بضغطة مطوّلة.
|
||||
Future<void> _navigate(double lat, double lng, String title) =>
|
||||
FoodNavigation.startInApp(lat: lat, lng: lng, title: title);
|
||||
|
||||
Future<void> _navigateExternal(double lat, double lng) =>
|
||||
FoodNavigation.startExternal(lat, lng);
|
||||
|
||||
Future<void> _call(String phone) async {
|
||||
final uri = Uri(scheme: 'tel', path: phone);
|
||||
@@ -89,7 +89,10 @@ class _FoodTaskDetailsPageState extends State<FoodTaskDetailsPage> {
|
||||
title: t.merchantNameAr,
|
||||
subtitle: t.merchantAddress ?? 'مطعم',
|
||||
onNavigate: (t.merchantLat != null && t.merchantLng != null)
|
||||
? () => _openMaps(t.merchantLat!, t.merchantLng!)
|
||||
? () => _navigate(t.merchantLat!, t.merchantLng!, t.merchantNameAr)
|
||||
: null,
|
||||
onNavigateExternal: (t.merchantLat != null && t.merchantLng != null)
|
||||
? () => _navigateExternal(t.merchantLat!, t.merchantLng!)
|
||||
: null,
|
||||
onCall: d.merchantPhone == null ? null : () => _call(d.merchantPhone!),
|
||||
),
|
||||
@@ -99,7 +102,12 @@ class _FoodTaskDetailsPageState extends State<FoodTaskDetailsPage> {
|
||||
color: AppColor.greenColor,
|
||||
title: 'عنوان الزبون',
|
||||
subtitle: t.deliveryAddress ?? 'غير متاح',
|
||||
onNavigate: t.deliveryLat == 0 ? null : () => _openMaps(t.deliveryLat, t.deliveryLng),
|
||||
onNavigate: t.deliveryLat == 0
|
||||
? null
|
||||
: () => _navigate(t.deliveryLat, t.deliveryLng, 'عنوان الزبون'),
|
||||
onNavigateExternal: t.deliveryLat == 0
|
||||
? null
|
||||
: () => _navigateExternal(t.deliveryLat, t.deliveryLng),
|
||||
// مكالمة مقنّعة: لا رقم هاتف للزبون يظهر أو يُخزَّن — اتصال صوتي
|
||||
// عبر جلسة مؤقتة، ومتاح فقط ما دامت المهمة نشطة.
|
||||
onCall: () => Get.find<FoodDeliveryController>().callCustomer(t.id),
|
||||
@@ -196,6 +204,7 @@ class _FoodTaskDetailsPageState extends State<FoodTaskDetailsPage> {
|
||||
required String title,
|
||||
required String subtitle,
|
||||
VoidCallback? onNavigate,
|
||||
VoidCallback? onNavigateExternal,
|
||||
VoidCallback? onCall,
|
||||
IconData callIcon = Icons.call_rounded,
|
||||
String callTooltip = 'اتصال',
|
||||
@@ -232,8 +241,10 @@ class _FoodTaskDetailsPageState extends State<FoodTaskDetailsPage> {
|
||||
if (onNavigate != null)
|
||||
IconButton(
|
||||
onPressed: onNavigate,
|
||||
// ضغطة مطوّلة = ملاحة جوجل، لمن اعتاد عليها
|
||||
onLongPress: onNavigateExternal,
|
||||
icon: Icon(Icons.navigation_rounded, color: AppColor.accentColor),
|
||||
tooltip: 'الملاحة',
|
||||
tooltip: 'ملاحة سيرو (اضغط مطوّلاً لجوجل)',
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user