mirror of
https://github.com/dz0ny/meshcore-sar.git
synced 2026-08-11 16:30:28 +00:00
Throttle message notifications during sync
This commit is contained in:
@@ -2567,8 +2567,11 @@ class AppProvider with ChangeNotifier {
|
|||||||
debugPrint(
|
debugPrint(
|
||||||
'🔄 [AppProvider] Performing initial message sync (fallback for missed pushes)',
|
'🔄 [AppProvider] Performing initial message sync (fallback for missed pushes)',
|
||||||
);
|
);
|
||||||
final initialMessageCount = await connectionProvider.syncAllMessages(
|
final initialMessageCount =
|
||||||
|
await messagesProvider.withReceivedNotificationsSuppressed(
|
||||||
|
() => connectionProvider.syncAllMessages(
|
||||||
force: true,
|
force: true,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
debugPrint(
|
debugPrint(
|
||||||
'📥 [AppProvider] Initial sync retrieved $initialMessageCount message(s)',
|
'📥 [AppProvider] Initial sync retrieved $initialMessageCount message(s)',
|
||||||
@@ -2627,8 +2630,11 @@ class AppProvider with ChangeNotifier {
|
|||||||
);
|
);
|
||||||
await refreshChannelLocationSharingState();
|
await refreshChannelLocationSharingState();
|
||||||
|
|
||||||
final messageCount = await connectionProvider.syncAllMessages(
|
final messageCount =
|
||||||
|
await messagesProvider.withReceivedNotificationsSuppressed(
|
||||||
|
() => connectionProvider.syncAllMessages(
|
||||||
force: true,
|
force: true,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
debugPrint(
|
debugPrint(
|
||||||
'📥 [AppProvider] Reconnect sync retrieved $messageCount message(s)',
|
'📥 [AppProvider] Reconnect sync retrieved $messageCount message(s)',
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ class MessagesProvider with ChangeNotifier {
|
|||||||
bool _isInitialized = false;
|
bool _isInitialized = false;
|
||||||
bool _isPersisting = false;
|
bool _isPersisting = false;
|
||||||
bool _persistRequested = false;
|
bool _persistRequested = false;
|
||||||
|
bool _suppressReceivedNotifications = false;
|
||||||
AppLocalizations? _localizations;
|
AppLocalizations? _localizations;
|
||||||
final Map<String, MessageContactLocation> _messageContactLocations = {};
|
final Map<String, MessageContactLocation> _messageContactLocations = {};
|
||||||
final Map<String, MessageReceptionDetails> _messageReceptionDetails = {};
|
final Map<String, MessageReceptionDetails> _messageReceptionDetails = {};
|
||||||
@@ -850,11 +851,13 @@ class MessagesProvider with ChangeNotifier {
|
|||||||
_sarMarkers[marker.id] = marker;
|
_sarMarkers[marker.id] = marker;
|
||||||
|
|
||||||
// Trigger urgent notification for received SAR messages (not sent by user)
|
// Trigger urgent notification for received SAR messages (not sent by user)
|
||||||
if (!finalMessage.isSentMessage) {
|
if (!finalMessage.isSentMessage && !_suppressReceivedNotifications) {
|
||||||
_triggerSarNotification(finalMessage, marker);
|
_triggerSarNotification(finalMessage, marker);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (!finalMessage.isSentMessage && !finalMessage.isSystemMessage) {
|
} else if (!finalMessage.isSentMessage &&
|
||||||
|
!finalMessage.isSystemMessage &&
|
||||||
|
!_suppressReceivedNotifications) {
|
||||||
// Trigger notification for regular messages (not SAR, not sent by user, not system)
|
// Trigger notification for regular messages (not SAR, not sent by user, not system)
|
||||||
_triggerMessageNotification(finalMessage);
|
_triggerMessageNotification(finalMessage);
|
||||||
}
|
}
|
||||||
@@ -865,6 +868,18 @@ class MessagesProvider with ChangeNotifier {
|
|||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<T> withReceivedNotificationsSuppressed<T>(
|
||||||
|
Future<T> Function() action,
|
||||||
|
) async {
|
||||||
|
final previous = _suppressReceivedNotifications;
|
||||||
|
_suppressReceivedNotifications = true;
|
||||||
|
try {
|
||||||
|
return await action();
|
||||||
|
} finally {
|
||||||
|
_suppressReceivedNotifications = previous;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Check if a message is a duplicate
|
/// Check if a message is a duplicate
|
||||||
///
|
///
|
||||||
/// Messages are considered duplicates if they have:
|
/// Messages are considered duplicates if they have:
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
@@ -29,6 +31,13 @@ class NotificationService {
|
|||||||
bool _muteForegroundNotifications = true;
|
bool _muteForegroundNotifications = true;
|
||||||
AppLifecycleState _lifecycleState = AppLifecycleState.resumed;
|
AppLifecycleState _lifecycleState = AppLifecycleState.resumed;
|
||||||
String? _launchPayload;
|
String? _launchPayload;
|
||||||
|
Timer? _messageNotificationTimer;
|
||||||
|
int _pendingMessageNotificationCount = 0;
|
||||||
|
String? _pendingMessageSenderName;
|
||||||
|
String? _pendingMessageText;
|
||||||
|
bool _pendingMessageIsChannel = false;
|
||||||
|
String? _pendingMessageChannelName;
|
||||||
|
AppLocalizations? _pendingMessageLocalizations;
|
||||||
|
|
||||||
// Notification IDs
|
// Notification IDs
|
||||||
static const int _sarNotificationId = 1000;
|
static const int _sarNotificationId = 1000;
|
||||||
@@ -36,6 +45,8 @@ class NotificationService {
|
|||||||
static const int _updateNotificationId = 3000;
|
static const int _updateNotificationId = 3000;
|
||||||
static const int _batteryNotificationId = 4000;
|
static const int _batteryNotificationId = 4000;
|
||||||
static const int _discoveryNotificationId = 5000;
|
static const int _discoveryNotificationId = 5000;
|
||||||
|
static const Duration _messageNotificationCoalesceWindow =
|
||||||
|
Duration(seconds: 2);
|
||||||
|
|
||||||
// Notification channels
|
// Notification channels
|
||||||
static const String _urgentChannelId = 'sar_urgent';
|
static const String _urgentChannelId = 'sar_urgent';
|
||||||
@@ -533,17 +544,53 @@ class NotificationService {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
_pendingMessageNotificationCount++;
|
||||||
// Generate unique notification ID based on timestamp
|
_pendingMessageSenderName = senderName;
|
||||||
final notificationId =
|
_pendingMessageText = messageText;
|
||||||
_messageNotificationId +
|
_pendingMessageIsChannel = isChannelMessage;
|
||||||
(DateTime.now().millisecondsSinceEpoch % 1000);
|
_pendingMessageChannelName = channelName;
|
||||||
|
_pendingMessageLocalizations = localizations;
|
||||||
|
|
||||||
|
_messageNotificationTimer?.cancel();
|
||||||
|
_messageNotificationTimer = Timer(_messageNotificationCoalesceWindow, () {
|
||||||
|
unawaited(_flushMessageNotification());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _flushMessageNotification() async {
|
||||||
|
final count = _pendingMessageNotificationCount;
|
||||||
|
final senderName = _pendingMessageSenderName;
|
||||||
|
final messageText = _pendingMessageText;
|
||||||
|
final isChannelMessage = _pendingMessageIsChannel;
|
||||||
|
final channelName = _pendingMessageChannelName;
|
||||||
|
final localizations = _pendingMessageLocalizations;
|
||||||
|
|
||||||
|
_pendingMessageNotificationCount = 0;
|
||||||
|
_pendingMessageSenderName = null;
|
||||||
|
_pendingMessageText = null;
|
||||||
|
_pendingMessageIsChannel = false;
|
||||||
|
_pendingMessageChannelName = null;
|
||||||
|
_pendingMessageLocalizations = null;
|
||||||
|
|
||||||
|
if (count == 0 || senderName == null || messageText == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_isInitialized ||
|
||||||
|
!_permissionGranted ||
|
||||||
|
!_messageNotificationsEnabled ||
|
||||||
|
_shouldSuppressForegroundNotifications()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
// Build notification title and body
|
// Build notification title and body
|
||||||
final resolvedChannelName = channelName?.trim().isNotEmpty == true
|
final resolvedChannelName = channelName?.trim().isNotEmpty == true
|
||||||
? channelName!.trim()
|
? channelName!.trim()
|
||||||
: (localizations?.publicChannel ?? 'Public');
|
: (localizations?.publicChannel ?? 'Public');
|
||||||
final title = isChannelMessage
|
final title = count > 1
|
||||||
|
? (localizations?.messages ?? 'Messages')
|
||||||
|
: isChannelMessage
|
||||||
? (localizations != null
|
? (localizations != null
|
||||||
? '${localizations.channel}: $resolvedChannelName'
|
? '${localizations.channel}: $resolvedChannelName'
|
||||||
: 'Channel: $resolvedChannelName')
|
: 'Channel: $resolvedChannelName')
|
||||||
@@ -551,7 +598,9 @@ class NotificationService {
|
|||||||
? '${localizations.newMessage} ${localizations.from} $senderName'
|
? '${localizations.newMessage} ${localizations.from} $senderName'
|
||||||
: 'New message from $senderName');
|
: 'New message from $senderName');
|
||||||
|
|
||||||
final body = messageText.length > 200
|
final body = count > 1
|
||||||
|
? 'You have $count new messages'
|
||||||
|
: messageText.length > 200
|
||||||
? '${messageText.substring(0, 200)}...'
|
? '${messageText.substring(0, 200)}...'
|
||||||
: messageText;
|
: messageText;
|
||||||
|
|
||||||
@@ -570,7 +619,7 @@ class NotificationService {
|
|||||||
styleInformation: BigTextStyleInformation(
|
styleInformation: BigTextStyleInformation(
|
||||||
body,
|
body,
|
||||||
contentTitle: title,
|
contentTitle: title,
|
||||||
summaryText: senderName,
|
summaryText: count > 1 ? body : senderName,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -594,7 +643,7 @@ class NotificationService {
|
|||||||
|
|
||||||
// Show notification
|
// Show notification
|
||||||
await _notificationsPlugin.show(
|
await _notificationsPlugin.show(
|
||||||
id: notificationId,
|
id: _messageNotificationId,
|
||||||
title: title,
|
title: title,
|
||||||
body: body,
|
body: body,
|
||||||
notificationDetails: notificationDetails,
|
notificationDetails: notificationDetails,
|
||||||
@@ -602,6 +651,7 @@ class NotificationService {
|
|||||||
);
|
);
|
||||||
|
|
||||||
debugPrint('✅ [NotificationService] Showed message notification');
|
debugPrint('✅ [NotificationService] Showed message notification');
|
||||||
|
debugPrint(' Count: $count');
|
||||||
debugPrint(' Sender: $senderName');
|
debugPrint(' Sender: $senderName');
|
||||||
debugPrint(' Type: ${isChannelMessage ? "Channel" : "Direct"}');
|
debugPrint(' Type: ${isChannelMessage ? "Channel" : "Direct"}');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
Reference in New Issue
Block a user