mirror of
				https://github.com/ImranR98/Obtainium.git
				synced 2025-11-04 07:13:28 +01: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,
 | 
						|
  );
 | 
						|
}
 |