mirror of
https://github.com/zjs81/meshcore-open.git
synced 2026-04-20 22:13:48 +00:00
this removes the 'Received new message: ' prefix from notications when there is a message preview available
242 lines
6.4 KiB
Dart
242 lines
6.4 KiB
Dart
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
|
import 'package:flutter/foundation.dart';
|
|
|
|
class NotificationService {
|
|
static final NotificationService _instance = NotificationService._internal();
|
|
factory NotificationService() => _instance;
|
|
NotificationService._internal();
|
|
|
|
final FlutterLocalNotificationsPlugin _notifications = FlutterLocalNotificationsPlugin();
|
|
bool _isInitialized = false;
|
|
|
|
Future<void> initialize() async {
|
|
if (_isInitialized) return;
|
|
|
|
const androidSettings = AndroidInitializationSettings('@mipmap/ic_launcher');
|
|
const iosSettings = DarwinInitializationSettings(
|
|
requestAlertPermission: true,
|
|
requestBadgePermission: true,
|
|
requestSoundPermission: true,
|
|
);
|
|
const macSettings = DarwinInitializationSettings(
|
|
requestAlertPermission: true,
|
|
requestBadgePermission: true,
|
|
requestSoundPermission: true,
|
|
);
|
|
|
|
const initSettings = InitializationSettings(
|
|
android: androidSettings,
|
|
iOS: iosSettings,
|
|
macOS: macSettings,
|
|
);
|
|
|
|
try {
|
|
await _notifications.initialize(
|
|
initSettings,
|
|
onDidReceiveNotificationResponse: _onNotificationTapped,
|
|
);
|
|
_isInitialized = true;
|
|
} catch (e) {
|
|
debugPrint('Error initializing notifications: $e');
|
|
}
|
|
}
|
|
|
|
Future<bool> requestPermissions() async {
|
|
if (!_isInitialized) {
|
|
await initialize();
|
|
}
|
|
|
|
// Request Android 13+ notification permission
|
|
final androidPlugin = _notifications.resolvePlatformSpecificImplementation<
|
|
AndroidFlutterLocalNotificationsPlugin>();
|
|
if (androidPlugin != null) {
|
|
final granted = await androidPlugin.requestNotificationsPermission();
|
|
return granted ?? false;
|
|
}
|
|
|
|
// iOS permissions are requested during initialization
|
|
final iosPlugin = _notifications.resolvePlatformSpecificImplementation<
|
|
IOSFlutterLocalNotificationsPlugin>();
|
|
if (iosPlugin != null) {
|
|
final granted = await iosPlugin.requestPermissions(
|
|
alert: true,
|
|
badge: true,
|
|
sound: true,
|
|
);
|
|
return granted ?? false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
Future<void> showMessageNotification({
|
|
required String contactName,
|
|
required String message,
|
|
String? contactId,
|
|
int? badgeCount,
|
|
}) async {
|
|
if (!_isInitialized) {
|
|
await initialize();
|
|
}
|
|
|
|
final androidDetails = AndroidNotificationDetails(
|
|
'messages',
|
|
'Messages',
|
|
channelDescription: 'New message notifications',
|
|
importance: Importance.high,
|
|
priority: Priority.high,
|
|
icon: '@mipmap/ic_launcher',
|
|
number: badgeCount,
|
|
);
|
|
|
|
final iosDetails = DarwinNotificationDetails(
|
|
presentAlert: true,
|
|
presentBadge: true,
|
|
presentSound: true,
|
|
badgeNumber: badgeCount,
|
|
);
|
|
|
|
final macDetails = DarwinNotificationDetails(
|
|
presentAlert: true,
|
|
presentBadge: true,
|
|
presentSound: true,
|
|
badgeNumber: badgeCount,
|
|
);
|
|
|
|
final notificationDetails = NotificationDetails(
|
|
android: androidDetails,
|
|
iOS: iosDetails,
|
|
macOS: macDetails,
|
|
);
|
|
|
|
await _notifications.show(
|
|
contactId?.hashCode ?? 0,
|
|
'New message from $contactName',
|
|
message.length > 100 ? '${message.substring(0, 100)}...' : message,
|
|
notificationDetails,
|
|
payload: 'message:$contactId',
|
|
);
|
|
}
|
|
|
|
Future<void> showAdvertNotification({
|
|
required String contactName,
|
|
required String contactType,
|
|
String? contactId,
|
|
}) async {
|
|
if (!_isInitialized) {
|
|
await initialize();
|
|
}
|
|
|
|
const androidDetails = AndroidNotificationDetails(
|
|
'adverts',
|
|
'Advertisements',
|
|
channelDescription: 'New node advertisement notifications',
|
|
importance: Importance.defaultImportance,
|
|
priority: Priority.defaultPriority,
|
|
icon: '@mipmap/ic_launcher',
|
|
);
|
|
|
|
const iosDetails = DarwinNotificationDetails(
|
|
presentAlert: true,
|
|
presentBadge: true,
|
|
presentSound: true,
|
|
);
|
|
|
|
const macDetails = DarwinNotificationDetails(
|
|
presentAlert: true,
|
|
presentBadge: true,
|
|
presentSound: true,
|
|
);
|
|
|
|
const notificationDetails = NotificationDetails(
|
|
android: androidDetails,
|
|
iOS: iosDetails,
|
|
macOS: macDetails,
|
|
);
|
|
|
|
await _notifications.show(
|
|
contactId?.hashCode ?? DateTime.now().millisecondsSinceEpoch,
|
|
'New $contactType discovered',
|
|
contactName,
|
|
notificationDetails,
|
|
payload: 'advert:$contactId',
|
|
);
|
|
}
|
|
|
|
Future<void> showChannelMessageNotification({
|
|
required String channelName,
|
|
required String message,
|
|
int? channelIndex,
|
|
int? badgeCount,
|
|
}) async {
|
|
if (!_isInitialized) {
|
|
await initialize();
|
|
}
|
|
|
|
final androidDetails = AndroidNotificationDetails(
|
|
'channel_messages',
|
|
'Channel Messages',
|
|
channelDescription: 'New channel message notifications',
|
|
importance: Importance.high,
|
|
priority: Priority.high,
|
|
icon: '@mipmap/ic_launcher',
|
|
number: badgeCount,
|
|
);
|
|
|
|
final iosDetails = DarwinNotificationDetails(
|
|
presentAlert: true,
|
|
presentBadge: true,
|
|
presentSound: true,
|
|
badgeNumber: badgeCount,
|
|
);
|
|
|
|
final macDetails = DarwinNotificationDetails(
|
|
presentAlert: true,
|
|
presentBadge: true,
|
|
presentSound: true,
|
|
badgeNumber: badgeCount,
|
|
);
|
|
|
|
final notificationDetails = NotificationDetails(
|
|
android: androidDetails,
|
|
iOS: iosDetails,
|
|
macOS: macDetails,
|
|
);
|
|
|
|
final preview = _truncateMessage(message, 30);
|
|
final body = preview.isEmpty
|
|
? 'Received new message'
|
|
: preview;
|
|
|
|
await _notifications.show(
|
|
channelIndex?.hashCode ?? DateTime.now().millisecondsSinceEpoch,
|
|
channelName,
|
|
body,
|
|
notificationDetails,
|
|
payload: 'channel:$channelIndex',
|
|
);
|
|
}
|
|
|
|
String _truncateMessage(String message, int maxLength) {
|
|
final trimmed = message.trim();
|
|
if (trimmed.length <= maxLength) return trimmed;
|
|
return '${trimmed.substring(0, maxLength)}...';
|
|
}
|
|
|
|
void _onNotificationTapped(NotificationResponse response) {
|
|
final payload = response.payload;
|
|
if (payload != null) {
|
|
debugPrint('Notification tapped: $payload');
|
|
// Handle navigation based on payload
|
|
// This can be extended to navigate to specific screens
|
|
}
|
|
}
|
|
|
|
Future<void> cancelAll() async {
|
|
await _notifications.cancelAll();
|
|
}
|
|
|
|
Future<void> cancel(int id) async {
|
|
await _notifications.cancel(id);
|
|
}
|
|
}
|