mirror of
https://github.com/zjs81/meshcore-open.git
synced 2026-04-20 22:13:48 +00:00
formats all dart files using `dart format .` from the root project dir this makes the code style repeatable by new contributors and makes PR review easier
241 lines
6.2 KiB
Dart
241 lines
6.2 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,
|
|
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 = message.trim();
|
|
final body = preview.isEmpty ? 'Received new message' : preview;
|
|
|
|
await _notifications.show(
|
|
channelIndex?.hashCode ?? DateTime.now().millisecondsSinceEpoch,
|
|
channelName,
|
|
body,
|
|
notificationDetails,
|
|
payload: 'channel:$channelIndex',
|
|
);
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|