mirror of
https://github.com/ImranR98/Obtainium.git
synced 2025-07-13 05:16:43 +02:00
324 lines
9.1 KiB
Dart
324 lines
9.1 KiB
Dart
// Exposes functions that can be used to send notifications to the user
|
|
// Contains a set of pre-defined ObtainiumNotification objects that should be used throughout the app
|
|
|
|
import 'package:easy_localization/easy_localization.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
|
import 'package:obtainium/main.dart';
|
|
import 'package:obtainium/providers/settings_provider.dart';
|
|
import 'package:obtainium/providers/source_provider.dart';
|
|
|
|
class ObtainiumNotification {
|
|
late int id;
|
|
late String title;
|
|
late String message;
|
|
late String channelCode;
|
|
late String channelName;
|
|
late String channelDescription;
|
|
Importance importance;
|
|
int? progPercent;
|
|
bool onlyAlertOnce;
|
|
String? payload;
|
|
|
|
ObtainiumNotification(
|
|
this.id,
|
|
this.title,
|
|
this.message,
|
|
this.channelCode,
|
|
this.channelName,
|
|
this.channelDescription,
|
|
this.importance, {
|
|
this.onlyAlertOnce = false,
|
|
this.progPercent,
|
|
this.payload,
|
|
});
|
|
}
|
|
|
|
class UpdateNotification extends ObtainiumNotification {
|
|
UpdateNotification(List<App> updates, {int? id})
|
|
: super(
|
|
id ?? 2,
|
|
tr('updatesAvailable'),
|
|
'',
|
|
'UPDATES_AVAILABLE',
|
|
tr('updatesAvailableNotifChannel'),
|
|
tr('updatesAvailableNotifDescription'),
|
|
Importance.max,
|
|
) {
|
|
message = updates.isEmpty
|
|
? tr('noNewUpdates')
|
|
: updates.length == 1
|
|
? tr('xHasAnUpdate', args: [updates[0].finalName])
|
|
: plural(
|
|
'xAndNMoreUpdatesAvailable',
|
|
updates.length - 1,
|
|
args: [updates[0].finalName, (updates.length - 1).toString()],
|
|
);
|
|
}
|
|
}
|
|
|
|
class SilentUpdateNotification extends ObtainiumNotification {
|
|
SilentUpdateNotification(List<App> updates, bool succeeded, {int? id})
|
|
: super(
|
|
id ?? 3,
|
|
succeeded ? tr('appsUpdated') : tr('appsNotUpdated'),
|
|
'',
|
|
'APPS_UPDATED',
|
|
tr('appsUpdatedNotifChannel'),
|
|
tr('appsUpdatedNotifDescription'),
|
|
Importance.defaultImportance,
|
|
) {
|
|
message = updates.length == 1
|
|
? tr(
|
|
succeeded ? 'xWasUpdatedToY' : 'xWasNotUpdatedToY',
|
|
args: [updates[0].finalName, updates[0].latestVersion],
|
|
)
|
|
: plural(
|
|
succeeded ? 'xAndNMoreUpdatesInstalled' : "xAndNMoreUpdatesFailed",
|
|
updates.length - 1,
|
|
args: [updates[0].finalName, (updates.length - 1).toString()],
|
|
);
|
|
}
|
|
}
|
|
|
|
class SilentUpdateAttemptNotification extends ObtainiumNotification {
|
|
SilentUpdateAttemptNotification(List<App> updates, {int? id})
|
|
: super(
|
|
id ?? 3,
|
|
tr('appsPossiblyUpdated'),
|
|
'',
|
|
'APPS_POSSIBLY_UPDATED',
|
|
tr('appsPossiblyUpdatedNotifChannel'),
|
|
tr('appsPossiblyUpdatedNotifDescription'),
|
|
Importance.defaultImportance,
|
|
) {
|
|
message = updates.length == 1
|
|
? tr(
|
|
'xWasPossiblyUpdatedToY',
|
|
args: [updates[0].finalName, updates[0].latestVersion],
|
|
)
|
|
: plural(
|
|
'xAndNMoreUpdatesPossiblyInstalled',
|
|
updates.length - 1,
|
|
args: [updates[0].finalName, (updates.length - 1).toString()],
|
|
);
|
|
}
|
|
}
|
|
|
|
class ErrorCheckingUpdatesNotification extends ObtainiumNotification {
|
|
ErrorCheckingUpdatesNotification(String error, {int? id})
|
|
: super(
|
|
id ?? 5,
|
|
tr('errorCheckingUpdates'),
|
|
error,
|
|
'BG_UPDATE_CHECK_ERROR',
|
|
tr('errorCheckingUpdatesNotifChannel'),
|
|
tr('errorCheckingUpdatesNotifDescription'),
|
|
Importance.high,
|
|
payload: "${tr('errorCheckingUpdates')}\n$error",
|
|
);
|
|
}
|
|
|
|
class AppsRemovedNotification extends ObtainiumNotification {
|
|
AppsRemovedNotification(List<List<String>> namedReasons)
|
|
: super(
|
|
6,
|
|
tr('appsRemoved'),
|
|
'',
|
|
'APPS_REMOVED',
|
|
tr('appsRemovedNotifChannel'),
|
|
tr('appsRemovedNotifDescription'),
|
|
Importance.max,
|
|
) {
|
|
message = '';
|
|
for (var r in namedReasons) {
|
|
message += '${tr('xWasRemovedDueToErrorY', args: [r[0], r[1]])} \n';
|
|
}
|
|
message = message.trim();
|
|
}
|
|
}
|
|
|
|
class DownloadNotification extends ObtainiumNotification {
|
|
DownloadNotification(String appName, int progPercent)
|
|
: super(
|
|
appName.hashCode,
|
|
tr('downloadingX', args: [appName]),
|
|
'',
|
|
'APP_DOWNLOADING',
|
|
tr('downloadingXNotifChannel', args: [tr('app')]),
|
|
tr('downloadNotifDescription'),
|
|
Importance.low,
|
|
onlyAlertOnce: true,
|
|
progPercent: progPercent,
|
|
);
|
|
}
|
|
|
|
class DownloadedNotification extends ObtainiumNotification {
|
|
DownloadedNotification(String fileName, String downloadUrl)
|
|
: super(
|
|
downloadUrl.hashCode,
|
|
tr('downloadedX', args: [fileName]),
|
|
'',
|
|
'FILE_DOWNLOADED',
|
|
tr('downloadedXNotifChannel', args: [tr('app')]),
|
|
tr('downloadedX', args: [tr('app')]),
|
|
Importance.defaultImportance,
|
|
);
|
|
}
|
|
|
|
final completeInstallationNotification = ObtainiumNotification(
|
|
1,
|
|
tr('completeAppInstallation'),
|
|
tr('obtainiumMustBeOpenToInstallApps'),
|
|
'COMPLETE_INSTALL',
|
|
tr('completeAppInstallationNotifChannel'),
|
|
tr('completeAppInstallationNotifDescription'),
|
|
Importance.max,
|
|
);
|
|
|
|
class CheckingUpdatesNotification extends ObtainiumNotification {
|
|
CheckingUpdatesNotification(String appName)
|
|
: super(
|
|
4,
|
|
tr('checkingForUpdates'),
|
|
appName,
|
|
'BG_UPDATE_CHECK',
|
|
tr('checkingForUpdatesNotifChannel'),
|
|
tr('checkingForUpdatesNotifDescription'),
|
|
Importance.min,
|
|
);
|
|
}
|
|
|
|
class NotificationsProvider {
|
|
FlutterLocalNotificationsPlugin notifications =
|
|
FlutterLocalNotificationsPlugin();
|
|
|
|
bool isInitialized = false;
|
|
|
|
Map<Importance, Priority> importanceToPriority = {
|
|
Importance.defaultImportance: Priority.defaultPriority,
|
|
Importance.high: Priority.high,
|
|
Importance.low: Priority.low,
|
|
Importance.max: Priority.max,
|
|
Importance.min: Priority.min,
|
|
Importance.none: Priority.min,
|
|
Importance.unspecified: Priority.defaultPriority,
|
|
};
|
|
|
|
Future<void> initialize() async {
|
|
isInitialized =
|
|
await notifications.initialize(
|
|
const InitializationSettings(
|
|
android: AndroidInitializationSettings('ic_notification'),
|
|
),
|
|
onDidReceiveNotificationResponse: (NotificationResponse response) {
|
|
_showNotificationPayload(response.payload);
|
|
},
|
|
) ??
|
|
false;
|
|
}
|
|
|
|
Future<void> checkLaunchByNotif() async {
|
|
final NotificationAppLaunchDetails? launchDetails = await notifications
|
|
.getNotificationAppLaunchDetails();
|
|
if (launchDetails?.didNotificationLaunchApp ?? false) {
|
|
_showNotificationPayload(
|
|
launchDetails!.notificationResponse?.payload,
|
|
doublePop: true,
|
|
);
|
|
}
|
|
}
|
|
|
|
void _showNotificationPayload(String? payload, {bool doublePop = false}) {
|
|
if (payload?.isNotEmpty == true) {
|
|
var title = (payload ?? '\n\n').split('\n').first;
|
|
var content = (payload ?? '\n\n').split('\n').sublist(1).join('\n');
|
|
globalNavigatorKey.currentState?.push(
|
|
PageRouteBuilder(
|
|
pageBuilder: (context, _, __) => AlertDialog(
|
|
title: Text(title),
|
|
content: Text(content),
|
|
actions: [
|
|
TextButton(
|
|
onPressed: () {
|
|
Navigator.of(context).pop(null);
|
|
if (doublePop) {
|
|
Navigator.of(context).pop(null);
|
|
}
|
|
},
|
|
child: Text(tr('ok')),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
Future<void> cancel(int id) async {
|
|
if (!isInitialized) {
|
|
await initialize();
|
|
}
|
|
await notifications.cancel(id);
|
|
}
|
|
|
|
Future<void> notifyRaw(
|
|
int id,
|
|
String title,
|
|
String message,
|
|
String channelCode,
|
|
String channelName,
|
|
String channelDescription,
|
|
Importance importance, {
|
|
bool cancelExisting = false,
|
|
int? progPercent,
|
|
bool onlyAlertOnce = false,
|
|
String? payload,
|
|
}) async {
|
|
if (cancelExisting) {
|
|
await cancel(id);
|
|
}
|
|
if (!isInitialized) {
|
|
await initialize();
|
|
}
|
|
await notifications.show(
|
|
id,
|
|
title,
|
|
message,
|
|
NotificationDetails(
|
|
android: AndroidNotificationDetails(
|
|
channelCode,
|
|
channelName,
|
|
channelDescription: channelDescription,
|
|
importance: importance,
|
|
priority: importanceToPriority[importance]!,
|
|
groupKey: '$obtainiumId.$channelCode',
|
|
progress: progPercent ?? 0,
|
|
maxProgress: 100,
|
|
showProgress: progPercent != null,
|
|
onlyAlertOnce: onlyAlertOnce,
|
|
indeterminate: progPercent != null && progPercent < 0,
|
|
),
|
|
),
|
|
payload: payload,
|
|
);
|
|
}
|
|
|
|
Future<void> notify(
|
|
ObtainiumNotification notif, {
|
|
bool cancelExisting = false,
|
|
}) => notifyRaw(
|
|
notif.id,
|
|
notif.title,
|
|
notif.message,
|
|
notif.channelCode,
|
|
notif.channelName,
|
|
notif.channelDescription,
|
|
notif.importance,
|
|
cancelExisting: cancelExisting,
|
|
onlyAlertOnce: notif.onlyAlertOnce,
|
|
progPercent: notif.progPercent,
|
|
payload: notif.payload,
|
|
);
|
|
}
|