feat: implement core architecture, design system, localization, and trip features for both driver and rider apps.
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user