Skip to content

Commit 05ec7af

Browse files
committed
✨(feat) New message notification
1. If someone sends message then notificaion will appear in notification tray.
1 parent 9effe94 commit 05ec7af

File tree

6 files changed

+169
-51
lines changed

6 files changed

+169
-51
lines changed

lib/helper/enum.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,13 @@ enum SortUser{
1616
ByNewest,
1717
ByOldest,
1818
ByMaxFollower
19+
}
20+
21+
enum NotificationType{
22+
NOT_DETERMINED,
23+
Message,
24+
Tweet,
25+
Reply,
26+
Retweet,
27+
Follow,
1928
}

lib/model/fcmNotificationModel.dart

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import 'dart:convert';
2+
3+
import 'package:flutter_twitter_clone/helper/enum.dart';
4+
5+
class FcmNotificationModel {
6+
String clickAction;
7+
String id;
8+
String status;
9+
String type;
10+
String userId;
11+
String title;
12+
String body;
13+
String tweetId;
14+
15+
FcmNotificationModel({
16+
this.clickAction,
17+
this.id,
18+
this.status,
19+
this.type,
20+
this.userId,
21+
this.title,
22+
this.body,
23+
this.tweetId,
24+
});
25+
26+
factory FcmNotificationModel.fromRawJson(String str) => FcmNotificationModel.fromJson(json.decode(str));
27+
28+
String toRawJson() => json.encode(toJson());
29+
30+
factory FcmNotificationModel.fromJson(Map<String, dynamic> json) {
31+
print("dat jbj bkkn,");
32+
return FcmNotificationModel(
33+
clickAction: json["click_action"] == null ? null : json["click_action"],
34+
id: json["id"] == null ? null : json["id"],
35+
status: json["status"] == null ? null : json["status"],
36+
type: json["type"] == null ? null : json["type"],
37+
userId: json["userId"] == null ? null : json["userId"],
38+
title: json["title"] == null ? null : json["title"],
39+
body: json["body"] == null ? null : json["body"],
40+
tweetId: json["tweetId"] == null ? null : json["tweetId"],
41+
);}
42+
43+
Map<String, dynamic> toJson() => {
44+
"click_action": clickAction == null ? null : clickAction,
45+
"id": id == null ? null : id,
46+
"status": status == null ? null : status,
47+
"type": type == null ? null : type,
48+
"userId": userId == null ? null : userId,
49+
"title": title == null ? null : title,
50+
"body": body == null ? null : body,
51+
"tweetId": tweetId == null ? null : tweetId,
52+
};
53+
54+
NotificationType getNotificationType(){
55+
switch (type) {
56+
case 'NotificationType.Follow' : return NotificationType.Follow;
57+
case 'NotificationType.Message' : return NotificationType.Message;
58+
case 'NotificationType.NOT_DETERMINED' : return NotificationType.NOT_DETERMINED;
59+
case 'NotificationType.Reply' : return NotificationType.Reply;
60+
case 'NotificationType.Retweet' : return NotificationType.Retweet;
61+
default: return NotificationType.NOT_DETERMINED;
62+
}}
63+
}

lib/page/homePage.dart

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import 'package:flutter/material.dart';
2+
import 'package:flutter_twitter_clone/helper/enum.dart';
3+
import 'package:flutter_twitter_clone/helper/utility.dart';
24
import 'package:flutter_twitter_clone/page/feed/feedPage.dart';
35
import 'package:flutter_twitter_clone/page/message/chatListPage.dart';
46
import 'package:flutter_twitter_clone/state/appState.dart';
@@ -27,10 +29,10 @@ class _HomePageState extends State<HomePage> {
2729
var state = Provider.of<AppState>(context, listen: false);
2830
state.setpageIndex = 0;
2931
initTweets();
32+
initProfile();
3033
initSearch();
3134
initNotificaiton();
3235
initChat();
33-
initProfile();
3436
});
3537

