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: 66 67 98.5 %
Date: Tue Jul 13 13:39:38 2021 Functions: 0 0 -

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

Generated by: LCOV version 1.15.alpha0w