blob: c02a1b3452477500e3b92c1d0757aa516b937671 [file] [log] [blame]
simon21f7d9f2022-11-28 14:21:54 -05001/*
2 * Copyright (C) 2022 Savoir-faire Linux Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Affero General Public License as
6 * published by the Free Software Foundation; either version 3 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Affero General Public License for more details.
13 *
14 * You should have received a copy of the GNU Affero General Public
15 * License along with this program. If not, see
16 * <https://www.gnu.org/licenses/>.
17 */
Misha Krieger-Raynauldcfa44302022-11-30 18:36:36 -050018import { ConversationMessage, IConversation, LookupResult, WebSocketMessageType } from 'jami-web-common';
simon5c677962022-12-02 16:51:54 -050019import { createContext, ReactNode, useContext, useEffect, useMemo, useState } from 'react';
simon21f7d9f2022-11-28 14:21:54 -050020
Misha Krieger-Raynauldcfa44302022-11-30 18:36:36 -050021import { Contact } from '../models/contact';
22import { Conversation } from '../models/conversation';
simon21f7d9f2022-11-28 14:21:54 -050023import { setRefreshFromSlice } from '../redux/appSlice';
24import { useAppDispatch, useAppSelector } from '../redux/hooks';
25import { SetState } from '../utils/utils';
26import { useAuthContext } from './AuthProvider';
27import { WebSocketContext } from './WebSocketProvider';
28
29export interface IMessengerContext {
30 conversations: Conversation[] | undefined;
31
32 setSearchQuery: SetState<string | undefined>;
33
34 searchResult: Conversation | undefined;
35
36 newContactId: string | undefined;
37 setNewContactId: SetState<string | undefined>;
38}
39
40const defaultMessengerContext: IMessengerContext = {
41 conversations: undefined,
42 newContactId: undefined,
43 setNewContactId: () => {},
44 setSearchQuery: () => {},
45 searchResult: undefined,
46};
47
48export const MessengerContext = createContext<IMessengerContext>(defaultMessengerContext);
49
50export default ({ children }: { children: ReactNode }) => {
51 const { refresh } = useAppSelector((state) => state.userInfo);
52 const dispatch = useAppDispatch();
53 const { accountId, axiosInstance } = useAuthContext();
54 const webSocket = useContext(WebSocketContext);
55
56 const [conversations, setConversations] = useState<Conversation[] | undefined>(undefined);
57 const [searchQuery, setSearchQuery] = useState<string>();
58 const [searchResult, setSearchResults] = useState<Conversation | undefined>(undefined);
59 const [newContactId, setNewContactId] = useState<string>();
60
61 useEffect(() => {
62 const controller = new AbortController();
63 axiosInstance
Misha Krieger-Raynauldcfa44302022-11-30 18:36:36 -050064 .get<IConversation[]>('/conversations', {
simon21f7d9f2022-11-28 14:21:54 -050065 signal: controller.signal,
66 })
67 .then(({ data }) => {
Misha Krieger-Raynauldcfa44302022-11-30 18:36:36 -050068 setConversations(
69 Object.values(data).map((conversationInterface) => Conversation.fromInterface(conversationInterface))
70 );
simon21f7d9f2022-11-28 14:21:54 -050071 });
72 // return () => controller.abort()
73 }, [axiosInstance, accountId, refresh]);
74
75 useEffect(() => {
76 if (!webSocket) {
77 return;
78 }
79
80 const conversationMessageListener = (_data: ConversationMessage) => {
81 dispatch(setRefreshFromSlice());
82 };
83
84 webSocket.bind(WebSocketMessageType.ConversationMessage, conversationMessageListener);
85
86 return () => {
87 webSocket.unbind(WebSocketMessageType.ConversationMessage, conversationMessageListener);
88 };
89 }, [webSocket, dispatch]);
90
91 useEffect(() => {
92 if (!searchQuery) return;
93 const controller = new AbortController();
simon21f7d9f2022-11-28 14:21:54 -050094 axiosInstance
Misha Krieger-Raynauldcfa44302022-11-30 18:36:36 -050095 .get<LookupResult>(`/ns/username/${searchQuery}`, {
simon21f7d9f2022-11-28 14:21:54 -050096 signal: controller.signal,
97 })
98 .then(({ data }) => {
Misha Krieger-Raynauldcfa44302022-11-30 18:36:36 -050099 const contact = new Contact(data.address, data.username);
100 setSearchResults(contact ? Conversation.fromSingleContact(contact) : undefined);
simon21f7d9f2022-11-28 14:21:54 -0500101 })
102 .catch(() => {
103 setSearchResults(undefined);
104 });
105 // return () => controller.abort() // crash on React18
106 }, [accountId, searchQuery, axiosInstance]);
107
simon5c677962022-12-02 16:51:54 -0500108 const value = useMemo(
109 () => ({
110 conversations,
111 setSearchQuery,
112 searchResult,
113 newContactId,
114 setNewContactId,
115 }),
116 [conversations, setSearchQuery, searchResult, newContactId, setNewContactId]
simon21f7d9f2022-11-28 14:21:54 -0500117 );
simon5c677962022-12-02 16:51:54 -0500118
119 return <MessengerContext.Provider value={value}>{children}</MessengerContext.Provider>;
simon21f7d9f2022-11-28 14:21:54 -0500120};