Skip to content

Commit

Permalink
Add notification realtime
Browse files Browse the repository at this point in the history
  • Loading branch information
ledhcg committed Jun 13, 2023
1 parent 32da6e3 commit 83c9970
Show file tree
Hide file tree
Showing 9 changed files with 177 additions and 13 deletions.
4 changes: 4 additions & 0 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import 'package:rikedu/src/utils/constants/roles_constants.dart';
import 'package:rikedu/src/utils/constants/storage_constants.dart';
import 'package:rikedu/src/utils/service/api_service.dart';
import 'package:rikedu/src/utils/service/firebase_service.dart';
import 'package:rikedu/src/utils/service/notification_service.dart';
import 'package:rikedu/src/utils/service/storage_service.dart';
import 'package:skeletons/skeletons.dart';

Expand All @@ -43,6 +44,9 @@ void main() async {
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
await Get.putAsync<StorageService>(() => StorageService().init());
await Get.putAsync<FirebaseService>(() => FirebaseService().init());
final notificationService = NotificationService();
await Get.putAsync<NotificationService>(() => notificationService.init());
notificationService.listenToNotificationChanges();
initializeDateFormatting(Get.locale.toString());

final authProvider = AuthProvider();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@ import 'package:get/get.dart';
import 'package:provider/provider.dart';
import 'package:rikedu/src/features/authentication/models/user_model.dart';
import 'package:rikedu/src/features/authentication/providers/auth_provider.dart';
import 'package:rikedu/src/utils/constants/firebase_constants.dart';
import 'package:rikedu/src/utils/service/firebase_service.dart';
import 'package:rikedu/src/utils/widgets/snackbar_widget.dart';

class ParentalControlsController extends GetxController {
final authProvider = Provider.of<AuthProvider>(Get.context!);
final FirebaseService firebaseService = Get.find();

final Rx<User> _student = User.defaultUser().obs;
User get student => _student.value;
Expand Down Expand Up @@ -42,19 +45,22 @@ class ParentalControlsController extends GetxController {
return null;
}

void clearForm() {
titleController.clear();
messageController.clear();
}

void sendNoti() async {
if (formKey.currentState!.validate()) {
SnackbarWidget.showSnackbar('Thành công');

// _isLoading.value = true;
// await authProvider.login(_email.value, _password.value);
// _isLoading.value = false;
// if (authProvider.isAuthenticated) {
// Get.offAllNamed(Routes.HOME);
// SnackbarWidget.showSnackbar(authProvider.responseMessage);
// } else {
// SnackbarWidget.showSnackbar(authProvider.responseMessage);
// }
final collectionRef =
firebaseService.collectionReference(FirebaseConst.USER_NOTIFICATION);
final documentRef = await collectionRef.add({
'title': titleNoti,
'message': messageNoti,
'to_user_id': student.id,
'from': 'Other',
});
print('Notification added with ID: ${documentRef.id}');
} else {
SnackbarWidget.showSnackbar('Please enter valid credentials');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,11 @@ class MessageModal extends GetView<ParentalControlsController> {
),
const SizedBox(height: 16.0),
FilledButton(
onPressed: () => controller.sendNoti(),
onPressed: () {
controller.sendNoti();
controller.clearForm();
FocusScope.of(context).requestFocus(FocusNode());
},
child: Text('Send'.tr),
),
],
Expand Down
1 change: 1 addition & 0 deletions lib/src/utils/constants/firebase_constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ class FirebaseConst {
static const String STUDENT_LOCATION = "student_location";
static const String STUDENT_STATUS = "student_status";
static const String STUDENT_APP_USAGE = "student_app_usage";
static const String USER_NOTIFICATION = "user_notification";
}
10 changes: 10 additions & 0 deletions lib/src/utils/service/firebase_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,14 @@ class FirebaseService extends GetxService {
String collection, String documentId) async {
return _firestore!.collection(collection).doc(documentId).snapshots();
}

Future<Stream<QuerySnapshot<Map<String, dynamic>>>> listenDataChange(
String collection) async {
return _firestore!.collection(collection).snapshots();
}

CollectionReference<Map<String, dynamic>> collectionReference(
String collection) {
return _firestore!.collection(collection);
}
}
101 changes: 101 additions & 0 deletions lib/src/utils/service/notification_service.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import 'dart:io';

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:get/get.dart';
import 'package:rikedu/src/utils/constants/firebase_constants.dart';
import 'package:rikedu/src/utils/service/firebase_service.dart';

class NotificationService extends GetxService {
static NotificationService get to => Get.find();
final FirebaseService firebaseService = Get.find();
final FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();

int notificationIdCounter = 0;

Future<NotificationService> init() async {
const initializationSettingsAndroid = AndroidInitializationSettings('logo');
const initializationSettingsDarwin = DarwinInitializationSettings();
const initializationSettings = InitializationSettings(
android: initializationSettingsAndroid,
iOS: initializationSettingsDarwin);
await _flutterLocalNotificationsPlugin.initialize(initializationSettings);
_isAndroidPermissionGranted();
_requestPermissions();
return this;
}

Future<void> _isAndroidPermissionGranted() async {
if (Platform.isAndroid) {
final bool granted = await _flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
?.areNotificationsEnabled() ??
false;
}
}

Future<void> _requestPermissions() async {
if (Platform.isIOS || Platform.isMacOS) {
await _flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
IOSFlutterLocalNotificationsPlugin>()
?.requestPermissions(
alert: true,
badge: true,
sound: true,
);
await _flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
MacOSFlutterLocalNotificationsPlugin>()
?.requestPermissions(
alert: true,
badge: true,
sound: true,
);
} else if (Platform.isAndroid) {
final AndroidFlutterLocalNotificationsPlugin? androidImplementation =
_flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>();

final bool? granted = await androidImplementation?.requestPermission();
}
}

Future<void> showNotification(String title, String message) async {
const androidPlatformChannelSpecifics = AndroidNotificationDetails(
'notification',
'notification',
channelDescription: 'notification',
importance: Importance.max,
priority: Priority.high,
);
const iOSPlatformChannelSpecifics = DarwinNotificationDetails();
const platformChannelSpecifics = NotificationDetails(
android: androidPlatformChannelSpecifics,
iOS: iOSPlatformChannelSpecifics);
notificationIdCounter++;
await _flutterLocalNotificationsPlugin.show(
notificationIdCounter, title, message, platformChannelSpecifics);
}

void listenToNotificationChanges() {
firebaseService
.listenDataChange(FirebaseConst.USER_NOTIFICATION)
.then((stream) {
stream.listen((snapshot) {
for (var change in snapshot.docChanges) {
print("New notification: ${change.doc.data()}");
if (change.type == DocumentChangeType.added) {
final title = change.doc['title'];
final message = change.doc['message'];
print("New notification detail: ${change.doc['message']}");
showNotification(title, message);
}
}
});
});
}
}
4 changes: 4 additions & 0 deletions macos/Flutter/GeneratedPluginRegistrant.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,27 @@ import cloud_firestore
import firebase_analytics
import firebase_auth
import firebase_core
import flutter_local_notifications
import flutter_localization
import flutter_secure_storage_macos
import location
import package_info_plus
import path_provider_foundation
import shared_preferences_foundation
import sqflite

func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
BatteryPlusMacosPlugin.register(with: registry.registrar(forPlugin: "BatteryPlusMacosPlugin"))
FLTFirebaseFirestorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseFirestorePlugin"))
FLTFirebaseAnalyticsPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAnalyticsPlugin"))
FLTFirebaseAuthPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAuthPlugin"))
FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin"))
FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin"))
FlutterLocalizationPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalizationPlugin"))
FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin"))
LocationPlugin.register(with: registry.registrar(forPlugin: "LocationPlugin"))
FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
}
34 changes: 33 additions & 1 deletion pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,30 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.1"
flutter_local_notifications:
dependency: "direct main"
description:
name: flutter_local_notifications
sha256: "812791d43ccfc1b443a0d39fa02a206fc228c597e28ff9337e09e3ca8d370391"
url: "https://pub.dev"
source: hosted
version: "14.1.1"
flutter_local_notifications_linux:
dependency: transitive
description:
name: flutter_local_notifications_linux
sha256: "33f741ef47b5f63cc7f78fe75eeeac7e19f171ff3c3df054d84c1e38bedb6a03"
url: "https://pub.dev"
source: hosted
version: "4.0.0+1"
flutter_local_notifications_platform_interface:
dependency: transitive
description:
name: flutter_local_notifications_platform_interface
sha256: "7cf643d6d5022f3baed0be777b0662cce5919c0a7b86e700299f22dc4ae660ef"
url: "https://pub.dev"
source: hosted
version: "7.0.0+1"
flutter_localization:
dependency: "direct main"
description:
Expand Down Expand Up @@ -1202,6 +1226,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.4.16"
timezone:
dependency: transitive
description:
name: timezone
sha256: "1cfd8ddc2d1cfd836bc93e67b9be88c3adaeca6f40a00ca999104c30693cdca0"
url: "https://pub.dev"
source: hosted
version: "0.9.2"
typed_data:
dependency: transitive
description:
Expand Down Expand Up @@ -1235,7 +1267,7 @@ packages:
source: hosted
version: "1.2.0"
uuid:
dependency: transitive
dependency: "direct main"
description:
name: uuid
sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313"
Expand Down
2 changes: 2 additions & 0 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ dependencies:
carousel_indicator: ^1.0.6
usage_stats: ^1.2.0
flutter_animarker: ^3.2.0
flutter_local_notifications: ^14.1.1
uuid: ^3.0.7

dev_dependencies:
flutter_test:
Expand Down

0 comments on commit 83c9970

Please sign in to comment.