119 lines
3.2 KiB
Dart
119 lines
3.2 KiB
Dart
import 'dart:async';
|
|
import 'package:equatable/equatable.dart';
|
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
import '../data/driver_repository.dart';
|
|
import '../data/driver_location_service.dart';
|
|
import '../data/models/driver_profile_model.dart';
|
|
|
|
/// حالة DriverCubit.
|
|
class DriverState extends Equatable {
|
|
final DriverProfileModel? profile;
|
|
final bool loading;
|
|
final bool online;
|
|
final String? error;
|
|
|
|
const DriverState({
|
|
this.profile,
|
|
this.loading = true,
|
|
this.online = false,
|
|
this.error,
|
|
});
|
|
|
|
DriverState copyWith({
|
|
DriverProfileModel? profile,
|
|
bool? loading,
|
|
bool? online,
|
|
String? error,
|
|
bool clearError = false,
|
|
}) {
|
|
return DriverState(
|
|
profile: profile ?? this.profile,
|
|
loading: loading ?? this.loading,
|
|
online: online ?? this.online,
|
|
error: clearError ? null : (error ?? this.error),
|
|
);
|
|
}
|
|
|
|
@override
|
|
List<Object?> get props => [profile, loading, online, error];
|
|
}
|
|
|
|
/// Cubit مُتّصل/مُنقطع — يدير ملف السائق وتبديل الحالة وموقع الخلفية.
|
|
///
|
|
/// يُقدّم:
|
|
/// - جلب الملف عند بدء التشغيل
|
|
/// - تبديل الحالة (online/offline)
|
|
/// - بدء/إيقاف تتبع الموقع عند التنشيط
|
|
class DriverCubit extends Cubit<DriverState> {
|
|
final DriverRepository _repo;
|
|
DriverLocationService? _locationService;
|
|
Timer? _heartbeatTimer;
|
|
|
|
DriverCubit(this._repo) : super(const DriverState(loading: true));
|
|
|
|
/// جلب ملف السائق وتحديد الحالة الأولية.
|
|
Future<void> loadProfile() async {
|
|
try {
|
|
final profile = await _repo.getProfile();
|
|
if (profile != null) {
|
|
emit(state.copyWith(
|
|
profile: profile,
|
|
online: profile.online,
|
|
loading: false,
|
|
));
|
|
// إذا كان مُتصلاً مسبقاً، أعد بدء التتبع.
|
|
if (profile.online) {
|
|
_startLocationTracking();
|
|
}
|
|
} else {
|
|
emit(state.copyWith(loading: false));
|
|
}
|
|
} catch (e) {
|
|
emit(state.copyWith(loading: false, error: e.toString()));
|
|
}
|
|
}
|
|
|
|
/// تبديل الحالة (مُتصل/مُنقطع).
|
|
Future<void> toggleOnline() async {
|
|
final newOnline = !state.online;
|
|
emit(state.copyWith(online: newOnline));
|
|
|
|
final result = await _repo.setOnline(newOnline);
|
|
if (!result) {
|
|
// فشل — أعد الحالة السابقة.
|
|
emit(state.copyWith(online: !newOnline));
|
|
return;
|
|
}
|
|
|
|
if (newOnline) {
|
|
_startLocationTracking();
|
|
} else {
|
|
_stopLocationTracking();
|
|
}
|
|
}
|
|
|
|
/// بدء تتبع الموقع.
|
|
void _startLocationTracking() {
|
|
if (_locationService?.isActive == true) return;
|
|
|
|
_locationService = DriverLocationService((lat, lng, {heading, speed}) async {
|
|
await _repo.sendLocation(lat: lat, lng: lng, heading: heading, speed: speed);
|
|
});
|
|
_locationService!.start();
|
|
}
|
|
|
|
/// إيقاف تتبع الموقع.
|
|
void _stopLocationTracking() {
|
|
_locationService?.stop();
|
|
_locationService = null;
|
|
_heartbeatTimer?.cancel();
|
|
_heartbeatTimer = null;
|
|
}
|
|
|
|
@override
|
|
Future<void> close() {
|
|
_stopLocationTracking();
|
|
return super.close();
|
|
}
|
|
}
|