Files
tripz-llc/apps/rider/lib/features/trip/data/trip_socket_service.dart
T

106 lines
3.0 KiB
Dart

import 'dart:async';
import 'package:socket_io_client/socket_io_client.dart' as io;
import '../../../core/config.dart';
import '../../../core/storage/token_store.dart';
import 'trip_event_merger.dart';
/// خدمة WebSocket — تتبع رحلة عبر Socket.IO.
///
/// الاتصال مُصادق عبر JWT (نفس توكن API).
/// الأحداث الواردة تُمرّ عبر TripEventMerger.
class TripSocketService {
final TokenStore _tokenStore;
final TripEventMerger _merger;
io.Socket? _socket;
bool _connected = false;
String? _currentTripId;
TripSocketService(this._tokenStore, this._merger);
/// الاتصال بالخادم.
Future<void> connect() async {
if (_connected) return;
final token = await _tokenStore.access();
if (token == null || token.isEmpty) return;
_socket = io.io(
AppConfig.baseUrl.replaceAll('/api', ''),
io.OptionBuilder()
.setTransports(['websocket'])
.enableAutoConnect()
.enableReconnection()
.setReconnectionDelay(2000)
.setReconnectionAttempts(10)
.setAuth({'token': token})
.build(),
);
_socket!.onConnect((_) {
_connected = true;
});
_socket!.onDisconnect((_) {
_connected = false;
});
_socket!.onReconnect((_) {
// عند إعادة الاتصال: أعد الانضمام لغرفة الرحلة.
if (_currentTripId != null) {
joinTrip(_currentTripId!);
}
});
// استقبال تحديثات الحالة.
_socket!.on('trip:update', (data) {
if (data is! Map) return;
final map = Map<String, dynamic>.from(data);
_merger.addUpdate(TripUpdate(
tripId: map['tripId'] as String? ?? '',
status: map['status'] as String? ?? '',
driverId: map['driverId'] as String?,
extra: map..remove('tripId')..remove('status')..remove('driverId'),
));
});
// استقبال موقع السائق الحي.
_socket!.on('driver:location', (data) {
if (data is! Map) return;
final map = Map<String, dynamic>.from(data);
_merger.addLocation(DriverLocationUpdate(
tripId: map['tripId'] as String? ?? '',
lat: (map['lat'] as num?)?.toDouble() ?? 0,
lng: (map['lng'] as num?)?.toDouble() ?? 0,
heading: (map['heading'] as num?)?.toDouble() ?? 0,
speed: (map['speed'] as num?)?.toDouble() ?? 0,
));
});
_socket!.connect();
}
/// الانضمام لغرفة الرحلة.
void joinTrip(String tripId) {
_currentTripId = tripId;
_socket?.emit('trip:join', {'tripId': tripId});
}
/// مغادرة غرفة الرحلة.
void leaveTrip(String tripId) {
_currentTripId = null;
// Socket.IO لا يدعم مغادرة الغرفة بشكل صريح،
// لكن عند رحلة جديدة سننضم للغرفة الجديدة.
}
/// قطع الاتصال.
void disconnect() {
_socket?.disconnect();
_socket?.dispose();
_socket = null;
_connected = false;
}
bool get isConnected => _connected;
}