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/components/CallButtons.tsx b/client/src/components/CallButtons.tsx
index 9243c33..0b179bd 100644
--- a/client/src/components/CallButtons.tsx
+++ b/client/src/components/CallButtons.tsx
@@ -16,16 +16,16 @@
  * <https://www.gnu.org/licenses/>.
  */
 
-import { IconButton, IconButtonProps, PaletteColor } from '@mui/material';
-import { styled, Theme } from '@mui/material/styles';
+import { IconButtonProps } from '@mui/material';
+import { styled } from '@mui/material/styles';
 import { ChangeEvent, useMemo } from 'react';
 
 import { CallStatus, useCallContext, VideoStatus } from '../contexts/CallProvider';
 import {
+  ColoredRoundButton,
   ExpandableButton,
   ExpandableButtonProps,
   ExpandMenuRadioOption,
-  ShapedButtonProps,
   ToggleIconButton,
 } from './Button';
 import {
@@ -56,37 +56,6 @@
   },
 });
 
-const ColoredCallButton = styled(
-  ({
-    paletteColor,
-    Icon,
-    ...props
-  }: ShapedButtonProps & {
-    paletteColor?: PaletteColor | ((theme: Theme) => PaletteColor);
-  }) => {
-    return (
-      <IconButton {...props} disableRipple={true}>
-        <Icon fontSize="inherit" />
-      </IconButton>
-    );
-  }
-)(({ theme, paletteColor = theme.palette.primary }) => {
-  if (typeof paletteColor === 'function') {
-    paletteColor = paletteColor(theme);
-  }
-
-  return {
-    color: paletteColor.contrastText,
-    backgroundColor: paletteColor.dark,
-    '&:hover': {
-      backgroundColor: paletteColor.main,
-    },
-    '&:disabled': {
-      backgroundColor: theme.palette.action.disabled,
-    },
-  };
-});
-
 export const CallingChatButton = (props: ExpandableButtonProps) => {
   const { setIsChatShown } = useCallContext();
   return (
@@ -104,7 +73,7 @@
 export const CallingEndButton = (props: ExpandableButtonProps) => {
   const { endCall } = useCallContext();
   return (
-    <ColoredCallButton
+    <ColoredRoundButton
       paletteColor={(theme) => theme.palette.error}
       onClick={() => {
         endCall();
@@ -269,7 +238,7 @@
   const { endCall } = useCallContext();
 
   return (
-    <ColoredCallButton
+    <ColoredRoundButton
       aria-label="cancel call"
       onClick={() => {
         endCall();
@@ -285,7 +254,7 @@
   const { acceptCall, callStatus } = useCallContext();
 
   return (
-    <ColoredCallButton
+    <ColoredRoundButton
       disabled={callStatus === CallStatus.Loading || callStatus === CallStatus.Connecting}
       aria-label="answer call audio"
       onClick={() => {
@@ -301,7 +270,7 @@
 export const CallingAnswerVideoButton = (props: IconButtonProps) => {
   const { acceptCall, callStatus } = useCallContext();
   return (
-    <ColoredCallButton
+    <ColoredRoundButton
       disabled={callStatus === CallStatus.Connecting || callStatus === CallStatus.Loading}
       aria-label="answer call video"
       onClick={() => {
@@ -317,7 +286,7 @@
 export const CallingRefuseButton = (props: IconButtonProps) => {
   const { endCall } = useCallContext();
   return (
-    <ColoredCallButton
+    <ColoredRoundButton
       aria-label="refuse call"
       onClick={() => {
         endCall();