2026-04-15

This commit is contained in:
mageshwaran committed 2026-04-15 12:32:30 +05:30
1 parent d01e5ba860
commit 96de59e9be
46 files changed
+1299 -1191

No files matched your search

+52 -24
View File
@@ -185,10 +185,14 @@ class ServiceHistoryNotifier
fetchServiceHistory();
}
Future<void> fetchServiceHistory() async {
Future<void> fetchServiceHistory({bool isSilent = false}) async {
try {
if (!mounted) return;
state = const AsyncValue.loading();
// 🔄 Skip loading state for silent refresh
if (!isSilent) {
state = const AsyncValue.loading();
}
final repo = ref.read(apiRepositoryProvider);
@@ -238,8 +242,6 @@ final notificationTriggerProvider = StateProvider<int>((ref) => 0);
// 🔥 fetch notification count API
final notificationCountProvider =
FutureProvider.autoDispose<NotificationCountModel>((ref) async {
ref.watch(notificationTriggerProvider); // listen for refresh trigger
final repo = ref.read(apiRepositoryProvider);
return await repo.fetchNotificationCount();
});
@@ -409,34 +411,55 @@ class ChatMessagesNotifier
return dateA.compareTo(dateB);
});
// ⭐ Check if we have any new messages
final lastMessageId = _messages.isNotEmpty ? _messages.last.id : -1;
final latestMessageId = result.last.id;
// ⭐ Merge strategy:
// 1. Update existing messages (read/delivered status)
// 2. Add new messages
bool hasChanges = false;
if (latestMessageId != lastMessageId) {
// ⭐ New messages found - merge them smoothly
print("✅ Found new messages, updating list");
for (var incomingMsg in result) {
final existingIndex = _messages.indexWhere((m) => m.id == incomingMsg.id);
if (existingIndex != -1) {
// Check if status changed
final existingMsg = _messages[existingIndex];
if (existingMsg.isRead != incomingMsg.isRead ||
existingMsg.isDelivered != incomingMsg.isDelivered) {
print("♻️ Updating status for message ID ${incomingMsg.id}");
_messages[existingIndex] = incomingMsg;
hasChanges = true;
}
} else {
// ⭐ NEW: Check if this server message replaces an optimistic one
final optimisticIndex = _messages.indexWhere(
(m) => (m.id > 1000000000000 &&
m.message == incomingMsg.message &&
m.chatBy == incomingMsg.chatBy)
);
// Add only new messages that don't exist in current list
for (var newMsg in result) {
final exists = _messages.any((m) => m.id == newMsg.id);
if (!exists) {
_messages.add(newMsg);
if (optimisticIndex != -1) {
print("🔄 refresh: Replacing optimistic message with ID ${incomingMsg.id}");
_messages[optimisticIndex] = incomingMsg;
hasChanges = true;
} else {
// Truly new message (e.g. incoming from someone else)
print("➕ Adding new message ID ${incomingMsg.id}");
_messages.add(incomingMsg);
hasChanges = true;
}
}
}
// Sort the entire list
if (hasChanges) {
// Sort the entire list to be sure
_messages.sort((a, b) {
final dateA =
DateTime.tryParse(a.createdAt ?? '') ?? DateTime(1970);
final dateB =
DateTime.tryParse(b.createdAt ?? '') ?? DateTime(1970);
final dateA = DateTime.tryParse(a.createdAt ?? '') ?? DateTime(1970);
final dateB = DateTime.tryParse(b.createdAt ?? '') ?? DateTime(1970);
return dateA.compareTo(dateB);
});
if (mounted) state = AsyncData(List.from(_messages));
} else {
print("✅ No new messages");
print("✅ No new messages or status changes");
}
}
} catch (e) {
@@ -472,10 +495,8 @@ class ChatMessagesNotifier
// 2. Check if this is a server confirmation of an optimistic message
// Optimistic messages have large positive IDs from DateTime.now().millisecondsSinceEpoch
// OR content match for very recent messages
final optimisticIndex = _messages.indexWhere(
(m) =>
// Match by content and sender if it's a very recent "local" message
(m.id > 1000000000000 &&
m.message == msg.message &&
m.chatBy == msg.chatBy),
@@ -489,6 +510,13 @@ class ChatMessagesNotifier
_messages.add(msg);
}
// Sort to ensure order (important if multiple local messages are sent)
_messages.sort((a, b) {
final dateA = DateTime.tryParse(a.createdAt ?? '') ?? DateTime(1970);
final dateB = DateTime.tryParse(b.createdAt ?? '') ?? DateTime(1970);
return dateA.compareTo(dateB);
});
if (mounted) state = AsyncData(List.from(_messages));
}
+25 -24
View File
@@ -458,7 +458,7 @@ class ApiRepository {
headers: await _authorizedHeaders(),
);
});
debugPrint("response: ${response.body}");
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
return DetailModel.fromJson(data);
@@ -635,17 +635,17 @@ class ApiRepository {
File? panFile,
File? gstFile,
File? incorporationFile,
required int countryId,
required int stateId,
required int cityId,
required String companyPincode,
required String companyAddress,
required String panNumber,
required String gstNumber,
required String tanNumber,
required String cinNumber,
required String yearOfIncorporation,
required String address,
int? countryId,
int? stateId,
int? cityId,
String? companyPincode,
String? companyAddress,
String? panNumber,
String? gstNumber,
String? tanNumber,
String? cinNumber,
String? yearOfIncorporation,
String? address,
}) async {
try {
final token = await _localStore.getToken();
@@ -658,17 +658,17 @@ class ApiRepository {
'Connection': 'keep-alive',
})
..fields.addAll({
'country_id': countryId.toString(),
'state_id': stateId.toString(),
'district_id': cityId.toString(),
'company_pincode': companyPincode,
'company_address': companyAddress,
'pan_number': panNumber,
'gst_number': gstNumber,
'tan_number': tanNumber,
'cin': cinNumber,
'year_of_incorporation': yearOfIncorporation,
'address': address,
if (countryId != null) 'country_id': countryId.toString(),
if (stateId != null) 'state_id': stateId.toString(),
if (cityId != null) 'district_id': cityId.toString(),
if (companyPincode != null) 'company_pincode': companyPincode,
if (companyAddress != null) 'company_address': companyAddress,
if (panNumber != null) 'pan_number': panNumber,
if (gstNumber != null) 'gst_number': gstNumber,
if (tanNumber != null) 'tan_number': tanNumber,
if (cinNumber != null) 'cin': cinNumber,
if (yearOfIncorporation != null) 'year_of_incorporation': yearOfIncorporation,
if (address != null) 'address': address,
});
await Future.wait([
@@ -686,7 +686,8 @@ class ApiRepository {
);
final response = await http.Response.fromStream(streamedResponse);
debugPrint('📦 KYC Response Status: ${response.statusCode}');
debugPrint('📦 KYC Response Body: ${response.body}');
// Handle token expiry
if (response.statusCode == 401 || response.statusCode == 403) {
await _handleUnauthorized();