Skip to content

Commit

Permalink
feat: introduced notification support for android
Browse files Browse the repository at this point in the history
  • Loading branch information
IamMuuo committed Sep 24, 2024
2 parents 6f24e7a + a685c94 commit 6937abd
Show file tree
Hide file tree
Showing 9 changed files with 455 additions and 68 deletions.
73 changes: 5 additions & 68 deletions lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,42 +1,18 @@
import 'package:academia/exports/barrel.dart';
import 'package:academia/notifier/notifier.dart';
import 'package:get/get.dart';

void main() async {
WidgetsFlutterBinding.ensureInitialized();

/// Initialize the flutter notifications plugin
AwesomeNotifications().initialize(
'resource://drawable/academia',
[
NotificationChannel(
channelKey: "reminders",
channelName: "Academia Reminders",
channelDescription: "Academia's reminder notifications",
importance: NotificationImportance.High,
enableLights: true,
defaultColor: Colors.blueGrey,
playSound: true,
enableVibration: true,
channelShowBadge: true,
),
NotificationChannel(
channelKey: "social",
channelName: "Academia Social Notifications",
channelDescription: "Academia's social notification",
importance: NotificationImportance.Max,
enableLights: true,
defaultColor: Colors.blueGrey,
playSound: true,
enableVibration: true,
channelShowBadge: true,
)
],
);
// await Workmanager().initialize(
// callbackDispatcher,
// isInDebugMode: true,
// );

await LocalNotifierService().initialize();
await LocalNotificationStatusManager().initialize();

runApp(
GetMaterialApp(
home: const Academia(),
Expand All @@ -62,46 +38,7 @@ class Academia extends StatelessWidget {
Get.put(CoursesController());
Get.put(EventsController());

// Prompt for notification permission
AwesomeNotifications().isNotificationAllowed().then(
(value) {
if ((!value) && (Platform.isAndroid || Platform.isIOS)) {
if (context.mounted) {
showDialog(
barrierDismissible: false,
context: context,
builder: (context) {
return AlertDialog(
title: const Text("Allow Notifications"),
content: const Text(
"Academia would like to send you notifications about classes and your school work",
),
actions: [
FilledButton(
onPressed: () {
AwesomeNotifications()
.requestPermissionToSendNotifications()
.then((value) {
if (context.mounted) {
Navigator.pop(context);
}
});
},
child: const Text("Allow"),
),
OutlinedButton(
onPressed: () {
Navigator.of(context).pop();
},
child: const Text("No"),
),
],
);
});
}
}
},
);
LocalNotifierService().requestPermission();
return Obx(
() => userController.isLoggedIn.value
? const LayoutPage()
Expand Down
34 changes: 34 additions & 0 deletions lib/notifier/local_notification_channel.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/// Enum representing different notification channels within the app.
///
/// Each channel contains a `channelKey`, `channelName`, and
/// `channelDescription` which are required for initializing
/// notification channels in the app.
enum LocalNotificationChannelType {
reminders(
channelKey: 'reminders',
channelName: 'Academia Reminders',
channelDescription: "Academia's reminder notifications",
),
general(
channelKey: 'general',
channelName: 'Academia General Notifications',
channelDescription: "Academia's general notifications",
),
social(
channelKey: 'social',
channelName: 'Academia Social Notifications',
channelDescription: "Academia's social notifications",
);

// Notification channel properties
final String channelKey;
final String channelName;
final String channelDescription;

// Constructor for the enum, initializing the properties
const LocalNotificationChannelType({
required this.channelKey,
required this.channelName,
required this.channelDescription,
});
}
103 changes: 103 additions & 0 deletions lib/notifier/local_notification_status_manager.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import 'package:shared_preferences/shared_preferences.dart';

class LocalNotificationStatusManager {
static final LocalNotificationStatusManager _instance =
LocalNotificationStatusManager._internal();

factory LocalNotificationStatusManager() {
return _instance;
}

/// Private named constructor that prevents external instantiation.
LocalNotificationStatusManager._internal();

// Maps to hold notification status and counters
final Map<int, bool> _notificationStatus = {};
int _notificationIdCounter = 1; // Start from 1 and increment indefinitely

/// Initializes the notification status manager.
///
/// This method should be called during the app's startup to load
/// the notification ID counter and any existing notification statuses
/// from shared preferences.
///
/// Example:
/// ```dart
/// await LocalNotificationStatusManager().initialize();
/// ```
Future<void> initialize() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
_notificationIdCounter = prefs.getInt('notificationIdCounter') ?? 1;

await loadNotificationStatuses();
}

/// Saves the current notification ID counter to shared preferences.
Future<void> saveCounters() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setInt('notificationIdCounter', _notificationIdCounter);
}

/// Gets the next available notification ID.
///
/// This method increments the notification ID counter, saves it,
/// and returns the new ID, which can be used to create a new notification.
///
/// Returns:
/// - `int`: The next notification ID.
int getNextId() {
int newId = _notificationIdCounter++;
saveCounters(); // Save immediately after generating the ID
return newId;
}

/// Updates the shown status of a notification.
///
/// Parameters:
/// - `int id`: The ID of the notification to update.
/// - `bool isShown`: The new shown status of the notification.
void setNotificationShown(int id, bool isShown) {
_notificationStatus[id] = isShown;
}

/// Checks if a notification has been shown.
///
/// Parameters:
/// - `int id`: The ID of the notification to check.
///
/// Returns:
/// - `bool`: True if the notification has been shown, false otherwise.
bool isNotificationShown(int id) {
return _notificationStatus[id] ?? false;
}

/// Resets the shown status of a notification.
///
/// Parameters:
/// - `int id`: The ID of the notification to reset.
void resetNotificationStatus(int id) {
_notificationStatus[id] = false;
}

/// Loads stored notification statuses from shared preferences.
///
/// This method populates the `_notificationStatus` map with
/// previously stored statuses.
Future<void> loadNotificationStatuses() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
for (int i = 1; i < _notificationIdCounter; i++) {
_notificationStatus[i] = prefs.getBool('notification_$i') ?? false;
}
}

/// Saves notification statuses to shared preferences.
///
/// This method persists the current notification statuses in
/// shared preferences for future retrieval.
Future<void> saveNotificationStatuses() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
_notificationStatus.forEach((key, value) {
prefs.setBool('notification_$key', value);
});
}
}
5 changes: 5 additions & 0 deletions lib/notifier/local_notification_type.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
enum LocalNotificationType {
course,
todo,
general,
}
Loading

0 comments on commit 6937abd

Please sign in to comment.