Transfer showLocalNotification, backgroundKeepAlive from LLC to Core
Signed-off-by: Sahil Kumar <[email protected]>
This commit is contained in:
@@ -79,8 +79,6 @@ class Client {
|
||||
Duration connectTimeout = const Duration(seconds: 6),
|
||||
Duration receiveTimeout = const Duration(seconds: 6),
|
||||
Dio httpClient,
|
||||
this.showLocalNotification,
|
||||
this.backgroundKeepAlive = const Duration(minutes: 1),
|
||||
RetryPolicy retryPolicy,
|
||||
}) {
|
||||
_retryPolicy ??= RetryPolicy(
|
||||
@@ -110,14 +108,6 @@ class Client {
|
||||
/// The retry policy options getter
|
||||
RetryPolicy get retryPolicy => _retryPolicy;
|
||||
|
||||
/// Method used to show a local notification while the app is in background
|
||||
/// Switching to another application will not disconnect the client immediately
|
||||
/// So, use this method to show the notification when receiving a new message via events
|
||||
final void Function(Message, ChannelModel) showLocalNotification;
|
||||
|
||||
/// The amount of time that will pass before disconnecting the client in the background
|
||||
final Duration backgroundKeepAlive;
|
||||
|
||||
/// This client state
|
||||
ClientState state;
|
||||
|
||||
|
||||
@@ -277,9 +277,6 @@ class _AdvancedOptionsPageState extends State<AdvancedOptionsPage> {
|
||||
final client = Client(
|
||||
apiKey,
|
||||
logLevel: Level.INFO,
|
||||
showLocalNotification: (!kIsWeb && Platform.isAndroid)
|
||||
? showLocalNotification
|
||||
: null,
|
||||
)..chatPersistenceClient = chatPersistentClient;
|
||||
|
||||
try {
|
||||
|
||||
@@ -33,8 +33,6 @@ void main() async {
|
||||
final client = Client(
|
||||
apiKey ?? kDefaultStreamApiKey,
|
||||
logLevel: Level.INFO,
|
||||
showLocalNotification:
|
||||
(!kIsWeb && Platform.isAndroid) ? showLocalNotification : null,
|
||||
)..chatPersistenceClient = chatPersistentClient;
|
||||
|
||||
if (userId != null) {
|
||||
@@ -73,6 +71,7 @@ class MyApp extends StatelessWidget {
|
||||
builder: (context, child) {
|
||||
return StreamChat(
|
||||
client: client,
|
||||
onBackgroundEventReceived: showLocalNotification,
|
||||
child: Builder(
|
||||
builder: (context) => AnnotatedRegion<SystemUiOverlayStyle>(
|
||||
child: child,
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:example/main.dart';
|
||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||
import 'package:flutter_apns/flutter_apns.dart';
|
||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart'
|
||||
hide Message;
|
||||
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
||||
|
||||
void showLocalNotification(Message message, ChannelModel channel) async {
|
||||
void showLocalNotification(Event event) async {
|
||||
if (event.message == null) return;
|
||||
final flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
|
||||
final initializationSettingsAndroid =
|
||||
AndroidInitializationSettings('launch_background');
|
||||
@@ -17,9 +19,9 @@ void showLocalNotification(Message message, ChannelModel channel) async {
|
||||
);
|
||||
await flutterLocalNotificationsPlugin.initialize(initializationSettings);
|
||||
await flutterLocalNotificationsPlugin.show(
|
||||
message.id.hashCode,
|
||||
'${message.user.name} @ ${channel.name}',
|
||||
message.text,
|
||||
event.message.id.hashCode,
|
||||
event.message.user.name,
|
||||
event.message.text,
|
||||
NotificationDetails(
|
||||
android: AndroidNotificationDetails(
|
||||
'message channel',
|
||||
@@ -35,24 +37,24 @@ void showLocalNotification(Message message, ChannelModel channel) async {
|
||||
|
||||
Future backgroundHandler(Map<String, dynamic> notification) async {
|
||||
print('new notification ${notification}');
|
||||
final messageId = notification['data']['id'];
|
||||
|
||||
final notificationData = await NotificationService.getAndStoreMessage(
|
||||
messageId: messageId,
|
||||
storeMessageHandler: (messageResponse) {
|
||||
return chatPersistentClient.updateChannelState(
|
||||
ChannelState(
|
||||
messages: [messageResponse.message],
|
||||
channel: messageResponse.channel,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
showLocalNotification(
|
||||
notificationData.message,
|
||||
notificationData.channel,
|
||||
);
|
||||
// final messageId = notification['data']['id'];
|
||||
//
|
||||
// final notificationData = await NotificationService.getAndStoreMessage(
|
||||
// messageId: messageId,
|
||||
// storeMessageHandler: (messageResponse) {
|
||||
// return chatPersistentClient.updateChannelState(
|
||||
// ChannelState(
|
||||
// messages: [messageResponse.message],
|
||||
// channel: messageResponse.channel,
|
||||
// ),
|
||||
// );
|
||||
// },
|
||||
// );
|
||||
//
|
||||
// showLocalNotification(
|
||||
// notificationData.message,
|
||||
// notificationData.channel,
|
||||
// );
|
||||
}
|
||||
|
||||
void initNotifications(Client client) {
|
||||
|
||||
@@ -34,11 +34,21 @@ class StreamChat extends StatefulWidget {
|
||||
final Widget child;
|
||||
final StreamChatThemeData streamChatThemeData;
|
||||
|
||||
/// The amount of time that will pass before disconnecting the client in the background
|
||||
final Duration backgroundKeepAlive;
|
||||
|
||||
/// Handler called whenever the [client] receives a new [Event] while the app
|
||||
/// is in background. Can be used to display various notifications depending
|
||||
/// upon the [Event.type]
|
||||
final EventHandler onBackgroundEventReceived;
|
||||
|
||||
StreamChat({
|
||||
Key key,
|
||||
@required this.client,
|
||||
@required this.child,
|
||||
this.streamChatThemeData,
|
||||
this.onBackgroundEventReceived,
|
||||
this.backgroundKeepAlive = const Duration(minutes: 1),
|
||||
}) : super(
|
||||
key: key,
|
||||
);
|
||||
@@ -82,8 +92,10 @@ class StreamChatState extends State<StreamChat> {
|
||||
scaffoldBackgroundColor: streamTheme.colorTheme.white,
|
||||
),
|
||||
child: StreamChatCore(
|
||||
child: widget.child,
|
||||
client: client,
|
||||
child: widget.child,
|
||||
onBackgroundEventReceived: widget.onBackgroundEventReceived,
|
||||
backgroundKeepAlive: widget.backgroundKeepAlive,
|
||||
),
|
||||
);
|
||||
},
|
||||
|
||||
@@ -4,6 +4,8 @@ import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:stream_chat/stream_chat.dart';
|
||||
|
||||
typedef EventHandler = void Function(Event event);
|
||||
|
||||
/// Widget used to provide information about the chat to the widget tree
|
||||
///
|
||||
/// class MyApp extends StatelessWidget {
|
||||
@@ -28,17 +30,26 @@ import 'package:stream_chat/stream_chat.dart';
|
||||
class StreamChatCore extends StatefulWidget {
|
||||
// ignore: public_member_api_docs
|
||||
final Client client;
|
||||
|
||||
// ignore: public_member_api_docs
|
||||
final Widget child;
|
||||
|
||||
/// The amount of time that will pass before disconnecting the client in the background
|
||||
final Duration backgroundKeepAlive;
|
||||
|
||||
/// Handler called whenever the [client] receives a new [Event] while the app
|
||||
/// is in background. Can be used to display various notifications depending
|
||||
/// upon the [Event.type]
|
||||
final EventHandler onBackgroundEventReceived;
|
||||
|
||||
// ignore: public_member_api_docs
|
||||
StreamChatCore({
|
||||
Key key,
|
||||
@required this.client,
|
||||
@required this.child,
|
||||
}) : super(
|
||||
key: key,
|
||||
);
|
||||
this.onBackgroundEventReceived,
|
||||
this.backgroundKeepAlive = const Duration(minutes: 1),
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
StreamChatCoreState createState() => StreamChatCoreState();
|
||||
@@ -82,56 +93,28 @@ class StreamChatCoreState extends State<StreamChatCore>
|
||||
WidgetsBinding.instance.addObserver(this);
|
||||
}
|
||||
|
||||
StreamSubscription _newMessageSubscription;
|
||||
StreamSubscription _eventSubscription;
|
||||
|
||||
@override
|
||||
void didChangeAppLifecycleState(AppLifecycleState state) {
|
||||
if (client.state?.user != null) {
|
||||
if (state == AppLifecycleState.paused) {
|
||||
if (client.showLocalNotification != null) {
|
||||
_newMessageSubscription = client
|
||||
.on(EventType.messageNew)
|
||||
.where((e) => e.user?.id != user.id)
|
||||
.where((e) => e.message.silent != true)
|
||||
.where((e) => e.message.shadowed != true)
|
||||
.listen((event) async {
|
||||
final channel = client.channel(
|
||||
event.channelType,
|
||||
id: event.channelId,
|
||||
);
|
||||
|
||||
client.showLocalNotification(
|
||||
event.message,
|
||||
ChannelModel(
|
||||
id: channel.id,
|
||||
createdAt: channel.createdAt,
|
||||
extraData: channel.extraData,
|
||||
type: channel.type,
|
||||
memberCount: channel.memberCount,
|
||||
frozen: channel.frozen,
|
||||
cid: channel.cid,
|
||||
deletedAt: channel.deletedAt,
|
||||
config: channel.config,
|
||||
createdBy: channel.createdBy,
|
||||
updatedAt: channel.updatedAt,
|
||||
lastMessageAt: channel.lastMessageAt,
|
||||
),
|
||||
);
|
||||
});
|
||||
_disconnectTimer = Timer(client.backgroundKeepAlive, () {
|
||||
client.disconnect();
|
||||
});
|
||||
if (widget.onBackgroundEventReceived != null) {
|
||||
_eventSubscription =
|
||||
client.on().listen(widget.onBackgroundEventReceived);
|
||||
_disconnectTimer = Timer(
|
||||
widget.backgroundKeepAlive,
|
||||
client.disconnect,
|
||||
);
|
||||
} else {
|
||||
client.disconnect();
|
||||
}
|
||||
} else if (state == AppLifecycleState.resumed) {
|
||||
_newMessageSubscription?.cancel();
|
||||
_eventSubscription?.cancel();
|
||||
if (_disconnectTimer?.isActive == true) {
|
||||
_disconnectTimer.cancel();
|
||||
} else {
|
||||
if (client.wsConnectionStatus.value ==
|
||||
ConnectionStatus.disconnected) {
|
||||
NotificationService.handleIosMessageQueue(client);
|
||||
if (client.wsConnectionStatus == ConnectionStatus.disconnected) {
|
||||
client.connect();
|
||||
}
|
||||
}
|
||||
@@ -142,6 +125,7 @@ class StreamChatCoreState extends State<StreamChatCore>
|
||||
@override
|
||||
void dispose() {
|
||||
WidgetsBinding.instance.removeObserver(this);
|
||||
_eventSubscription?.cancel();
|
||||
_disconnectTimer?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import 'package:mockito/mockito.dart';
|
||||
import 'mocks.dart';
|
||||
|
||||
class MockShowLocalNotifications extends Mock {
|
||||
void call(Message m, ChannelModel cm);
|
||||
void call(Event event);
|
||||
}
|
||||
|
||||
void main() {
|
||||
@@ -97,14 +97,8 @@ void main() {
|
||||
),
|
||||
);
|
||||
final showLocalNotificationMock = MockShowLocalNotifications().call;
|
||||
when(client.showLocalNotification)
|
||||
.thenReturn(showLocalNotificationMock);
|
||||
when(client.backgroundKeepAlive).thenReturn(Duration(
|
||||
seconds: 4,
|
||||
));
|
||||
final eventStreamController = StreamController<Event>();
|
||||
when(client.on(EventType.messageNew))
|
||||
.thenAnswer((_) => eventStreamController.stream);
|
||||
when(client.on()).thenAnswer((_) => eventStreamController.stream);
|
||||
|
||||
when(client.channel('test', id: 'testid')).thenReturn(channel);
|
||||
|
||||
@@ -113,6 +107,8 @@ void main() {
|
||||
StreamChatCore(
|
||||
key: scKey,
|
||||
client: client,
|
||||
onBackgroundEventReceived: showLocalNotificationMock,
|
||||
backgroundKeepAlive: const Duration(seconds: 4),
|
||||
child: Builder(
|
||||
builder: (context) {
|
||||
return Container();
|
||||
@@ -144,13 +140,8 @@ void main() {
|
||||
),
|
||||
);
|
||||
final showLocalNotificationMock = MockShowLocalNotifications().call;
|
||||
when(client.showLocalNotification).thenReturn(showLocalNotificationMock);
|
||||
when(client.backgroundKeepAlive).thenReturn(Duration(
|
||||
seconds: 4,
|
||||
));
|
||||
final eventStreamController = StreamController<Event>();
|
||||
when(client.on(EventType.messageNew))
|
||||
.thenAnswer((_) => eventStreamController.stream);
|
||||
when(client.on()).thenAnswer((_) => eventStreamController.stream);
|
||||
|
||||
when(client.channel('test', id: 'testid')).thenReturn(channel);
|
||||
|
||||
@@ -159,6 +150,8 @@ void main() {
|
||||
StreamChatCore(
|
||||
key: scKey,
|
||||
client: client,
|
||||
onBackgroundEventReceived: showLocalNotificationMock,
|
||||
backgroundKeepAlive: const Duration(seconds: 4),
|
||||
child: Builder(
|
||||
builder: (context) {
|
||||
return Container();
|
||||
@@ -178,12 +171,9 @@ void main() {
|
||||
);
|
||||
eventStreamController.add(event);
|
||||
|
||||
await untilCalled(showLocalNotificationMock(any, any));
|
||||
await untilCalled(showLocalNotificationMock(event));
|
||||
|
||||
verify(showLocalNotificationMock(
|
||||
event.message,
|
||||
any,
|
||||
)).called(1);
|
||||
verify(showLocalNotificationMock(event)).called(1);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user