import 'dart:async'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../../../core/api/api_exception.dart'; import '../../../core/ui/view_status.dart'; import '../data/chat_repository.dart'; class ChatState { const ChatState({ this.status = ViewStatus.idle, this.messages = const [], this.sending = false, this.error, }); final ViewStatus status; final List messages; final bool sending; final String? error; } class ChatCubit extends Cubit { ChatCubit(this._repo) : super(const ChatState()); final ChatRepository _repo; Timer? _poll; String? _tripId; @override Future close() { _poll?.cancel(); return super.close(); } /// استطلاع كل خمس ثوانٍ — الخادم لا يبثّ الرسائل عبر السوكت /// (راجع `ChatRepository`). يتوقّف مع إغلاق الشاشة. Future open(String tripId) async { _tripId = tripId; emit(const ChatState(status: ViewStatus.loading)); await _refresh(); _poll = Timer.periodic(const Duration(seconds: 5), (_) => _refresh()); } Future _refresh() async { final tripId = _tripId; if (tripId == null || isClosed) return; try { final messages = await _repo.messages(tripId); if (isClosed) return; emit(ChatState( status: ViewStatus.success, messages: messages, sending: state.sending, )); } on ApiException catch (e) { // فشل الاستطلاع لا يمسح ما وصل: الرسائل المعروضة تبقى. if (!isClosed && state.messages.isEmpty) { emit(ChatState(status: ViewStatus.error, error: e.message)); } } } Future send(String body) async { final tripId = _tripId; if (tripId == null || body.trim().isEmpty) return; emit(ChatState( status: state.status, messages: state.messages, sending: true, )); try { await _repo.send(tripId, body.trim()); await _refresh(); } on ApiException { if (!isClosed) { emit(ChatState(status: state.status, messages: state.messages)); } } } }