blob: 3ec6164cc150f9b7bc3d63843272dfc16b64cc64 [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-Raynauld6bbdacf2022-11-29 21:45:40 -050018import { ConversationMessage, WebSocketMessageType } from 'jami-web-common';
19import { createContext, ReactNode, useContext, useEffect, useState } from 'react';
simon21f7d9f2022-11-28 14:21:54 -050020
Misha Krieger-Raynauld6bbdacf2022-11-29 21:45:40 -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
64 .get<Conversation[]>('/conversations', {
65 signal: controller.signal,
66 })
67 .then(({ data }) => {
68 setConversations(Object.values(data).map((c) => Conversation.from(accountId, c)));
69 });
70 // return () => controller.abort()
71 }, [axiosInstance, accountId, refresh]);
72
73 useEffect(() => {
74 if (!webSocket) {
75 return;
76 }
77
78 const conversationMessageListener = (_data: ConversationMessage) => {
79 dispatch(setRefreshFromSlice());
80 };
81
82 webSocket.bind(WebSocketMessageType.ConversationMessage, conversationMessageListener);
83
84 return () => {
85 webSocket.unbind(WebSocketMessageType.ConversationMessage, conversationMessageListener);
86 };
87 }, [webSocket, dispatch]);
88
89 useEffect(() => {
90 if (!searchQuery) return;
91 const controller = new AbortController();
92 // TODO: Type properly https://git.jami.net/savoirfairelinux/jami-web/-/issues/92
93 axiosInstance
94 .get<{ state: number; address: string; username: string }>(`/ns/username/${searchQuery}`, {
95 signal: controller.signal,
96 })
97 .then(({ data }) => {
98 const contact = new Contact(data.address);
99 contact.setRegisteredName(data.username);
100 setSearchResults(contact ? Conversation.fromSingleContact(accountId, contact) : undefined);
101 })
102 .catch(() => {
103 setSearchResults(undefined);
104 });
105 // return () => controller.abort() // crash on React18
106 }, [accountId, searchQuery, axiosInstance]);
107
108 return (
109 <MessengerContext.Provider
110 value={{
111 conversations,
112 setSearchQuery,
113 searchResult,
114 newContactId,
115 setNewContactId,
116 }}
117 >
118 {children}
119 </MessengerContext.Provider>
120 );
121};