mirror of
https://github.com/Iconica-Development/flutter_notification_center.git
synced 2025-05-19 00:53:44 +02:00
refactor: make changes based on review comments
This commit is contained in:
parent
718395fb53
commit
a29ecba146
10 changed files with 222 additions and 70 deletions
68
README.md
68
README.md
|
@ -1,16 +1,66 @@
|
||||||
# flutter_notification_center
|
# flutter_notification_center
|
||||||
|
A Flutter package for creating notification center displaying a list of notifications.
|
||||||
|
|
||||||
A new Flutter project.
|
## Features
|
||||||
|
|
||||||
## Getting Started
|
- Notification center: A page containing a list of notifications.
|
||||||
|
- Notification bell: A clickable bell icon that can be placed anywere showing the amound of unread notifications. Clicking the bell takes the user to the notification center.
|
||||||
|
- Pinned notifications: A pinned notification can't be dismissed by the user from the notification center.
|
||||||
|
- Dismissable notifications: A dismissable notification can be dismissed by the user from the notification center.
|
||||||
|
- Notification detail page: Clicking on a notification takes the user to a notification detail page.
|
||||||
|
- Notification types: Notification types that can be created are: instant, scheduled, recurring.
|
||||||
|
|
||||||
This project is a starting point for a Flutter application.
|
## Setup
|
||||||
|
|
||||||
A few resources to get you started if this is your first Flutter project:
|
To use this package, add `flutter_notification_center` as a dependency in your pubspec.yaml file.
|
||||||
|
|
||||||
- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
|
- For custom notification styling provide the optional notificationWidgetBuilder with your own implementation.
|
||||||
- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
|
|
||||||
|
|
||||||
For help getting started with Flutter development, view the
|
The `NotificationConfig` has its own parameters, as specified below:
|
||||||
[online documentation](https://docs.flutter.dev/), which offers tutorials,
|
| Parameter | Explanation |
|
||||||
samples, guidance on mobile development, and a full API reference.
|
|-----------|-------------|
|
||||||
|
| service | The notification service that will be used |
|
||||||
|
| seperateNotificationsWithDivider | If true notifications will be seperated with dividers within the notification center |
|
||||||
|
| translations | The translations that will be used |
|
||||||
|
| notificationWidgetBuilder | The widget that defines the styles and logic for every notification |
|
||||||
|
|
||||||
|
The `notificationWidgetBuilder` expects the following parameters, as specified below:
|
||||||
|
| Parameter | Explanation |
|
||||||
|
|-----------|-------------|
|
||||||
|
| notification | The notification that is being defined |
|
||||||
|
| style | The styling that will be used for the notification |
|
||||||
|
| notificationService | The notification service that will be used |
|
||||||
|
| notificationTranslations | The translations that will be used for the notification|
|
||||||
|
| context | The provided context |
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
Create instant notification:
|
||||||
|
- Make a call to pushNotification() and provide a NotificationModel with the required attributes.
|
||||||
|
|
||||||
|
Create scheduled notification:
|
||||||
|
- Make a call to createScheduledNotification() and provide a NotificationModel with the required attributes + scheduledFor.
|
||||||
|
|
||||||
|
Create recurring notification:
|
||||||
|
- Make a call to createRecurringNotification() and provide a NotificationModel with the required attributes and the following additional attributes:
|
||||||
|
- scheduledFor
|
||||||
|
- recurring = true
|
||||||
|
- occuringInterval with the pre defined interval (daily, weekly, monthly)
|
||||||
|
|
||||||
|
To create a pinned notification, set isPinned = true when creating the notification.
|
||||||
|
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
See [Example Code](example/lib/main.dart) for more info.
|
||||||
|
|
||||||
|
## Issues
|
||||||
|
|
||||||
|
Please file any issues, bugs or feature request as an issue on our [GitHub](https://github.com/Iconica-Development/flutter_notification_center/pulls) page. Commercial support is available if you need help with integration with your app or services. You can contact us at [support@iconica.nl](mailto:support@iconica.nl).
|
||||||
|
|
||||||
|
## Want to contribute
|
||||||
|
|
||||||
|
If you would like to contribute to the plugin (e.g. by improving the documentation, solving a bug or adding a cool new feature), please carefully review our [contribution guide](./CONTRIBUTING.md) and send us your [pull request](https://github.com/Iconica-Development/flutter_notification_center/pulls).
|
||||||
|
|
||||||
|
## Author
|
||||||
|
|
||||||
|
This `flutter_notification_center` for Flutter is developed by [Iconica](https://iconica.nl). You can contact us at <support@iconica.nl>
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
# flutter_notification_center
|
|
||||||
|
|
||||||
A new Flutter project.
|
|
||||||
|
|
||||||
## Getting Started
|
|
||||||
|
|
||||||
This project is a starting point for a Flutter application.
|
|
||||||
|
|
||||||
A few resources to get you started if this is your first Flutter project:
|
|
||||||
|
|
||||||
- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
|
|
||||||
- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
|
|
||||||
|
|
||||||
For help getting started with Flutter development, view the
|
|
||||||
[online documentation](https://docs.flutter.dev/), which offers tutorials,
|
|
||||||
samples, guidance on mobile development, and a full API reference.
|
|
|
@ -1,16 +0,0 @@
|
||||||
# example
|
|
||||||
|
|
||||||
A new Flutter project.
|
|
||||||
|
|
||||||
## Getting Started
|
|
||||||
|
|
||||||
This project is a starting point for a Flutter application.
|
|
||||||
|
|
||||||
A few resources to get you started if this is your first Flutter project:
|
|
||||||
|
|
||||||
- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
|
|
||||||
- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
|
|
||||||
|
|
||||||
For help getting started with Flutter development, view the
|
|
||||||
[online documentation](https://docs.flutter.dev/), which offers tutorials,
|
|
||||||
samples, guidance on mobile development, and a full API reference.
|
|
|
@ -92,7 +92,7 @@ class CustomNotificationWidget extends StatelessWidget {
|
||||||
height: 12.0,
|
height: 12.0,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
color: style.isReadDotColor ?? Colors.red,
|
color: style.isReadDotColor,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: null,
|
: null,
|
|
@ -1,11 +1,10 @@
|
||||||
import 'package:example/customer_notification.dart';
|
import 'package:example/custom_notification.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_dotenv/flutter_dotenv.dart';
|
import 'package:flutter_dotenv/flutter_dotenv.dart';
|
||||||
import 'package:firebase_core/firebase_core.dart';
|
import 'package:firebase_core/firebase_core.dart';
|
||||||
import 'package:flutter_notification_center_firebase/flutter_notification_center_firebase.dart';
|
import 'package:flutter_notification_center_firebase/flutter_notification_center_firebase.dart';
|
||||||
import 'package:intl/date_symbol_data_local.dart';
|
import 'package:intl/date_symbol_data_local.dart';
|
||||||
import 'package:firebase_auth/firebase_auth.dart';
|
|
||||||
import 'package:flutter_notification_center/flutter_notification_center.dart';
|
import 'package:flutter_notification_center/flutter_notification_center.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
|
|
@ -12,9 +12,9 @@ class NotificationConfig {
|
||||||
/// translations for notification messages.
|
/// translations for notification messages.
|
||||||
const NotificationConfig({
|
const NotificationConfig({
|
||||||
required this.service,
|
required this.service,
|
||||||
required this.seperateNotificationsWithDivider,
|
this.seperateNotificationsWithDivider = true,
|
||||||
this.translations = const NotificationTranslations(),
|
this.translations = const NotificationTranslations(),
|
||||||
required this.notificationWidgetBuilder,
|
this.notificationWidgetBuilder,
|
||||||
});
|
});
|
||||||
|
|
||||||
/// The notification service to use for delivering notifications.
|
/// The notification service to use for delivering notifications.
|
||||||
|
@ -27,6 +27,6 @@ class NotificationConfig {
|
||||||
final NotificationTranslations translations;
|
final NotificationTranslations translations;
|
||||||
|
|
||||||
/// Widget for building each notification item.
|
/// Widget for building each notification item.
|
||||||
final Widget Function(NotificationModel, BuildContext)
|
final Widget Function(NotificationModel, BuildContext)?
|
||||||
notificationWidgetBuilder;
|
notificationWidgetBuilder;
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,10 +82,117 @@ class NotificationCenterState extends State<NotificationCenter> {
|
||||||
}
|
}
|
||||||
var notification = snapshot.data![index ~/ 2];
|
var notification = snapshot.data![index ~/ 2];
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 12.0),
|
padding: const EdgeInsets.symmetric(horizontal: 12.0),
|
||||||
child: widget.config
|
child: widget.config.notificationWidgetBuilder != null
|
||||||
.notificationWidgetBuilder(notification, context),
|
? widget.config.notificationWidgetBuilder!(
|
||||||
);
|
notification, context)
|
||||||
|
: notification.isPinned
|
||||||
|
//Pinned notification
|
||||||
|
? GestureDetector(
|
||||||
|
onTap: () async =>
|
||||||
|
_navigateToNotificationDetail(
|
||||||
|
context,
|
||||||
|
notification,
|
||||||
|
widget.config.service,
|
||||||
|
widget.config.translations,
|
||||||
|
const NotificationStyle()),
|
||||||
|
child: ListTile(
|
||||||
|
leading: Icon(
|
||||||
|
notification.icon,
|
||||||
|
color: Colors.grey,
|
||||||
|
),
|
||||||
|
title: Row(
|
||||||
|
crossAxisAlignment:
|
||||||
|
CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
notification.title,
|
||||||
|
style: const TextStyle(
|
||||||
|
color: Colors.black,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
fontSize: 16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
trailing: IconButton(
|
||||||
|
icon: const Icon(Icons.push_pin),
|
||||||
|
color: Colors.grey,
|
||||||
|
onPressed: () async =>
|
||||||
|
_navigateToNotificationDetail(
|
||||||
|
context,
|
||||||
|
notification,
|
||||||
|
widget.config.service,
|
||||||
|
widget.config.translations,
|
||||||
|
const NotificationStyle()),
|
||||||
|
padding:
|
||||||
|
const EdgeInsets.only(left: 60.0),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
//Dismissable notification
|
||||||
|
: Dismissible(
|
||||||
|
key: Key(notification.id),
|
||||||
|
onDismissed: (direction) async {
|
||||||
|
await dismissNotification(
|
||||||
|
widget.config.service,
|
||||||
|
notification,
|
||||||
|
context);
|
||||||
|
},
|
||||||
|
background: Container(
|
||||||
|
color: Colors.red,
|
||||||
|
alignment: Alignment.centerRight,
|
||||||
|
child: const Icon(
|
||||||
|
Icons.delete,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () async =>
|
||||||
|
_navigateToNotificationDetail(
|
||||||
|
context,
|
||||||
|
notification,
|
||||||
|
widget.config.service,
|
||||||
|
widget.config.translations,
|
||||||
|
const NotificationStyle()),
|
||||||
|
child: ListTile(
|
||||||
|
leading: Icon(
|
||||||
|
notification.icon,
|
||||||
|
color: Colors.grey,
|
||||||
|
),
|
||||||
|
title: Row(
|
||||||
|
crossAxisAlignment:
|
||||||
|
CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
notification.title,
|
||||||
|
style: const TextStyle(
|
||||||
|
color: Colors.black,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
fontSize: 16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
trailing: !notification.isRead
|
||||||
|
? Container(
|
||||||
|
margin: const EdgeInsets.only(
|
||||||
|
right: 8.0),
|
||||||
|
width: 12.0,
|
||||||
|
height: 12.0,
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
shape: BoxShape.circle,
|
||||||
|
color: Colors.red,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
));
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -93,3 +200,47 @@ class NotificationCenterState extends State<NotificationCenter> {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _navigateToNotificationDetail(
|
||||||
|
BuildContext context,
|
||||||
|
NotificationModel notification,
|
||||||
|
NotificationService notificationService,
|
||||||
|
NotificationTranslations notificationTranslations,
|
||||||
|
NotificationStyle style,
|
||||||
|
) async {
|
||||||
|
await markNotificationAsRead(notificationService, notification);
|
||||||
|
if (context.mounted) {
|
||||||
|
await Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => NotificationDetailPage(
|
||||||
|
translations: notificationTranslations,
|
||||||
|
notification: notification,
|
||||||
|
notificationStyle: style,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> dismissNotification(
|
||||||
|
NotificationService notificationService,
|
||||||
|
NotificationModel notification,
|
||||||
|
BuildContext context,
|
||||||
|
) async {
|
||||||
|
await notificationService.dismissActiveNotification(notification);
|
||||||
|
if (context.mounted) {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
const SnackBar(
|
||||||
|
content: Text("Notification dismissed"),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> markNotificationAsRead(
|
||||||
|
NotificationService notificationService,
|
||||||
|
NotificationModel notification,
|
||||||
|
) async {
|
||||||
|
await notificationService.markNotificationAsRead(notification);
|
||||||
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ abstract class NotificationService with ChangeNotifier {
|
||||||
Future createRecurringNotification(NotificationModel notification);
|
Future createRecurringNotification(NotificationModel notification);
|
||||||
|
|
||||||
/// Deletes a scheduled notification.
|
/// Deletes a scheduled notification.
|
||||||
Future deleteScheduledNotification(NotificationModel notification);
|
Future deletePlannedNotification(NotificationModel notification);
|
||||||
|
|
||||||
/// Dismisses an active notification.
|
/// Dismisses an active notification.
|
||||||
Future dismissActiveNotification(NotificationModel notification);
|
Future dismissActiveNotification(NotificationModel notification);
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
# example
|
|
||||||
|
|
||||||
A new Flutter project.
|
|
||||||
|
|
||||||
## Getting Started
|
|
||||||
|
|
||||||
This project is a starting point for a Flutter application.
|
|
||||||
|
|
||||||
A few resources to get you started if this is your first Flutter project:
|
|
||||||
|
|
||||||
- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
|
|
||||||
- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
|
|
||||||
|
|
||||||
For help getting started with Flutter development, view the
|
|
||||||
[online documentation](https://docs.flutter.dev/), which offers tutorials,
|
|
||||||
samples, guidance on mobile development, and a full API reference.
|
|
|
@ -113,7 +113,7 @@ class FirebaseNotificationService
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> deleteScheduledNotification(
|
Future<void> deletePlannedNotification(
|
||||||
NotificationModel notificationModel) async {
|
NotificationModel notificationModel) async {
|
||||||
try {
|
try {
|
||||||
DocumentReference documentReference = FirebaseFirestore.instance
|
DocumentReference documentReference = FirebaseFirestore.instance
|
||||||
|
@ -192,7 +192,7 @@ class FirebaseNotificationService
|
||||||
if (notification.scheduledFor!.isBefore(currentTime) ||
|
if (notification.scheduledFor!.isBefore(currentTime) ||
|
||||||
notification.scheduledFor!.isAtSameMomentAs(currentTime)) {
|
notification.scheduledFor!.isAtSameMomentAs(currentTime)) {
|
||||||
await pushNotification(notification);
|
await pushNotification(notification);
|
||||||
await deleteScheduledNotification(notification);
|
await deletePlannedNotification(notification);
|
||||||
|
|
||||||
//Plan new recurring notification instance
|
//Plan new recurring notification instance
|
||||||
if (notification.recurring) {
|
if (notification.recurring) {
|
||||||
|
|
Loading…
Reference in a new issue