3638
super.initState();
@@ -67,6 +69,20 @@ class _HomePageState extends State<HomePage> {
6769

6870
Widget _body() {
6971
var state = Provider.of<AppState>(context);
72+
WidgetsBinding.instance.addPostFrameCallback((_) {
73+
var state = Provider.of<NotificationState>(context);
74+
/// Check if user recieve chat notification from firebase
75+
/// Redirect to chat screen
76+
if (state.notificationType == NotificationType.Message) {
77+
state.notificationType = NotificationType.NOT_DETERMINED;
78+
state.getuserDetail(state.notificationSenderId).then((user) {
79+
cprint("Opening user chat screen");
80+
final chatState = Provider.of<ChatState>(context, listen: false);
81+
chatState.setChatUser = user;
82+
Navigator.pushNamed(context, '/ChatScreenPage');
83+
});
84+
}
85+
});
7086
return SafeArea(child: Container(child: _getPage(state.pageIndex)));
7187
}
7288

lib/state/authState.dart

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -190,11 +190,12 @@ class AuthState extends AppState {
190190

191191
// Time at which user is created
192192
user.createdAt = DateTime.now().toUtc().toString();
193-
194-
_firebaseMessaging.getToken().then((String token) {
195-
assert(token != null);
196-
user.fcmToken = token;
197-
});
193+
/// Get firebase token
194+
/// Helps to send notification
195+
_firebaseMessaging.getToken().then((String token) {
196+
assert(token != null);
197+
user.fcmToken = token;
198+
});
198199
}
199200
kDatabase.child('profile').child(user.userId).set(user.toJson());
200201
_userModel = user;
@@ -320,8 +321,7 @@ class AuthState extends AppState {
320321
cprint(error, errorIn: 'updateUserProfile');
321322
}
322323
}
323-
324-
324+
325325
/// `Fetch` user `detail` whoose userId is passed
326326
Future<User> getuserDetail(String userId) async {
327327
User user;
@@ -360,7 +360,17 @@ class AuthState extends AppState {
360360
// Check if user verified his email address
361361
reloadUser();
362362
}
363+
if (_userModel.fcmToken == null) {
364+
/// if firebase token not available in frofile
365+
/// Then get token from firebase and save it to profile
366+
_firebaseMessaging.getToken().then((String token) {
367+
assert(token != null);
368+
_userModel.fcmToken = token;
369+
createUser(_userModel);
370+
});
371+
}
363372
}
373+
364374
logEvent('get_profile');
365375
}
366376
}

lib/state/chats/chatState.dart

Lines changed: 44 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import 'dart:async';
22
import 'dart:convert';
33

