LCOV - code coverage report
Current view: top level - lib\data\chatwoot_repository.dart - chatwoot_repository.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 76 79 96.2 %
Date: Thu Jul 15 17:16:16 2021 Functions: 0 0 -

          Line data    Source code
       1             : import 'dart:async';
       2             : import 'dart:convert';
       3             : import 'dart:core';
       4             : 
       5             : import 'package:chatwoot_client_sdk/chatwoot_callbacks.dart';
       6             : import 'package:chatwoot_client_sdk/chatwoot_client.dart';
       7             : import 'package:chatwoot_client_sdk/data/local/entity/chatwoot_user.dart';
       8             : import 'package:chatwoot_client_sdk/data/local/local_storage.dart';
       9             : import 'package:chatwoot_client_sdk/data/remote/chatwoot_client_exception.dart';
      10             : import 'package:chatwoot_client_sdk/data/remote/requests/chatwoot_action_data.dart';
      11             : import 'package:chatwoot_client_sdk/data/remote/requests/chatwoot_new_message_request.dart';
      12             : import 'package:chatwoot_client_sdk/data/remote/responses/chatwoot_event.dart';
      13             : import 'package:chatwoot_client_sdk/data/remote/service/chatwoot_client_service.dart';
      14             : import 'package:flutter/material.dart';
      15             : 
      16             : /// Handles interactions between chatwoot client api service[clientService] and
      17             : /// [localStorage] if persistence is enabled.
      18             : ///
      19             : /// Results from repository operations are passed through [callbacks] to be handled
      20             : /// appropriately
      21             : abstract class ChatwootRepository {
      22             :   @protected
      23             :   final ChatwootClientService clientService;
      24             :   @protected
      25             :   final LocalStorage localStorage;
      26             :   @protected
      27             :   ChatwootCallbacks callbacks;
      28             :   List<StreamSubscription> _subscriptions = [];
      29             : 
      30           1 :   ChatwootRepository(this.clientService, this.localStorage, this.callbacks);
      31             : 
      32             :   Future<void> initialize(ChatwootUser? user);
      33             : 
      34             :   void getPersistedMessages();
      35             : 
      36             :   Future<void> getMessages();
      37             : 
      38             :   void listenForEvents();
      39             : 
      40             :   Future<void> sendMessage(ChatwootNewMessageRequest request);
      41             : 
      42             :   void sendAction(ChatwootActionType action);
      43             : 
      44             :   Future<void> clear();
      45             : 
      46             :   void dispose();
      47             : }
      48             : 
      49             : class ChatwootRepositoryImpl extends ChatwootRepository {
      50             :   bool _isListeningForEvents = false;
      51             : 
      52           1 :   ChatwootRepositoryImpl(
      53             :       {required ChatwootClientService clientService,
      54             :       required LocalStorage localStorage,
      55             :       required ChatwootCallbacks streamCallbacks})
      56           1 :       : super(clientService, localStorage, streamCallbacks);
      57             : 
      58             :   /// Fetches persisted messages.
      59             :   ///
      60             :   /// Calls [ChatwootCallbacks.onMessagesRetrieved] when [ChatwootClientService.getAllMessages] is successful
      61             :   /// Calls [ChatwootCallbacks.onError] when [ChatwootClientService.getAllMessages] fails
      62             :   @override
      63           1 :   Future<void> getMessages() async {
      64             :     try {
      65           3 :       final messages = await clientService.getAllMessages();
      66           4 :       await localStorage.messagesDao.saveAllMessages(messages);
      67           3 :       callbacks.onMessagesRetrieved?.call(messages);
      68           1 :     } on ChatwootClientException catch (e) {
      69           3 :       callbacks.onError?.call(e);
      70             :     }
      71             :   }
      72             : 
      73             :   /// Fetches persisted messages.
      74             :   ///
      75             :   /// Calls [ChatwootCallbacks.onPersistedMessagesRetrieved] if persisted messages are found
      76           1 :   @override
      77             :   void getPersistedMessages() {
      78           3 :     final persistedMessages = localStorage.messagesDao.getMessages();
      79           1 :     if (persistedMessages.isNotEmpty) {
      80           3 :       callbacks.onPersistedMessagesRetrieved?.call(persistedMessages);
      81             :     }
      82             :   }
      83             : 
      84             :   /// Initializes chatwoot client repository
      85           1 :   Future<void> initialize(ChatwootUser? user) async {
      86             :     try {
      87             :       if (user != null) {
      88           4 :         await localStorage.userDao.saveUser(user);
      89             :       }
      90             : 
      91             :       //refresh contact
      92           3 :       final contact = await clientService.getContact();
      93           3 :       localStorage.contactDao.saveContact(contact);
      94             : 
      95             :       //refresh conversation
      96           3 :       final conversations = await clientService.getConversations();
      97             :       final persistedConversation =
      98           3 :           localStorage.conversationDao.getConversation()!;
      99           1 :       final refreshedConversation = conversations.firstWhere(
     100           4 :           (element) => element.id == persistedConversation.id,
     101           0 :           orElse: () =>
     102             :               persistedConversation //highly unlikely orElse will be called but still added it just in case
     103             :           );
     104           3 :       localStorage.conversationDao.saveConversation(refreshedConversation);
     105           0 :     } on ChatwootClientException catch (e) {
     106           0 :       callbacks.onError?.call(e);
     107             :     }
     108             : 
     109           1 :     listenForEvents();
     110             :   }
     111             : 
     112             :   ///Sends message to chatwoot inbox
     113           1 :   Future<void> sendMessage(ChatwootNewMessageRequest request) async {
     114             :     try {
     115           3 :       final createdMessage = await clientService.createMessage(request);
     116           4 :       await localStorage.messagesDao.saveMessage(createdMessage);
     117           4 :       callbacks.onMessageSent?.call(createdMessage, request.echoId);
     118           3 :       if (clientService.connection != null && !_isListeningForEvents) {
     119           1 :         listenForEvents();
     120             :       }
     121           1 :     } on ChatwootClientException catch (e) {
     122           3 :       callbacks.onError?.call(
     123           4 :           ChatwootClientException(e.cause, e.type, data: request.echoId));
     124             :     }
     125             :   }
     126             : 
     127             :   /// Connects to chatwoot websocket and starts listening for updates
     128             :   ///
     129             :   /// Received events/messages are pushed through [ChatwootClient.callbacks]
     130           1 :   @override
     131             :   void listenForEvents() {
     132           4 :     final token = localStorage.contactDao.getContact()?.pubsubToken;
     133             :     if (token == null) {
     134             :       return;
     135             :     }
     136           2 :     clientService.startWebSocketConnection(
     137           4 :         localStorage.contactDao.getContact()!.pubsubToken);
     138             : 
     139           5 :     final newSubscription = clientService.connection!.stream.listen((event) {
     140           2 :       ChatwootEvent chatwootEvent = ChatwootEvent.fromJson(jsonDecode(event));
     141           2 :       if (chatwootEvent.type == ChatwootEventType.welcome) {
     142           3 :         callbacks.onWelcome?.call();
     143           2 :       } else if (chatwootEvent.type == ChatwootEventType.ping) {
     144           3 :         callbacks.onPing?.call();
     145           2 :       } else if (chatwootEvent.type == ChatwootEventType.confirm_subscription) {
     146           1 :         if (!_isListeningForEvents) {
     147           1 :           _isListeningForEvents = true;
     148             :         }
     149           3 :         callbacks.onConfirmedSubscription?.call();
     150           3 :       } else if (chatwootEvent.message?.event ==
     151             :           ChatwootEventMessageType.message_created) {
     152           2 :         print("here comes message: $event");
     153           3 :         final message = chatwootEvent.message!.data!.getMessage();
     154           3 :         localStorage.messagesDao.saveMessage(message);
     155           1 :         if (message.isMine) {
     156           2 :           callbacks.onMessageDelivered
     157           4 :               ?.call(message, chatwootEvent.message!.data!.echoId!);
     158             :         } else {
     159           3 :           callbacks.onMessageReceived?.call(message);
     160             :         }
     161           3 :       } else if (chatwootEvent.message?.event ==
     162             :           ChatwootEventMessageType.conversation_typing_off) {
     163           3 :         callbacks.onConversationStoppedTyping?.call();
     164           3 :       } else if (chatwootEvent.message?.event ==
     165             :           ChatwootEventMessageType.conversation_typing_on) {
     166           3 :         callbacks.onConversationStartedTyping?.call();
     167           3 :       } else if (chatwootEvent.message?.event ==
     168             :           ChatwootEventMessageType.presence_update) {
     169             :         final presenceStatuses =
     170           3 :             (chatwootEvent.message!.data!.users as Map<dynamic, dynamic>)
     171           1 :                 .values;
     172           1 :         final isOnline = presenceStatuses.contains("online");
     173             :         if (isOnline) {
     174           3 :           callbacks.onConversationIsOnline?.call();
     175             :         } else {
     176           3 :           callbacks.onConversationIsOffline?.call();
     177             :         }
     178             :       } else {
     179           2 :         print("chatwoot unknown event: $event");
     180             :       }
     181             :     });
     182           2 :     _subscriptions.add(newSubscription);
     183             :   }
     184             : 
     185             :   /// Clears all data related to current chatwoot client instance
     186             :   @override
     187           1 :   Future<void> clear() async {
     188           3 :     await localStorage.clear();
     189             :   }
     190             : 
     191             :   /// Cancels websocket stream subscriptions and disposes [localStorage]
     192           1 :   @override
     193             :   void dispose() {
     194           2 :     localStorage.dispose();
     195           2 :     callbacks = ChatwootCallbacks();
     196           3 :     _subscriptions.forEach((subs) {
     197           1 :       subs.cancel();
     198             :     });
     199             :   }
     200             : 
     201             :   ///Send actions like user started typing
     202           1 :   @override
     203             :   void sendAction(ChatwootActionType action) {
     204           2 :     clientService.sendAction(
     205           4 :         localStorage.contactDao.getContact()!.pubsubToken, action);
     206             :   }
     207             : }

Generated by: LCOV version 1.15.alpha0w