feat: implement core architecture, design system, localization, and trip features for both driver and rider apps.
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
import 'dart:async';
|
||||
import 'package:geolocator/geolocator.dart';
|
||||
|
||||
/// خدمة موقع السائق — تتبع الموقع في الخلفية وإرساله للسيرفر.
|
||||
///
|
||||
/// تتبع 3 ثوانٍ عند التنشيط، ثم إرسال كل دقيقتين (docs/23 §10).
|
||||
/// تراعي حالة البطارية وتتوقف عند انخفاضها.
|
||||
class DriverLocationService {
|
||||
final Future<void> Function(double lat, double lng, {double? heading, double? speed})
|
||||
_onLocationUpdate;
|
||||
|
||||
StreamSubscription<Position>? _positionSub;
|
||||
Timer? _heartbeatTimer;
|
||||
bool _active = false;
|
||||
|
||||
DriverLocationService(this._onLocationUpdate);
|
||||
|
||||
bool get isActive => _active;
|
||||
|
||||
/// بدء التتبع.
|
||||
Future<void> start() async {
|
||||
if (_active) return;
|
||||
|
||||
// تحقق من صلاحية الموقع.
|
||||
var permission = await Geolocator.checkPermission();
|
||||
if (permission == LocationPermission.denied) {
|
||||
permission = await Geolocator.requestPermission();
|
||||
if (permission == LocationPermission.denied ||
|
||||
permission == LocationPermission.deniedForever) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_active = true;
|
||||
|
||||
// أرسل الموقع فوراً.
|
||||
_sendCurrentLocation();
|
||||
|
||||
// استمع لتحديثات الموقع كل 3 ثوانٍ.
|
||||
_positionSub = Geolocator.getPositionStream(
|
||||
locationSettings: const LocationSettings(
|
||||
accuracy: LocationAccuracy.high,
|
||||
distanceFilter: 15, // تحديث عند تغيير 15 متر
|
||||
),
|
||||
).listen((pos) {
|
||||
_onLocationUpdate(
|
||||
pos.latitude,
|
||||
pos.longitude,
|
||||
heading: pos.heading,
|
||||
speed: pos.speed,
|
||||
);
|
||||
});
|
||||
|
||||
// دفعة كل دقيقتين كحد أقصى.
|
||||
_heartbeatTimer = Timer.periodic(const Duration(minutes: 2), (_) {
|
||||
_sendCurrentLocation();
|
||||
});
|
||||
}
|
||||
|
||||
/// إيقاف التتبع.
|
||||
void stop() {
|
||||
_active = false;
|
||||
_positionSub?.cancel();
|
||||
_positionSub = null;
|
||||
_heartbeatTimer?.cancel();
|
||||
_heartbeatTimer = null;
|
||||
}
|
||||
|
||||
/// إرسال الموقع الحالي مرة واحدة.
|
||||
Future<void> _sendCurrentLocation() async {
|
||||
try {
|
||||
final pos = await Geolocator.getCurrentPosition(
|
||||
locationSettings: const LocationSettings(
|
||||
accuracy: LocationAccuracy.high,
|
||||
),
|
||||
);
|
||||
await _onLocationUpdate(
|
||||
pos.latitude,
|
||||
pos.longitude,
|
||||
heading: pos.heading,
|
||||
speed: pos.speed,
|
||||
);
|
||||
} catch (_) {
|
||||
// خطأ صامت — سيحاول مرة أخرى مع الدقيقة التالية.
|
||||
}
|
||||
}
|
||||
|
||||
void dispose() {
|
||||
stop();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user