Add conversation requests list

- Add routes to REST API for conversation requests
- Add websocket notification on new conversation requests. This is unreliable.
- Rename 'ColoredCallButton' as 'ColoredRoundButton' and move it to Buttons file for reuse
- Review logic to show conversation tabs
- Add useConversationDisplayNameShort for conversations' names in lists. Will need more work.
- Add hooks to help managing React Query's cache
- Use React Query to remove conversations and update the cache doing so.
- Add ContactService and ConversationService as a way to group reusable functions for the server. This is inspired by jami-android

Known bug: The server often freezes on getContactFromUri (in ContactService) when a new conversation request is received.

Change-Id: I46a60a401f09c3941c864afcdb2625b5fcfe054a
diff --git a/client/src/contexts/MessengerProvider.tsx b/client/src/contexts/MessengerProvider.tsx
index fba24dc..2f86ad9 100644
--- a/client/src/contexts/MessengerProvider.tsx
+++ b/client/src/contexts/MessengerProvider.tsx
@@ -15,10 +15,10 @@
  * License along with this program.  If not, see
  * <https://www.gnu.org/licenses/>.
  */
-import { ConversationMessage, WebSocketMessageType } from 'jami-web-common';
+import { ConversationMessage, IConversationRequest, WebSocketMessageType } from 'jami-web-common';
 import { createContext, ReactNode, useContext, useEffect, useMemo } from 'react';
 
-import { useRefreshConversationsSummaries } from '../services/conversationQueries';
+import { useAddConversationRequestToCache, useRefreshConversationsSummaries } from '../services/conversationQueries';
 import { WebSocketContext } from './WebSocketProvider';
 
 // It is not sure yet we want this context to have no value
@@ -33,6 +33,7 @@
   const webSocket = useContext(WebSocketContext);
 
   const refreshConversationsSummaries = useRefreshConversationsSummaries();
+  const addConversationRequestToCache = useAddConversationRequestToCache();
 
   useEffect(() => {
     if (!webSocket) {
@@ -43,12 +44,18 @@
       refreshConversationsSummaries();
     };
 
+    const conversationRequestListener = (conversationRequest: IConversationRequest) => {
+      addConversationRequestToCache(conversationRequest);
+    };
+
     webSocket.bind(WebSocketMessageType.ConversationMessage, conversationMessageListener);
+    webSocket.bind(WebSocketMessageType.ConversationRequest, conversationRequestListener);
 
     return () => {
       webSocket.unbind(WebSocketMessageType.ConversationMessage, conversationMessageListener);
+      webSocket.unbind(WebSocketMessageType.ConversationRequest, conversationRequestListener);
     };
-  }, [refreshConversationsSummaries, webSocket]);
+  }, [addConversationRequestToCache, refreshConversationsSummaries, webSocket]);
 
   const value = useMemo<IMessengerContext>(() => ({}), []);