import 'dart:convert'; import 'package:logging/logging.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:stream_chat/src/api/responses.dart'; import 'package:stream_chat/src/db/offline_storage.dart'; import 'package:stream_chat/src/models/channel_model.dart'; import 'package:stream_chat/src/models/channel_state.dart'; import 'package:stream_chat/src/models/message.dart'; import 'client.dart'; import 'models/own_user.dart'; /// Utility class to handle and show notifications class NotificationService { static Future _handleNotification( Message message, ChannelModel channelModel, Client client, ) async { if (message != null && client.persistenceEnabled) { if (client?.state?.channels == null) { final sharedPreferences = await _getSharedPreferences(); final userId = sharedPreferences.getString(KEY_USER_ID); final offlineStorage = OfflineStorage(userId, Logger('💽')); await offlineStorage.updateChannelState( ChannelState( channel: channelModel, messages: [message], ), ); await offlineStorage.disconnect(); } else { final channel = client.state.channels[channelModel.cid]; channel.state.updateChannelState( ChannelState( channel: channelModel, messages: [message], ), ); } } } static SharedPreferences _sharedPreferences; static Future _getSharedPreferences() async { _sharedPreferences ??= await SharedPreferences.getInstance(); return _sharedPreferences; } /// Gets the message using the client without storing it in the offline storage /// It returns an object containing the information about the message and the channel static Future getMessage(String messageId) async { final sharedPreferences = await _getSharedPreferences(); final apiKey = sharedPreferences.getString(KEY_API_KEY); final client = Client( apiKey, persistenceEnabled: false, ); final userId = sharedPreferences.getString(KEY_USER_ID); final token = sharedPreferences.getString(KEY_TOKEN); client.state.user = OwnUser(id: userId); client.token = token; final res = await client.getMessage(messageId); return res; } /// Stores the message in the offline storage static Future storeMessage(GetMessageResponse messageResponse) async { final sharedPreferences = await _getSharedPreferences(); final userId = sharedPreferences.getString(KEY_USER_ID); final offlineStorage = OfflineStorage( userId, Logger('💽'), ); await offlineStorage.updateChannelState(ChannelState( messages: [messageResponse.message], channel: messageResponse.channel, )); await offlineStorage.disconnect(); } /// Gets the message using the client and stores it in the offline storage /// It returns an object containing the information about the message and the channel static Future getAndStoreMessage(String messageId) async { final getMessageResponse = await getMessage(messageId); await storeMessage(getMessageResponse); return getMessageResponse; } /// Handles the ios message queue generated by the Notification Service Extension static Future handleIosMessageQueue(Client client) async { final sharedPreferences = await SharedPreferences.getInstance(); await sharedPreferences.reload(); final messageQueue = sharedPreferences.getStringList('messageQueue'); if (messageQueue != null) { messageQueue.forEach((m) { final jsonMessage = jsonDecode(m); final message = Message.fromJson(jsonMessage); final channelModel = ChannelModel.fromJson(jsonMessage['channel']); _handleNotification( message, channelModel, client, ); }); await sharedPreferences.remove('messageQueue'); } } }