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/utils/reactquery.ts b/client/src/utils/reactquery.ts
new file mode 100644
index 0000000..6ae5f71
--- /dev/null
+++ b/client/src/utils/reactquery.ts
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2022 Savoir-faire Linux Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this program. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+import { QueryKey, useQueryClient } from '@tanstack/react-query';
+import { useCallback } from 'react';
+
+// Test whether two elements are equals or not
+// Return 'true' if they are equal, 'false' otherwise
+export type CheckElementsAreEqual<ElementType> = (element1: ElementType, element2: ElementType) => boolean;
+
+type AddToCacheFn<ElementType> = (element: ElementType) => void;
+
+export const useAddToCache = <ElementType>(
+ queryKey: QueryKey,
+ CheckElementsAreEqual: CheckElementsAreEqual<ElementType>
+): AddToCacheFn<ElementType> => {
+ const queryClient = useQueryClient();
+ return useCallback(
+ (newElement: ElementType) => {
+ // Make sure the element is not already in the cache
+ // This is expected to happen all the time on strict mode
+ const data = queryClient.getQueryData<ElementType[]>(queryKey);
+ if (data?.find((element) => CheckElementsAreEqual(element, newElement))) {
+ return;
+ }
+
+ // Add the element
+ queryClient.setQueryData<ElementType[]>(queryKey, (elements) => [...(elements || []), newElement]);
+ },
+ [CheckElementsAreEqual, queryClient, queryKey]
+ );
+};
+
+// Check whether the passed element is the one we are looking for or not
+type CheckIsElementFn<ElementType, IdentifierType> = (element: ElementType, identifier: IdentifierType) => boolean;
+
+type RemoveFromCacheFn<IdentifierType> = (element: IdentifierType) => void;
+
+export const useRemoveFromCache = <ElementType, IdentifierType>(
+ queryKey: QueryKey,
+ checkIsElementFn: CheckIsElementFn<ElementType, IdentifierType>
+): RemoveFromCacheFn<IdentifierType> => {
+ const queryClient = useQueryClient();
+ return useCallback(
+ (identifier: IdentifierType) => {
+ queryClient.setQueryData<ElementType[]>(queryKey, (elements) =>
+ elements?.filter((element) => !checkIsElementFn(element, identifier))
+ );
+ },
+ [checkIsElementFn, queryClient, queryKey]
+ );
+};