44
import 'package:firebase_analytics/firebase_analytics.dart';
5+
import 'package:flutter_twitter_clone/helper/enum.dart';
56
import 'package:http/http.dart' as http;
67
import 'package:firebase_database/firebase_database.dart';
78
import 'package:firebase_messaging/firebase_messaging.dart';
@@ -13,7 +14,7 @@ import 'package:flutter_twitter_clone/state/appState.dart';
1314
class ChatState extends AppState {
1415
bool setIsChatScreenOpen;
1516
final FirebaseDatabase _database = FirebaseDatabase.instance;
16-
17+
1718
List<ChatMessage> _messageList;
1819
List<User> _chatUserList;
1920
User _chatUser;
@@ -29,8 +30,9 @@ class ChatState extends AppState {
2930
if (_messageList == null) {
3031
return null;
3132
} else {
32-
_messageList.sort((x, y) =>
33-
DateTime.parse(x.createdAt).toLocal().compareTo(DateTime.parse(y.createdAt).toLocal()));
33+
_messageList.sort((x, y) => DateTime.parse(x.createdAt)
34+
.toLocal()
35+
.compareTo(DateTime.parse(y.createdAt).toLocal()));
3436
_messageList.reversed;
3537
_messageList = _messageList.reversed.toList();
3638
return List.from(_messageList);
@@ -143,7 +145,7 @@ class ChatState extends AppState {
143145
.child(_channelName)
144146
.push()
145147
.set(message.toJson());
146-
sendAndRetrieveMessage(secondUser.fcmToken);
148+
sendAndRetrieveMessage(message);
147149
logEvent('send_message');
148150
} catch (error) {
149151
cprint(error);
@@ -229,38 +231,43 @@ class ChatState extends AppState {
229231
// _channelName = null;
230232
}
231233

232-
final FirebaseMessaging firebaseMessaging = FirebaseMessaging();
233-
234-
void sendAndRetrieveMessage(String message) async {
235-
await firebaseMessaging.requestNotificationPermissions(
236-
const IosNotificationSettings(sound: true, badge: true, alert: true, provisional: false),
237-
);
238-
final String serverToken = '';
239-
String token = await firebaseMessaging.getToken();
240-
var body = jsonEncode(
241-
<String, dynamic>{
242-
'notification': <String, dynamic>{
243-
'body': 'this is a body',
244-
'title': 'this is a title'
245-
},
246-
'priority': 'high',
247-
'data': <String, dynamic>{
248-
'click_action': 'FLUTTER_NOTIFICATION_CLICK',
249-
'id': '1',
250-
'status': 'done'
251-
},
252-
'to': token
253-
});
254-
print(token);
234+
final FirebaseMessaging firebaseMessaging = FirebaseMessaging();
255235

256-
var response =await http.post(
257-
'https://fcm.googleapis.com/fcm/send',
258-
headers: <String, String>{
259-
'Content-Type': 'application/json',
260-
'Authorization': 'key=$serverToken',
261-
},
262-
body:body
263-
);
264-
print(response.body.toString());
265-
}
236+
void sendAndRetrieveMessage(ChatMessage model) async {
237+
/// on noti
238+
await firebaseMessaging.requestNotificationPermissions(
239+
const IosNotificationSettings(
240+
sound: true, badge: true, alert: true, provisional: false),
241+
);
242+
if (chatUser.fcmToken == null) {
243+
return;
244+
}
245+
final String serverToken = "ADD FIREBASE SERVER KEY HERE";
246+
247+
var body = jsonEncode(<String, dynamic>{
248+
'notification': <String, dynamic>{
249+
'body': model.message,
250+
'title': "Message from ${model.senderName}"
251+
},
252+
'priority': 'high',
253+
'data': <String, dynamic>{
254+
'click_action': 'FLUTTER_NOTIFICATION_CLICK',
255+
'id': '1',
256+
'status': 'done',
257+
"type": NotificationType.Message.toString(),
258+
"senderId": model.senderId,
259+
"title": "title",
260+
"body": model.message,
261+
"tweetId": ""
262+
},
263+
'to': chatUser.fcmToken
264+
});
265+
var response = await http.post('https://fcm.googleapis.com/fcm/send',
266+
headers: <String, String>{
267+
'Content-Type': 'application/json',
268+
'Authorization': 'key=$serverToken',
269+
},
270+
body: body);
271+
print(response.body.toString());
272+
}
266273
}

lib/state/notificationState.dart

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import 'dart:async';
22
import 'dart:convert';
3+
import 'package:flutter_twitter_clone/helper/enum.dart';
4+
import 'package:flutter_twitter_clone/model/fcmNotificationModel.dart';
35
import 'package:http/http.dart' as http;
46
import 'package:firebase_database/firebase_database.dart';
57
import 'package:firebase_messaging/firebase_messaging.dart';
@@ -13,6 +15,9 @@ import 'package:flutter_twitter_clone/state/appState.dart';
1315

1416
class NotificationState extends AppState {
1517
String fcmToken;
18+
NotificationType notificationType = NotificationType.NOT_DETERMINED;
19+
// FcmNotificationModel notification;
20+
String notificationSenderId;
1621
dabase.Query query;
1722
List<User> userList = [];
1823

@@ -147,15 +152,24 @@ class NotificationState extends AppState {
147152
_firebaseMessaging.configure(
148153
onMessage: (Map<String, dynamic> message) async {
149154
print("onMessage: $message");
150-
// _showItemDialog(message);
155+
print(message['data']);
156+
notifyListeners();
151157
},
152158
onLaunch: (Map<String, dynamic> message) async {
153-
print("onLaunch: $message");
154-
// _navigateToItemDetail(message);
159+
cprint("Send to ",event: "UnBox");
160+
var data = message['data'];
161+
print(message['data']);
162+
notificationSenderId = data["userId"];
163+
notificationType = NotificationType.Message;
164+
notifyListeners();
155165
},
156166
onResume: (Map<String, dynamic> message) async {
157-
print("onResume: $message");
158-
// _navigateToItemDetail(message);
167+
cprint("Send to ",event: "UnBox");
168+
var data = message['data'];
169+
print(message['data']);
170+
notificationSenderId = data["userId"];
171+
notificationType = NotificationType.Message;
172+
notifyListeners();
159173
},
160174
);
161175
_firebaseMessaging.requestNotificationPermissions(
@@ -172,5 +186,4 @@ class NotificationState extends AppState {
172186
});
173187
}
174188

175-
176189
}

0 commit comments

Comments
 (0)