diff --git a/src/components/Chat/AnnouncementList.tsx b/src/components/Chat/AnnouncementList.tsx
index b55ebb5..efaf1fa 100644
--- a/src/components/Chat/AnnouncementList.tsx
+++ b/src/components/Chat/AnnouncementList.tsx
@@ -1,13 +1,13 @@
-import React, { useCallback, useState, useEffect, useRef } from "react";
+import React, { useCallback, useState, useEffect, useRef } from 'react';
import {
List,
AutoSizer,
CellMeasurerCache,
CellMeasurer,
-} from "react-virtualized";
-import { AnnouncementItem } from "./AnnouncementItem";
-import { Box } from "@mui/material";
-import { CustomButton } from "../../App-styles";
+} from 'react-virtualized';
+import { AnnouncementItem } from './AnnouncementItem';
+import { Box } from '@mui/material';
+import { CustomButton } from '../../styles/App-styles';
const cache = new CellMeasurerCache({
fixedWidth: true,
@@ -21,9 +21,8 @@ export const AnnouncementList = ({
disableComment,
showLoadMore,
loadMore,
- myName
+ myName,
}) => {
-
const listRef = useRef();
const [messages, setMessages] = useState(initialMessages);
@@ -35,39 +34,44 @@ export const AnnouncementList = ({
setMessages(initialMessages);
}, [initialMessages]);
-
return (
);
};
diff --git a/src/components/Chat/ChatDirect.tsx b/src/components/Chat/ChatDirect.tsx
index d23f026..1af3f8e 100644
--- a/src/components/Chat/ChatDirect.tsx
+++ b/src/components/Chat/ChatDirect.tsx
@@ -1,52 +1,78 @@
-import React, { useCallback, useEffect, useMemo, useReducer, useRef, useState } from 'react'
+import React, {
+ useCallback,
+ useEffect,
+ useMemo,
+ useReducer,
+ useRef,
+ useState,
+} from 'react';
-import { objectToBase64 } from '../../qdn/encryption/group-encryption'
-import { ChatList } from './ChatList'
-import "@chatscope/chat-ui-kit-styles/dist/default/styles.min.css";
-import Tiptap from './TipTap'
-import { CustomButton } from '../../App-styles'
+import { objectToBase64 } from '../../qdn/encryption/group-encryption';
+import { ChatList } from './ChatList';
+import '@chatscope/chat-ui-kit-styles/dist/default/styles.min.css';
+import Tiptap from './TipTap';
+import { CustomButton } from '../../styles/App-styles';
import CircularProgress from '@mui/material/CircularProgress';
import { Box, ButtonBase, Input, Typography } from '@mui/material';
import { LoadingSnackbar } from '../Snackbar/LoadingSnackbar';
import { getNameInfo } from '../Group/Group';
import { Spacer } from '../../common/Spacer';
import { CustomizedSnackbars } from '../Snackbar/Snackbar';
-import { getBaseApiReact, getBaseApiReactSocket, isMobile, pauseAllQueues, resumeAllQueues } from '../../App';
+import {
+ getBaseApiReact,
+ getBaseApiReactSocket,
+ isMobile,
+ pauseAllQueues,
+ resumeAllQueues,
+} from '../../App';
import { getPublicKey } from '../../background';
import { useMessageQueue } from '../../MessageQueueContext';
-import { executeEvent, subscribeToEvent, unsubscribeFromEvent } from '../../utils/events';
+import {
+ executeEvent,
+ subscribeToEvent,
+ unsubscribeFromEvent,
+} from '../../utils/events';
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
-import ShortUniqueId from "short-unique-id";
+import ShortUniqueId from 'short-unique-id';
import { ReturnIcon } from '../../assets/Icons/ReturnIcon';
import { ExitIcon } from '../../assets/Icons/ExitIcon';
import { MessageItem, ReplyPreview } from './MessageItem';
-
const uid = new ShortUniqueId({ length: 5 });
+export const ChatDirect = ({
+ myAddress,
+ isNewChat,
+ selectedDirect,
+ setSelectedDirect,
+ setNewChat,
+ getTimestampEnterChat,
+ myName,
+ balance,
+ close,
+ setMobileViewModeKeepOpen,
+}) => {
+ const { queueChats, addToQueue, processWithNewMessages } = useMessageQueue();
+ const [isFocusedParent, setIsFocusedParent] = useState(false);
+ const [onEditMessage, setOnEditMessage] = useState(null);
-export const ChatDirect = ({ myAddress, isNewChat, selectedDirect, setSelectedDirect, setNewChat, getTimestampEnterChat, myName, balance, close, setMobileViewModeKeepOpen}) => {
- const { queueChats, addToQueue, processWithNewMessages} = useMessageQueue();
- const [isFocusedParent, setIsFocusedParent] = useState(false);
- const [onEditMessage, setOnEditMessage] = useState(null)
-
- const [messages, setMessages] = useState([])
- const [isSending, setIsSending] = useState(false)
- const [directToValue, setDirectToValue] = useState('')
- const hasInitialized = useRef(false)
- const [isLoading, setIsLoading] = useState(false)
+ const [messages, setMessages] = useState([]);
+ const [isSending, setIsSending] = useState(false);
+ const [directToValue, setDirectToValue] = useState('');
+ const hasInitialized = useRef(false);
+ const [isLoading, setIsLoading] = useState(false);
const [openSnack, setOpenSnack] = React.useState(false);
const [infoSnack, setInfoSnack] = React.useState(null);
- const [publicKeyOfRecipient, setPublicKeyOfRecipient] = React.useState("")
- const hasInitializedWebsocket = useRef(false)
- const [chatReferences, setChatReferences] = useState({})
+ const [publicKeyOfRecipient, setPublicKeyOfRecipient] = React.useState('');
+ const hasInitializedWebsocket = useRef(false);
+ const [chatReferences, setChatReferences] = useState({});
const editorRef = useRef(null);
const socketRef = useRef(null);
const timeoutIdRef = useRef(null);
- const [messageSize, setMessageSize] = useState(0)
+ const [messageSize, setMessageSize] = useState(0);
const groupSocketTimeoutRef = useRef(null);
- const [replyMessage, setReplyMessage] = useState(null)
+ const [replyMessage, setReplyMessage] = useState(null);
const setEditorRef = (editorInstance) => {
editorRef.current = editorInstance;
};
@@ -55,42 +81,47 @@ export const ChatDirect = ({ myAddress, isNewChat, selectedDirect, setSelectedDi
const triggerRerender = () => {
forceUpdate(); // Trigger re-render by updating the state
};
- const publicKeyOfRecipientRef = useRef(null)
- const getPublicKeyFunc = async (address)=> {
+ const publicKeyOfRecipientRef = useRef(null);
+ const getPublicKeyFunc = async (address) => {
try {
- const publicKey = await getPublicKey(address)
- if(publicKeyOfRecipientRef.current !== selectedDirect?.address) return
- setPublicKeyOfRecipient(publicKey)
- } catch (error) {
-
- }
- }
+ const publicKey = await getPublicKey(address);
+ if (publicKeyOfRecipientRef.current !== selectedDirect?.address) return;
+ setPublicKeyOfRecipient(publicKey);
+ } catch (error) {}
+ };
- const tempMessages = useMemo(()=> {
- if(!selectedDirect?.address) return []
- if(queueChats[selectedDirect?.address]){
- return queueChats[selectedDirect?.address]?.filter((item)=> !item?.chatReference)
+ const tempMessages = useMemo(() => {
+ if (!selectedDirect?.address) return [];
+ if (queueChats[selectedDirect?.address]) {
+ return queueChats[selectedDirect?.address]?.filter(
+ (item) => !item?.chatReference
+ );
}
- return []
- }, [selectedDirect?.address, queueChats])
+ return [];
+ }, [selectedDirect?.address, queueChats]);
- const tempChatReferences = useMemo(()=> {
- if(!selectedDirect?.address) return []
- if(queueChats[selectedDirect?.address]){
- return queueChats[selectedDirect?.address]?.filter((item)=> !!item?.chatReference)
+ const tempChatReferences = useMemo(() => {
+ if (!selectedDirect?.address) return [];
+ if (queueChats[selectedDirect?.address]) {
+ return queueChats[selectedDirect?.address]?.filter(
+ (item) => !!item?.chatReference
+ );
}
- return []
- }, [selectedDirect?.address, queueChats])
+ return [];
+ }, [selectedDirect?.address, queueChats]);
- useEffect(()=> {
- if(selectedDirect?.address){
- publicKeyOfRecipientRef.current = selectedDirect?.address
- getPublicKeyFunc(publicKeyOfRecipientRef.current)
+ useEffect(() => {
+ if (selectedDirect?.address) {
+ publicKeyOfRecipientRef.current = selectedDirect?.address;
+ getPublicKeyFunc(publicKeyOfRecipientRef.current);
}
- }, [selectedDirect?.address])
-
+ }, [selectedDirect?.address]);
- const middletierFunc = async (data: any, selectedDirectAddress: string, myAddress: string) => {
+ const middletierFunc = async (
+ data: any,
+ selectedDirectAddress: string,
+ myAddress: string
+ ) => {
try {
if (hasInitialized.current) {
decryptMessages(data, true);
@@ -99,9 +130,9 @@ export const ChatDirect = ({ myAddress, isNewChat, selectedDirect, setSelectedDi
hasInitialized.current = true;
const url = `${getBaseApiReact()}/chat/messages?involving=${selectedDirectAddress}&involving=${myAddress}&encoding=BASE64&limit=0&reverse=false`;
const response = await fetch(url, {
- method: "GET",
+ method: 'GET',
headers: {
- "Content-Type": "application/json",
+ 'Content-Type': 'application/json',
},
});
const responseData = await response.json();
@@ -109,589 +140,666 @@ export const ChatDirect = ({ myAddress, isNewChat, selectedDirect, setSelectedDi
} catch (error) {
console.error(error);
}
- }
+ };
- const decryptMessages = (encryptedMessages: any[], isInitiated: boolean)=> {
- try {
- return new Promise((res, rej)=> {
- window.sendMessage("decryptDirect", {
+ const decryptMessages = (encryptedMessages: any[], isInitiated: boolean) => {
+ try {
+ return new Promise((res, rej) => {
+ window
+ .sendMessage('decryptDirect', {
data: encryptedMessages,
involvingAddress: selectedDirect?.address,
})
- .then((decryptResponse) => {
- if (!decryptResponse?.error) {
- const response = processWithNewMessages(decryptResponse, selectedDirect?.address);
- res(response);
-
- if (isInitiated) {
- const formatted = response.filter((rawItem) => !rawItem?.chatReference).map((item) => ({
+ .then((decryptResponse) => {
+ if (!decryptResponse?.error) {
+ const response = processWithNewMessages(
+ decryptResponse,
+ selectedDirect?.address
+ );
+ res(response);
+
+ if (isInitiated) {
+ const formatted = response
+ .filter((rawItem) => !rawItem?.chatReference)
+ .map((item) => ({
...item,
id: item.signature,
text: item.message,
unread: item?.sender === myAddress ? false : true,
}));
- setMessages((prev) => [...prev, ...formatted]);
- setChatReferences((prev) => {
- const organizedChatReferences = { ...prev };
+ setMessages((prev) => [...prev, ...formatted]);
+ setChatReferences((prev) => {
+ const organizedChatReferences = { ...prev };
- response.filter((rawItem) => !!rawItem?.chatReference && rawItem?.type === 'edit').forEach((item) => {
- try {
- organizedChatReferences[item.chatReference] = {
- ...(organizedChatReferences[item.chatReference] || {}),
- edit: item
- };
- } catch(error){
-
- }
- })
- return organizedChatReferences
- })
- } else {
- hasInitialized.current = true;
- const formatted = response.filter((rawItem) => !rawItem?.chatReference)
+ response
+ .filter(
+ (rawItem) =>
+ !!rawItem?.chatReference && rawItem?.type === 'edit'
+ )
+ .forEach((item) => {
+ try {
+ organizedChatReferences[item.chatReference] = {
+ ...(organizedChatReferences[item.chatReference] ||
+ {}),
+ edit: item,
+ };
+ } catch (error) {}
+ });
+ return organizedChatReferences;
+ });
+ } else {
+ hasInitialized.current = true;
+ const formatted = response
+ .filter((rawItem) => !rawItem?.chatReference)
.map((item) => ({
...item,
id: item.signature,
text: item.message,
unread: false,
}));
- setMessages(formatted);
+ setMessages(formatted);
- setChatReferences((prev) => {
- const organizedChatReferences = { ...prev };
+ setChatReferences((prev) => {
+ const organizedChatReferences = { ...prev };
- response.filter((rawItem) => !!rawItem?.chatReference && rawItem?.type === 'edit').forEach((item) => {
- try {
- organizedChatReferences[item.chatReference] = {
- ...(organizedChatReferences[item.chatReference] || {}),
- edit: item
- };
- } catch(error){
-
- }
- })
- return organizedChatReferences
- })
- }
- return;
+ response
+ .filter(
+ (rawItem) =>
+ !!rawItem?.chatReference && rawItem?.type === 'edit'
+ )
+ .forEach((item) => {
+ try {
+ organizedChatReferences[item.chatReference] = {
+ ...(organizedChatReferences[item.chatReference] ||
+ {}),
+ edit: item,
+ };
+ } catch (error) {}
+ });
+ return organizedChatReferences;
+ });
}
- rej(response.error);
- })
- .catch((error) => {
- rej(error.message || "An error occurred");
- });
-
- })
- } catch (error) {
-
- }
- }
+ return;
+ }
+ rej(response.error);
+ })
+ .catch((error) => {
+ rej(error.message || 'An error occurred');
+ });
+ });
+ } catch (error) {}
+ };
- const forceCloseWebSocket = () => {
+ const forceCloseWebSocket = () => {
+ if (socketRef.current) {
+ clearTimeout(timeoutIdRef.current);
+ clearTimeout(groupSocketTimeoutRef.current);
+ socketRef.current.close(1000, 'forced');
+ socketRef.current = null;
+ }
+ };
+
+ const pingWebSocket = () => {
+ try {
+ if (socketRef.current?.readyState === WebSocket.OPEN) {
+ socketRef.current.send('ping');
+ timeoutIdRef.current = setTimeout(() => {
+ if (socketRef.current) {
+ socketRef.current.close();
+ clearTimeout(groupSocketTimeoutRef.current);
+ }
+ }, 5000); // Close if no pong in 5 seconds
+ }
+ } catch (error) {
+ console.error('Error during ping:', error);
+ }
+ };
+
+ const initWebsocketMessageGroup = () => {
+ forceCloseWebSocket(); // Close any existing connection
+
+ if (!selectedDirect?.address || !myAddress) return;
+
+ const socketLink = `${getBaseApiReactSocket()}/websockets/chat/messages?involving=${selectedDirect?.address}&involving=${myAddress}&encoding=BASE64&limit=100`;
+ socketRef.current = new WebSocket(socketLink);
+
+ socketRef.current.onopen = () => {
+ setTimeout(pingWebSocket, 50); // Initial ping
+ };
+
+ socketRef.current.onmessage = (e) => {
+ try {
+ if (e.data === 'pong') {
+ clearTimeout(timeoutIdRef.current);
+ groupSocketTimeoutRef.current = setTimeout(pingWebSocket, 45000); // Ping every 45 seconds
+ } else {
+ middletierFunc(
+ JSON.parse(e.data),
+ selectedDirect?.address,
+ myAddress
+ );
+
+ setIsLoading(false);
+ }
+ } catch (error) {
+ console.error('Error handling WebSocket message:', error);
+ }
+ };
+
+ socketRef.current.onclose = (event) => {
+ clearTimeout(groupSocketTimeoutRef.current);
+ clearTimeout(timeoutIdRef.current);
+ console.warn(`WebSocket closed: ${event.reason || 'unknown reason'}`);
+ if (event.reason !== 'forced' && event.code !== 1000) {
+ setTimeout(() => initWebsocketMessageGroup(), 10000); // Retry after 10 seconds
+ }
+ };
+
+ socketRef.current.onerror = (error) => {
+ console.error('WebSocket error:', error);
+ clearTimeout(groupSocketTimeoutRef.current);
+ clearTimeout(timeoutIdRef.current);
if (socketRef.current) {
- clearTimeout(timeoutIdRef.current);
- clearTimeout(groupSocketTimeoutRef.current);
- socketRef.current.close(1000, 'forced');
- socketRef.current = null;
+ socketRef.current.close();
}
};
-
- const pingWebSocket = () => {
- try {
- if (socketRef.current?.readyState === WebSocket.OPEN) {
- socketRef.current.send('ping');
- timeoutIdRef.current = setTimeout(() => {
- if (socketRef.current) {
- socketRef.current.close();
- clearTimeout(groupSocketTimeoutRef.current);
- }
- }, 5000); // Close if no pong in 5 seconds
- }
- } catch (error) {
- console.error('Error during ping:', error);
- }
+ };
+
+ const setDirectChatValueFunc = async (e) => {
+ setDirectToValue(e.detail.directToValue);
+ };
+ useEffect(() => {
+ subscribeToEvent('setDirectToValueNewChat', setDirectChatValueFunc);
+
+ return () => {
+ unsubscribeFromEvent('setDirectToValueNewChat', setDirectChatValueFunc);
};
-
+ }, []);
- const initWebsocketMessageGroup = () => {
- forceCloseWebSocket(); // Close any existing connection
-
- if (!selectedDirect?.address || !myAddress) return;
-
- const socketLink = `${getBaseApiReactSocket()}/websockets/chat/messages?involving=${selectedDirect?.address}&involving=${myAddress}&encoding=BASE64&limit=100`;
- socketRef.current = new WebSocket(socketLink);
-
- socketRef.current.onopen = () => {
- setTimeout(pingWebSocket, 50); // Initial ping
- };
-
- socketRef.current.onmessage = (e) => {
- try {
- if (e.data === 'pong') {
- clearTimeout(timeoutIdRef.current);
- groupSocketTimeoutRef.current = setTimeout(pingWebSocket, 45000); // Ping every 45 seconds
- } else {
- middletierFunc(JSON.parse(e.data), selectedDirect?.address, myAddress)
+ useEffect(() => {
+ if (hasInitializedWebsocket.current || isNewChat) return;
+ setIsLoading(true);
+ initWebsocketMessageGroup();
+ hasInitializedWebsocket.current = true;
- setIsLoading(false);
- }
- } catch (error) {
- console.error('Error handling WebSocket message:', error);
- }
- };
-
- socketRef.current.onclose = (event) => {
- clearTimeout(groupSocketTimeoutRef.current);
- clearTimeout(timeoutIdRef.current);
- console.warn(`WebSocket closed: ${event.reason || 'unknown reason'}`);
- if (event.reason !== 'forced' && event.code !== 1000) {
- setTimeout(() => initWebsocketMessageGroup(), 10000); // Retry after 10 seconds
- }
- };
-
- socketRef.current.onerror = (error) => {
- console.error('WebSocket error:', error);
- clearTimeout(groupSocketTimeoutRef.current);
- clearTimeout(timeoutIdRef.current);
- if (socketRef.current) {
- socketRef.current.close();
- }
- };
+ return () => {
+ forceCloseWebSocket(); // Clean up WebSocket on component unmount
};
+ }, [selectedDirect?.address, myAddress, isNewChat]);
- const setDirectChatValueFunc = async (e)=> {
- setDirectToValue(e.detail.directToValue)
- }
- useEffect(() => {
- subscribeToEvent("setDirectToValueNewChat", setDirectChatValueFunc);
-
- return () => {
- unsubscribeFromEvent("setDirectToValueNewChat", setDirectChatValueFunc);
- };
- }, []);
-
- useEffect(() => {
- if (hasInitializedWebsocket.current || isNewChat) return;
- setIsLoading(true);
- initWebsocketMessageGroup();
- hasInitializedWebsocket.current = true;
-
- return () => {
- forceCloseWebSocket(); // Clean up WebSocket on component unmount
- };
- }, [selectedDirect?.address, myAddress, isNewChat]);
+ const sendChatDirect = async (
+ { chatReference = undefined, messageText, otherData }: any,
+ address,
+ publicKeyOfRecipient,
+ isNewChatVar
+ ) => {
+ try {
+ const directTo = isNewChatVar ? directToValue : address;
+ if (!directTo) return;
+ return new Promise((res, rej) => {
+ window
+ .sendMessage(
+ 'sendChatDirect',
+ {
+ directTo,
+ chatReference,
+ messageText,
+ otherData,
+ publicKeyOfRecipient,
+ address: directTo,
+ },
+ 120000
+ )
+ .then(async (response) => {
+ if (!response?.error) {
+ if (isNewChatVar) {
+ let getRecipientName = null;
+ try {
+ getRecipientName = await getNameInfo(response.recipient);
+ } catch (error) {
+ console.error('Error fetching recipient name:', error);
+ }
+ setSelectedDirect({
+ address: response.recipient,
+ name: getRecipientName,
+ timestamp: Date.now(),
+ sender: myAddress,
+ senderName: myName,
+ });
+ setNewChat(null);
+ window
+ .sendMessage('addTimestampEnterChat', {
+ timestamp: Date.now(),
+ groupId: response.recipient,
+ })
+ .catch((error) => {
+ console.error(
+ 'Failed to add timestamp:',
+ error.message || 'An error occurred'
+ );
+ });
-const sendChatDirect = async ({ chatReference = undefined, messageText, otherData}: any, address, publicKeyOfRecipient, isNewChatVar)=> {
- try {
- const directTo = isNewChatVar ? directToValue : address
-
- if(!directTo) return
- return new Promise((res, rej)=> {
- window.sendMessage("sendChatDirect", {
- directTo,
- chatReference,
- messageText,
- otherData,
- publicKeyOfRecipient,
- address: directTo,
- }, 120000)
- .then(async (response) => {
- if (!response?.error) {
- if (isNewChatVar) {
- let getRecipientName = null;
- try {
- getRecipientName = await getNameInfo(response.recipient);
- } catch (error) {
- console.error("Error fetching recipient name:", error);
+ setTimeout(() => {
+ getTimestampEnterChat();
+ }, 400);
}
- setSelectedDirect({
- address: response.recipient,
- name: getRecipientName,
- timestamp: Date.now(),
- sender: myAddress,
- senderName: myName,
- });
- setNewChat(null);
-
- window.sendMessage("addTimestampEnterChat", {
- timestamp: Date.now(),
- groupId: response.recipient,
- }).catch((error) => {
- console.error("Failed to add timestamp:", error.message || "An error occurred");
- });
-
- setTimeout(() => {
- getTimestampEnterChat();
- }, 400);
+ res(response);
+ return;
}
- res(response);
- return;
- }
- rej(response.error);
- })
- .catch((error) => {
- rej(error.message || "An error occurred");
- });
-
- })
- } catch (error) {
- throw new Error(error)
- } finally {
- }
-}
-const clearEditorContent = () => {
- if (editorRef.current) {
- setMessageSize(0)
- editorRef.current.chain().focus().clearContent().run();
- if(isMobile){
- setTimeout(() => {
- editorRef.current?.chain().blur().run();
- setIsFocusedParent(false)
- executeEvent("sent-new-message-group", {})
- setTimeout(() => {
- triggerRerender();
- }, 300);
- }, 200);
+ rej(response.error);
+ })
+ .catch((error) => {
+ rej(error.message || 'An error occurred');
+ });
+ });
+ } catch (error) {
+ throw new Error(error);
+ } finally {
}
- }
-};
-useEffect(() => {
- if (!editorRef?.current) return;
- const handleUpdate = () => {
- const htmlContent = editorRef?.current.getHTML();
- const stringified = JSON.stringify(htmlContent);
- const size = new Blob([stringified]).size;
- setMessageSize(size + 200);
};
-
- // Add a listener for the editorRef?.current's content updates
- editorRef?.current.on('update', handleUpdate);
-
- // Cleanup the listener on unmount
- return () => {
- editorRef?.current.off('update', handleUpdate);
+ const clearEditorContent = () => {
+ if (editorRef.current) {
+ setMessageSize(0);
+ editorRef.current.chain().focus().clearContent().run();
+ if (isMobile) {
+ setTimeout(() => {
+ editorRef.current?.chain().blur().run();
+ setIsFocusedParent(false);
+ executeEvent('sent-new-message-group', {});
+ setTimeout(() => {
+ triggerRerender();
+ }, 300);
+ }, 200);
+ }
+ }
};
-}, [editorRef?.current]);
+ useEffect(() => {
+ if (!editorRef?.current) return;
+ const handleUpdate = () => {
+ const htmlContent = editorRef?.current.getHTML();
+ const stringified = JSON.stringify(htmlContent);
+ const size = new Blob([stringified]).size;
+ setMessageSize(size + 200);
+ };
- const sendMessage = async ()=> {
- try {
- if(messageSize > 4000) return
+ // Add a listener for the editorRef?.current's content updates
+ editorRef?.current.on('update', handleUpdate);
-
- if(+balance < 4) throw new Error('You need at least 4 QORT to send a message')
- if(isSending) return
- if (editorRef.current) {
- const htmlContent = editorRef.current.getHTML();
-
- if(!htmlContent?.trim() || htmlContent?.trim() === '
') return
- setIsSending(true)
- pauseAllQueues()
- const message = JSON.stringify(htmlContent)
-
-
- if(isNewChat){
- await sendChatDirect({ messageText: htmlContent}, null, null, true)
- return
+ // Cleanup the listener on unmount
+ return () => {
+ editorRef?.current.off('update', handleUpdate);
+ };
+ }, [editorRef?.current]);
+
+ const sendMessage = async () => {
+ try {
+ if (messageSize > 4000) return;
+
+ if (+balance < 4)
+ throw new Error('You need at least 4 QORT to send a message');
+ if (isSending) return;
+ if (editorRef.current) {
+ const htmlContent = editorRef.current.getHTML();
+
+ if (!htmlContent?.trim() || htmlContent?.trim() === '
') return;
+ setIsSending(true);
+ pauseAllQueues();
+ const message = JSON.stringify(htmlContent);
+
+ if (isNewChat) {
+ await sendChatDirect({ messageText: htmlContent }, null, null, true);
+ return;
}
- let repliedTo = replyMessage?.signature
+ let repliedTo = replyMessage?.signature;
- if (replyMessage?.chatReference) {
- repliedTo = replyMessage?.chatReference
- }
- let chatReference = onEditMessage?.signature
+ if (replyMessage?.chatReference) {
+ repliedTo = replyMessage?.chatReference;
+ }
+ let chatReference = onEditMessage?.signature;
const otherData = {
...(onEditMessage?.decryptedData || {}),
specialId: uid.rnd(),
repliedTo: onEditMessage ? onEditMessage?.repliedTo : repliedTo,
- type: chatReference ? 'edit' : ''
- }
+ type: chatReference ? 'edit' : '',
+ };
const sendMessageFunc = async () => {
- return await sendChatDirect({ chatReference, messageText: htmlContent, otherData}, selectedDirect?.address, publicKeyOfRecipient, false)
+ return await sendChatDirect(
+ { chatReference, messageText: htmlContent, otherData },
+ selectedDirect?.address,
+ publicKeyOfRecipient,
+ false
+ );
};
-
-
// Add the function to the queue
const messageObj = {
message: {
timestamp: Date.now(),
- senderName: myName,
- sender: myAddress,
- ...(otherData || {}),
- text: htmlContent,
+ senderName: myName,
+ sender: myAddress,
+ ...(otherData || {}),
+ text: htmlContent,
},
- chatReference
- }
- addToQueue(sendMessageFunc, messageObj, 'chat-direct',
- selectedDirect?.address );
+ chatReference,
+ };
+ addToQueue(
+ sendMessageFunc,
+ messageObj,
+ 'chat-direct',
+ selectedDirect?.address
+ );
setTimeout(() => {
- executeEvent("sent-new-message-group", {})
+ executeEvent('sent-new-message-group', {});
}, 150);
- clearEditorContent()
- setReplyMessage(null)
- setOnEditMessage(null)
-
- }
- // send chat message
- } catch (error) {
- const errorMsg = error?.message || error
- setInfoSnack({
- type: "error",
- message: errorMsg === 'invalid signature' ? 'You need at least 4 QORT to send a message' : errorMsg,
- });
- setOpenSnack(true);
- console.error(error)
- } finally {
- setIsSending(false)
- resumeAllQueues()
+ clearEditorContent();
+ setReplyMessage(null);
+ setOnEditMessage(null);
}
+ // send chat message
+ } catch (error) {
+ const errorMsg = error?.message || error;
+ setInfoSnack({
+ type: 'error',
+ message:
+ errorMsg === 'invalid signature'
+ ? 'You need at least 4 QORT to send a message'
+ : errorMsg,
+ });
+ setOpenSnack(true);
+ console.error(error);
+ } finally {
+ setIsSending(false);
+ resumeAllQueues();
}
+ };
- const onReply = useCallback((message)=> {
- if(onEditMessage){
- clearEditorContent()
+ const onReply = useCallback(
+ (message) => {
+ if (onEditMessage) {
+ clearEditorContent();
}
- setReplyMessage(message)
- setOnEditMessage(null)
- editorRef?.current?.chain().focus()
- }, [onEditMessage])
-
-
- const onEdit = useCallback((message)=> {
- setOnEditMessage(message)
- setReplyMessage(null)
- editorRef.current.chain().focus().setContent(message?.text).run();
-
- }, [])
-
+ setReplyMessage(message);
+ setOnEditMessage(null);
+ editorRef?.current?.chain().focus();
+ },
+ [onEditMessage]
+ );
+
+ const onEdit = useCallback((message) => {
+ setOnEditMessage(message);
+ setReplyMessage(null);
+ editorRef.current.chain().focus().setContent(message?.text).run();
+ }, []);
+
return (
-
+
{!isMobile && (
-
-
- Close Direct Chat
+
+
+
+ Close Direct Chat
+
+
+ )}
+ {isMobile && (
+
+
+
+ {
+ close();
+ }}
+ >
+
+
+
+
+ {isNewChat
+ ? ''
+ : selectedDirect?.name ||
+ selectedDirect?.address?.slice(0, 10) + '...'}
+
+
+ {
+ setSelectedDirect(null);
+ setMobileViewModeKeepOpen('');
+ setNewChat(false);
+ }}
+ >
+
+
+
+
)}
- {isMobile && (
-
-
-
- {
- close()
- }}
- >
-
-
-
-
- {isNewChat ? '' : selectedDirect?.name || (selectedDirect?.address?.slice(0,10) + '...')}
-
-
- {
- setSelectedDirect(null)
- setMobileViewModeKeepOpen('')
- setNewChat(false)
- }}
- >
-
-
-
-
-
- )}
{isNewChat && (
<>
-
- setDirectToValue(e.target.value)} />
-
+
+ setDirectToValue(e.target.value)}
+ />
>
)}
-
-
-
-
-
+
+
+
- {replyMessage && (
-
-
-
- {
- setReplyMessage(null)
- setOnEditMessage(null)
-
- }}
- >
-
-
-
- )}
- {onEditMessage && (
-
-
-
- {
- setReplyMessage(null)
- setOnEditMessage(null)
-
- clearEditorContent()
-
-
- }}
- >
-
-
-
- )}
-
-
- {messageSize > 750 && (
-
- 4000 ? 'var(--danger)' : 'unset'
- }}>{`Your message size is of ${messageSize} bytes out of a maximum of 4000`}
-
-
- )}
-
-
-
-
- {
-
- if(isSending) return
- sendMessage()
- }}
- style={{
- marginTop: 'auto',
- alignSelf: 'center',
- cursor: isSending ? 'default' : 'pointer',
- background: isSending && 'rgba(0, 0, 0, 0.8)',
- flexShrink: 0,
- padding: '5px',
- width: '100px',
- minWidth: 'auto'
+ justifyContent: 'flex-end',
+ }}
+ >
+ {replyMessage && (
+
- {isSending && (
-
+
+ {
+ setReplyMessage(null);
+ setOnEditMessage(null);
+ }}
+ >
+
+
+
+ )}
+ {onEditMessage && (
+
+
+
+ {
+ setReplyMessage(null);
+ setOnEditMessage(null);
+
+ clearEditorContent();
+ }}
+ >
+
+
+
+ )}
+
+
+ {messageSize > 750 && (
+
+ 4000 ? 'var(--danger)' : 'unset',
+ }}
+ >{`Your message size is of ${messageSize} bytes out of a maximum of 4000`}
+
+ )}
+
+
+
+ {
+ if (isSending) return;
+ sendMessage();
+ }}
+ style={{
+ marginTop: 'auto',
+ alignSelf: 'center',
+ cursor: isSending ? 'default' : 'pointer',
+ background: isSending && 'rgba(0, 0, 0, 0.8)',
+ flexShrink: 0,
+ padding: '5px',
+ width: '100px',
+ minWidth: 'auto',
+ }}
+ >
+ {isSending && (
+ {
left: '50%',
marginTop: '-12px',
marginLeft: '-12px',
- color: 'white'
+ color: 'white',
}}
/>
- )}
- {` Send`}
-
-
-
+ )}
+ {` Send`}
+
+
-
-
+
+
- )
-}
+ );
+};
diff --git a/src/components/Chat/ChatGroup.tsx b/src/components/Chat/ChatGroup.tsx
index e054bd9..4cf5a7a 100644
--- a/src/components/Chat/ChatGroup.tsx
+++ b/src/components/Chat/ChatGroup.tsx
@@ -1,100 +1,140 @@
-import React, { useCallback, useContext, useEffect, useMemo, useReducer, useRef, useState } from 'react'
-import { CreateCommonSecret } from './CreateCommonSecret'
-import { reusableGet } from '../../qdn/publish/pubish'
-import { uint8ArrayToObject } from '../../backgroundFunctions/encryption'
-import { base64ToUint8Array, decodeBase64ForUIChatMessages, objectToBase64 } from '../../qdn/encryption/group-encryption'
-import { ChatContainerComp } from './ChatContainer'
-import { ChatList } from './ChatList'
-import "@chatscope/chat-ui-kit-styles/dist/default/styles.min.css";
-import Tiptap from './TipTap'
-import { CustomButton } from '../../App-styles'
+import React, {
+ useCallback,
+ useContext,
+ useEffect,
+ useMemo,
+ useReducer,
+ useRef,
+ useState,
+} from 'react';
+import { CreateCommonSecret } from './CreateCommonSecret';
+import { reusableGet } from '../../qdn/publish/pubish';
+import { uint8ArrayToObject } from '../../backgroundFunctions/encryption';
+import {
+ base64ToUint8Array,
+ decodeBase64ForUIChatMessages,
+ objectToBase64,
+} from '../../qdn/encryption/group-encryption';
+import { ChatContainerComp } from './ChatContainer';
+import { ChatList } from './ChatList';
+import '@chatscope/chat-ui-kit-styles/dist/default/styles.min.css';
+import Tiptap from './TipTap';
+import { CustomButton } from '../../styles/App-styles';
import CircularProgress from '@mui/material/CircularProgress';
-import { LoadingSnackbar } from '../Snackbar/LoadingSnackbar'
-import { getBaseApiReact, getBaseApiReactSocket, isMobile, MyContext, pauseAllQueues, resumeAllQueues } from '../../App'
-import { CustomizedSnackbars } from '../Snackbar/Snackbar'
-import { PUBLIC_NOTIFICATION_CODE_FIRST_SECRET_KEY } from '../../constants/codes'
-import { useMessageQueue } from '../../MessageQueueContext'
-import { executeEvent, subscribeToEvent, unsubscribeFromEvent } from '../../utils/events'
-import { Box, ButtonBase, Divider, Typography } from '@mui/material'
-import ShortUniqueId from "short-unique-id";
-import { ReplyPreview } from './MessageItem'
-import { ExitIcon } from '../../assets/Icons/ExitIcon'
-import { RESOURCE_TYPE_NUMBER_GROUP_CHAT_REACTIONS } from '../../constants/resourceTypes'
-import { isExtMsg } from '../../background'
-import AppViewerContainer from '../Apps/AppViewerContainer'
-import CloseIcon from "@mui/icons-material/Close";
-import { throttle } from 'lodash'
+import { LoadingSnackbar } from '../Snackbar/LoadingSnackbar';
+import {
+ getBaseApiReact,
+ getBaseApiReactSocket,
+ isMobile,
+ MyContext,
+ pauseAllQueues,
+ resumeAllQueues,
+} from '../../App';
+import { CustomizedSnackbars } from '../Snackbar/Snackbar';
+import { PUBLIC_NOTIFICATION_CODE_FIRST_SECRET_KEY } from '../../constants/codes';
+import { useMessageQueue } from '../../MessageQueueContext';
+import {
+ executeEvent,
+ subscribeToEvent,
+ unsubscribeFromEvent,
+} from '../../utils/events';
+import { Box, ButtonBase, Divider, Typography } from '@mui/material';
+import ShortUniqueId from 'short-unique-id';
+import { ReplyPreview } from './MessageItem';
+import { ExitIcon } from '../../assets/Icons/ExitIcon';
+import { RESOURCE_TYPE_NUMBER_GROUP_CHAT_REACTIONS } from '../../constants/resourceTypes';
+import { isExtMsg } from '../../background';
+import AppViewerContainer from '../Apps/AppViewerContainer';
+import CloseIcon from '@mui/icons-material/Close';
+import { throttle } from 'lodash';
const uid = new ShortUniqueId({ length: 5 });
-export const ChatGroup = ({selectedGroup, secretKey, setSecretKey, getSecretKey, myAddress, handleNewEncryptionNotification, hide, handleSecretKeyCreationInProgress, triedToFetchSecretKey, myName, balance, getTimestampEnterChatParent, hideView, isPrivate}) => {
- const {isUserBlocked} = useContext(MyContext)
- const [messages, setMessages] = useState([])
- const [chatReferences, setChatReferences] = useState({})
- const [isSending, setIsSending] = useState(false)
- const [isLoading, setIsLoading] = useState(false)
+export const ChatGroup = ({
+ selectedGroup,
+ secretKey,
+ setSecretKey,
+ getSecretKey,
+ myAddress,
+ handleNewEncryptionNotification,
+ hide,
+ handleSecretKeyCreationInProgress,
+ triedToFetchSecretKey,
+ myName,
+ balance,
+ getTimestampEnterChatParent,
+ hideView,
+ isPrivate,
+}) => {
+ const { isUserBlocked } = useContext(MyContext);
+ const [messages, setMessages] = useState([]);
+ const [chatReferences, setChatReferences] = useState({});
+ const [isSending, setIsSending] = useState(false);
+ const [isLoading, setIsLoading] = useState(false);
const [isMoved, setIsMoved] = useState(false);
const [openSnack, setOpenSnack] = React.useState(false);
const [infoSnack, setInfoSnack] = React.useState(null);
- const hasInitialized = useRef(false)
+ const hasInitialized = useRef(false);
const [isFocusedParent, setIsFocusedParent] = useState(false);
- const [replyMessage, setReplyMessage] = useState(null)
- const [onEditMessage, setOnEditMessage] = useState(null)
- const [isOpenQManager, setIsOpenQManager] = useState(null)
+ const [replyMessage, setReplyMessage] = useState(null);
+ const [onEditMessage, setOnEditMessage] = useState(null);
+ const [isOpenQManager, setIsOpenQManager] = useState(null);
-const [messageSize, setMessageSize] = useState(0)
- const hasInitializedWebsocket = useRef(false)
+ const [messageSize, setMessageSize] = useState(0);
+ const hasInitializedWebsocket = useRef(false);
const socketRef = useRef(null); // WebSocket reference
const timeoutIdRef = useRef(null); // Timeout ID reference
const groupSocketTimeoutRef = useRef(null); // Group Socket Timeout reference
const editorRef = useRef(null);
const { queueChats, addToQueue, processWithNewMessages } = useMessageQueue();
const [, forceUpdate] = useReducer((x) => x + 1, 0);
- const lastReadTimestamp = useRef(null)
+ const lastReadTimestamp = useRef(null);
const handleUpdateRef = useRef(null);
-
const getTimestampEnterChat = async (selectedGroup) => {
try {
return new Promise((res, rej) => {
- window.sendMessage("getTimestampEnterChat")
- .then((response) => {
- if (!response?.error) {
- if(response && selectedGroup){
- lastReadTimestamp.current = response[selectedGroup] || undefined
- window.sendMessage("addTimestampEnterChat", {
- timestamp: Date.now(),
- groupId: selectedGroup
- }).catch((error) => {
- console.error("Failed to add timestamp:", error.message || "An error occurred");
+ window
+ .sendMessage('getTimestampEnterChat')
+ .then((response) => {
+ if (!response?.error) {
+ if (response && selectedGroup) {
+ lastReadTimestamp.current =
+ response[selectedGroup] || undefined;
+ window
+ .sendMessage('addTimestampEnterChat', {
+ timestamp: Date.now(),
+ groupId: selectedGroup,
+ })
+ .catch((error) => {
+ console.error(
+ 'Failed to add timestamp:',
+ error.message || 'An error occurred'
+ );
+ });
+
+ setTimeout(() => {
+ getTimestampEnterChatParent();
+ }, 600);
+ }
+
+ res(response);
+ return;
+ }
+ rej(response.error);
+ })
+ .catch((error) => {
+ rej(error.message || 'An error occurred');
});
-
-
- setTimeout(() => {
- getTimestampEnterChatParent();
- }, 600);
- }
-
- res(response);
- return;
- }
- rej(response.error);
- })
- .catch((error) => {
- rej(error.message || "An error occurred");
- });
-
});
} catch (error) {}
};
- useEffect(()=> {
- if(!selectedGroup) return
- getTimestampEnterChat(selectedGroup)
- }, [selectedGroup])
-
-
+ useEffect(() => {
+ if (!selectedGroup) return;
+ getTimestampEnterChat(selectedGroup);
+ }, [selectedGroup]);
const members = useMemo(() => {
const uniqueMembers = new Set();
@@ -115,70 +155,77 @@ const [messageSize, setMessageSize] = useState(0)
editorRef.current = editorInstance;
};
- const tempMessages = useMemo(()=> {
- if(!selectedGroup) return []
- if(queueChats[selectedGroup]){
- return queueChats[selectedGroup]?.filter((item)=> !item?.chatReference)
+ const tempMessages = useMemo(() => {
+ if (!selectedGroup) return [];
+ if (queueChats[selectedGroup]) {
+ return queueChats[selectedGroup]?.filter((item) => !item?.chatReference);
}
- return []
- }, [selectedGroup, queueChats])
- const tempChatReferences = useMemo(()=> {
- if(!selectedGroup) return []
- if(queueChats[selectedGroup]){
- return queueChats[selectedGroup]?.filter((item)=> !!item?.chatReference)
+ return [];
+ }, [selectedGroup, queueChats]);
+ const tempChatReferences = useMemo(() => {
+ if (!selectedGroup) return [];
+ if (queueChats[selectedGroup]) {
+ return queueChats[selectedGroup]?.filter((item) => !!item?.chatReference);
}
- return []
- }, [selectedGroup, queueChats])
+ return [];
+ }, [selectedGroup, queueChats]);
- const secretKeyRef = useRef(null)
+ const secretKeyRef = useRef(null);
- useEffect(()=> {
- if(secretKey){
- secretKeyRef.current = secretKey
+ useEffect(() => {
+ if (secretKey) {
+ secretKeyRef.current = secretKey;
}
- }, [secretKey])
+ }, [secretKey]);
- // const getEncryptedSecretKey = useCallback(()=> {
- // const response = getResource()
- // const decryptResponse = decryptResource()
- // return
- // }, [])
+ // const getEncryptedSecretKey = useCallback(()=> {
+ // const response = getResource()
+ // const decryptResponse = decryptResource()
+ // return
+ // }, [])
-
- const checkForFirstSecretKeyNotification = (messages)=> {
- messages?.forEach((message)=> {
+ const checkForFirstSecretKeyNotification = (messages) => {
+ messages?.forEach((message) => {
try {
- const decodeMsg = atob(message.data);
- if(decodeMsg === PUBLIC_NOTIFICATION_CODE_FIRST_SECRET_KEY){
- handleSecretKeyCreationInProgress()
- return
+ const decodeMsg = atob(message.data);
+ if (decodeMsg === PUBLIC_NOTIFICATION_CODE_FIRST_SECRET_KEY) {
+ handleSecretKeyCreationInProgress();
+ return;
}
- } catch (error) {
-
- }
- })
- }
+ } catch (error) {}
+ });
+ };
- const updateChatMessagesWithBlocksFunc = (e) => {
- if(e.detail){
- setMessages((prev)=> prev?.filter((item)=> {
- return !isUserBlocked(item?.sender, item?.senderName)
- }))
- }
- };
-
- useEffect(() => {
- subscribeToEvent("updateChatMessagesWithBlocks", updateChatMessagesWithBlocksFunc);
-
- return () => {
- unsubscribeFromEvent("updateChatMessagesWithBlocks", updateChatMessagesWithBlocksFunc);
- };
- }, []);
+ const updateChatMessagesWithBlocksFunc = (e) => {
+ if (e.detail) {
+ setMessages((prev) =>
+ prev?.filter((item) => {
+ return !isUserBlocked(item?.sender, item?.senderName);
+ })
+ );
+ }
+ };
- const middletierFunc = async (data: any, groupId: string) => {
+ useEffect(() => {
+ subscribeToEvent(
+ 'updateChatMessagesWithBlocks',
+ updateChatMessagesWithBlocksFunc
+ );
+
+ return () => {
+ unsubscribeFromEvent(
+ 'updateChatMessagesWithBlocks',
+ updateChatMessagesWithBlocksFunc
+ );
+ };
+ }, []);
+
+ const middletierFunc = async (data: any, groupId: string) => {
try {
if (hasInitialized.current) {
- const dataRemovedBlock = data?.filter((item)=> !isUserBlocked(item?.sender, item?.senderName))
+ const dataRemovedBlock = data?.filter(
+ (item) => !isUserBlocked(item?.sender, item?.senderName)
+ );
decryptMessages(dataRemovedBlock, true);
return;
@@ -186,351 +233,462 @@ const [messageSize, setMessageSize] = useState(0)
hasInitialized.current = true;
const url = `${getBaseApiReact()}/chat/messages?txGroupId=${groupId}&encoding=BASE64&limit=0&reverse=false`;
const response = await fetch(url, {
- method: "GET",
+ method: 'GET',
headers: {
- "Content-Type": "application/json",
+ 'Content-Type': 'application/json',
},
});
const responseData = await response.json();
- const dataRemovedBlock = responseData?.filter((item)=> {
- return !isUserBlocked(item?.sender, item?.senderName)
- })
+ const dataRemovedBlock = responseData?.filter((item) => {
+ return !isUserBlocked(item?.sender, item?.senderName);
+ });
decryptMessages(dataRemovedBlock, false);
} catch (error) {
console.error(error);
}
- }
-
- const decryptMessages = (encryptedMessages: any[], isInitiated: boolean )=> {
- try {
- if(!secretKeyRef.current){
- checkForFirstSecretKeyNotification(encryptedMessages)
- }
- return new Promise((res, rej)=> {
- window.sendMessage("decryptSingle", {
+ };
+
+ const decryptMessages = (encryptedMessages: any[], isInitiated: boolean) => {
+ try {
+ if (!secretKeyRef.current) {
+ checkForFirstSecretKeyNotification(encryptedMessages);
+ }
+ return new Promise((res, rej) => {
+ window
+ .sendMessage('decryptSingle', {
data: encryptedMessages,
secretKeyObject: secretKey,
})
- .then((response) => {
- if (!response?.error) {
- const filterUIMessages = encryptedMessages.filter((item) => !isExtMsg(item.data));
- const decodedUIMessages = decodeBase64ForUIChatMessages(filterUIMessages);
-
- const combineUIAndExtensionMsgsBefore = [...decodedUIMessages, ...response];
- const combineUIAndExtensionMsgs = processWithNewMessages(
- combineUIAndExtensionMsgsBefore.map((item) => ({
- ...item,
- ...(item?.decryptedData || {}),
- })),
- selectedGroup
- );
- res(combineUIAndExtensionMsgs);
-
- if (isInitiated) {
+ .then((response) => {
+ if (!response?.error) {
+ const filterUIMessages = encryptedMessages.filter(
+ (item) => !isExtMsg(item.data)
+ );
+ const decodedUIMessages =
+ decodeBase64ForUIChatMessages(filterUIMessages);
- const formatted = combineUIAndExtensionMsgs
- .filter((rawItem) => !rawItem?.chatReference)
- .map((item) => {
- const additionalFields = item?.data === 'NDAwMQ==' ? {
- text: "
First group key created.
"
- } : {}
- return {
- ...item,
- id: item.signature,
- text: item?.decryptedData?.message || "",
- repliedTo: item?.repliedTo || item?.decryptedData?.repliedTo,
- unread: item?.sender === myAddress ? false : !!item?.chatReference ? false : true,
- isNotEncrypted: !!item?.messageText,
- ...additionalFields
- }
- });
- setMessages((prev) => [...prev, ...formatted]);
-
- setChatReferences((prev) => {
- const organizedChatReferences = { ...prev };
- combineUIAndExtensionMsgs
- .filter((rawItem) => rawItem && rawItem.chatReference && (rawItem?.decryptedData?.type === "reaction" || rawItem?.decryptedData?.type === "edit" || rawItem?.type === "edit" || rawItem?.isEdited || rawItem?.type === "reaction"))
- .forEach((item) => {
- try {
- if(item?.decryptedData?.type === "edit"){
- organizedChatReferences[item.chatReference] = {
- ...(organizedChatReferences[item.chatReference] || {}),
- edit: item.decryptedData,
- };
- } else if(item?.type === "edit" || item?.isEdited){
- organizedChatReferences[item.chatReference] = {
- ...(organizedChatReferences[item.chatReference] || {}),
- edit: item,
- };
- } else {
- const content = item?.content || item.decryptedData?.content;
- const sender = item.sender;
- const newTimestamp = item.timestamp;
- const contentState = item?.contentState !== undefined ? item?.contentState : item.decryptedData?.contentState;
-
- if (!content || typeof content !== "string" || !sender || typeof sender !== "string" || !newTimestamp) {
- console.warn("Invalid content, sender, or timestamp in reaction data", item);
- return;
- }
-
- organizedChatReferences[item.chatReference] = {
- ...(organizedChatReferences[item.chatReference] || {}),
- reactions: organizedChatReferences[item.chatReference]?.reactions || {},
- };
-
- organizedChatReferences[item.chatReference].reactions[content] =
- organizedChatReferences[item.chatReference].reactions[content] || [];
-
- let latestTimestampForSender = null;
-
- organizedChatReferences[item.chatReference].reactions[content] =
- organizedChatReferences[item.chatReference].reactions[content].filter((reaction) => {
- if (reaction.sender === sender) {
- latestTimestampForSender = Math.max(latestTimestampForSender || 0, reaction.timestamp);
- }
- return reaction.sender !== sender;
- });
-
- if (latestTimestampForSender && newTimestamp < latestTimestampForSender) {
- return;
- }
-
- if (contentState !== false) {
- organizedChatReferences[item.chatReference].reactions[content].push(item);
- }
-
- if (organizedChatReferences[item.chatReference].reactions[content].length === 0) {
- delete organizedChatReferences[item.chatReference].reactions[content];
- }
+ const combineUIAndExtensionMsgsBefore = [
+ ...decodedUIMessages,
+ ...response,
+ ];
+ const combineUIAndExtensionMsgs = processWithNewMessages(
+ combineUIAndExtensionMsgsBefore.map((item) => ({
+ ...item,
+ ...(item?.decryptedData || {}),
+ })),
+ selectedGroup
+ );
+ res(combineUIAndExtensionMsgs);
+
+ if (isInitiated) {
+ const formatted = combineUIAndExtensionMsgs
+ .filter((rawItem) => !rawItem?.chatReference)
+ .map((item) => {
+ const additionalFields =
+ item?.data === 'NDAwMQ=='
+ ? {
+ text: '
First group key created.
',
}
-
- } catch (error) {
- console.error("Error processing reaction/edit item:", error, item);
- }
- });
-
- return organizedChatReferences;
+ : {};
+ return {
+ ...item,
+ id: item.signature,
+ text: item?.decryptedData?.message || '',
+ repliedTo:
+ item?.repliedTo || item?.decryptedData?.repliedTo,
+ unread:
+ item?.sender === myAddress
+ ? false
+ : !!item?.chatReference
+ ? false
+ : true,
+ isNotEncrypted: !!item?.messageText,
+ ...additionalFields,
+ };
});
- } else {
- let firstUnreadFound = false;
- const formatted = combineUIAndExtensionMsgs
- .filter((rawItem) => !rawItem?.chatReference)
- .map((item) => {
- const additionalFields = item?.data === 'NDAwMQ==' ? {
- text: "
First group key created.
"
- } : {}
- const divide = lastReadTimestamp.current && !firstUnreadFound && item.timestamp > lastReadTimestamp.current && myAddress !== item?.sender;
-
- if(divide){
- firstUnreadFound = true
- }
- return {
- ...item,
- id: item.signature,
- text: item?.decryptedData?.message || "",
- repliedTo: item?.repliedTo || item?.decryptedData?.repliedTo,
- isNotEncrypted: !!item?.messageText,
- unread: false,
- divide,
- ...additionalFields
- }
- });
- setMessages(formatted);
-
- setChatReferences((prev) => {
- const organizedChatReferences = { ...prev };
-
- combineUIAndExtensionMsgs
- .filter((rawItem) => rawItem && rawItem.chatReference && (rawItem?.decryptedData?.type === "reaction" || rawItem?.decryptedData?.type === "edit" || rawItem?.type === "edit" || rawItem?.isEdited || rawItem?.type === "reaction"))
- .forEach((item) => {
- try {
- if(item?.decryptedData?.type === "edit"){
- organizedChatReferences[item.chatReference] = {
- ...(organizedChatReferences[item.chatReference] || {}),
- edit: item.decryptedData,
- };
- } else if(item?.type === "edit" || item?.isEdited){
- organizedChatReferences[item.chatReference] = {
- ...(organizedChatReferences[item.chatReference] || {}),
- edit: item,
- };
- } else {
- const content = item?.content || item.decryptedData?.content;
+ setMessages((prev) => [...prev, ...formatted]);
+
+ setChatReferences((prev) => {
+ const organizedChatReferences = { ...prev };
+ combineUIAndExtensionMsgs
+ .filter(
+ (rawItem) =>
+ rawItem &&
+ rawItem.chatReference &&
+ (rawItem?.decryptedData?.type === 'reaction' ||
+ rawItem?.decryptedData?.type === 'edit' ||
+ rawItem?.type === 'edit' ||
+ rawItem?.isEdited ||
+ rawItem?.type === 'reaction')
+ )
+ .forEach((item) => {
+ try {
+ if (item?.decryptedData?.type === 'edit') {
+ organizedChatReferences[item.chatReference] = {
+ ...(organizedChatReferences[item.chatReference] ||
+ {}),
+ edit: item.decryptedData,
+ };
+ } else if (item?.type === 'edit' || item?.isEdited) {
+ organizedChatReferences[item.chatReference] = {
+ ...(organizedChatReferences[item.chatReference] ||
+ {}),
+ edit: item,
+ };
+ } else {
+ const content =
+ item?.content || item.decryptedData?.content;
const sender = item.sender;
const newTimestamp = item.timestamp;
- const contentState = item?.contentState !== undefined ? item?.contentState : item.decryptedData?.contentState;
-
- if (!content || typeof content !== "string" || !sender || typeof sender !== "string" || !newTimestamp) {
- console.warn("Invalid content, sender, or timestamp in reaction data", item);
+ const contentState =
+ item?.contentState !== undefined
+ ? item?.contentState
+ : item.decryptedData?.contentState;
+
+ if (
+ !content ||
+ typeof content !== 'string' ||
+ !sender ||
+ typeof sender !== 'string' ||
+ !newTimestamp
+ ) {
+ console.warn(
+ 'Invalid content, sender, or timestamp in reaction data',
+ item
+ );
return;
}
-
+
organizedChatReferences[item.chatReference] = {
- ...(organizedChatReferences[item.chatReference] || {}),
- reactions: organizedChatReferences[item.chatReference]?.reactions || {},
+ ...(organizedChatReferences[item.chatReference] ||
+ {}),
+ reactions:
+ organizedChatReferences[item.chatReference]
+ ?.reactions || {},
};
-
- organizedChatReferences[item.chatReference].reactions[content] =
- organizedChatReferences[item.chatReference].reactions[content] || [];
-
+
+ organizedChatReferences[item.chatReference].reactions[
+ content
+ ] =
+ organizedChatReferences[item.chatReference]
+ .reactions[content] || [];
+
let latestTimestampForSender = null;
-
- organizedChatReferences[item.chatReference].reactions[content] =
- organizedChatReferences[item.chatReference].reactions[content].filter((reaction) => {
- if (reaction.sender === sender) {
- latestTimestampForSender = Math.max(latestTimestampForSender || 0, reaction.timestamp);
- }
- return reaction.sender !== sender;
- });
-
- if (latestTimestampForSender && newTimestamp < latestTimestampForSender) {
+
+ organizedChatReferences[item.chatReference].reactions[
+ content
+ ] = organizedChatReferences[
+ item.chatReference
+ ].reactions[content].filter((reaction) => {
+ if (reaction.sender === sender) {
+ latestTimestampForSender = Math.max(
+ latestTimestampForSender || 0,
+ reaction.timestamp
+ );
+ }
+ return reaction.sender !== sender;
+ });
+
+ if (
+ latestTimestampForSender &&
+ newTimestamp < latestTimestampForSender
+ ) {
return;
}
-
+
if (contentState !== false) {
- organizedChatReferences[item.chatReference].reactions[content].push(item);
+ organizedChatReferences[
+ item.chatReference
+ ].reactions[content].push(item);
}
-
- if (organizedChatReferences[item.chatReference].reactions[content].length === 0) {
- delete organizedChatReferences[item.chatReference].reactions[content];
+
+ if (
+ organizedChatReferences[item.chatReference]
+ .reactions[content].length === 0
+ ) {
+ delete organizedChatReferences[item.chatReference]
+ .reactions[content];
}
}
- } catch (error) {
- console.error("Error processing reaction item:", error, item);
- }
- });
-
- return organizedChatReferences;
+ } catch (error) {
+ console.error(
+ 'Error processing reaction/edit item:',
+ error,
+ item
+ );
+ }
+ });
+
+ return organizedChatReferences;
+ });
+ } else {
+ let firstUnreadFound = false;
+ const formatted = combineUIAndExtensionMsgs
+ .filter((rawItem) => !rawItem?.chatReference)
+ .map((item) => {
+ const additionalFields =
+ item?.data === 'NDAwMQ=='
+ ? {
+ text: '
First group key created.
',
+ }
+ : {};
+ const divide =
+ lastReadTimestamp.current &&
+ !firstUnreadFound &&
+ item.timestamp > lastReadTimestamp.current &&
+ myAddress !== item?.sender;
+
+ if (divide) {
+ firstUnreadFound = true;
+ }
+ return {
+ ...item,
+ id: item.signature,
+ text: item?.decryptedData?.message || '',
+ repliedTo:
+ item?.repliedTo || item?.decryptedData?.repliedTo,
+ isNotEncrypted: !!item?.messageText,
+ unread: false,
+ divide,
+ ...additionalFields,
+ };
});
- }
+ setMessages(formatted);
+
+ setChatReferences((prev) => {
+ const organizedChatReferences = { ...prev };
+
+ combineUIAndExtensionMsgs
+ .filter(
+ (rawItem) =>
+ rawItem &&
+ rawItem.chatReference &&
+ (rawItem?.decryptedData?.type === 'reaction' ||
+ rawItem?.decryptedData?.type === 'edit' ||
+ rawItem?.type === 'edit' ||
+ rawItem?.isEdited ||
+ rawItem?.type === 'reaction')
+ )
+ .forEach((item) => {
+ try {
+ if (item?.decryptedData?.type === 'edit') {
+ organizedChatReferences[item.chatReference] = {
+ ...(organizedChatReferences[item.chatReference] ||
+ {}),
+ edit: item.decryptedData,
+ };
+ } else if (item?.type === 'edit' || item?.isEdited) {
+ organizedChatReferences[item.chatReference] = {
+ ...(organizedChatReferences[item.chatReference] ||
+ {}),
+ edit: item,
+ };
+ } else {
+ const content =
+ item?.content || item.decryptedData?.content;
+ const sender = item.sender;
+ const newTimestamp = item.timestamp;
+ const contentState =
+ item?.contentState !== undefined
+ ? item?.contentState
+ : item.decryptedData?.contentState;
+
+ if (
+ !content ||
+ typeof content !== 'string' ||
+ !sender ||
+ typeof sender !== 'string' ||
+ !newTimestamp
+ ) {
+ console.warn(
+ 'Invalid content, sender, or timestamp in reaction data',
+ item
+ );
+ return;
+ }
+
+ organizedChatReferences[item.chatReference] = {
+ ...(organizedChatReferences[item.chatReference] ||
+ {}),
+ reactions:
+ organizedChatReferences[item.chatReference]
+ ?.reactions || {},
+ };
+
+ organizedChatReferences[item.chatReference].reactions[
+ content
+ ] =
+ organizedChatReferences[item.chatReference]
+ .reactions[content] || [];
+
+ let latestTimestampForSender = null;
+
+ organizedChatReferences[item.chatReference].reactions[
+ content
+ ] = organizedChatReferences[
+ item.chatReference
+ ].reactions[content].filter((reaction) => {
+ if (reaction.sender === sender) {
+ latestTimestampForSender = Math.max(
+ latestTimestampForSender || 0,
+ reaction.timestamp
+ );
+ }
+ return reaction.sender !== sender;
+ });
+
+ if (
+ latestTimestampForSender &&
+ newTimestamp < latestTimestampForSender
+ ) {
+ return;
+ }
+
+ if (contentState !== false) {
+ organizedChatReferences[
+ item.chatReference
+ ].reactions[content].push(item);
+ }
+
+ if (
+ organizedChatReferences[item.chatReference]
+ .reactions[content].length === 0
+ ) {
+ delete organizedChatReferences[item.chatReference]
+ .reactions[content];
+ }
+ }
+ } catch (error) {
+ console.error(
+ 'Error processing reaction item:',
+ error,
+ item
+ );
+ }
+ });
+
+ return organizedChatReferences;
+ });
}
- rej(response.error);
- })
- .catch((error) => {
- rej(error.message || "An error occurred");
- });
-
- })
- } catch (error) {
-
- }
+ }
+ rej(response.error);
+ })
+ .catch((error) => {
+ rej(error.message || 'An error occurred');
+ });
+ });
+ } catch (error) {}
+ };
+
+ const forceCloseWebSocket = () => {
+ if (socketRef.current) {
+ clearTimeout(timeoutIdRef.current);
+ clearTimeout(groupSocketTimeoutRef.current);
+ socketRef.current.close(1000, 'forced');
+ socketRef.current = null;
}
+ };
-
+ const pingGroupSocket = () => {
+ try {
+ if (socketRef.current?.readyState === WebSocket.OPEN) {
+ socketRef.current.send('ping');
+ timeoutIdRef.current = setTimeout(() => {
+ if (socketRef.current) {
+ socketRef.current.close();
+ clearTimeout(groupSocketTimeoutRef.current);
+ }
+ }, 5000); // Close if no pong in 5 seconds
+ }
+ } catch (error) {
+ console.error('Error during ping:', error);
+ }
+ };
+ const initWebsocketMessageGroup = () => {
+ let socketLink = `${getBaseApiReactSocket()}/websockets/chat/messages?txGroupId=${selectedGroup}&encoding=BASE64&limit=100`;
+ socketRef.current = new WebSocket(socketLink);
- const forceCloseWebSocket = () => {
- if (socketRef.current) {
-
- clearTimeout(timeoutIdRef.current);
- clearTimeout(groupSocketTimeoutRef.current);
- socketRef.current.close(1000, 'forced');
- socketRef.current = null;
+ socketRef.current.onopen = () => {
+ setTimeout(pingGroupSocket, 50);
+ };
+ socketRef.current.onmessage = (e) => {
+ try {
+ if (e.data === 'pong') {
+ clearTimeout(timeoutIdRef.current);
+ groupSocketTimeoutRef.current = setTimeout(pingGroupSocket, 45000); // Ping every 45 seconds
+ } else {
+ middletierFunc(JSON.parse(e.data), selectedGroup);
+ setIsLoading(false);
+ }
+ } catch (error) {}
+ };
+ socketRef.current.onclose = () => {
+ clearTimeout(groupSocketTimeoutRef.current);
+ clearTimeout(timeoutIdRef.current);
+ console.warn(`WebSocket closed: ${event.reason || 'unknown reason'}`);
+ if (event.reason !== 'forced' && event.code !== 1000) {
+ setTimeout(() => initWebsocketMessageGroup(), 1000); // Retry after 10 seconds
}
};
-
- const pingGroupSocket = () => {
- try {
- if (socketRef.current?.readyState === WebSocket.OPEN) {
- socketRef.current.send('ping');
- timeoutIdRef.current = setTimeout(() => {
- if (socketRef.current) {
- socketRef.current.close();
- clearTimeout(groupSocketTimeoutRef.current);
- }
- }, 5000); // Close if no pong in 5 seconds
- }
- } catch (error) {
- console.error('Error during ping:', error);
+ socketRef.current.onerror = (e) => {
+ clearTimeout(groupSocketTimeoutRef.current);
+ clearTimeout(timeoutIdRef.current);
+ if (socketRef.current) {
+ socketRef.current.close();
+ }
+ };
+ };
+
+ useEffect(() => {
+ if (hasInitializedWebsocket.current) return;
+ if (triedToFetchSecretKey && !secretKey) {
+ forceCloseWebSocket();
+ setMessages([]);
+ setIsLoading(true);
+ initWebsocketMessageGroup();
}
- }
- const initWebsocketMessageGroup = () => {
-
+ }, [triedToFetchSecretKey, secretKey, isPrivate]);
- let socketLink = `${getBaseApiReactSocket()}/websockets/chat/messages?txGroupId=${selectedGroup}&encoding=BASE64&limit=100`
- socketRef.current = new WebSocket(socketLink)
+ useEffect(() => {
+ if (isPrivate === null) return;
+ if (isPrivate === false || !secretKey || hasInitializedWebsocket.current)
+ return;
+ forceCloseWebSocket();
+ setMessages([]);
+ setIsLoading(true);
+ pauseAllQueues();
+ setTimeout(() => {
+ resumeAllQueues();
+ }, 6000);
+ initWebsocketMessageGroup();
+ hasInitializedWebsocket.current = true;
+ }, [secretKey, isPrivate]);
-
- socketRef.current.onopen = () => {
- setTimeout(pingGroupSocket, 50)
- }
- socketRef.current.onmessage = (e) => {
- try {
- if (e.data === 'pong') {
- clearTimeout(timeoutIdRef.current);
- groupSocketTimeoutRef.current = setTimeout(pingGroupSocket, 45000); // Ping every 45 seconds
- } else {
- middletierFunc(JSON.parse(e.data), selectedGroup)
- setIsLoading(false)
- }
- } catch (error) {
-
- }
-
-
- }
- socketRef.current.onclose = () => {
- clearTimeout(groupSocketTimeoutRef.current);
- clearTimeout(timeoutIdRef.current);
- console.warn(`WebSocket closed: ${event.reason || 'unknown reason'}`);
- if (event.reason !== 'forced' && event.code !== 1000) {
- setTimeout(() => initWebsocketMessageGroup(), 1000); // Retry after 10 seconds
- }
- }
- socketRef.current.onerror = (e) => {
- clearTimeout(groupSocketTimeoutRef.current);
- clearTimeout(timeoutIdRef.current);
- if (socketRef.current) {
- socketRef.current.close();
- }
- }
- }
+ useEffect(() => {
+ const notifications = messages.filter(
+ (message) => message?.decryptedData?.type === 'notification'
+ );
+ if (notifications.length === 0) return;
+ const latestNotification = notifications.reduce((latest, current) => {
+ return current.timestamp > latest.timestamp ? current : latest;
+ }, notifications[0]);
+ handleNewEncryptionNotification(latestNotification);
+ }, [messages]);
- useEffect(()=> {
- if(hasInitializedWebsocket.current) return
- if(triedToFetchSecretKey && !secretKey){
- forceCloseWebSocket()
- setMessages([])
- setIsLoading(true)
- initWebsocketMessageGroup()
- }
- }, [triedToFetchSecretKey, secretKey, isPrivate])
-
- useEffect(()=> {
- if(isPrivate === null) return
- if(isPrivate === false || !secretKey || hasInitializedWebsocket.current) return
- forceCloseWebSocket()
- setMessages([])
- setIsLoading(true)
- pauseAllQueues()
- setTimeout(() => {
- resumeAllQueues()
- }, 6000);
- initWebsocketMessageGroup()
- hasInitializedWebsocket.current = true
- }, [secretKey, isPrivate])
-
-
- useEffect(()=> {
- const notifications = messages.filter((message)=> message?.decryptedData
- ?.type === 'notification')
- if(notifications.length === 0) return
- const latestNotification = notifications.reduce((latest, current) => {
- return current.timestamp > latest.timestamp ? current : latest;
- }, notifications[0]);
- handleNewEncryptionNotification(latestNotification)
-
- }, [messages])
-
-
- const encryptChatMessage = async (data: string, secretKeyObject: any, reactiontypeNumber?: number)=> {
+ const encryptChatMessage = async (
+ data: string,
+ secretKeyObject: any,
+ reactiontypeNumber?: number
+ ) => {
try {
- return new Promise((res, rej)=> {
- window.sendMessage("encryptSingle", {
- data,
- secretKeyObject,
- typeNumber: reactiontypeNumber,
- })
+ return new Promise((res, rej) => {
+ window
+ .sendMessage('encryptSingle', {
+ data,
+ secretKeyObject,
+ typeNumber: reactiontypeNumber,
+ })
.then((response) => {
if (!response?.error) {
res(response);
@@ -539,172 +697,189 @@ const [messageSize, setMessageSize] = useState(0)
rej(response.error);
})
.catch((error) => {
- rej(error.message || "An error occurred");
+ rej(error.message || 'An error occurred');
});
-
- })
+ });
+ } catch (error) {}
+ };
+
+ const sendChatGroup = async ({
+ groupId,
+ typeMessage = undefined,
+ chatReference = undefined,
+ messageText,
+ }: any) => {
+ try {
+ return new Promise((res, rej) => {
+ window
+ .sendMessage(
+ 'sendChatGroup',
+ {
+ groupId,
+ typeMessage,
+ chatReference,
+ messageText,
+ },
+ 120000
+ )
+ .then((response) => {
+ if (!response?.error) {
+ res(response);
+ return;
+ }
+ rej(response.error);
+ })
+ .catch((error) => {
+ rej(error.message || 'An error occurred');
+ });
+ });
} catch (error) {
-
+ throw new Error(error);
}
-}
-
-const sendChatGroup = async ({groupId, typeMessage = undefined, chatReference = undefined, messageText}: any)=> {
- try {
- return new Promise((res, rej)=> {
- window.sendMessage("sendChatGroup", {
- groupId,
- typeMessage,
- chatReference,
- messageText,
- }, 120000)
- .then((response) => {
- if (!response?.error) {
- res(response);
- return;
- }
- rej(response.error);
- })
- .catch((error) => {
- rej(error.message || "An error occurred");
- });
-
- })
- } catch (error) {
- throw new Error(error)
- }
-}
-const clearEditorContent = () => {
- if (editorRef.current) {
- setMessageSize(0)
- editorRef.current.chain().focus().clearContent().run();
- if(isMobile){
- setTimeout(() => {
- editorRef.current?.chain().blur().run();
- setIsFocusedParent(false)
- executeEvent("sent-new-message-group", {})
+ };
+ const clearEditorContent = () => {
+ if (editorRef.current) {
+ setMessageSize(0);
+ editorRef.current.chain().focus().clearContent().run();
+ if (isMobile) {
setTimeout(() => {
- triggerRerender();
- }, 300);
- }, 200);
+ editorRef.current?.chain().blur().run();
+ setIsFocusedParent(false);
+ executeEvent('sent-new-message-group', {});
+ setTimeout(() => {
+ triggerRerender();
+ }, 300);
+ }, 200);
+ }
}
- }
-};
+ };
+ const sendMessage = async () => {
+ try {
+ if (messageSize > 4000) return;
+ if (isPrivate === null)
+ throw new Error('Unable to determine if group is private');
+ if (isSending) return;
+ if (+balance < 4)
+ throw new Error('You need at least 4 QORT to send a message');
+ pauseAllQueues();
+ if (editorRef.current) {
+ const htmlContent = editorRef.current.getHTML();
- const sendMessage = async ()=> {
- try {
- if(messageSize > 4000) return
- if(isPrivate === null) throw new Error('Unable to determine if group is private')
- if(isSending) return
- if(+balance < 4) throw new Error('You need at least 4 QORT to send a message')
- pauseAllQueues()
- if (editorRef.current) {
- const htmlContent = editorRef.current.getHTML();
-
- if(!htmlContent?.trim() || htmlContent?.trim() === '
') return
-
+ if (!htmlContent?.trim() || htmlContent?.trim() === '
') return;
- setIsSending(true)
- const message = isPrivate === false ? editorRef.current.getJSON() : htmlContent
- const secretKeyObject = await getSecretKey(false, true)
+ setIsSending(true);
+ const message =
+ isPrivate === false ? editorRef.current.getJSON() : htmlContent;
+ const secretKeyObject = await getSecretKey(false, true);
- let repliedTo = replyMessage?.signature
+ let repliedTo = replyMessage?.signature;
- if (replyMessage?.chatReference) {
- repliedTo = replyMessage?.chatReference
- }
- let chatReference = onEditMessage?.signature
-
- const publicData = isPrivate ? {} : {
- isEdited : chatReference ? true : false,
+ if (replyMessage?.chatReference) {
+ repliedTo = replyMessage?.chatReference;
}
+ let chatReference = onEditMessage?.signature;
+
+ const publicData = isPrivate
+ ? {}
+ : {
+ isEdited: chatReference ? true : false,
+ };
const otherData = {
repliedTo,
...(onEditMessage?.decryptedData || {}),
type: chatReference ? 'edit' : '',
specialId: uid.rnd(),
- ...publicData
- }
+ ...publicData,
+ };
const objectMessage = {
...(otherData || {}),
[isPrivate ? 'message' : 'messageText']: message,
- version: 3
- }
- const message64: any = await objectToBase64(objectMessage)
-
- const encryptSingle = isPrivate === false ? JSON.stringify(objectMessage) : await encryptChatMessage(message64, secretKeyObject)
- // const res = await sendChatGroup({groupId: selectedGroup,messageText: encryptSingle})
-
- const sendMessageFunc = async () => {
- return await sendChatGroup({groupId: selectedGroup,messageText: encryptSingle, chatReference})
+ version: 3,
};
-
+ const message64: any = await objectToBase64(objectMessage);
+
+ const encryptSingle =
+ isPrivate === false
+ ? JSON.stringify(objectMessage)
+ : await encryptChatMessage(message64, secretKeyObject);
+ // const res = await sendChatGroup({groupId: selectedGroup,messageText: encryptSingle})
+
+ const sendMessageFunc = async () => {
+ return await sendChatGroup({
+ groupId: selectedGroup,
+ messageText: encryptSingle,
+ chatReference,
+ });
+ };
+
// Add the function to the queue
const messageObj = {
message: {
text: htmlContent,
timestamp: Date.now(),
- senderName: myName,
- sender: myAddress,
- ...(otherData || {})
+ senderName: myName,
+ sender: myAddress,
+ ...(otherData || {}),
},
- chatReference
- }
- addToQueue(sendMessageFunc, messageObj, 'chat',
- selectedGroup );
+ chatReference,
+ };
+ addToQueue(sendMessageFunc, messageObj, 'chat', selectedGroup);
setTimeout(() => {
- executeEvent("sent-new-message-group", {})
+ executeEvent('sent-new-message-group', {});
}, 150);
- clearEditorContent()
- setReplyMessage(null)
- setOnEditMessage(null)
- }
- // send chat message
- } catch (error) {
- const errorMsg = error?.message || error
- setInfoSnack({
- type: "error",
- message: errorMsg,
- });
- setOpenSnack(true);
- console.error(error)
- } finally {
- setIsSending(false)
- resumeAllQueues()
+ clearEditorContent();
+ setReplyMessage(null);
+ setOnEditMessage(null);
}
+ // send chat message
+ } catch (error) {
+ const errorMsg = error?.message || error;
+ setInfoSnack({
+ type: 'error',
+ message: errorMsg,
+ });
+ setOpenSnack(true);
+ console.error(error);
+ } finally {
+ setIsSending(false);
+ resumeAllQueues();
}
+ };
- useEffect(() => {
- if (!editorRef?.current) return;
-
- handleUpdateRef.current = throttle(async () => {
- try {
- if(isPrivate){
+ useEffect(() => {
+ if (!editorRef?.current) return;
+
+ handleUpdateRef.current = throttle(async () => {
+ try {
+ if (isPrivate) {
const htmlContent = editorRef.current.getHTML();
- const message64 = await objectToBase64(JSON.stringify(htmlContent))
- const secretKeyObject = await getSecretKey(false, true)
- const encryptSingle = await encryptChatMessage(message64, secretKeyObject)
+ const message64 = await objectToBase64(JSON.stringify(htmlContent));
+ const secretKeyObject = await getSecretKey(false, true);
+ const encryptSingle = await encryptChatMessage(
+ message64,
+ secretKeyObject
+ );
setMessageSize((encryptSingle?.length || 0) + 200);
} else {
const htmlContent = editorRef.current.getJSON();
- const message = JSON.stringify(htmlContent)
- const size = new Blob([message]).size
+ const message = JSON.stringify(htmlContent);
+ const size = new Blob([message]).size;
setMessageSize(size + 300);
}
-
- } catch (error) {
+ } catch (error) {
// calc size error
- }
- }, 1200);
-
- const currentEditor = editorRef.current;
-
- currentEditor.on("update", handleUpdateRef.current);
-
- return () => {
- currentEditor.off("update", handleUpdateRef.current);
- };
- }, [editorRef, setMessageSize, isPrivate]);
+ }
+ }, 1200);
+
+ const currentEditor = editorRef.current;
+
+ currentEditor.on('update', handleUpdateRef.current);
+
+ return () => {
+ currentEditor.off('update', handleUpdateRef.current);
+ };
+ }, [editorRef, setMessageSize, isPrivate]);
useEffect(() => {
if (hide) {
@@ -713,210 +888,260 @@ const clearEditorContent = () => {
setIsMoved(false); // Reset the position immediately when showing
}
}, [hide]);
-
- const onReply = useCallback((message)=> {
- if(onEditMessage){
- clearEditorContent()
- }
- setReplyMessage(message)
- setOnEditMessage(null)
- editorRef?.current?.chain().focus()
- }, [onEditMessage])
-
- const onEdit = useCallback((message)=> {
- setOnEditMessage(message)
- setReplyMessage(null)
- editorRef.current.chain().focus().setContent(message?.messageText || message?.text).run();
-
- }, [])
- const handleReaction = useCallback(async (reaction, chatMessage, reactionState = true)=> {
- try {
-
- if(isSending) return
- if(+balance < 4) throw new Error('You need at least 4 QORT to send a message')
- pauseAllQueues()
-
-
- setIsSending(true)
- const message = ''
- const secretKeyObject = await getSecretKey(false, true)
-
-
- const otherData = {
- specialId: uid.rnd(),
- type: 'reaction',
- content: reaction,
- contentState: reactionState
+ const onReply = useCallback(
+ (message) => {
+ if (onEditMessage) {
+ clearEditorContent();
}
- const objectMessage = {
- message,
- ...(otherData || {})
+ setReplyMessage(message);
+ setOnEditMessage(null);
+ editorRef?.current?.chain().focus();
+ },
+ [onEditMessage]
+ );
+
+ const onEdit = useCallback((message) => {
+ setOnEditMessage(message);
+ setReplyMessage(null);
+ editorRef.current
+ .chain()
+ .focus()
+ .setContent(message?.messageText || message?.text)
+ .run();
+ }, []);
+ const handleReaction = useCallback(
+ async (reaction, chatMessage, reactionState = true) => {
+ try {
+ if (isSending) return;
+ if (+balance < 4)
+ throw new Error('You need at least 4 QORT to send a message');
+ pauseAllQueues();
+
+ setIsSending(true);
+ const message = '';
+ const secretKeyObject = await getSecretKey(false, true);
+
+ const otherData = {
+ specialId: uid.rnd(),
+ type: 'reaction',
+ content: reaction,
+ contentState: reactionState,
+ };
+ const objectMessage = {
+ message,
+ ...(otherData || {}),
+ };
+ const message64: any = await objectToBase64(objectMessage);
+ const reactiontypeNumber = RESOURCE_TYPE_NUMBER_GROUP_CHAT_REACTIONS;
+ const encryptSingle =
+ isPrivate === false
+ ? JSON.stringify(objectMessage)
+ : await encryptChatMessage(
+ message64,
+ secretKeyObject,
+ reactiontypeNumber
+ );
+ // const res = await sendChatGroup({groupId: selectedGroup,messageText: encryptSingle})
+
+ const sendMessageFunc = async () => {
+ return await sendChatGroup({
+ groupId: selectedGroup,
+ messageText: encryptSingle,
+ chatReference: chatMessage.signature,
+ });
+ };
+
+ // Add the function to the queue
+ const messageObj = {
+ message: {
+ text: message,
+ timestamp: Date.now(),
+ senderName: myName,
+ sender: myAddress,
+ ...(otherData || {}),
+ },
+ chatReference: chatMessage.signature,
+ };
+ addToQueue(sendMessageFunc, messageObj, 'chat-reaction', selectedGroup);
+ // setTimeout(() => {
+ // executeEvent("sent-new-message-group", {})
+ // }, 150);
+ // clearEditorContent()
+ // setReplyMessage(null)
+
+ // send chat message
+ } catch (error) {
+ const errorMsg = error?.message || error;
+ setInfoSnack({
+ type: 'error',
+ message: errorMsg,
+ });
+ setOpenSnack(true);
+ console.error(error);
+ } finally {
+ setIsSending(false);
+ resumeAllQueues();
}
- const message64: any = await objectToBase64(objectMessage)
- const reactiontypeNumber = RESOURCE_TYPE_NUMBER_GROUP_CHAT_REACTIONS
- const encryptSingle = isPrivate === false ? JSON.stringify(objectMessage) : await encryptChatMessage(message64, secretKeyObject, reactiontypeNumber)
- // const res = await sendChatGroup({groupId: selectedGroup,messageText: encryptSingle})
-
- const sendMessageFunc = async () => {
- return await sendChatGroup({groupId: selectedGroup,messageText: encryptSingle, chatReference: chatMessage.signature})
- };
+ },
+ [isPrivate]
+ );
- // Add the function to the queue
- const messageObj = {
- message: {
- text: message,
- timestamp: Date.now(),
- senderName: myName,
- sender: myAddress,
- ...(otherData || {})
- },
- chatReference: chatMessage.signature
- }
- addToQueue(sendMessageFunc, messageObj, 'chat-reaction',
- selectedGroup );
- // setTimeout(() => {
- // executeEvent("sent-new-message-group", {})
- // }, 150);
- // clearEditorContent()
- // setReplyMessage(null)
+ const openQManager = useCallback(() => {
+ setIsOpenQManager(true);
+ }, []);
- // send chat message
- } catch (error) {
- const errorMsg = error?.message || error
- setInfoSnack({
- type: "error",
- message: errorMsg,
- });
- setOpenSnack(true);
- console.error(error)
- } finally {
- setIsSending(false)
- resumeAllQueues()
- }
- }, [isPrivate])
-
- const openQManager = useCallback(()=> {
- setIsOpenQManager(true)
- }, [])
-
return (
-
-
-
-
- {(!!secretKey || isPrivate === false) && (
-
-
-
+
+
+ {(!!secretKey || isPrivate === false) && (
+
- {replyMessage && (
-
-
+ }}
+ >
+
+ {replyMessage && (
+
+
- {
- setReplyMessage(null)
-
- setOnEditMessage(null)
+ {
+ setReplyMessage(null);
- }}
- >
-
-
-
- )}
- {onEditMessage && (
-
-
+ setOnEditMessage(null);
+ }}
+ >
+
+
+
+ )}
+ {onEditMessage && (
+
+
- {
- setReplyMessage(null)
- setOnEditMessage(null)
-
- clearEditorContent()
-
- }}
- >
-
-
-
- )}
-
-
-
- {messageSize > 750 && (
-
- 4000 ? 'var(--danger)' : 'unset'
- }}>{`Your message size is of ${messageSize} bytes out of a maximum of 4000`}
+ {
+ setReplyMessage(null);
+ setOnEditMessage(null);
-
- )}
-
-
-
+ clearEditorContent();
+ }}
+ >
+
+
+
+ )}
- {
-
- if(isSending) return
- sendMessage()
+
+ {messageSize > 750 && (
+
+ 4000 ? 'var(--danger)' : 'unset',
+ }}
+ >{`Your message size is of ${messageSize} bytes out of a maximum of 4000`}
+
+ )}
+
+
+
+ {
+ if (isSending) return;
+ sendMessage();
}}
style={{
marginTop: 'auto',
@@ -926,85 +1151,108 @@ const clearEditorContent = () => {
flexShrink: 0,
padding: '5px',
width: '100px',
- minWidth: 'auto'
-
+ minWidth: 'auto',
}}
>
{isSending && (
+ size={18}
+ sx={{
+ position: 'absolute',
+ top: '50%',
+ left: '50%',
+ marginTop: '-12px',
+ marginLeft: '-12px',
+ color: 'white',
+ }}
+ />
)}
{` Send`}
-
-
-
- )}
- {isOpenQManager !== null && (
-
-
-
- Q-Manager
- {
- setIsOpenQManager(false)
- }}>
-
-
-
-
-
+
+
)}
-
- {/*
*/}
-
-
+ {isOpenQManager !== null && (
+
+
+
+ Q-Manager
+ {
+ setIsOpenQManager(false);
+ }}
+ >
+
+
+
+
+
+
+
+ )}
+
+ {/*
*/}
+
+
- )
-}
+ );
+};
diff --git a/src/components/Chat/GroupAnnouncements.tsx b/src/components/Chat/GroupAnnouncements.tsx
index 9ba7668..98dd48b 100644
--- a/src/components/Chat/GroupAnnouncements.tsx
+++ b/src/components/Chat/GroupAnnouncements.tsx
@@ -4,30 +4,33 @@ import React, {
useMemo,
useRef,
useState,
-} from "react";
-import { CreateCommonSecret } from "./CreateCommonSecret";
-import { reusableGet } from "../../qdn/publish/pubish";
-import { uint8ArrayToObject } from "../../backgroundFunctions/encryption";
+} from 'react';
+import { CreateCommonSecret } from './CreateCommonSecret';
+import { reusableGet } from '../../qdn/publish/pubish';
+import { uint8ArrayToObject } from '../../backgroundFunctions/encryption';
import {
base64ToUint8Array,
objectToBase64,
-} from "../../qdn/encryption/group-encryption";
-import { ChatContainerComp } from "./ChatContainer";
-import { ChatList } from "./ChatList";
-import "@chatscope/chat-ui-kit-styles/dist/default/styles.min.css";
-import Tiptap from "./TipTap";
-import { AuthenticatedContainerInnerTop, CustomButton } from "../../App-styles";
-import CircularProgress from "@mui/material/CircularProgress";
-import { getBaseApi, getFee } from "../../background";
-import { LoadingSnackbar } from "../Snackbar/LoadingSnackbar";
-import { Box, Typography } from "@mui/material";
-import { Spacer } from "../../common/Spacer";
-import ShortUniqueId from "short-unique-id";
-import { AnnouncementList } from "./AnnouncementList";
+} from '../../qdn/encryption/group-encryption';
+import { ChatContainerComp } from './ChatContainer';
+import { ChatList } from './ChatList';
+import '@chatscope/chat-ui-kit-styles/dist/default/styles.min.css';
+import Tiptap from './TipTap';
+import {
+ AuthenticatedContainerInnerTop,
+ CustomButton,
+} from '../../styles/App-styles';
+import CircularProgress from '@mui/material/CircularProgress';
+import { getBaseApi, getFee } from '../../background';
+import { LoadingSnackbar } from '../Snackbar/LoadingSnackbar';
+import { Box, Typography } from '@mui/material';
+import { Spacer } from '../../common/Spacer';
+import ShortUniqueId from 'short-unique-id';
+import { AnnouncementList } from './AnnouncementList';
const uid = new ShortUniqueId({ length: 8 });
-import CampaignIcon from "@mui/icons-material/Campaign";
-import ArrowBackIcon from "@mui/icons-material/ArrowBack";
-import { AnnouncementDiscussion } from "./AnnouncementDiscussion";
+import CampaignIcon from '@mui/icons-material/Campaign';
+import ArrowBackIcon from '@mui/icons-material/ArrowBack';
+import { AnnouncementDiscussion } from './AnnouncementDiscussion';
import {
MyContext,
getArbitraryEndpointReact,
@@ -35,11 +38,11 @@ import {
isMobile,
pauseAllQueues,
resumeAllQueues,
-} from "../../App";
-import { RequestQueueWithPromise } from "../../utils/queue/queue";
-import { CustomizedSnackbars } from "../Snackbar/Snackbar";
-import { addDataPublishesFunc, getDataPublishesFunc } from "../Group/Group";
-import { getRootHeight } from "../../utils/mobile/mobileUtils";
+} from '../../App';
+import { RequestQueueWithPromise } from '../../utils/queue/queue';
+import { CustomizedSnackbars } from '../Snackbar/Snackbar';
+import { addDataPublishesFunc, getDataPublishesFunc } from '../Group/Group';
+import { getRootHeight } from '../../utils/mobile/mobileUtils';
export const requestQueueCommentCount = new RequestQueueWithPromise(3);
export const requestQueuePublishedAccouncements = new RequestQueueWithPromise(
@@ -48,10 +51,11 @@ export const requestQueuePublishedAccouncements = new RequestQueueWithPromise(
export const saveTempPublish = async ({ data, key }: any) => {
return new Promise((res, rej) => {
- window.sendMessage("saveTempPublish", {
- data,
- key,
- })
+ window
+ .sendMessage('saveTempPublish', {
+ data,
+ key,
+ })
.then((response) => {
if (!response?.error) {
res(response);
@@ -60,37 +64,37 @@ export const saveTempPublish = async ({ data, key }: any) => {
rej(response.error);
})
.catch((error) => {
- rej(error.message || "An error occurred");
+ rej(error.message || 'An error occurred');
});
-
});
};
export const getTempPublish = async () => {
return new Promise((res, rej) => {
- window.sendMessage("getTempPublish", {})
- .then((response) => {
- if (!response?.error) {
- res(response);
- return;
- }
- rej(response.error);
- })
- .catch((error) => {
- rej(error.message || "An error occurred");
- });
-
+ window
+ .sendMessage('getTempPublish', {})
+ .then((response) => {
+ if (!response?.error) {
+ res(response);
+ return;
+ }
+ rej(response.error);
+ })
+ .catch((error) => {
+ rej(error.message || 'An error occurred');
+ });
});
};
export const decryptPublishes = async (encryptedMessages: any[], secretKey) => {
try {
return await new Promise((res, rej) => {
- window.sendMessage("decryptSingleForPublishes", {
- data: encryptedMessages,
- secretKeyObject: secretKey,
- skipDecodeBase64: true,
- })
+ window
+ .sendMessage('decryptSingleForPublishes', {
+ data: encryptedMessages,
+ secretKeyObject: secretKey,
+ skipDecodeBase64: true,
+ })
.then((response) => {
if (!response?.error) {
res(response);
@@ -99,26 +103,23 @@ export const decryptPublishes = async (encryptedMessages: any[], secretKey) => {
rej(response.error);
})
.catch((error) => {
- rej(error.message || "An error occurred");
+ rej(error.message || 'An error occurred');
});
-
});
} catch (error) {}
};
-export const handleUnencryptedPublishes = (publishes) => {
- let publishesData = []
- publishes.forEach((pub)=> {
+export const handleUnencryptedPublishes = (publishes) => {
+ let publishesData = [];
+ publishes.forEach((pub) => {
try {
const decryptToUnit8Array = base64ToUint8Array(pub);
const decodedData = uint8ArrayToObject(decryptToUnit8Array);
- if(decodedData){
- publishesData.push({decryptedData: decodedData})
+ if (decodedData) {
+ publishesData.push({ decryptedData: decodedData });
}
- } catch (error) {
-
- }
- })
- return publishesData
+ } catch (error) {}
+ });
+ return publishesData;
};
export const GroupAnnouncements = ({
selectedGroup,
@@ -130,7 +131,7 @@ export const GroupAnnouncements = ({
isAdmin,
hide,
myName,
- isPrivate
+ isPrivate,
}) => {
const [messages, setMessages] = useState([]);
const [isSending, setIsSending] = useState(false);
@@ -159,12 +160,15 @@ export const GroupAnnouncements = ({
useEffect(() => {
if (!selectedGroup) return;
(async () => {
- const res = await getDataPublishesFunc(selectedGroup, "anc");
+ const res = await getDataPublishesFunc(selectedGroup, 'anc');
dataPublishes.current = res || {};
})();
}, [selectedGroup]);
- const getAnnouncementData = async ({ identifier, name, resource }, isPrivate) => {
+ const getAnnouncementData = async (
+ { identifier, name, resource },
+ isPrivate
+ ) => {
try {
let data = dataPublishes.current[`${name}-${identifier}`];
if (
@@ -179,14 +183,17 @@ export const GroupAnnouncements = ({
});
if (!res?.ok) return;
data = await res.text();
- await addDataPublishesFunc({ ...resource, data }, selectedGroup, "anc");
+ await addDataPublishesFunc({ ...resource, data }, selectedGroup, 'anc');
} else {
data = data.data;
}
- const response = isPrivate === false ? handleUnencryptedPublishes([data]) : await decryptPublishes([{ data }], secretKey);
+ const response =
+ isPrivate === false
+ ? handleUnencryptedPublishes([data])
+ : await decryptPublishes([{ data }], secretKey);
const messageData = response[0];
- if(!messageData) return
+ if (!messageData) return;
setAnnouncementData((prev) => {
return {
...prev,
@@ -194,12 +201,17 @@ export const GroupAnnouncements = ({
};
});
} catch (error) {
- console.error("error", error);
+ console.error('error', error);
}
};
useEffect(() => {
- if ((!secretKey && isPrivate) || hasInitializedWebsocket.current || isPrivate === null) return;
+ if (
+ (!secretKey && isPrivate) ||
+ hasInitializedWebsocket.current ||
+ isPrivate === null
+ )
+ return;
setIsLoading(true);
// initWebsocketMessageGroup()
hasInitializedWebsocket.current = true;
@@ -208,10 +220,11 @@ export const GroupAnnouncements = ({
const encryptChatMessage = async (data: string, secretKeyObject: any) => {
try {
return new Promise((res, rej) => {
- window.sendMessage("encryptSingle", {
- data,
- secretKeyObject,
- })
+ window
+ .sendMessage('encryptSingle', {
+ data,
+ secretKeyObject,
+ })
.then((response) => {
if (!response?.error) {
res(response);
@@ -220,19 +233,19 @@ export const GroupAnnouncements = ({
rej(response.error);
})
.catch((error) => {
- rej(error.message || "An error occurred");
+ rej(error.message || 'An error occurred');
});
-
});
} catch (error) {}
};
const publishAnc = async ({ encryptedData, identifier }: any) => {
return new Promise((res, rej) => {
- window.sendMessage("publishGroupEncryptedResource", {
- encryptedData,
- identifier,
- })
+ window
+ .sendMessage('publishGroupEncryptedResource', {
+ encryptedData,
+ identifier,
+ })
.then((response) => {
if (!response?.error) {
res(response);
@@ -241,9 +254,8 @@ export const GroupAnnouncements = ({
rej(response.error);
})
.catch((error) => {
- rej(error.message || "An error occurred");
+ rej(error.message || 'An error occurred');
});
-
});
};
const clearEditorContent = () => {
@@ -255,7 +267,7 @@ export const GroupAnnouncements = ({
setIsFocusedParent(false);
setTimeout(() => {
triggerRerender();
- }, 300);
+ }, 300);
}, 200);
}
}
@@ -266,10 +278,12 @@ export const GroupAnnouncements = ({
const getTempAnnouncements = await getTempPublish();
if (getTempAnnouncements?.announcement) {
let tempData = [];
- Object.keys(getTempAnnouncements?.announcement || {}).filter((annKey)=> annKey?.startsWith(`grp-${selectedGroup}-anc`)).map((key) => {
- const value = getTempAnnouncements?.announcement[key];
- tempData.push(value.data);
- });
+ Object.keys(getTempAnnouncements?.announcement || {})
+ .filter((annKey) => annKey?.startsWith(`grp-${selectedGroup}-anc`))
+ .map((key) => {
+ const value = getTempAnnouncements?.announcement[key];
+ tempData.push(value.data);
+ });
setTempPublishedList(tempData);
}
} catch (error) {}
@@ -278,27 +292,28 @@ export const GroupAnnouncements = ({
const publishAnnouncement = async () => {
try {
pauseAllQueues();
- const fee = await getFee("ARBITRARY");
+ const fee = await getFee('ARBITRARY');
await show({
- message: "Would you like to perform a ARBITRARY transaction?",
- publishFee: fee.fee + " QORT",
+ message: 'Would you like to perform a ARBITRARY transaction?',
+ publishFee: fee.fee + ' QORT',
});
if (isSending) return;
if (editorRef.current) {
const htmlContent = editorRef.current.getHTML();
- if (!htmlContent?.trim() || htmlContent?.trim() === "
") return;
+ if (!htmlContent?.trim() || htmlContent?.trim() === '
') return;
setIsSending(true);
const message = {
version: 1,
extra: {},
message: htmlContent,
};
- const secretKeyObject = isPrivate === false ? null : await getSecretKey(false, true);
- const message64: any = await objectToBase64(message);
- const encryptSingle = isPrivate === false ? message64 : await encryptChatMessage(
- message64,
- secretKeyObject
- );
+ const secretKeyObject =
+ isPrivate === false ? null : await getSecretKey(false, true);
+ const message64: any = await objectToBase64(message);
+ const encryptSingle =
+ isPrivate === false
+ ? message64
+ : await encryptChatMessage(message64, secretKeyObject);
const randomUid = uid.rnd();
const identifier = `grp-${selectedGroup}-anc-${randomUid}`;
const res = await publishAnc({
@@ -309,13 +324,13 @@ export const GroupAnnouncements = ({
const dataToSaveToStorage = {
name: myName,
identifier,
- service: "DOCUMENT",
+ service: 'DOCUMENT',
tempData: message,
created: Date.now(),
};
await saveTempPublish({
data: dataToSaveToStorage,
- key: "announcement",
+ key: 'announcement',
});
setTempData(selectedGroup);
clearEditorContent();
@@ -324,7 +339,7 @@ export const GroupAnnouncements = ({
} catch (error) {
if (!error) return;
setInfoSnack({
- type: "error",
+ type: 'error',
message: error,
});
setOpenSnack(true);
@@ -343,9 +358,9 @@ export const GroupAnnouncements = ({
const identifier = `grp-${selectedGroup}-anc-`;
const url = `${getBaseApiReact()}${getArbitraryEndpointReact()}?mode=ALL&service=DOCUMENT&identifier=${identifier}&limit=20&includemetadata=false&offset=${offset}&reverse=true&prefix=true`;
const response = await fetch(url, {
- method: "GET",
+ method: 'GET',
headers: {
- "Content-Type": "application/json",
+ 'Content-Type': 'application/json',
},
});
const responseData = await response.json();
@@ -354,11 +369,14 @@ export const GroupAnnouncements = ({
setAnnouncements(responseData);
setIsLoading(false);
for (const data of responseData) {
- getAnnouncementData({
- name: data.name,
- identifier: data.identifier,
- resource: data,
- }, isPrivate);
+ getAnnouncementData(
+ {
+ name: data.name,
+ identifier: data.identifier,
+ resource: data,
+ },
+ isPrivate
+ );
}
} catch (error) {
} finally {
@@ -369,8 +387,13 @@ export const GroupAnnouncements = ({
);
React.useEffect(() => {
- if(!secretKey && isPrivate) return
- if (selectedGroup && !hasInitialized.current && !hide && isPrivate !== null) {
+ if (!secretKey && isPrivate) return;
+ if (
+ selectedGroup &&
+ !hasInitialized.current &&
+ !hide &&
+ isPrivate !== null
+ ) {
getAnnouncements(selectedGroup, isPrivate);
hasInitialized.current = true;
}
@@ -384,9 +407,9 @@ export const GroupAnnouncements = ({
const identifier = `grp-${selectedGroup}-anc-`;
const url = `${getBaseApiReact()}${getArbitraryEndpointReact()}?mode=ALL&service=DOCUMENT&identifier=${identifier}&limit=20&includemetadata=false&offset=${offset}&reverse=true&prefix=true`;
const response = await fetch(url, {
- method: "GET",
+ method: 'GET',
headers: {
- "Content-Type": "application/json",
+ 'Content-Type': 'application/json',
},
});
const responseData = await response.json();
@@ -394,7 +417,10 @@ export const GroupAnnouncements = ({
setAnnouncements((prev) => [...prev, ...responseData]);
setIsLoading(false);
for (const data of responseData) {
- getAnnouncementData({ name: data.name, identifier: data.identifier }, isPrivate);
+ getAnnouncementData(
+ { name: data.name, identifier: data.identifier },
+ isPrivate
+ );
}
} catch (error) {}
};
@@ -406,9 +432,9 @@ export const GroupAnnouncements = ({
const identifier = `grp-${selectedGroup}-anc-`;
const url = `${getBaseApiReact()}${getArbitraryEndpointReact()}?mode=ALL&service=DOCUMENT&identifier=${identifier}&limit=20&includemetadata=false&offset=${0}&reverse=true&prefix=true`;
const response = await fetch(url, {
- method: "GET",
+ method: 'GET',
headers: {
- "Content-Type": "application/json",
+ 'Content-Type': 'application/json',
},
});
const responseData = await response.json();
@@ -416,10 +442,13 @@ export const GroupAnnouncements = ({
if (!latestMessage) {
for (const data of responseData) {
try {
- getAnnouncementData({
- name: data.name,
- identifier: data.identifier,
- }, isPrivate);
+ getAnnouncementData(
+ {
+ name: data.name,
+ identifier: data.identifier,
+ },
+ isPrivate
+ );
} catch (error) {}
}
setAnnouncements(responseData);
@@ -434,7 +463,10 @@ export const GroupAnnouncements = ({
for (const data of newArray) {
try {
- getAnnouncementData({ name: data.name, identifier: data.identifier }, isPrivate);
+ getAnnouncementData(
+ { name: data.name, identifier: data.identifier },
+ isPrivate
+ );
} catch (error) {}
}
setAnnouncements((prev) => [...newArray, ...prev]);
@@ -486,13 +518,15 @@ export const GroupAnnouncements = ({
{!isMobile && (
Group Announcements
)}
-
+
{!isLoading && combinedListTempAndReal?.length === 0 && (
No announcements
@@ -589,28 +622,28 @@ export const GroupAnnouncements = ({
style={{
// position: 'fixed',
// bottom: '0px',
- backgroundColor: "#232428",
- minHeight: isMobile ? "0px" : "150px",
- maxHeight: isMobile ? "auto" : "400px",
- display: "flex",
- flexDirection: "column",
- overflow: "hidden",
- width: "100%",
- boxSizing: "border-box",
- padding: isMobile ? "10px" : "20px",
- position: isFocusedParent ? "fixed" : "relative",
- bottom: isFocusedParent ? "0px" : "unset",
- top: isFocusedParent ? "0px" : "unset",
- zIndex: isFocusedParent ? 5 : "unset",
+ backgroundColor: '#232428',
+ minHeight: isMobile ? '0px' : '150px',
+ maxHeight: isMobile ? 'auto' : '400px',
+ display: 'flex',
+ flexDirection: 'column',
+ overflow: 'hidden',
+ width: '100%',
+ boxSizing: 'border-box',
+ padding: isMobile ? '10px' : '20px',
+ position: isFocusedParent ? 'fixed' : 'relative',
+ bottom: isFocusedParent ? '0px' : 'unset',
+ top: isFocusedParent ? '0px' : 'unset',
+ zIndex: isFocusedParent ? 5 : 'unset',
flexShrink: 0,
}}
>
@@ -625,12 +658,12 @@ export const GroupAnnouncements = ({
{isFocusedParent && (
@@ -639,19 +672,19 @@ export const GroupAnnouncements = ({
if (isSending) return;
setIsFocusedParent(false);
clearEditorContent();
- setTimeout(() => {
- triggerRerender();
- }, 300);
+ setTimeout(() => {
+ triggerRerender();
+ }, 300);
// Unfocus the editor
}}
style={{
- marginTop: "auto",
- alignSelf: "center",
- cursor: isSending ? "default" : "pointer",
- background: "var(--danger)",
+ marginTop: 'auto',
+ alignSelf: 'center',
+ cursor: isSending ? 'default' : 'pointer',
+ background: 'var(--danger)',
flexShrink: 0,
- padding: isMobile && "5px",
- fontSize: isMobile && "14px",
+ padding: isMobile && '5px',
+ fontSize: isMobile && '14px',
}}
>
{` Close`}
@@ -663,25 +696,25 @@ export const GroupAnnouncements = ({
publishAnnouncement();
}}
style={{
- marginTop: "auto",
- alignSelf: "center",
- cursor: isSending ? "default" : "pointer",
- background: isSending && "rgba(0, 0, 0, 0.8)",
+ marginTop: 'auto',
+ alignSelf: 'center',
+ cursor: isSending ? 'default' : 'pointer',
+ background: isSending && 'rgba(0, 0, 0, 0.8)',
flexShrink: 0,
- padding: isMobile && "5px",
- fontSize: isMobile && "14px",
+ padding: isMobile && '5px',
+ fontSize: isMobile && '14px',
}}
>
{isSending && (
)}
@@ -701,7 +734,7 @@ export const GroupAnnouncements = ({
diff --git a/src/components/CoreSyncStatus.tsx b/src/components/CoreSyncStatus.tsx
index 2334bef..e0e4692 100644
--- a/src/components/CoreSyncStatus.tsx
+++ b/src/components/CoreSyncStatus.tsx
@@ -1,28 +1,31 @@
-import React, { useEffect, useState } from 'react';
-import syncedImg from '../assets/syncStatus/synced.png'
-import syncedMintingImg from '../assets/syncStatus/synced_minting.png'
-import syncingImg from '../assets/syncStatus/syncing.png'
+import { useEffect, useState } from 'react';
+import syncedImg from '../assets/syncStatus/synced.png';
+import syncedMintingImg from '../assets/syncStatus/synced_minting.png';
+import syncingImg from '../assets/syncStatus/syncing.png';
import { getBaseApiReact } from '../App';
-import './CoreSyncStatus.css'
-export const CoreSyncStatus = ({imageSize, position}) => {
+import '../styles/CoreSyncStatus.css';
+import { useTheme } from '@mui/material';
+
+export const CoreSyncStatus = () => {
const [nodeInfos, setNodeInfos] = useState({});
const [coreInfos, setCoreInfos] = useState({});
const [isUsingGateway, setIsUsingGateway] = useState(false);
+ const theme = useTheme();
useEffect(() => {
const getNodeInfos = async () => {
-
-
try {
- setIsUsingGateway(!!getBaseApiReact()?.includes('ext-node.qortal.link'))
- const url = `${getBaseApiReact()}/admin/status`;
- const response = await fetch(url, {
- method: "GET",
- headers: {
- "Content-Type": "application/json",
- },
- });
- const data = await response.json();
+ setIsUsingGateway(
+ !!getBaseApiReact()?.includes('ext-node.qortal.link')
+ );
+ const url = `${getBaseApiReact()}/admin/status`;
+ const response = await fetch(url, {
+ method: 'GET',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ });
+ const data = await response.json();
setNodeInfos(data);
} catch (error) {
console.error('Request failed', error);
@@ -30,14 +33,12 @@ export const CoreSyncStatus = ({imageSize, position}) => {
};
const getCoreInfos = async () => {
-
-
try {
const url = `${getBaseApiReact()}/admin/info`;
const response = await fetch(url, {
- method: "GET",
+ method: 'GET',
headers: {
- "Content-Type": "application/json",
+ 'Content-Type': 'application/json',
},
});
const data = await response.json();
@@ -59,55 +60,85 @@ export const CoreSyncStatus = ({imageSize, position}) => {
}, []);
const renderSyncStatusIcon = () => {
- const { isSynchronizing = false, syncPercent = 0, isMintingPossible = false, height = 0, numberOfConnections = 0 } = nodeInfos;
- const buildVersion = coreInfos?.buildVersion ? coreInfos?.buildVersion.substring(0, 12) : '';
+ const {
+ isSynchronizing = false,
+ syncPercent = 0,
+ isMintingPossible = false,
+ height = 0,
+ numberOfConnections = 0,
+ } = nodeInfos;
+ const buildVersion = coreInfos?.buildVersion
+ ? coreInfos?.buildVersion.substring(0, 12)
+ : '';
let imagePath = syncingImg;
- let message = `Synchronizing`
+ let message = `Synchronizing`;
if (isMintingPossible && !isUsingGateway) {
imagePath = syncedMintingImg;
- message = `${isSynchronizing ? 'Synchronizing' : 'Synchronized'} ${'(Minting)'}`
+ message = `${isSynchronizing ? 'Synchronizing' : 'Synchronized'} ${'(Minting)'}`;
} else if (isSynchronizing === true && syncPercent === 99) {
- imagePath = syncingImg
+ imagePath = syncingImg;
} else if (isSynchronizing && !isMintingPossible && syncPercent === 100) {
imagePath = syncingImg;
- message = `Synchronizing ${isUsingGateway ? '' :'(Not Minting)'}`
+ message = `Synchronizing ${isUsingGateway ? '' : '(Not Minting)'}`;
} else if (!isSynchronizing && !isMintingPossible && syncPercent === 100) {
- imagePath = syncedImg
- message = `Synchronized ${isUsingGateway ? '' :'(Not Minting)'}`
+ imagePath = syncedImg;
+ message = `Synchronized ${isUsingGateway ? '' : '(Not Minting)'}`;
} else if (isSynchronizing && isMintingPossible && syncPercent === 100) {
imagePath = syncingImg;
- message = `Synchronizing ${isUsingGateway ? '' :'(Minting)'}`
+ message = `Synchronizing ${isUsingGateway ? '' : '(Minting)'}`;
} else if (!isSynchronizing && isMintingPossible && syncPercent === 100) {
imagePath = syncedMintingImg;
- message = `Synchronized ${isUsingGateway ? '' :'(Minting)'}`
+ message = `Synchronized ${isUsingGateway ? '' : '(Minting)'}`;
}
-
-
return (
-
-
-
+
+
+
+
+
Core Information
- Core Version: {buildVersion}
+
+ Core Version:{' '}
+ {buildVersion}
+
{message}
- Block Height: {height || ''}
- Connected Peers: {numberOfConnections || ''}
- Using public node: {isUsingGateway?.toString()}
+
+ Block Height:{' '}
+ {height || ''}
+
+
+ Connected Peers:{' '}
+
+ {numberOfConnections || ''}
+
+
+
+ Using public node:{' '}
+
+ {isUsingGateway?.toString()}
+
+
);
};
- return (
-
- {renderSyncStatusIcon()}
-
- );
+ return
{renderSyncStatusIcon()}
;
};
-
diff --git a/src/components/Desktop/DesktopFooter.tsx b/src/components/Desktop/DesktopFooter.tsx
index aa2e864..3bcaad5 100644
--- a/src/components/Desktop/DesktopFooter.tsx
+++ b/src/components/Desktop/DesktopFooter.tsx
@@ -1,13 +1,13 @@
-import { ButtonBase, Typography, useTheme } from "@mui/material";
-import Box from "@mui/material/Box";
-import { HubsIcon } from "../../assets/Icons/HubsIcon";
-import { MessagingIcon } from "../../assets/Icons/MessagingIcon";
-import AppIcon from "../../assets/svgs/AppIcon.svg";
+import { ButtonBase, Typography, useTheme } from '@mui/material';
+import Box from '@mui/material/Box';
+import { HubsIcon } from '../../assets/Icons/HubsIcon';
+import { MessagingIcon } from '../../assets/Icons/MessagingIcon';
+import AppIcon from '../../assets/svgs/AppIcon.svg';
-import { HomeIcon } from "../../assets/Icons/HomeIcon";
-import { Save } from "../Save/Save";
-import { useRecoilState } from "recoil";
-import { enabledDevModeAtom } from "../../atoms/global";
+import { HomeIcon } from '../../assets/Icons/HomeIcon';
+import { Save } from '../Save/Save';
+import { useRecoilState } from 'recoil';
+import { enabledDevModeAtom } from '../../atoms/global';
export const IconWrapper = ({
children,
@@ -22,25 +22,25 @@ export const IconWrapper = ({
return (
{children}
-
+
{
- setDesktopViewMode("apps");
+ setDesktopViewMode('apps');
setIsOpenSideViewDirects(false);
setIsOpenSideViewGroups(false);
}}
@@ -114,7 +112,7 @@ export const DesktopFooter = ({
{
- setDesktopSideView("groups");
+ setDesktopSideView('groups');
}}
>
@@ -122,10 +120,10 @@ export const DesktopFooter = ({
height={30}
color={
hasUnreadGroups
- ? "var(--danger)"
+ ? 'var(--danger)'
: isGroups
- ? "white"
- : "rgba(250, 250, 250, 0.5)"
+ ? 'white'
+ : 'rgba(250, 250, 250, 0.5)'
}
/>
@@ -133,7 +131,7 @@ export const DesktopFooter = ({
{
- setDesktopSideView("directs");
+ setDesktopSideView('directs');
}}
>
@@ -141,10 +139,10 @@ export const DesktopFooter = ({
height={30}
color={
hasUnreadDirects
- ? "var(--danger)"
+ ? 'var(--danger)'
: isDirects
- ? "white"
- : "rgba(250, 250, 250, 0.5)"
+ ? 'white'
+ : 'rgba(250, 250, 250, 0.5)'
}
/>
@@ -154,7 +152,7 @@ export const DesktopFooter = ({
{isEnabledDevMode && (
{
- setDesktopViewMode("dev");
+ setDesktopViewMode('dev');
setIsOpenSideViewDirects(false);
setIsOpenSideViewGroups(false);
}}
diff --git a/src/components/Desktop/DesktopHeader.tsx b/src/components/Desktop/DesktopHeader.tsx
index 4820054..9dbe111 100644
--- a/src/components/Desktop/DesktopHeader.tsx
+++ b/src/components/Desktop/DesktopHeader.tsx
@@ -1,47 +1,55 @@
-import * as React from "react";
+import * as React from 'react';
import {
BottomNavigation,
BottomNavigationAction,
ButtonBase,
Typography,
-} from "@mui/material";
-import { Home, Groups, Message, ShowChart } from "@mui/icons-material";
-import Box from "@mui/material/Box";
-import BottomLogo from "../../assets/svgs/BottomLogo5.svg";
-import { CustomSvg } from "../../common/CustomSvg";
-import { WalletIcon } from "../../assets/Icons/WalletIcon";
-import { HubsIcon } from "../../assets/Icons/HubsIcon";
-import { TradingIcon } from "../../assets/Icons/TradingIcon";
-import { MessagingIcon } from "../../assets/Icons/MessagingIcon";
-import { HomeIcon } from "../../assets/Icons/HomeIcon";
-import { NotificationIcon2 } from "../../assets/Icons/NotificationIcon2";
-import { ChatIcon } from "../../assets/Icons/ChatIcon";
-import { ThreadsIcon } from "../../assets/Icons/ThreadsIcon";
-import { MembersIcon } from "../../assets/Icons/MembersIcon";
-import { AdminsIcon } from "../../assets/Icons/AdminsIcon";
+} from '@mui/material';
+import { Home, Groups, Message, ShowChart } from '@mui/icons-material';
+import Box from '@mui/material/Box';
+import BottomLogo from '../../assets/svgs/BottomLogo5.svg';
+import { CustomSvg } from '../../common/CustomSvg';
+import { HubsIcon } from '../../assets/Icons/HubsIcon';
+import { TradingIcon } from '../../assets/Icons/TradingIcon';
+import { MessagingIcon } from '../../assets/Icons/MessagingIcon';
+import { HomeIcon } from '../../assets/Icons/HomeIcon';
+import { NotificationIcon2 } from '../../assets/Icons/NotificationIcon2';
+import { ChatIcon } from '../../assets/Icons/ChatIcon';
+import { ThreadsIcon } from '../../assets/Icons/ThreadsIcon';
+import { MembersIcon } from '../../assets/Icons/MembersIcon';
+import { AdminsIcon } from '../../assets/Icons/AdminsIcon';
import LockIcon from '@mui/icons-material/Lock';
import NoEncryptionGmailerrorredIcon from '@mui/icons-material/NoEncryptionGmailerrorred';
-const IconWrapper = ({ children, label, color, selected, selectColor, customHeight }) => {
+const IconWrapper = ({
+ children,
+ label,
+ color,
+ selected,
+ selectColor,
+ customHeight,
+}) => {
return (
{children}
{
const [value, setValue] = React.useState(0);
return (
-
+
{isPrivate && (
-
+
)}
{isPrivate === false && (
-
+
)}
- {selectedGroup?.groupId === '0' ? 'General' :selectedGroup?.groupName}
+ {selectedGroup?.groupId === '0'
+ ? 'General'
+ : selectedGroup?.groupName}
-
{
- goToAnnouncements()
+ goToAnnouncements();
}}
>
@@ -158,11 +173,11 @@ export const DesktopHeader = ({
{
- goToChat()
+ goToChat();
}}
>
@@ -184,12 +199,11 @@ export const DesktopHeader = ({
{
- setGroupSection("forum");
-
+ setGroupSection('forum');
}}
>
{
- setOpenManageMembers(true)
-
+ setOpenManageMembers(true);
}}
>
{
- setGroupSection("adminSpace");
-
+ setGroupSection('adminSpace');
}}
>
diff --git a/src/components/DesktopSideBar.tsx b/src/components/DesktopSideBar.tsx
index bd883be..dce577b 100644
--- a/src/components/DesktopSideBar.tsx
+++ b/src/components/DesktopSideBar.tsx
@@ -1,12 +1,12 @@
-import { Box, ButtonBase, useTheme } from "@mui/material";
-import { HomeIcon } from "../assets/Icons/HomeIcon";
-import { MessagingIcon } from "../assets/Icons/MessagingIcon";
-import { Save } from "./Save/Save";
-import { IconWrapper } from "./Desktop/DesktopFooter";
-import { useRecoilState } from "recoil";
-import { enabledDevModeAtom } from "../atoms/global";
-import { AppsIcon } from "../assets/Icons/AppsIcon";
-import ThemeSelector from "./Theme/ThemeSelector";
+import { Box, ButtonBase, useTheme } from '@mui/material';
+import { HomeIcon } from '../assets/Icons/HomeIcon';
+import { MessagingIcon } from '../assets/Icons/MessagingIcon';
+import { Save } from './Save/Save';
+import { IconWrapper } from './Desktop/DesktopFooter';
+import { useRecoilState } from 'recoil';
+import { enabledDevModeAtom } from '../atoms/global';
+import { AppsIcon } from '../assets/Icons/AppsIcon';
+import ThemeSelector from './Theme/ThemeSelector';
export const DesktopSideBar = ({
goToHome,
@@ -24,25 +24,25 @@ export const DesktopSideBar = ({
}) => {
const [isEnabledDevMode, setIsEnabledDevMode] =
useRecoilState(enabledDevModeAtom);
-
+
const theme = useTheme();
return (
{
goToHome();
@@ -51,39 +51,39 @@ export const DesktopSideBar = ({
{
- setDesktopViewMode("apps");
+ setDesktopViewMode('apps');
// setIsOpenSideViewDirects(false)
// setIsOpenSideViewGroups(false)
}}
>
{
- setDesktopViewMode("chat");
+ setDesktopViewMode('chat');
}}
>
@@ -121,24 +121,22 @@ export const DesktopSideBar = ({
{isEnabledDevMode && (
{
- setDesktopViewMode("dev");
+ setDesktopViewMode('dev');
}}
>
-
+
)}
-
+
);
};
diff --git a/src/components/GeneralNotifications.tsx b/src/components/GeneralNotifications.tsx
index c7336dc..3235fbb 100644
--- a/src/components/GeneralNotifications.tsx
+++ b/src/components/GeneralNotifications.tsx
@@ -1,5 +1,4 @@
-import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
-
+import { useState } from 'react';
import {
Box,
ButtonBase,
@@ -8,58 +7,72 @@ import {
Popover,
Tooltip,
Typography,
-} from "@mui/material";
-import NotificationsIcon from "@mui/icons-material/Notifications";
-import AccountBalanceWalletIcon from "@mui/icons-material/AccountBalanceWallet";
-import { formatDate } from "../utils/time";
-import { useHandlePaymentNotification } from "../hooks/useHandlePaymentNotification";
-import { executeEvent } from "../utils/events";
+ useTheme,
+} from '@mui/material';
+import NotificationsIcon from '@mui/icons-material/Notifications';
+import AccountBalanceWalletIcon from '@mui/icons-material/AccountBalanceWallet';
+import { formatDate } from '../utils/time';
+import { useHandlePaymentNotification } from '../hooks/useHandlePaymentNotification';
+import { executeEvent } from '../utils/events';
export const GeneralNotifications = ({ address }) => {
const [anchorEl, setAnchorEl] = useState(null);
- const {latestTx,
+
+ const {
+ latestTx,
getNameOrAddressOfSenderMiddle,
- hasNewPayment, setLastEnteredTimestampPayment, nameAddressOfSender} = useHandlePaymentNotification(address)
-
+ hasNewPayment,
+ setLastEnteredTimestampPayment,
+ nameAddressOfSender,
+ } = useHandlePaymentNotification(address);
+
const handlePopupClick = (event) => {
event.stopPropagation(); // Prevent parent onClick from firing
setAnchorEl(event.currentTarget);
};
+ const theme = useTheme();
+
return (
<>
{
handlePopupClick(e);
-
-
}}
style={{}}
>
- PAYMENT NOTIFICATION}
- placement="left"
- arrow
- sx={{ fontSize: "24" }}
- slotProps={{
- tooltip: {
- sx: {
- color: "#ffffff",
- backgroundColor: "#444444",
- },
- },
- arrow: {
- sx: {
- color: "#444444",
- },
- },
- }}
- >
-
+ PAYMENT NOTIFICATION
+
+ }
+ placement="left"
+ arrow
+ sx={{ fontSize: '24' }}
+ slotProps={{
+ tooltip: {
+ sx: {
+ color: '#ffffff',
+ backgroundColor: '#444444',
+ },
+ },
+ arrow: {
+ sx: {
+ color: '#444444',
+ },
+ },
}}
- />
+ >
+
@@ -67,81 +80,91 @@ export const GeneralNotifications = ({ address }) => {
open={!!anchorEl}
anchorEl={anchorEl}
onClose={() => {
- if(hasNewPayment){
- setLastEnteredTimestampPayment(Date.now())
+ if (hasNewPayment) {
+ setLastEnteredTimestampPayment(Date.now());
}
- setAnchorEl(null)
-
+ setAnchorEl(null);
}} // Close popover on click outside
>
- {!hasNewPayment && No new notifications }
+ {!hasNewPayment && (
+
+ No new notifications
+
+ )}
{hasNewPayment && (
{
- setAnchorEl(null)
- executeEvent('openWalletsApp', {})
+ onClick={() => {
+ setAnchorEl(null);
+ executeEvent('openWalletsApp', {});
}}
>
-
-
- {" "}
- {formatDate(latestTx?.timestamp)}
-
-
-
- {latestTx?.amount}
-
- {nameAddressOfSender.current[latestTx?.creatorAddress] || getNameOrAddressOfSenderMiddle(latestTx?.creatorAddress)}
-
+ >
+ {' '}
+ {formatDate(latestTx?.timestamp)}
+
+
+ {latestTx?.amount}
+
+
+ {nameAddressOfSender.current[latestTx?.creatorAddress] ||
+ getNameOrAddressOfSenderMiddle(latestTx?.creatorAddress)}
+
)}
diff --git a/src/components/GlobalActions/JoinGroup.tsx b/src/components/GlobalActions/JoinGroup.tsx
index f03430b..5085bac 100644
--- a/src/components/GlobalActions/JoinGroup.tsx
+++ b/src/components/GlobalActions/JoinGroup.tsx
@@ -1,5 +1,5 @@
-import React, { useContext, useEffect, useMemo, useState } from "react";
-import { subscribeToEvent, unsubscribeFromEvent } from "../../utils/events";
+import React, { useContext, useEffect, useMemo, useState } from 'react';
+import { subscribeToEvent, unsubscribeFromEvent } from '../../utils/events';
import {
Box,
Button,
@@ -9,12 +9,12 @@ import {
DialogActions,
DialogContent,
Typography,
-} from "@mui/material";
-import { CustomButton, CustomButtonAccept } from "../../App-styles";
-import { getBaseApiReact, MyContext } from "../../App";
-import { getFee } from "../../background";
-import { CustomizedSnackbars } from "../Snackbar/Snackbar";
-import { FidgetSpinner } from "react-loader-spinner";
+} from '@mui/material';
+import { CustomButton, CustomButtonAccept } from '../../styles/App-styles';
+import { getBaseApiReact, MyContext } from '../../App';
+import { getFee } from '../../background';
+import { CustomizedSnackbars } from '../Snackbar/Snackbar';
+import { FidgetSpinner } from 'react-loader-spinner';
export const JoinGroup = ({ memberGroups }) => {
const { show, setTxList } = useContext(MyContext);
@@ -42,43 +42,45 @@ export const JoinGroup = ({ memberGroups }) => {
};
useEffect(() => {
- subscribeToEvent("globalActionJoinGroup", handleJoinGroup);
+ subscribeToEvent('globalActionJoinGroup', handleJoinGroup);
return () => {
- unsubscribeFromEvent("globalActionJoinGroup", handleJoinGroup);
+ unsubscribeFromEvent('globalActionJoinGroup', handleJoinGroup);
};
}, []);
- const isInGroup = useMemo(()=> {
- return !!memberGroups.find((item)=> +item?.groupId === +groupInfo?.groupId)
- }, [memberGroups, groupInfo])
+ const isInGroup = useMemo(() => {
+ return !!memberGroups.find(
+ (item) => +item?.groupId === +groupInfo?.groupId
+ );
+ }, [memberGroups, groupInfo]);
const joinGroup = async (group, isOpen) => {
try {
const groupId = group.groupId;
- const fee = await getFee("JOIN_GROUP");
+ const fee = await getFee('JOIN_GROUP');
await show({
- message: "Would you like to perform an JOIN_GROUP transaction?",
- publishFee: fee.fee + " QORT",
+ message: 'Would you like to perform an JOIN_GROUP transaction?',
+ publishFee: fee.fee + ' QORT',
});
setIsLoadingJoinGroup(true);
await new Promise((res, rej) => {
window
- .sendMessage("joinGroup", {
+ .sendMessage('joinGroup', {
groupId,
})
.then((response) => {
if (!response?.error) {
setInfoSnack({
- type: "success",
+ type: 'success',
message:
- "Successfully requested to join group. It may take a couple of minutes for the changes to propagate",
+ 'Successfully requested to join group. It may take a couple of minutes for the changes to propagate',
});
if (isOpen) {
setTxList((prev) => [
{
...response,
- type: "joined-group",
+ type: 'joined-group',
label: `Joined Group ${group?.groupName}: awaiting confirmation`,
labelDone: `Joined Group ${group?.groupName}: success!`,
done: false,
@@ -90,7 +92,7 @@ export const JoinGroup = ({ memberGroups }) => {
setTxList((prev) => [
{
...response,
- type: "joined-group-request",
+ type: 'joined-group-request',
label: `Requested to join Group ${group?.groupName}: awaiting confirmation`,
labelDone: `Requested to join Group ${group?.groupName}: success!`,
done: false,
@@ -105,7 +107,7 @@ export const JoinGroup = ({ memberGroups }) => {
return;
} else {
setInfoSnack({
- type: "error",
+ type: 'error',
message: response?.error,
});
setOpenSnack(true);
@@ -114,8 +116,8 @@ export const JoinGroup = ({ memberGroups }) => {
})
.catch((error) => {
setInfoSnack({
- type: "error",
- message: error.message || "An error occurred",
+ type: 'error',
+ message: error.message || 'An error occurred',
});
setOpenSnack(true);
rej(error);
@@ -138,37 +140,37 @@ export const JoinGroup = ({ memberGroups }) => {
{!groupInfo && (
- {" "}
+ {' '}
{" "}
+ />{' '}
)}
@@ -176,7 +178,7 @@ export const JoinGroup = ({ memberGroups }) => {
@@ -185,7 +187,7 @@ export const JoinGroup = ({ memberGroups }) => {
{groupInfo?.description && (
@@ -193,19 +195,19 @@ export const JoinGroup = ({ memberGroups }) => {
)}
{isInGroup && (
-
- *You are already in this group!
-
+
+ *You are already in this group!
+
)}
{!isInGroup && groupInfo?.isOpen === false && (
@@ -216,32 +218,34 @@ export const JoinGroup = ({ memberGroups }) => {
- {
+ {
joinGroup(groupInfo, groupInfo?.isOpen);
setIsOpen(false);
- }} disabled={isInGroup}>
-
- Join
-
+
+ Join
+
-
+
setIsOpen(false)}
>
@@ -259,14 +263,14 @@ export const JoinGroup = ({ memberGroups }) => {
{isLoadingJoinGroup && (
{
+import { executeEvent, subscribeToEvent, unsubscribeFromEvent } from "../../utils/events";
+import { validateAddress } from "../../utils/validateAddress";
+import { getNameInfo, requestQueueMemberNames } from "./Group";
+import { useModal } from "../../common/useModal";
+import { useRecoilState } from "recoil";
+import { isOpenBlockedModalAtom } from "../../atoms/global";
+import InfoIcon from '@mui/icons-material/Info';
+export const BlockedUsersModal = () => {
+ const [isOpenBlockedModal, setIsOpenBlockedModal] = useRecoilState(isOpenBlockedModalAtom)
const [hasChanged, setHasChanged] = useState(false);
const [value, setValue] = useState("");
-
- const { getAllBlockedUsers, removeBlockFromList, addToBlockList } = useContext(MyContext);
+ const [addressesWithNames, setAddressesWithNames] = useState({})
+ const { isShow, onCancel, onOk, show, message } = useModal();
+ const { getAllBlockedUsers, removeBlockFromList, addToBlockList, setOpenSnackGlobal, setInfoSnackCustom } =
+ useContext(MyContext);
const [blockedUsers, setBlockedUsers] = useState({
addresses: {},
names: {},
@@ -28,60 +36,162 @@ export const BlockedUsersModal = ({ close }) => {
};
useEffect(() => {
+ if(!isOpenBlockedModal) return
fetchBlockedUsers();
- }, []);
+ }, [isOpenBlockedModal]);
+
+ const getNames = async () => {
+ // const validApi = await findUsableApi();
+ const addresses = Object.keys(blockedUsers?.addresses)
+ const addressNames = {}
+
+
+ const getMemNames = addresses.map(async (address) => {
+ const name = await requestQueueMemberNames.enqueue(() => {
+ return getNameInfo(address);
+ });
+ if (name) {
+ addressNames[address] = name
+ }
+
+
+ return true;
+ });
+
+ await Promise.all(getMemNames);
+
+ setAddressesWithNames(addressNames)
+ };
+
+ const blockUser = async (e, user?: string) => {
+ try {
+ const valUser = user || value
+ if (!valUser) return;
+ const isAddress = validateAddress(valUser);
+ let userName = null;
+ let userAddress = null;
+ if (isAddress) {
+ userAddress = valUser;
+ const name = await getNameInfo(valUser);
+ if (name) {
+ userName = name;
+ }
+ }
+ if (!isAddress) {
+ const response = await fetch(`${getBaseApiReact()}/names/${valUser}`);
+ const data = await response.json();
+ if (!data?.owner) throw new Error("Name does not exist");
+ if (data?.owner) {
+ userAddress = data.owner;
+ userName = valUser;
+ }
+ }
+ if(!userName){
+ await addToBlockList(userAddress, null);
+ fetchBlockedUsers();
+ setHasChanged(true);
+ executeEvent('updateChatMessagesWithBlocks', true)
+ setValue('')
+ return
+ }
+ const responseModal = await show({
+ userName,
+ userAddress,
+ });
+ if (responseModal === "both") {
+ await addToBlockList(userAddress, userName);
+ } else if (responseModal === "address") {
+ await addToBlockList(userAddress, null);
+ } else if (responseModal === "name") {
+ await addToBlockList(null, userName);
+ }
+ fetchBlockedUsers();
+ setHasChanged(true);
+ setValue('')
+ if(user){
+ setIsOpenBlockedModal(false)
+ }
+ if(responseModal === 'both' || responseModal === 'address'){
+ executeEvent('updateChatMessagesWithBlocks', true)
+ }
+ } catch (error) {
+ setOpenSnackGlobal(true);
+
+ setInfoSnackCustom({
+ type: "error",
+ message: error?.message || "Unable to block user",
+ });
+ }
+ };
+ const blockUserFromOutsideModalFunc = (e) => {
+ const user = e.detail?.user;
+ setIsOpenBlockedModal(true)
+ blockUser(null, user)
+ };
+
+ useEffect(() => {
+ subscribeToEvent("blockUserFromOutside", blockUserFromOutsideModalFunc);
+
+ return () => {
+ unsubscribeFromEvent("blockUserFromOutside", blockUserFromOutsideModalFunc);
+ };
+ }, []);
return (
- Blocked Users
-
- Blocked Users
+
- {
- setValue(e.target.value);
+ >
+
- {
- try {
- if(!value) return
- await addToBlockList(undefined, value)
- fetchBlockedUsers()
- setHasChanged(true)
- } catch (error) {
- console.error(error)
- }
- }}>Block
-
-
+ >
+ {
+ setValue(e.target.value);
+ }}
+ />
+
+ Block
+
+
+
{Object.entries(blockedUsers?.addresses).length > 0 && (
<>
- Blocked Users for Chat ( addresses )
+ Blocked addresses- blocks processing of txs
+ Fetch names
+
>
)}
-
+
{Object.entries(blockedUsers?.addresses || {})?.map(
([key, value]) => {
return (
@@ -90,18 +200,22 @@ export const BlockedUsersModal = ({ close }) => {
display: "flex",
alignItems: "center",
gap: "10px",
- width: '100%',
- justifyContent: 'space-between'
+ width: "100%",
+ justifyContent: "space-between",
}}
>
- {key}
+ {addressesWithNames[key] || key}
{
try {
await removeBlockFromList(key, undefined);
setHasChanged(true);
- setValue('')
+ setValue("");
fetchBlockedUsers();
} catch (error) {
console.error(error);
@@ -119,17 +233,19 @@ export const BlockedUsersModal = ({ close }) => {
<>
- Blocked Users for QDN and Chat (names)
+ Blocked names for QDN
>
)}
-
+
{Object.entries(blockedUsers?.names || {})?.map(([key, value]) => {
return (
{
display: "flex",
alignItems: "center",
gap: "10px",
- width: '100%',
- justifyContent: 'space-between'
+ width: "100%",
+ justifyContent: "space-between",
}}
>
{key}
{
try {
@@ -175,16 +295,67 @@ export const BlockedUsersModal = ({ close }) => {
},
}}
variant="contained"
- onClick={()=> {
- if(hasChanged){
- executeEvent('updateChatMessagesWithBlocks', true)
+ onClick={() => {
+ if (hasChanged) {
+ executeEvent("updateChatMessagesWithBlocks", true);
}
- close()
+ setIsOpenBlockedModal(false);
}}
>
close
+
+
+
+ {"Decide what to block"}
+
+
+
+ Blocking {message?.userName || message?.userAddress}
+
+
+ Choose "block txs" or "all" to block chat messages
+
+
+
+ {
+ onOk("address");
+ }}
+ >
+ Block txs
+
+ {
+ onOk("name");
+ }}
+ >
+ Block QDN data
+
+ {
+ onOk("both");
+ }}
+ >
+ Block All
+
+
+
);
};
diff --git a/src/components/Group/Forum/Thread copy.tsx b/src/components/Group/Forum/Thread copy.tsx
deleted file mode 100644
index 9091a2c..0000000
--- a/src/components/Group/Forum/Thread copy.tsx
+++ /dev/null
@@ -1,329 +0,0 @@
-import React, {
- FC,
- useCallback,
- useEffect,
- useRef,
- useState
-} from 'react'
-
-import {
- Box,
-
- Skeleton,
-
-} from '@mui/material'
-import { ShowMessage } from './ShowMessageWithoutModal'
-// import {
-// setIsLoadingCustom,
-// } from '../../state/features/globalSlice'
-import { ComposeP, GroupContainer, GroupNameP, MailIconImg, ShowMessageReturnButton, SingleThreadParent, ThreadContainer, ThreadContainerFullWidth } from './Mail-styles'
-import { Spacer } from '../../../common/Spacer'
-import { threadIdentifier } from './GroupMail'
-import LazyLoad from '../../../common/LazyLoad'
-import ReturnSVG from '../../../assets/svgs/Return.svg'
-import { NewThread } from './NewThread'
-import { decryptPublishes } from '../../Chat/GroupAnnouncements'
-import { getBaseApi } from '../../../background'
-import { getArbitraryEndpointReact, getBaseApiReact } from '../../../App'
-interface ThreadProps {
- currentThread: any
- groupInfo: any
- closeThread: () => void
- members: any
-}
-
-const getEncryptedResource = async ({name, identifier, secretKey})=> {
-
- const res = await fetch(
- `${getBaseApiReact()}/arbitrary/DOCUMENT/${name}/${identifier}?encoding=base64`
- );
- const data = await res.text();
- const response = await decryptPublishes([{ data }], secretKey);
- const messageData = response[0];
- return messageData.decryptedData
-
-}
-
-export const Thread = ({
- currentThread,
- groupInfo,
- closeThread,
- members,
- userInfo,
- secretKey,
- getSecretKey
-}: ThreadProps) => {
- const [messages, setMessages] = useState([])
- const [hashMapMailMessages, setHashMapMailMessages] = useState({})
- const secretKeyRef = useRef(null)
-
-
- useEffect(() => {
- secretKeyRef.current = secretKey;
- }, [secretKey]);
- const getIndividualMsg = async (message: any) => {
- try {
- const responseDataMessage = await getEncryptedResource({identifier: message.identifier, name: message.name, secretKey})
-
-
- const fullObject = {
- ...message,
- ...(responseDataMessage || {}),
- id: message.identifier
- }
- setHashMapMailMessages((prev)=> {
- return {
- ...prev,
- [message.identifier]: fullObject
- }
- })
- } catch (error) {}
- }
-
- const getMailMessages = React.useCallback(
- async (groupInfo: any, reset?: boolean, hideAlert?: boolean) => {
- try {
- if(!hideAlert){
- // dispatch(setIsLoadingCustom('Loading messages'))
-
- }
- let threadId = groupInfo.threadId
-
- const offset = messages.length
- const identifier = `thmsg-${threadId}`
- const url = `${getBaseApiReact()}${getArbitraryEndpointReact()}?mode=ALL&service=${threadIdentifier}&identifier=${identifier}&limit=20&includemetadata=false&offset=${offset}&reverse=true&prefix=true`
- const response = await fetch(url, {
- method: 'GET',
- headers: {
- 'Content-Type': 'application/json'
- }
- })
- const responseData = await response.json()
- let fullArrayMsg = reset ? [] : [...messages]
- let newMessages: any[] = []
- for (const message of responseData) {
- const index = fullArrayMsg.findIndex(
- (p) => p.identifier === message.identifier
- )
- if (index !== -1) {
- fullArrayMsg[index] = message
- } else {
- fullArrayMsg.push(message)
- getIndividualMsg(message)
- }
- }
- setMessages(fullArrayMsg)
- } catch (error) {
- } finally {
- if(!hideAlert){
- // dispatch(setIsLoadingCustom(null))
- }
- }
- },
- [messages, secretKey]
- )
- const getMessages = React.useCallback(async () => {
- if (!currentThread || !secretKey) return
- await getMailMessages(currentThread, true)
- }, [getMailMessages, currentThread, secretKey])
- const firstMount = useRef(false)
-
- const saveTimestamp = useCallback((currentThread: any, username?: string)=> {
- if(!currentThread?.threadData?.groupId || !currentThread?.threadId || !username) return
- const threadIdForLocalStorage = `qmail_threads_${currentThread?.threadData?.groupId}_${currentThread?.threadId}`
- const threads = JSON.parse(
- localStorage.getItem(`qmail_threads_viewedtimestamp_${username}`) || "{}"
- );
- // Convert to an array of objects with identifier and all fields
- let dataArray = Object.entries(threads).map(([identifier, value]) => ({
- identifier,
- ...(value as any),
- }));
-
- // Sort the array based on timestamp in descending order
- dataArray.sort((a, b) => b.timestamp - a.timestamp);
-
- // Slice the array to keep only the first 500 elements
- let latest500 = dataArray.slice(0, 500);
-
- // Convert back to the original object format
- let latest500Data: any = {};
- latest500.forEach(item => {
- const { identifier, ...rest } = item;
- latest500Data[identifier] = rest;
- });
- latest500Data[threadIdForLocalStorage] = {
- timestamp: Date.now(),
- }
- localStorage.setItem(
- `qmail_threads_viewedtimestamp_${username}`,
- JSON.stringify(latest500Data)
- );
- }, [])
- useEffect(() => {
- if (currentThread && secretKey) {
- getMessages()
- firstMount.current = true
- // saveTimestamp(currentThread, user.name)
- }
- }, [ currentThread, secretKey])
- const messageCallback = useCallback((msg: any) => {
- // dispatch(addToHashMapMail(msg))
- setMessages((prev) => [msg, ...prev])
- }, [])
-
- const interval = useRef(null)
-
- const checkNewMessages = React.useCallback(
- async (groupInfo: any) => {
- try {
- let threadId = groupInfo.threadId
-
- const identifier = `thmsg-${threadId}`
- const url = `${getBaseApiReact()}${getArbitraryEndpointReact()}?mode=ALL&service=${threadIdentifier}&identifier=${identifier}&limit=20&includemetadata=false&offset=${0}&reverse=true&prefix=true`
- const response = await fetch(url, {
- method: 'GET',
- headers: {
- 'Content-Type': 'application/json'
- }
- })
- const responseData = await response.json()
- const latestMessage = messages[0]
- if (!latestMessage) return
- const findMessage = responseData?.findIndex(
- (item: any) => item?.identifier === latestMessage?.identifier
- )
- let sliceLength = responseData.length
- if (findMessage !== -1) {
- sliceLength = findMessage
- }
- const newArray = responseData.slice(0, findMessage).reverse()
- let fullArrayMsg = [...messages]
- for (const message of newArray) {
- try {
-
- const responseDataMessage = await getEncryptedResource({identifier: message.identifier, name: message.name, secretKey: secretKeyRef.current})
-
- const fullObject = {
- ...message,
- ...(responseDataMessage || {}),
- id: message.identifier
- }
- setHashMapMailMessages((prev)=> {
- return {
- ...prev,
- [message.identifier]: fullObject
- }
- })
- const index = messages.findIndex(
- (p) => p.identifier === fullObject.identifier
- )
- if (index !== -1) {
- fullArrayMsg[index] = fullObject
- } else {
- fullArrayMsg.unshift(fullObject)
- }
- } catch (error) {}
- }
- setMessages(fullArrayMsg)
- } catch (error) {
- } finally {
- }
- },
- [messages]
- )
-
- const checkNewMessagesFunc = useCallback(() => {
- let isCalling = false
- interval.current = setInterval(async () => {
- if (isCalling) return
- isCalling = true
- const res = await checkNewMessages(currentThread)
- isCalling = false
- }, 8000)
- }, [checkNewMessages, currentThread])
-
- useEffect(() => {
- checkNewMessagesFunc()
- return () => {
- if (interval?.current) {
- clearInterval(interval.current)
- }
- }
- }, [checkNewMessagesFunc])
-
-
-
- if (!currentThread) return null
- return (
-
-
-
-
-
-
-
- {currentThread?.threadData?.title}
-
- {
- setMessages([])
- closeThread()
- }}>
-
- Return to Threads
-
-
-
- {messages.map((message) => {
- let fullMessage = message
-
- if (hashMapMailMessages[message?.identifier]) {
- fullMessage = hashMapMailMessages[message.identifier]
- return
- }
-
- return (
-
-
-
-
-
- )
- })}
-
-
- {messages.length >= 20 && (
- getMailMessages(currentThread, false, true)}>
-
- )}
-
-
- )
-}
diff --git a/src/components/Group/Forum/Thread.tsx b/src/components/Group/Forum/Thread.tsx
index 22b2ba3..a0940c8 100644
--- a/src/components/Group/Forum/Thread.tsx
+++ b/src/components/Group/Forum/Thread.tsx
@@ -5,7 +5,7 @@ import React, {
useMemo,
useRef,
useState,
-} from "react";
+} from 'react';
import {
Avatar,
Box,
@@ -14,8 +14,8 @@ import {
IconButton,
Skeleton,
Typography,
-} from "@mui/material";
-import { ShowMessage } from "./ShowMessageWithoutModal";
+} from '@mui/material';
+import { ShowMessage } from './ShowMessageWithoutModal';
import {
ComposeP,
GroupContainer,
@@ -28,34 +28,33 @@ import {
ThreadInfoColumn,
ThreadInfoColumnNameP,
ThreadInfoColumnTime,
-} from "./Mail-styles";
-import { Spacer } from "../../../common/Spacer";
-import { threadIdentifier } from "./GroupMail";
-import LazyLoad from "../../../common/LazyLoad";
-import ReturnSVG from "../../../assets/svgs/Return.svg";
-import { NewThread } from "./NewThread";
+} from './Mail-styles';
+import { Spacer } from '../../../common/Spacer';
+import { threadIdentifier } from './GroupMail';
+import ReturnSVG from '../../../assets/svgs/Return.svg';
+import { NewThread } from './NewThread';
import {
decryptPublishes,
getTempPublish,
handleUnencryptedPublishes,
-} from "../../Chat/GroupAnnouncements";
-import { LoadingSnackbar } from "../../Snackbar/LoadingSnackbar";
-import { subscribeToEvent, unsubscribeFromEvent } from "../../../utils/events";
-import RefreshIcon from "@mui/icons-material/Refresh";
+} from '../../Chat/GroupAnnouncements';
+import { LoadingSnackbar } from '../../Snackbar/LoadingSnackbar';
+import { subscribeToEvent, unsubscribeFromEvent } from '../../../utils/events';
+import RefreshIcon from '@mui/icons-material/Refresh';
import {
getArbitraryEndpointReact,
getBaseApiReact,
isMobile,
-} from "../../../App";
+} from '../../../App';
import {
ArrowDownward as ArrowDownwardIcon,
ArrowUpward as ArrowUpwardIcon,
-} from "@mui/icons-material";
-import { addDataPublishesFunc, getDataPublishesFunc } from "../Group";
-import { RequestQueueWithPromise } from "../../../utils/queue/queue";
-import { CustomLoader } from "../../../common/CustomLoader";
-import { WrapperUserAction } from "../../WrapperUserAction";
-import { formatTimestampForum } from "../../../utils/time";
+} from '@mui/icons-material';
+import { addDataPublishesFunc, getDataPublishesFunc } from '../Group';
+import { RequestQueueWithPromise } from '../../../utils/queue/queue';
+import { CustomLoader } from '../../../common/CustomLoader';
+import { WrapperUserAction } from '../../WrapperUserAction';
+import { formatTimestampForum } from '../../../utils/time';
const requestQueueSaveToLocal = new RequestQueueWithPromise(1);
const requestQueueDownloadPost = new RequestQueueWithPromise(3);
interface ThreadProps {
@@ -65,14 +64,10 @@ interface ThreadProps {
members: any;
}
-const getEncryptedResource = async ({
- name,
- identifier,
- secretKey,
- resource,
- groupId,
- dataPublishes,
-}, isPrivate) => {
+const getEncryptedResource = async (
+ { name, identifier, secretKey, resource, groupId, dataPublishes },
+ isPrivate
+) => {
let data = dataPublishes[`${name}-${identifier}`];
if (
!data ||
@@ -92,15 +87,18 @@ const getEncryptedResource = async ({
};
}
data = await res.text();
-
- if (data?.error || typeof data !== "string") return;
+
+ if (data?.error || typeof data !== 'string') return;
await requestQueueSaveToLocal.enqueue(() => {
- return addDataPublishesFunc({ ...resource, data }, groupId, "thmsg");
+ return addDataPublishesFunc({ ...resource, data }, groupId, 'thmsg');
});
} else {
data = data.data;
}
- const response = isPrivate === false ? handleUnencryptedPublishes([data]) : await decryptPublishes([{ data }], secretKey);
+ const response =
+ isPrivate === false
+ ? handleUnencryptedPublishes([data])
+ : await decryptPublishes([{ data }], secretKey);
const messageData = response[0];
return messageData.decryptedData;
@@ -115,7 +113,7 @@ export const Thread = ({
secretKey,
getSecretKey,
updateThreadActivityCurrentThread,
- isPrivate
+ isPrivate,
}: ThreadProps) => {
const [tempPublishedList, setTempPublishedList] = useState([]);
const [messages, setMessages] = useState([]);
@@ -129,7 +127,7 @@ export const Thread = ({
// Update: Use a new ref for the scrollable container
const threadContainerRef = useRef(null);
- const threadBeginningRef = useRef(null)
+ const threadBeginningRef = useRef(null);
// New state variables
const [showScrollButton, setShowScrollButton] = useState(false);
const [isAtBottom, setIsAtBottom] = useState(false);
@@ -140,7 +138,7 @@ export const Thread = ({
const dataPublishes = useRef({});
const getSavedData = useCallback(async (groupId) => {
- const res = await getDataPublishesFunc(groupId, "thmsg");
+ const res = await getDataPublishesFunc(groupId, 'thmsg');
dataPublishes.current = res || {};
}, []);
@@ -159,14 +157,17 @@ export const Thread = ({
const getIndividualMsg = async (message: any) => {
try {
- const responseDataMessage = await getEncryptedResource({
- identifier: message.identifier,
- name: message.name,
- secretKey,
- resource: message,
- groupId: groupInfo?.groupId,
- dataPublishes: dataPublishes.current,
- }, isPrivate);
+ const responseDataMessage = await getEncryptedResource(
+ {
+ identifier: message.identifier,
+ name: message.name,
+ secretKey,
+ resource: message,
+ groupId: groupInfo?.groupId,
+ dataPublishes: dataPublishes.current,
+ },
+ isPrivate
+ );
if (responseDataMessage?.error) {
const fullObject = {
@@ -201,7 +202,7 @@ export const Thread = ({
try {
let threadId = currentThread.threadId;
- const keyTemp = "thread-post";
+ const keyTemp = 'thread-post';
const getTempAnnouncements = await getTempPublish();
if (getTempAnnouncements?.[keyTemp]) {
@@ -232,10 +233,10 @@ export const Thread = ({
const identifier = `thmsg-${threadId}`;
let url = `${getBaseApiReact()}${getArbitraryEndpointReact()}?mode=ALL&service=${threadIdentifier}&identifier=${identifier}&limit=20&includemetadata=false&prefix=true`;
if (!isReverse) {
- url = url + "&reverse=false";
+ url = url + '&reverse=false';
}
if (isReverse) {
- url = url + "&reverse=true";
+ url = url + '&reverse=true';
}
if (after) {
url = url + `&after=${after}`;
@@ -245,9 +246,9 @@ export const Thread = ({
}
const response = await fetch(url, {
- method: "GET",
+ method: 'GET',
headers: {
- "Content-Type": "application/json",
+ 'Content-Type': 'application/json',
},
});
const responseData = await response.json();
@@ -263,14 +264,13 @@ export const Thread = ({
setMessages(fullArrayMsg);
if (before === null && after === null && isReverse) {
setTimeout(() => {
- containerRef.current.scrollIntoView({ behavior: "smooth" });
+ containerRef.current.scrollIntoView({ behavior: 'smooth' });
}, 300);
}
- if(after || before === null && after === null && !isReverse){
+ if (after || (before === null && after === null && !isReverse)) {
setTimeout(() => {
threadBeginningRef.current.scrollIntoView();
}, 100);
-
}
if (fullArrayMsg.length === 0) {
@@ -282,9 +282,9 @@ export const Thread = ({
fullArrayMsg[0].created
}`;
const responseNewer = await fetch(urlNewer, {
- method: "GET",
+ method: 'GET',
headers: {
- "Content-Type": "application/json",
+ 'Content-Type': 'application/json',
},
});
const responseDataNewer = await responseNewer.json();
@@ -300,9 +300,9 @@ export const Thread = ({
fullArrayMsg[fullArrayMsg.length - 1].created
}`;
const responseOlder = await fetch(urlOlder, {
- method: "GET",
+ method: 'GET',
headers: {
- "Content-Type": "application/json",
+ 'Content-Type': 'application/json',
},
});
const responseDataOlder = await responseOlder.json();
@@ -316,7 +316,7 @@ export const Thread = ({
updateThreadActivityCurrentThread();
}
} catch (error) {
- console.log("error", error);
+ console.log('error', error);
} finally {
setIsLoading(false);
getSavedData(groupId);
@@ -325,9 +325,21 @@ export const Thread = ({
[messages, secretKey]
);
const getMessages = React.useCallback(async () => {
- if (!currentThread || (!secretKey && isPrivate) || !groupInfo?.groupId || isPrivate === null) return;
+ if (
+ !currentThread ||
+ (!secretKey && isPrivate) ||
+ !groupInfo?.groupId ||
+ isPrivate === null
+ )
+ return;
await getMailMessages(currentThread, null, null, false, groupInfo?.groupId);
- }, [getMailMessages, currentThread, secretKey, groupInfo?.groupId, isPrivate]);
+ }, [
+ getMailMessages,
+ currentThread,
+ secretKey,
+ groupInfo?.groupId,
+ isPrivate,
+ ]);
const firstMount = useRef(false);
const saveTimestamp = useCallback((currentThread: any, username?: string) => {
@@ -339,7 +351,7 @@ export const Thread = ({
return;
const threadIdForLocalStorage = `qmail_threads_${currentThread?.threadData?.groupId}_${currentThread?.threadId}`;
const threads = JSON.parse(
- localStorage.getItem(`qmail_threads_viewedtimestamp_${username}`) || "{}"
+ localStorage.getItem(`qmail_threads_viewedtimestamp_${username}`) || '{}'
);
// Convert to an array of objects with identifier and all fields
let dataArray = Object.entries(threads).map(([identifier, value]) => ({
@@ -382,8 +394,8 @@ export const Thread = ({
if (currentThreadRef.current?.threadId !== currentThread?.threadId) {
firstMount.current = false;
}
- if(!secretKey && isPrivate) return
- if (currentThread && !firstMount.current && isPrivate !== null) {
+ if (!secretKey && isPrivate) return;
+ if (currentThread && !firstMount.current && isPrivate !== null) {
getMessagesMiddleware();
}
}, [currentThread, secretKey, isPrivate]);
@@ -402,9 +414,9 @@ export const Thread = ({
const identifier = `thmsg-${threadId}`;
const url = `${getBaseApiReact()}${getArbitraryEndpointReact()}?mode=ALL&service=${threadIdentifier}&identifier=${identifier}&limit=20&includemetadata=false&offset=${0}&reverse=true&prefix=true`;
const response = await fetch(url, {
- method: "GET",
+ method: 'GET',
headers: {
- "Content-Type": "application/json",
+ 'Content-Type': 'application/json',
},
});
const responseData = await response.json();
@@ -469,17 +481,17 @@ export const Thread = ({
const threadFetchModeFunc = (e) => {
const mode = e.detail?.mode;
- if (mode === "last-page") {
+ if (mode === 'last-page') {
getMailMessages(currentThread, null, null, true, groupInfo?.groupId);
}
firstMount.current = true;
};
React.useEffect(() => {
- subscribeToEvent("threadFetchMode", threadFetchModeFunc);
+ subscribeToEvent('threadFetchMode', threadFetchModeFunc);
return () => {
- unsubscribeFromEvent("threadFetchMode", threadFetchModeFunc);
+ unsubscribeFromEvent('threadFetchMode', threadFetchModeFunc);
};
}, []);
@@ -526,11 +538,11 @@ export const Thread = ({
handleScroll();
}, 400);
- container.addEventListener("scroll", handleScroll);
+ container.addEventListener('scroll', handleScroll);
// Cleanup
return () => {
- container.removeEventListener("scroll", handleScroll);
+ container.removeEventListener('scroll', handleScroll);
};
}, [messages]);
@@ -540,9 +552,9 @@ export const Thread = ({
if (!container) return;
if (isAtBottom) {
- container.scrollTo({ top: 0, behavior: "smooth" }); // Scroll to top
+ container.scrollTo({ top: 0, behavior: 'smooth' }); // Scroll to top
} else {
- container.scrollTo({ top: container.scrollHeight, behavior: "smooth" }); // Scroll to bottom
+ container.scrollTo({ top: container.scrollHeight, behavior: 'smooth' }); // Scroll to bottom
}
};
@@ -550,19 +562,19 @@ export const Thread = ({
return (
@@ -583,16 +595,16 @@ export const Thread = ({
/>
{
setMessages([]);
@@ -608,9 +620,9 @@ export const Thread = ({
@@ -618,9 +630,9 @@ export const Thread = ({
@@ -631,45 +643,45 @@ export const Thread = ({
-
+
-
+
{currentThread?.threadData?.title}
-
+
{
getMailMessages(
@@ -687,9 +699,9 @@ export const Thread = ({
{
getMailMessages(
@@ -707,9 +719,9 @@ export const Thread = ({
{
getMailMessages(
@@ -727,9 +739,9 @@ export const Thread = ({
{
getMailMessages(
@@ -746,35 +758,34 @@ export const Thread = ({
Last
-
+
{combinedListTempAndReal.map((message, index, list) => {
let fullMessage = message;
if (hashMapMailMessages[message?.identifier]) {
fullMessage = hashMapMailMessages[message.identifier];
-
if (fullMessage?.error) {
return (
{fullMessage?.error}
-
);
@@ -855,23 +865,23 @@ export const Thread = ({
return (
Downloading from QDN
-
);
})}
-
+
{!hasLastPage && !isLoading && (
<>
Refetch page
@@ -964,112 +973,113 @@ export const Thread = ({
>
)}
-
- 4 ? 'visible' : 'hidden'
- }}>
-
- 4 ? 'visible' : 'hidden',
+ }}
+ >
+
+
+ {
+ getMailMessages(
+ currentThread,
+ null,
+ null,
+ false,
+ groupInfo?.groupId
+ );
+ }}
+ disabled={!hasFirstPage}
+ variant="contained"
>
- {
- getMailMessages(
- currentThread,
- null,
- null,
- false,
- groupInfo?.groupId
- );
- }}
- disabled={!hasFirstPage}
- variant="contained"
- >
- First
-
- {
- getMailMessages(
- currentThread,
- messages[0].created,
- null,
- false,
- groupInfo?.groupId
- );
- }}
- disabled={!hasPreviousPage}
- variant="contained"
- >
- Previous
-
- {
- getMailMessages(
- currentThread,
- null,
- messages[messages.length - 1].created,
- false,
- groupInfo?.groupId
- );
- }}
- disabled={!hasNextPage}
- variant="contained"
- >
- Next
-
- {
- getMailMessages(
- currentThread,
- null,
- null,
- true,
- groupInfo?.groupId
- );
- }}
- disabled={!hasLastPage}
- variant="contained"
- >
- Last
-
-
-
+ First
+
+ {
+ getMailMessages(
+ currentThread,
+ messages[0].created,
+ null,
+ false,
+ groupInfo?.groupId
+ );
+ }}
+ disabled={!hasPreviousPage}
+ variant="contained"
+ >
+ Previous
+
+ {
+ getMailMessages(
+ currentThread,
+ null,
+ messages[messages.length - 1].created,
+ false,
+ groupInfo?.groupId
+ );
+ }}
+ disabled={!hasNextPage}
+ variant="contained"
+ >
+ Next
+
+ {
+ getMailMessages(
+ currentThread,
+ null,
+ null,
+ true,
+ groupInfo?.groupId
+ );
+ }}
+ disabled={!hasLastPage}
+ variant="contained"
+ >
+ Last
+
-
-
+
+
+
+
diff --git a/src/components/Group/Group.tsx b/src/components/Group/Group.tsx
index 64dc541..0bc4dd7 100644
--- a/src/components/Group/Group.tsx
+++ b/src/components/Group/Group.tsx
@@ -7,7 +7,7 @@ import {
ListItemAvatar,
ListItemText,
Typography,
-} from "@mui/material";
+} from '@mui/material';
import React, {
useCallback,
useContext,
@@ -15,24 +15,23 @@ import React, {
useMemo,
useRef,
useState,
-} from "react";
-import { ChatGroup } from "../Chat/ChatGroup";
-import { CreateCommonSecret } from "../Chat/CreateCommonSecret";
-import { base64ToUint8Array } from "../../qdn/encryption/group-encryption";
-import { uint8ArrayToObject } from "../../backgroundFunctions/encryption";
-import CampaignIcon from "@mui/icons-material/Campaign";
-import { AddGroup } from "./AddGroup";
-import AddCircleOutlineIcon from "@mui/icons-material/AddCircleOutline";
-import CreateIcon from "@mui/icons-material/Create";
-
+} from 'react';
+import { ChatGroup } from '../Chat/ChatGroup';
+import { CreateCommonSecret } from '../Chat/CreateCommonSecret';
+import { base64ToUint8Array } from '../../qdn/encryption/group-encryption';
+import { uint8ArrayToObject } from '../../backgroundFunctions/encryption';
+import CampaignIcon from '@mui/icons-material/Campaign';
+import { AddGroup } from './AddGroup';
+import AddCircleOutlineIcon from '@mui/icons-material/AddCircleOutline';
+import CreateIcon from '@mui/icons-material/Create';
import {
AuthenticatedContainerInnerRight,
CustomButton,
-} from "../../App-styles";
-import { Spacer } from "../../common/Spacer";
-import { ManageMembers } from "./ManageMembers";
-import MarkChatUnreadIcon from "@mui/icons-material/MarkChatUnread";
+} from '../../styles/App-styles';
+import { Spacer } from '../../common/Spacer';
+import { ManageMembers } from './ManageMembers';
+import MarkChatUnreadIcon from '@mui/icons-material/MarkChatUnread';
import {
MyContext,
clearAllQueues,
@@ -41,63 +40,64 @@ import {
isMobile,
pauseAllQueues,
resumeAllQueues,
-} from "../../App";
-import { ChatDirect } from "../Chat/ChatDirect";
-import { CustomizedSnackbars } from "../Snackbar/Snackbar";
-import { LoadingButton } from "@mui/lab";
-import { LoadingSnackbar } from "../Snackbar/LoadingSnackbar";
-import { GroupAnnouncements } from "../Chat/GroupAnnouncements";
+} from '../../App';
+import { ChatDirect } from '../Chat/ChatDirect';
+import { CustomizedSnackbars } from '../Snackbar/Snackbar';
+import { LoadingButton } from '@mui/lab';
+import { LoadingSnackbar } from '../Snackbar/LoadingSnackbar';
+import { GroupAnnouncements } from '../Chat/GroupAnnouncements';
-
-
-import { GroupForum } from "../Chat/GroupForum";
+import { GroupForum } from '../Chat/GroupForum';
import {
executeEvent,
subscribeToEvent,
unsubscribeFromEvent,
-} from "../../utils/events";
-import { RequestQueueWithPromise } from "../../utils/queue/queue";
-import { WebSocketActive } from "./WebsocketActive";
-import { useMessageQueue } from "../../MessageQueueContext";
-import { isExtMsg, isUpdateMsg } from "../../background";
-import { ContextMenu } from "../ContextMenu";
+} from '../../utils/events';
+import { RequestQueueWithPromise } from '../../utils/queue/queue';
+import { WebSocketActive } from './WebsocketActive';
+import { useMessageQueue } from '../../MessageQueueContext';
+import { isExtMsg, isUpdateMsg } from '../../background';
+import { ContextMenu } from '../ContextMenu';
-import { ReturnIcon } from "../../assets/Icons/ReturnIcon";
-import { ExitIcon } from "../../assets/Icons/ExitIcon";
-import { HomeDesktop } from "./HomeDesktop";
-import { IconWrapper } from "../Desktop/DesktopFooter";
-import { DesktopHeader } from "../Desktop/DesktopHeader";
-import { AppsDesktop } from "../Apps/AppsDesktop";
-import { AppsDevMode } from "../Apps/AppsDevMode";
-import { DesktopSideBar } from "../DesktopSideBar";
-import { HubsIcon } from "../../assets/Icons/HubsIcon";
-import { MessagingIcon } from "../../assets/Icons/MessagingIcon";
-import { formatEmailDate } from "./QMailMessages";
-import { AdminSpace } from "../Chat/AdminSpace";
-import { useRecoilState, useSetRecoilState } from "recoil";
-import { addressInfoControllerAtom, groupsPropertiesAtom, selectedGroupIdAtom } from "../../atoms/global";
-import { sortArrayByTimestampAndGroupName } from "../../utils/time";
-import BlockIcon from '@mui/icons-material/Block';
+import { ReturnIcon } from '../../assets/Icons/ReturnIcon';
+import { ExitIcon } from '../../assets/Icons/ExitIcon';
+import { HomeDesktop } from './HomeDesktop';
+import { IconWrapper } from '../Desktop/DesktopFooter';
+import { DesktopHeader } from '../Desktop/DesktopHeader';
+import { AppsDesktop } from '../Apps/AppsDesktop';
+import { AppsDevMode } from '../Apps/AppsDevMode';
+import { DesktopSideBar } from '../DesktopSideBar';
+import { HubsIcon } from '../../assets/Icons/HubsIcon';
+import { MessagingIcon } from '../../assets/Icons/MessagingIcon';
+import { formatEmailDate } from './QMailMessages';
+import { AdminSpace } from '../Chat/AdminSpace';
+import { useRecoilState, useSetRecoilState } from 'recoil';
+import {
+ addressInfoControllerAtom,
+ groupsPropertiesAtom,
+ isOpenBlockedModalAtom,
+ selectedGroupIdAtom,
+} from '../../atoms/global';
+import { sortArrayByTimestampAndGroupName } from '../../utils/time';
+import PersonOffIcon from '@mui/icons-material/PersonOff';
import LockIcon from '@mui/icons-material/Lock';
import NoEncryptionGmailerrorredIcon from '@mui/icons-material/NoEncryptionGmailerrorred';
-import { BlockedUsersModal } from "./BlockedUsersModal";
-import { WalletsAppWrapper } from "./WalletsAppWrapper";
-
+import { BlockedUsersModal } from './BlockedUsersModal';
+import { WalletsAppWrapper } from './WalletsAppWrapper';
export const getPublishesFromAdmins = async (admins: string[], groupId) => {
- const queryString = admins.map((name) => `name=${name}`).join("&");
+ const queryString = admins.map((name) => `name=${name}`).join('&');
const url = `${getBaseApiReact()}${getArbitraryEndpointReact()}?mode=ALL&service=DOCUMENT_PRIVATE&identifier=symmetric-qchat-group-${
groupId
}&exactmatchnames=true&limit=0&reverse=true&${queryString}&prefix=true`;
const response = await fetch(url);
if (!response.ok) {
- throw new Error("network error");
+ throw new Error('network error');
}
const adminData = await response.json();
const filterId = adminData.filter(
- (data: any) =>
- data.identifier === `symmetric-qchat-group-${groupId}`
+ (data: any) => data.identifier === `symmetric-qchat-group-${groupId}`
);
if (filterId?.length === 0) {
return false;
@@ -111,7 +111,6 @@ export const getPublishesFromAdmins = async (admins: string[], groupId) => {
return dateB.getTime() - dateA.getTime();
});
-
return sortedData[0];
};
interface GroupProps {
@@ -149,7 +148,7 @@ export const getGroupAdminsAddress = async (groupNumber: number) => {
export function validateSecretKey(obj) {
// Check if the input is an object
- if (typeof obj !== "object" || obj === null) {
+ if (typeof obj !== 'object' || obj === null) {
return false;
}
@@ -164,19 +163,19 @@ export function validateSecretKey(obj) {
const value = obj[key];
// Check that value is an object and not null
- if (typeof value !== "object" || value === null) {
+ if (typeof value !== 'object' || value === null) {
return false;
}
- // Check for messageKey
- if (!value.hasOwnProperty("messageKey")) {
+ // Check for messageKey
+ if (!value.hasOwnProperty('messageKey')) {
return false;
}
// Ensure messageKey and nonce are non-empty strings
if (
- typeof value.messageKey !== "string" ||
- value.messageKey.trim() === ""
+ typeof value.messageKey !== 'string' ||
+ value.messageKey.trim() === ''
) {
return false;
}
@@ -196,33 +195,34 @@ export const getGroupMembers = async (groupNumber: number) => {
return groupData;
};
-
export const decryptResource = async (data: string, fromQortalRequest) => {
try {
return new Promise((res, rej) => {
- window.sendMessage("decryptGroupEncryption", {
- data,
- })
+ window
+ .sendMessage('decryptGroupEncryption', {
+ data,
+ })
.then((response) => {
if (!response?.error) {
res(response);
return;
}
- if(fromQortalRequest){
- rej({error: response.error, message: response?.error});
+ if (fromQortalRequest) {
+ rej({ error: response.error, message: response?.error });
} else {
rej(response.error);
-
}
})
.catch((error) => {
- if(fromQortalRequest){
- rej({message: error.message || "An error occurred", error: error.message || "An error occurred"});
+ if (fromQortalRequest) {
+ rej({
+ message: error.message || 'An error occurred',
+ error: error.message || 'An error occurred',
+ });
} else {
- rej(error.message || "An error occurred",);
+ rej(error.message || 'An error occurred');
}
});
-
});
} catch (error) {}
};
@@ -230,11 +230,12 @@ export const decryptResource = async (data: string, fromQortalRequest) => {
export const addDataPublishesFunc = async (data: string, groupId, type) => {
try {
return new Promise((res, rej) => {
- window.sendMessage("addDataPublishes", {
- data,
- groupId,
- type,
- })
+ window
+ .sendMessage('addDataPublishes', {
+ data,
+ groupId,
+ type,
+ })
.then((response) => {
if (!response?.error) {
res(response);
@@ -243,9 +244,8 @@ export const addDataPublishesFunc = async (data: string, groupId, type) => {
rej(response.error);
})
.catch((error) => {
- rej(error.message || "An error occurred");
+ rej(error.message || 'An error occurred');
});
-
});
} catch (error) {}
};
@@ -253,10 +253,11 @@ export const addDataPublishesFunc = async (data: string, groupId, type) => {
export const getDataPublishesFunc = async (groupId, type) => {
try {
return new Promise((res, rej) => {
- window.sendMessage("getDataPublishes", {
- groupId,
- type,
- })
+ window
+ .sendMessage('getDataPublishes', {
+ groupId,
+ type,
+ })
.then((response) => {
if (!response?.error) {
res(response);
@@ -265,9 +266,8 @@ export const getDataPublishesFunc = async (groupId, type) => {
rej(response.error);
})
.catch((error) => {
- rej(error.message || "An error occurred");
+ rej(error.message || 'An error occurred');
});
-
});
} catch (error) {}
};
@@ -279,7 +279,7 @@ export async function getNameInfo(address: string) {
if (nameData?.length > 0) {
return nameData[0]?.name;
} else {
- return "";
+ return '';
}
}
@@ -294,7 +294,6 @@ export const getGroupAdmins = async (groupNumber: number) => {
let membersAddresses = [];
let both = [];
-
const getMemNames = groupData?.members?.map(async (member) => {
if (member?.member) {
const name = await requestQueueAdminMemberNames.enqueue(() => {
@@ -327,7 +326,7 @@ export const getNames = async (listOfMembers) => {
if (name) {
members.push({ ...member, name });
} else {
- members.push({ ...member, name: "" });
+ members.push({ ...member, name: '' });
}
}
@@ -339,7 +338,6 @@ export const getNames = async (listOfMembers) => {
return members;
};
export const getNamesForAdmins = async (admins) => {
-
let members: any = [];
const getMemNames = admins?.map(async (admin) => {
@@ -379,9 +377,9 @@ export const Group = ({
balance,
setIsOpenDrawerProfile,
setDesktopViewMode,
- desktopViewMode
+ desktopViewMode,
}: GroupProps) => {
- const [desktopSideView, setDesktopSideView] = useState('groups')
+ const [desktopSideView, setDesktopSideView] = useState('groups');
const [secretKey, setSecretKey] = useState(null);
const [secretKeyPublishDate, setSecretKeyPublishDate] = useState(null);
@@ -405,10 +403,11 @@ export const Group = ({
const [openAddGroup, setOpenAddGroup] = useState(false);
const [isInitialGroups, setIsInitialGroups] = useState(false);
const [openManageMembers, setOpenManageMembers] = useState(false);
- const { setMemberGroups, rootHeight, isRunningPublicNode } = useContext(MyContext);
+ const { setMemberGroups, rootHeight, isRunningPublicNode } =
+ useContext(MyContext);
const lastGroupNotification = useRef
(null);
const [timestampEnterData, setTimestampEnterData] = useState({});
- const [chatMode, setChatMode] = useState("groups");
+ const [chatMode, setChatMode] = useState('groups');
const [newChat, setNewChat] = useState(false);
const [openSnack, setOpenSnack] = React.useState(false);
const [infoSnack, setInfoSnack] = React.useState(null);
@@ -417,18 +416,18 @@ export const Group = ({
const [isLoadingGroup, setIsLoadingGroup] = React.useState(false);
const [firstSecretKeyInCreation, setFirstSecretKeyInCreation] =
React.useState(false);
- const [groupSection, setGroupSection] = React.useState("home");
+ const [groupSection, setGroupSection] = React.useState('home');
const [groupAnnouncements, setGroupAnnouncements] = React.useState({});
const [defaultThread, setDefaultThread] = React.useState(null);
const [isOpenDrawer, setIsOpenDrawer] = React.useState(false);
- const [isOpenBlockedUserModal, setIsOpenBlockedUserModal] = React.useState(false);
+ const setIsOpenBlockedUserModal = useSetRecoilState(isOpenBlockedModalAtom);
const [hideCommonKeyPopup, setHideCommonKeyPopup] = React.useState(false);
- const [isLoadingGroupMessage, setIsLoadingGroupMessage] = React.useState("");
- const [drawerMode, setDrawerMode] = React.useState("groups");
+ const [isLoadingGroupMessage, setIsLoadingGroupMessage] = React.useState('');
+ const [drawerMode, setDrawerMode] = React.useState('groups');
const [mutedGroups, setMutedGroups] = useState([]);
- const [mobileViewMode, setMobileViewMode] = useState("home");
- const [mobileViewModeKeepOpen, setMobileViewModeKeepOpen] = useState("");
+ const [mobileViewMode, setMobileViewMode] = useState('home');
+ const [mobileViewModeKeepOpen, setMobileViewModeKeepOpen] = useState('');
const isFocusedRef = useRef(true);
const timestampEnterDataRef = useRef({});
const selectedGroupRef = useRef(null);
@@ -441,42 +440,42 @@ export const Group = ({
const { clearStatesMessageQueueProvider } = useMessageQueue();
const initiatedGetMembers = useRef(false);
const [groupChatTimestamps, setGroupChatTimestamps] = React.useState({});
- const [appsMode, setAppsMode] = useState('home')
- const [appsModeDev, setAppsModeDev] = useState('home')
- const [isOpenSideViewDirects, setIsOpenSideViewDirects] = useState(false)
- const [isOpenSideViewGroups, setIsOpenSideViewGroups] = useState(false)
- const [isForceShowCreationKeyPopup, setIsForceShowCreationKeyPopup] = useState(false)
+ const [appsMode, setAppsMode] = useState('home');
+ const [appsModeDev, setAppsModeDev] = useState('home');
+ const [isOpenSideViewDirects, setIsOpenSideViewDirects] = useState(false);
+ const [isOpenSideViewGroups, setIsOpenSideViewGroups] = useState(false);
+ const [isForceShowCreationKeyPopup, setIsForceShowCreationKeyPopup] =
+ useState(false);
- const [groupsProperties, setGroupsProperties] = useRecoilState(groupsPropertiesAtom)
+ const [groupsProperties, setGroupsProperties] =
+ useRecoilState(groupsPropertiesAtom);
const setUserInfoForLevels = useSetRecoilState(addressInfoControllerAtom);
- const isPrivate = useMemo(()=> {
- if(selectedGroup?.groupId === '0') return false
- if(!selectedGroup?.groupId || !groupsProperties[selectedGroup?.groupId]) return null
- if(groupsProperties[selectedGroup?.groupId]?.isOpen === true) return false
- if(groupsProperties[selectedGroup?.groupId]?.isOpen === false) return true
- return null
- }, [selectedGroup])
+ const isPrivate = useMemo(() => {
+ if (selectedGroup?.groupId === '0') return false;
+ if (!selectedGroup?.groupId || !groupsProperties[selectedGroup?.groupId])
+ return null;
+ if (groupsProperties[selectedGroup?.groupId]?.isOpen === true) return false;
+ if (groupsProperties[selectedGroup?.groupId]?.isOpen === false) return true;
+ return null;
+ }, [selectedGroup]);
-
-
-
- const setSelectedGroupId = useSetRecoilState(selectedGroupIdAtom)
- const toggleSideViewDirects = ()=> {
- if(isOpenSideViewGroups){
- setIsOpenSideViewGroups(false)
+ const setSelectedGroupId = useSetRecoilState(selectedGroupIdAtom);
+ const toggleSideViewDirects = () => {
+ if (isOpenSideViewGroups) {
+ setIsOpenSideViewGroups(false);
}
- setIsOpenSideViewDirects((prev)=> !prev)
- }
- const toggleSideViewGroups = ()=> {
- if(isOpenSideViewDirects){
- setIsOpenSideViewDirects(false)
+ setIsOpenSideViewDirects((prev) => !prev);
+ };
+ const toggleSideViewGroups = () => {
+ if (isOpenSideViewDirects) {
+ setIsOpenSideViewDirects(false);
}
- setIsOpenSideViewGroups((prev)=> !prev)
- }
- useEffect(()=> {
- timestampEnterDataRef.current = timestampEnterData
- }, [timestampEnterData])
+ setIsOpenSideViewGroups((prev) => !prev);
+ };
+ useEffect(() => {
+ timestampEnterDataRef.current = timestampEnterData;
+ }, [timestampEnterData]);
useEffect(() => {
isFocusedRef.current = isFocused;
@@ -487,21 +486,20 @@ export const Group = ({
useEffect(() => {
selectedGroupRef.current = selectedGroup;
- setSelectedGroupId(selectedGroup?.groupId)
+ setSelectedGroupId(selectedGroup?.groupId);
}, [selectedGroup]);
useEffect(() => {
selectedDirectRef.current = selectedDirect;
}, [selectedDirect]);
-
-
const getUserSettings = async () => {
try {
return new Promise((res, rej) => {
- window.sendMessage("getUserSettings", {
- key: "mutedGroups",
- })
+ window
+ .sendMessage('getUserSettings', {
+ key: 'mutedGroups',
+ })
.then((response) => {
if (!response?.error) {
setMutedGroups(response || []);
@@ -511,12 +509,11 @@ export const Group = ({
rej(response.error);
})
.catch((error) => {
- rej(error.message || "An error occurred");
+ rej(error.message || 'An error occurred');
});
-
});
} catch (error) {
- console.log("error", error);
+ console.log('error', error);
}
};
@@ -527,56 +524,56 @@ export const Group = ({
const getTimestampEnterChat = async () => {
try {
return new Promise((res, rej) => {
- window.sendMessage("getTimestampEnterChat")
- .then((response) => {
- if (!response?.error) {
- setTimestampEnterData(response);
- res(response);
- return;
- }
- rej(response.error);
- })
- .catch((error) => {
- rej(error.message || "An error occurred");
- });
-
+ window
+ .sendMessage('getTimestampEnterChat')
+ .then((response) => {
+ if (!response?.error) {
+ setTimestampEnterData(response);
+ res(response);
+ return;
+ }
+ rej(response.error);
+ })
+ .catch((error) => {
+ rej(error.message || 'An error occurred');
+ });
});
} catch (error) {}
};
const refreshHomeDataFunc = () => {
- setGroupSection("default");
+ setGroupSection('default');
setTimeout(() => {
- setGroupSection("home");
+ setGroupSection('home');
}, 300);
};
const getGroupAnnouncements = async () => {
try {
return new Promise((res, rej) => {
- window.sendMessage("getGroupNotificationTimestamp")
- .then((response) => {
- if (!response?.error) {
- setGroupAnnouncements(response);
- res(response);
- return;
- }
- rej(response.error);
- })
- .catch((error) => {
- rej(error.message || "An error occurred");
- });
-
+ window
+ .sendMessage('getGroupNotificationTimestamp')
+ .then((response) => {
+ if (!response?.error) {
+ setGroupAnnouncements(response);
+ res(response);
+ return;
+ }
+ rej(response.error);
+ })
+ .catch((error) => {
+ rej(error.message || 'An error occurred');
+ });
});
} catch (error) {}
};
- useEffect(()=> {
- if(myAddress){
- getGroupAnnouncements()
- getTimestampEnterChat()
+ useEffect(() => {
+ if (myAddress) {
+ getGroupAnnouncements();
+ getTimestampEnterChat();
}
- }, [myAddress])
+ }, [myAddress]);
const getGroupOwner = async (groupId) => {
try {
@@ -592,9 +589,6 @@ export const Group = ({
} catch (error) {}
};
-
-
-
const directChatHasUnread = useMemo(() => {
let hasUnread = false;
directs.forEach((direct) => {
@@ -615,13 +609,12 @@ export const Group = ({
const groupChatHasUnread = useMemo(() => {
let hasUnread = false;
groups.forEach((group) => {
-
-
if (
group?.data &&
group?.sender !== myAddress &&
- group?.timestamp && groupChatTimestamps[group?.groupId] &&
- ((!timestampEnterData[group?.groupId] &&
+ group?.timestamp &&
+ groupChatTimestamps[group?.groupId] &&
+ ((!timestampEnterData[group?.groupId] &&
Date.now() - group?.timestamp < timeDifferenceForNotificationChats) ||
timestampEnterData[group?.groupId] < group?.timestamp)
) {
@@ -644,15 +637,12 @@ export const Group = ({
return hasUnread;
}, [groupAnnouncements, groups]);
-
-
-
const getSecretKey = async (
loadingGroupParam?: boolean,
secretKeyToPublish?: boolean
) => {
try {
- setIsLoadingGroupMessage("Locating encryption keys");
+ setIsLoadingGroupMessage('Locating encryption keys');
pauseAllQueues();
let dataFromStorage;
let publishFromStorage;
@@ -660,8 +650,7 @@ export const Group = ({
if (
secretKeyToPublish &&
secretKey &&
- lastFetchedSecretKey.current
- &&
+ lastFetchedSecretKey.current &&
Date.now() - lastFetchedSecretKey.current < 600000
)
return secretKey;
@@ -681,10 +670,11 @@ export const Group = ({
setAdmins(addresses);
setAdminsWithNames(both);
if (!names.length) {
- throw new Error("Network error");
+ throw new Error('Network error');
}
const publish =
- publishFromStorage || (await getPublishesFromAdmins(names, selectedGroup?.groupId));
+ publishFromStorage ||
+ (await getPublishesFromAdmins(names, selectedGroup?.groupId));
if (prevGroupId !== selectedGroupRef.current.groupId) {
if (settimeoutForRefetchSecretKey.current) {
@@ -705,7 +695,7 @@ export const Group = ({
data = dataFromStorage;
} else {
// const shouldRebuild = !secretKeyPublishDate || (publish?.update && publish?.updated > secretKeyPublishDate)
- setIsLoadingGroupMessage("Downloading encryption keys");
+ setIsLoadingGroupMessage('Downloading encryption keys');
const res = await fetch(
`${getBaseApiReact()}/arbitrary/DOCUMENT_PRIVATE/${publish.name}/${
publish.identifier
@@ -717,20 +707,25 @@ export const Group = ({
const dataint8Array = base64ToUint8Array(decryptedKey.data);
const decryptedKeyToObject = uint8ArrayToObject(dataint8Array);
if (!validateSecretKey(decryptedKeyToObject))
- throw new Error("SecretKey is not valid");
+ throw new Error('SecretKey is not valid');
setSecretKeyDetails(publish);
setSecretKey(decryptedKeyToObject);
lastFetchedSecretKey.current = Date.now();
setMemberCountFromSecretKeyData(decryptedKey.count);
- window.sendMessage("setGroupData", {
- groupId: selectedGroup?.groupId,
- secretKeyData: data,
- secretKeyResource: publish,
- admins: { names, addresses, both },
- }).catch((error) => {
- console.error("Failed to set group data:", error.message || "An error occurred");
+ window
+ .sendMessage('setGroupData', {
+ groupId: selectedGroup?.groupId,
+ secretKeyData: data,
+ secretKeyResource: publish,
+ admins: { names, addresses, both },
+ })
+ .catch((error) => {
+ console.error(
+ 'Failed to set group data:',
+ error.message || 'An error occurred'
+ );
});
-
+
if (decryptedKeyToObject) {
setTriedToFetchSecretKey(true);
setFirstSecretKeyInCreation(false);
@@ -739,7 +734,7 @@ export const Group = ({
setTriedToFetchSecretKey(true);
}
} catch (error) {
- if (error === "Unable to decrypt data") {
+ if (error === 'Unable to decrypt data') {
setTriedToFetchSecretKey(true);
settimeoutForRefetchSecretKey.current = setTimeout(() => {
getSecretKey();
@@ -747,182 +742,197 @@ export const Group = ({
}
} finally {
setIsLoadingGroup(false);
- setIsLoadingGroupMessage("");
+ setIsLoadingGroupMessage('');
resumeAllQueues();
}
};
-
- const getAdminsForPublic = async(selectedGroup)=> {
+ const getAdminsForPublic = async (selectedGroup) => {
try {
- const { names, addresses, both } =
- await getGroupAdmins(selectedGroup?.groupId)
- setAdmins(addresses);
- setAdminsWithNames(both);
+ const { names, addresses, both } = await getGroupAdmins(
+ selectedGroup?.groupId
+ );
+ setAdmins(addresses);
+ setAdminsWithNames(both);
} catch (error) {
//error
}
- }
+ };
useEffect(() => {
if (selectedGroup && isPrivate !== null) {
- if(isPrivate){
+ if (isPrivate) {
setTriedToFetchSecretKey(false);
getSecretKey(true);
}
-
+
getGroupOwner(selectedGroup?.groupId);
}
- if(isPrivate === false){
+ if (isPrivate === false) {
setTriedToFetchSecretKey(true);
- if(selectedGroup?.groupId !== '0'){
- getAdminsForPublic(selectedGroup)
+ if (selectedGroup?.groupId !== '0') {
+ getAdminsForPublic(selectedGroup);
}
-
-
}
}, [selectedGroup, isPrivate]);
-
-
-
-
- const getCountNewMesg = async (groupId, after)=> {
+ const getCountNewMesg = async (groupId, after) => {
try {
const response = await fetch(
`${getBaseApiReact()}/chat/messages?after=${after}&txGroupId=${groupId}&haschatreference=false&encoding=BASE64&limit=1`
);
const data = await response.json();
- if(data && data[0]) return data[0].timestamp
- } catch (error) {
-
- }
- }
+ if (data && data[0]) return data[0].timestamp;
+ } catch (error) {}
+ };
- const getLatestRegularChat = async (groups)=> {
+ const getLatestRegularChat = async (groups) => {
try {
-
- const groupData = {}
+ const groupData = {};
- const getGroupData = groups.map(async(group)=> {
- if(!group.groupId || !group?.timestamp) return null
- if((!groupData[group.groupId] || groupData[group.groupId] < group.timestamp)){
- const hasMoreRecentMsg = await getCountNewMesg(group.groupId, timestampEnterDataRef.current[group?.groupId] || Date.now() - 24 * 60 * 60 * 1000)
- if(hasMoreRecentMsg){
- groupData[group.groupId] = hasMoreRecentMsg
+ const getGroupData = groups.map(async (group) => {
+ if (!group.groupId || !group?.timestamp) return null;
+ if (
+ !groupData[group.groupId] ||
+ groupData[group.groupId] < group.timestamp
+ ) {
+ const hasMoreRecentMsg = await getCountNewMesg(
+ group.groupId,
+ timestampEnterDataRef.current[group?.groupId] ||
+ Date.now() - 24 * 60 * 60 * 1000
+ );
+ if (hasMoreRecentMsg) {
+ groupData[group.groupId] = hasMoreRecentMsg;
}
} else {
- return null
+ return null;
}
- })
+ });
- await Promise.all(getGroupData)
- setGroupChatTimestamps(groupData)
- } catch (error) {
-
- }
- }
+ await Promise.all(getGroupData);
+ setGroupChatTimestamps(groupData);
+ } catch (error) {}
+ };
- const getGroupsProperties = useCallback(async(address)=> {
+ const getGroupsProperties = useCallback(async (address) => {
try {
const url = `${getBaseApiReact()}/groups/member/${address}`;
const response = await fetch(url);
- if(!response.ok) throw new Error('Cannot get group properties')
+ if (!response.ok) throw new Error('Cannot get group properties');
let data = await response.json();
- const transformToObject = data.reduce((result, item) => {
-
- result[item.groupId] = item
- return result;
- }, {});
- setGroupsProperties(transformToObject)
+ const transformToObject = data.reduce((result, item) => {
+ result[item.groupId] = item;
+ return result;
+ }, {});
+ setGroupsProperties(transformToObject);
} catch (error) {
// error
}
- }, [])
+ }, []);
-
- useEffect(()=> {
- if(!myAddress) return
- if(areKeysEqual(groups?.map((grp)=> grp?.groupId), Object.keys(groupsProperties))){
+ useEffect(() => {
+ if (!myAddress) return;
+ if (
+ areKeysEqual(
+ groups?.map((grp) => grp?.groupId),
+ Object.keys(groupsProperties)
+ )
+ ) {
} else {
- getGroupsProperties(myAddress)
+ getGroupsProperties(myAddress);
}
- }, [groups, myAddress])
-
-
+ }, [groups, myAddress]);
useEffect(() => {
// Handler function for incoming messages
const messageHandler = (event) => {
if (event.origin !== window.location.origin) {
- return;
+ return;
}
const message = event.data;
- if (message?.action === "SET_GROUPS") {
-
+ if (message?.action === 'SET_GROUPS') {
// Update the component state with the received 'sendqort' state
setGroups(sortArrayByTimestampAndGroupName(message.payload));
getLatestRegularChat(message.payload);
- setMemberGroups(message.payload?.filter((item)=> item?.groupId !== '0'));
-
- if (selectedGroupRef.current && groupSectionRef.current === "chat") {
- window.sendMessage("addTimestampEnterChat", {
- timestamp: Date.now(),
- groupId: selectedGroupRef.current.groupId,
- }).catch((error) => {
- console.error("Failed to add timestamp:", error.message || "An error occurred");
- });
+ setMemberGroups(
+ message.payload?.filter((item) => item?.groupId !== '0')
+ );
+
+ if (selectedGroupRef.current && groupSectionRef.current === 'chat') {
+ window
+ .sendMessage('addTimestampEnterChat', {
+ timestamp: Date.now(),
+ groupId: selectedGroupRef.current.groupId,
+ })
+ .catch((error) => {
+ console.error(
+ 'Failed to add timestamp:',
+ error.message || 'An error occurred'
+ );
+ });
}
-
+
if (selectedDirectRef.current) {
- window.sendMessage("addTimestampEnterChat", {
- timestamp: Date.now(),
- groupId: selectedDirectRef.current.address,
- }).catch((error) => {
- console.error("Failed to add timestamp:", error.message || "An error occurred");
- });
+ window
+ .sendMessage('addTimestampEnterChat', {
+ timestamp: Date.now(),
+ groupId: selectedDirectRef.current.address,
+ })
+ .catch((error) => {
+ console.error(
+ 'Failed to add timestamp:',
+ error.message || 'An error occurred'
+ );
+ });
}
-
+
setTimeout(() => {
getTimestampEnterChat();
}, 600);
}
-
- if (message?.action === "SET_GROUP_ANNOUNCEMENTS") {
+
+ if (message?.action === 'SET_GROUP_ANNOUNCEMENTS') {
// Update the component state with the received 'sendqort' state
setGroupAnnouncements(message.payload);
-
- if (selectedGroupRef.current && groupSectionRef.current === "announcement") {
- window.sendMessage("addGroupNotificationTimestamp", {
- timestamp: Date.now(),
- groupId: selectedGroupRef.current.groupId,
- }).catch((error) => {
- console.error("Failed to add group notification timestamp:", error.message || "An error occurred");
- });
-
+
+ if (
+ selectedGroupRef.current &&
+ groupSectionRef.current === 'announcement'
+ ) {
+ window
+ .sendMessage('addGroupNotificationTimestamp', {
+ timestamp: Date.now(),
+ groupId: selectedGroupRef.current.groupId,
+ })
+ .catch((error) => {
+ console.error(
+ 'Failed to add group notification timestamp:',
+ error.message || 'An error occurred'
+ );
+ });
+
setTimeout(() => {
getGroupAnnouncements();
}, 200);
}
}
-
- if (message?.action === "SET_DIRECTS") {
+
+ if (message?.action === 'SET_DIRECTS') {
// Update the component state with the received 'sendqort' state
setDirects(message.payload);
- } else if (message?.action === "PLAY_NOTIFICATION_SOUND") {
+ } else if (message?.action === 'PLAY_NOTIFICATION_SOUND') {
// audio.play();
}
};
-
+
// Attach the event listener
- window.addEventListener("message", messageHandler);
-
+ window.addEventListener('message', messageHandler);
+
// Clean up the event listener on component unmount
return () => {
- window.removeEventListener("message", messageHandler);
+ window.removeEventListener('message', messageHandler);
};
}, []);
-
useEffect(() => {
if (
@@ -933,11 +943,12 @@ export const Group = ({
)
return;
- window.sendMessage("setupGroupWebsocket", {})
- .catch((error) => {
- console.error("Failed to setup group websocket:", error.message || "An error occurred");
- });
-
+ window.sendMessage('setupGroupWebsocket', {}).catch((error) => {
+ console.error(
+ 'Failed to setup group websocket:',
+ error.message || 'An error occurred'
+ );
+ });
hasInitializedWebsocket.current = true;
}, [myAddress, groups]);
@@ -954,7 +965,8 @@ export const Group = ({
!initiatedGetMembers.current &&
selectedGroup?.groupId &&
secretKey &&
- admins.includes(myAddress) && selectedGroup?.groupId !== '0'
+ admins.includes(myAddress) &&
+ selectedGroup?.groupId !== '0'
) {
// getAdmins(selectedGroup?.groupId);
getMembers(selectedGroup?.groupId);
@@ -1000,10 +1012,11 @@ export const Group = ({
try {
setIsLoadingNotifyAdmin(true);
await new Promise((res, rej) => {
- window.sendMessage("notifyAdminRegenerateSecretKey", {
- adminAddress: admin.address,
- groupName: selectedGroup?.groupName,
- })
+ window
+ .sendMessage('notifyAdminRegenerateSecretKey', {
+ adminAddress: admin.address,
+ groupName: selectedGroup?.groupName,
+ })
.then((response) => {
if (!response?.error) {
res(response);
@@ -1012,19 +1025,18 @@ export const Group = ({
rej(response.error);
})
.catch((error) => {
- rej(error.message || "An error occurred");
+ rej(error.message || 'An error occurred');
});
-
});
setInfoSnack({
- type: "success",
- message: "Successfully sent notification.",
+ type: 'success',
+ message: 'Successfully sent notification.',
});
setOpenSnack(true);
} catch (error) {
setInfoSnack({
- type: "error",
- message: "Unable to send notification",
+ type: 'error',
+ message: 'Unable to send notification',
});
} finally {
setIsLoadingNotifyAdmin(false);
@@ -1038,7 +1050,8 @@ export const Group = ({
if (!findGroup) return false;
if (!findGroup?.data) return false;
return (
- findGroup?.timestamp && groupChatTimestamps[findGroup?.groupId] &&
+ findGroup?.timestamp &&
+ groupChatTimestamps[findGroup?.groupId] &&
((!timestampEnterData[selectedGroup?.groupId] &&
Date.now() - findGroup?.timestamp <
timeDifferenceForNotificationChats) ||
@@ -1066,23 +1079,27 @@ export const Group = ({
return;
}
if (findDirect) {
- if(!isMobile){
- setDesktopSideView("directs");
- setDesktopViewMode('home')
+ if (!isMobile) {
+ setDesktopSideView('directs');
+ setDesktopViewMode('home');
} else {
- setMobileViewModeKeepOpen("messaging");
+ setMobileViewModeKeepOpen('messaging');
}
setSelectedDirect(null);
setNewChat(false);
- window.sendMessage("addTimestampEnterChat", {
- timestamp: Date.now(),
- groupId: findDirect.address,
- }).catch((error) => {
- console.error("Failed to add timestamp:", error.message || "An error occurred");
+ window
+ .sendMessage('addTimestampEnterChat', {
+ timestamp: Date.now(),
+ groupId: findDirect.address,
+ })
+ .catch((error) => {
+ console.error(
+ 'Failed to add timestamp:',
+ error.message || 'An error occurred'
+ );
});
-
setTimeout(() => {
setSelectedDirect(findDirect);
@@ -1102,36 +1119,40 @@ export const Group = ({
);
if (findDirect) {
- if(!isMobile){
- setDesktopSideView("directs");
+ if (!isMobile) {
+ setDesktopSideView('directs');
} else {
- setMobileViewModeKeepOpen("messaging");
+ setMobileViewModeKeepOpen('messaging');
}
setSelectedDirect(null);
setNewChat(false);
- window.sendMessage("addTimestampEnterChat", {
- timestamp: Date.now(),
- groupId: findDirect.address,
- }).catch((error) => {
- console.error("Failed to add timestamp:", error.message || "An error occurred");
+ window
+ .sendMessage('addTimestampEnterChat', {
+ timestamp: Date.now(),
+ groupId: findDirect.address,
+ })
+ .catch((error) => {
+ console.error(
+ 'Failed to add timestamp:',
+ error.message || 'An error occurred'
+ );
});
-
setTimeout(() => {
setSelectedDirect(findDirect);
getTimestampEnterChat();
}, 200);
} else {
- if(!isMobile){
- setDesktopSideView("directs");
+ if (!isMobile) {
+ setDesktopSideView('directs');
} else {
- setMobileViewModeKeepOpen("messaging");
+ setMobileViewModeKeepOpen('messaging');
}
setNewChat(true);
setTimeout(() => {
- executeEvent("setDirectToValueNewChat", {
+ executeEvent('setDirectToValueNewChat', {
directToValue: name || directAddress,
});
}, 500);
@@ -1139,41 +1160,50 @@ export const Group = ({
};
useEffect(() => {
- subscribeToEvent("openDirectMessageInternal", openDirectChatFromInternal);
+ subscribeToEvent('openDirectMessageInternal', openDirectChatFromInternal);
return () => {
unsubscribeFromEvent(
- "openDirectMessageInternal",
+ 'openDirectMessageInternal',
openDirectChatFromInternal
);
};
}, [directs, selectedDirect]);
useEffect(() => {
- subscribeToEvent("openDirectMessage", openDirectChatFromNotification);
+ subscribeToEvent('openDirectMessage', openDirectChatFromNotification);
return () => {
- unsubscribeFromEvent("openDirectMessage", openDirectChatFromNotification);
+ unsubscribeFromEvent('openDirectMessage', openDirectChatFromNotification);
};
}, [directs, selectedDirect]);
const handleMarkAsRead = (e) => {
const { groupId } = e.detail;
- window.sendMessage("addTimestampEnterChat", {
- timestamp: Date.now(),
- groupId,
- }).catch((error) => {
- console.error("Failed to add timestamp:", error.message || "An error occurred");
- });
-
-
- window.sendMessage("addGroupNotificationTimestamp", {
+ window
+ .sendMessage('addTimestampEnterChat', {
timestamp: Date.now(),
groupId,
- }).catch((error) => {
- console.error("Failed to add group notification timestamp:", error.message || "An error occurred");
- });
-
+ })
+ .catch((error) => {
+ console.error(
+ 'Failed to add timestamp:',
+ error.message || 'An error occurred'
+ );
+ });
+
+ window
+ .sendMessage('addGroupNotificationTimestamp', {
+ timestamp: Date.now(),
+ groupId,
+ })
+ .catch((error) => {
+ console.error(
+ 'Failed to add group notification timestamp:',
+ error.message || 'An error occurred'
+ );
+ });
+
setTimeout(() => {
getGroupAnnouncements();
getTimestampEnterChat();
@@ -1181,10 +1211,10 @@ export const Group = ({
};
useEffect(() => {
- subscribeToEvent("markAsRead", handleMarkAsRead);
+ subscribeToEvent('markAsRead', handleMarkAsRead);
return () => {
- unsubscribeFromEvent("markAsRead", handleMarkAsRead);
+ unsubscribeFromEvent('markAsRead', handleMarkAsRead);
};
}, []);
@@ -1196,7 +1226,7 @@ export const Group = ({
setSecretKeyDetails(null);
setNewEncryptionNotification(null);
setMemberCountFromSecretKeyData(null);
- setIsForceShowCreationKeyPopup(false)
+ setIsForceShowCreationKeyPopup(false);
setSelectedGroup(null);
setSelectedDirect(null);
setGroups([]);
@@ -1212,7 +1242,7 @@ export const Group = ({
setOpenManageMembers(false);
setMemberGroups([]); // Assuming you're clearing the context here as well
setTimestampEnterData({});
- setChatMode("groups");
+ setChatMode('groups');
setNewChat(false);
setOpenSnack(false);
setInfoSnack(null);
@@ -1220,10 +1250,10 @@ export const Group = ({
setIsLoadingGroups(false);
setIsLoadingGroup(false);
setFirstSecretKeyInCreation(false);
- setGroupSection("home");
+ setGroupSection('home');
setGroupAnnouncements({});
setDefaultThread(null);
- setMobileViewMode("home");
+ setMobileViewMode('home');
// Reset all useRef values to their initial states
hasInitialized.current = false;
hasInitializedWebsocket.current = false;
@@ -1237,8 +1267,8 @@ export const Group = ({
setupGroupWebsocketInterval.current = null;
settimeoutForRefetchSecretKey.current = null;
initiatedGetMembers.current = false;
- if(!isMobile){
- setDesktopViewMode('home')
+ if (!isMobile) {
+ setDesktopViewMode('home');
}
};
@@ -1248,30 +1278,29 @@ export const Group = ({
};
useEffect(() => {
- subscribeToEvent("logout-event", logoutEventFunc);
+ subscribeToEvent('logout-event', logoutEventFunc);
return () => {
- unsubscribeFromEvent("logout-event", logoutEventFunc);
+ unsubscribeFromEvent('logout-event', logoutEventFunc);
};
}, []);
const openAppsMode = () => {
if (isMobile) {
- setMobileViewMode("apps");
+ setMobileViewMode('apps');
}
if (!isMobile) {
- setDesktopViewMode('apps')
-
+ setDesktopViewMode('apps');
}
- if(isMobile){
- setIsOpenSideViewDirects(false)
- setIsOpenSideViewGroups(false)
- setGroupSection("default");
+ if (isMobile) {
+ setIsOpenSideViewDirects(false);
+ setIsOpenSideViewGroups(false);
+ setGroupSection('default');
setSelectedGroup(null);
setNewChat(false);
setSelectedDirect(null);
setSecretKey(null);
- setGroupOwner(null)
+ setGroupOwner(null);
lastFetchedSecretKey.current = null;
initiatedGetMembers.current = false;
setSecretKeyPublishDate(null);
@@ -1282,23 +1311,19 @@ export const Group = ({
setMemberCountFromSecretKeyData(null);
setTriedToFetchSecretKey(false);
setFirstSecretKeyInCreation(false);
- setIsOpenSideViewDirects(false)
- setIsOpenSideViewGroups(false)
+ setIsOpenSideViewDirects(false);
+ setIsOpenSideViewGroups(false);
}
-
-
};
useEffect(() => {
- subscribeToEvent("open-apps-mode", openAppsMode);
+ subscribeToEvent('open-apps-mode', openAppsMode);
return () => {
- unsubscribeFromEvent("open-apps-mode", openAppsMode);
+ unsubscribeFromEvent('open-apps-mode', openAppsMode);
};
}, []);
-
-
const openGroupChatFromNotification = (e) => {
if (isLoadingOpenSectionFromNotification.current) return;
@@ -1306,18 +1331,18 @@ export const Group = ({
const findGroup = groups?.find((group) => +group?.groupId === +groupId);
if (findGroup?.groupId === selectedGroup?.groupId) {
isLoadingOpenSectionFromNotification.current = false;
- setChatMode("groups");
- setDesktopViewMode('chat')
+ setChatMode('groups');
+ setDesktopViewMode('chat');
return;
}
if (findGroup) {
- setChatMode("groups");
+ setChatMode('groups');
setSelectedGroup(null);
setSelectedDirect(null);
setNewChat(false);
setSecretKey(null);
- setGroupOwner(null)
+ setGroupOwner(null);
lastFetchedSecretKey.current = null;
initiatedGetMembers.current = false;
setSecretKeyPublishDate(null);
@@ -1326,26 +1351,30 @@ export const Group = ({
setAdminsWithNames([]);
setMembers([]);
setMemberCountFromSecretKeyData(null);
- setIsForceShowCreationKeyPopup(false)
+ setIsForceShowCreationKeyPopup(false);
setTriedToFetchSecretKey(false);
setFirstSecretKeyInCreation(false);
- setGroupSection("chat");
- if(!isMobile){
- setDesktopViewMode('chat')
+ setGroupSection('chat');
+ if (!isMobile) {
+ setDesktopViewMode('chat');
}
- window.sendMessage("addTimestampEnterChat", {
- timestamp: Date.now(),
- groupId: findGroup.groupId,
- }).catch((error) => {
- console.error("Failed to add timestamp:", error.message || "An error occurred");
+ window
+ .sendMessage('addTimestampEnterChat', {
+ timestamp: Date.now(),
+ groupId: findGroup.groupId,
+ })
+ .catch((error) => {
+ console.error(
+ 'Failed to add timestamp:',
+ error.message || 'An error occurred'
+ );
});
-
setTimeout(() => {
setSelectedGroup(findGroup);
- setMobileViewMode("group");
- setDesktopSideView('groups')
+ setMobileViewMode('group');
+ setDesktopSideView('groups');
getTimestampEnterChat();
isLoadingOpenSectionFromNotification.current = false;
}, 350);
@@ -1355,10 +1384,10 @@ export const Group = ({
};
useEffect(() => {
- subscribeToEvent("openGroupMessage", openGroupChatFromNotification);
+ subscribeToEvent('openGroupMessage', openGroupChatFromNotification);
return () => {
- unsubscribeFromEvent("openGroupMessage", openGroupChatFromNotification);
+ unsubscribeFromEvent('openGroupMessage', openGroupChatFromNotification);
};
}, [groups, selectedGroup]);
@@ -1368,10 +1397,10 @@ export const Group = ({
const findGroup = groups?.find((group) => +group?.groupId === +groupId);
if (findGroup?.groupId === selectedGroup?.groupId) return;
if (findGroup) {
- setChatMode("groups");
+ setChatMode('groups');
setSelectedGroup(null);
setSecretKey(null);
- setGroupOwner(null)
+ setGroupOwner(null);
lastFetchedSecretKey.current = null;
initiatedGetMembers.current = false;
setSecretKeyPublishDate(null);
@@ -1380,24 +1409,29 @@ export const Group = ({
setAdminsWithNames([]);
setMembers([]);
setMemberCountFromSecretKeyData(null);
- setIsForceShowCreationKeyPopup(false)
+ setIsForceShowCreationKeyPopup(false);
setTriedToFetchSecretKey(false);
setFirstSecretKeyInCreation(false);
- setGroupSection("announcement");
- if(!isMobile){
- setDesktopViewMode('chat')
+ setGroupSection('announcement');
+ if (!isMobile) {
+ setDesktopViewMode('chat');
}
- window.sendMessage("addGroupNotificationTimestamp", {
- timestamp: Date.now(),
- groupId: findGroup.groupId,
- }).catch((error) => {
- console.error("Failed to add group notification timestamp:", error.message || "An error occurred");
+ window
+ .sendMessage('addGroupNotificationTimestamp', {
+ timestamp: Date.now(),
+ groupId: findGroup.groupId,
+ })
+ .catch((error) => {
+ console.error(
+ 'Failed to add group notification timestamp:',
+ error.message || 'An error occurred'
+ );
});
-
+
setTimeout(() => {
setSelectedGroup(findGroup);
- setMobileViewMode("group");
- setDesktopSideView('groups')
+ setMobileViewMode('group');
+ setDesktopSideView('groups');
getGroupAnnouncements();
}, 350);
}
@@ -1405,13 +1439,13 @@ export const Group = ({
useEffect(() => {
subscribeToEvent(
- "openGroupAnnouncement",
+ 'openGroupAnnouncement',
openGroupAnnouncementFromNotification
);
return () => {
unsubscribeFromEvent(
- "openGroupAnnouncement",
+ 'openGroupAnnouncement',
openGroupAnnouncementFromNotification
);
};
@@ -1422,16 +1456,16 @@ export const Group = ({
const { groupId } = data;
const findGroup = groups?.find((group) => +group?.groupId === +groupId);
if (findGroup?.groupId === selectedGroup?.groupId) {
- setGroupSection("forum");
+ setGroupSection('forum');
setDefaultThread(data);
return;
}
if (findGroup) {
- setChatMode("groups");
+ setChatMode('groups');
setSelectedGroup(null);
setSecretKey(null);
- setGroupOwner(null)
+ setGroupOwner(null);
lastFetchedSecretKey.current = null;
initiatedGetMembers.current = false;
setSecretKeyPublishDate(null);
@@ -1440,28 +1474,28 @@ export const Group = ({
setAdminsWithNames([]);
setMembers([]);
setMemberCountFromSecretKeyData(null);
- setIsForceShowCreationKeyPopup(false)
+ setIsForceShowCreationKeyPopup(false);
setTriedToFetchSecretKey(false);
setFirstSecretKeyInCreation(false);
- setGroupSection("forum");
+ setGroupSection('forum');
setDefaultThread(data);
- if(!isMobile){
- setDesktopViewMode('chat')
+ if (!isMobile) {
+ setDesktopViewMode('chat');
}
setTimeout(() => {
setSelectedGroup(findGroup);
- setMobileViewMode("group");
- setDesktopSideView('groups')
+ setMobileViewMode('group');
+ setDesktopSideView('groups');
getGroupAnnouncements();
}, 350);
}
};
useEffect(() => {
- subscribeToEvent("openThreadNewPost", openThreadNewPostFunc);
+ subscribeToEvent('openThreadNewPost', openThreadNewPostFunc);
return () => {
- unsubscribeFromEvent("openThreadNewPost", openThreadNewPostFunc);
+ unsubscribeFromEvent('openThreadNewPost', openThreadNewPostFunc);
};
}, [groups, selectedGroup]);
@@ -1471,23 +1505,21 @@ export const Group = ({
const goToHome = async () => {
if (isMobile) {
- setMobileViewMode("home");
+ setMobileViewMode('home');
}
if (!isMobile) {
}
- setDesktopViewMode('home')
-
+ setDesktopViewMode('home');
await new Promise((res) => {
setTimeout(() => {
res(null);
}, 200);
});
-
};
const goToAnnouncements = async () => {
- setGroupSection("default");
+ setGroupSection('default');
await new Promise((res) => {
setTimeout(() => {
res(null);
@@ -1495,14 +1527,19 @@ export const Group = ({
});
setSelectedDirect(null);
setNewChat(false);
- setGroupSection("announcement");
- window.sendMessage("addGroupNotificationTimestamp", {
- timestamp: Date.now(),
- groupId: selectedGroupRef.current.groupId,
- }).catch((error) => {
- console.error("Failed to add group notification timestamp:", error.message || "An error occurred");
+ setGroupSection('announcement');
+ window
+ .sendMessage('addGroupNotificationTimestamp', {
+ timestamp: Date.now(),
+ groupId: selectedGroupRef.current.groupId,
+ })
+ .catch((error) => {
+ console.error(
+ 'Failed to add group notification timestamp:',
+ error.message || 'An error occurred'
+ );
});
-
+
setTimeout(() => {
getGroupAnnouncements();
}, 200);
@@ -1510,33 +1547,37 @@ export const Group = ({
const openDrawerGroups = () => {
setIsOpenDrawer(true);
- setDrawerMode("groups");
+ setDrawerMode('groups');
};
const goToThreads = () => {
setSelectedDirect(null);
setNewChat(false);
- setGroupSection("forum");
+ setGroupSection('forum');
};
const goToChat = async () => {
- setGroupSection("default");
+ setGroupSection('default');
await new Promise((res) => {
setTimeout(() => {
res(null);
}, 200);
});
- setGroupSection("chat");
+ setGroupSection('chat');
setNewChat(false);
setSelectedDirect(null);
if (selectedGroupRef.current) {
- window.sendMessage("addTimestampEnterChat", {
- timestamp: Date.now(),
- groupId: selectedGroupRef.current.groupId,
- }).catch((error) => {
- console.error("Failed to add timestamp:", error.message || "An error occurred");
+ window
+ .sendMessage('addTimestampEnterChat', {
+ timestamp: Date.now(),
+ groupId: selectedGroupRef.current.groupId,
+ })
+ .catch((error) => {
+ console.error(
+ 'Failed to add timestamp:',
+ error.message || 'An error occurred'
+ );
});
-
setTimeout(() => {
getTimestampEnterChat();
@@ -1544,39 +1585,42 @@ export const Group = ({
}
};
-
-
const renderDirects = () => {
return (
{!isMobile && (
-
-
+ {
- setDesktopSideView("groups");
+ setDesktopSideView('groups');
}}
>
{
- setDesktopSideView("directs");
+ setDesktopSideView('directs');
}}
>
@@ -1609,31 +1658,31 @@ export const Group = ({
height={24}
color={
directChatHasUnread
- ? "var(--unread)"
+ ? 'var(--unread)'
: desktopSideView === 'directs'
- ? "white"
- : "rgba(250, 250, 250, 0.5)"
+ ? 'white'
+ : 'rgba(250, 250, 250, 0.5)'
}
/>
-
-
+
+
)}
-
+
{directs.map((direct: any) => (
{
- console.error("Failed to add timestamp:", error.message || "An error occurred");
+ window
+ .sendMessage('addTimestampEnterChat', {
+ timestamp: Date.now(),
+ groupId: direct.address,
+ })
+ .catch((error) => {
+ console.error(
+ 'Failed to add timestamp:',
+ error.message || 'An error occurred'
+ );
});
-
+
setTimeout(() => {
setSelectedDirect(direct);
@@ -1657,29 +1711,29 @@ export const Group = ({
}, 200);
}}
sx={{
- display: "flex",
- width: "100%",
- flexDirection: "column",
- cursor: "pointer",
- border: "1px #232428 solid",
- padding: "2px",
- borderRadius: "2px",
+ display: 'flex',
+ width: '100%',
+ flexDirection: 'column',
+ cursor: 'pointer',
+ border: '1px #232428 solid',
+ padding: '2px',
+ borderRadius: '2px',
background:
- direct?.address === selectedDirect?.address && "white",
+ direct?.address === selectedDirect?.address && 'white',
}}
>
@@ -1688,28 +1742,32 @@ export const Group = ({
{direct?.sender !== myAddress &&
@@ -1721,7 +1779,7 @@ export const Group = ({
direct?.timestamp) && (
)}
@@ -1732,10 +1790,10 @@ export const Group = ({
New Chat
@@ -1757,142 +1815,150 @@ export const Group = ({
);
};
-
const renderGroups = () => {
return (
{!isMobile && (
-
- {
- setDesktopSideView("groups");
+
- {
+ setDesktopSideView('groups');
+ }}
>
-
-
-
- {
- setDesktopSideView("directs");
- }}
- >
-
+
+
+
+ {
+ setDesktopSideView('directs');
+ }}
>
-
-
+ label="Messaging"
+ selected={desktopSideView === 'directs'}
+ >
+
+
)}
-
+
{groups.map((group: any) => (
{
- setMobileViewMode("group");
- setDesktopSideView('groups')
+ setMobileViewMode('group');
+ setDesktopSideView('groups');
initiatedGetMembers.current = false;
clearAllQueues();
setSelectedDirect(null);
setTriedToFetchSecretKey(false);
setNewChat(false);
setSelectedGroup(null);
- setUserInfoForLevels({})
+ setUserInfoForLevels({});
setSecretKey(null);
lastFetchedSecretKey.current = null;
setSecretKeyPublishDate(null);
setAdmins([]);
setSecretKeyDetails(null);
setAdminsWithNames([]);
- setGroupOwner(null)
+ setGroupOwner(null);
setMembers([]);
setMemberCountFromSecretKeyData(null);
setHideCommonKeyPopup(false);
setFirstSecretKeyInCreation(false);
- setGroupSection("chat");
+ setGroupSection('chat');
setIsOpenDrawer(false);
- setIsForceShowCreationKeyPopup(false)
+ setIsForceShowCreationKeyPopup(false);
setTimeout(() => {
setSelectedGroup(group);
-
}, 200);
}}
sx={{
- display: "flex",
- width: "100%",
- flexDirection: "column",
- cursor: "pointer",
- border: "1px #232428 solid",
- padding: "2px",
- borderRadius: "2px",
+ display: 'flex',
+ width: '100%',
+ flexDirection: 'column',
+ cursor: 'pointer',
+ border: '1px #232428 solid',
+ padding: '2px',
+ borderRadius: '2px',
background:
- group?.groupId === selectedGroup?.groupId && "white",
+ group?.groupId === selectedGroup?.groupId && 'white',
}}
>
{groupsProperties[group?.groupId]?.isOpen === false ? (
-
-
+
+
- ): (
-
-
+ ) : (
+
+
- //
- // {group.groupName?.charAt(0)}
- //
+ //
+ // {group.groupName?.charAt(0)}
+ //
)}
-
{groupAnnouncements[group?.groupId] &&
!groupAnnouncements[group?.groupId]?.seentimestamp && (
)}
{group?.data &&
- groupChatTimestamps[group?.groupId] &&
+ groupChatTimestamps[group?.groupId] &&
group?.sender !== myAddress &&
group?.timestamp &&
((!timestampEnterData[group?.groupId] &&
@@ -1992,7 +2071,7 @@ export const Group = ({
group?.timestamp) && (
)}
@@ -2004,48 +2083,47 @@ export const Group = ({
- {chatMode === "groups" && (
+ {chatMode === 'groups' && (
<>
-
{
- setOpenAddGroup(true);
- }}
- >
- {
+ setOpenAddGroup(true);
}}
- />
- Group Mgmt
-
- {!isRunningPublicNode && (
-
{
- setIsOpenBlockedUserModal(true);
- }}
- sx={{
- minWidth: 'unset',
- padding: '10px'
- }}
- >
-
-
- )}
-
+ >
+
+ Group Mgmt
+
+ {!isRunningPublicNode && (
+
{
+ setIsOpenBlockedUserModal(true);
+ }}
+ sx={{
+ minWidth: 'unset',
+ padding: '10px',
+ }}
+ >
+
+
+ )}
>
)}
- {chatMode === "directs" && (
+ {chatMode === 'directs' && (
{
setNewChat(true);
@@ -2055,7 +2133,7 @@ export const Group = ({
>
New Chat
@@ -2065,7 +2143,7 @@ export const Group = ({
);
};
-
+
return (
<>
-
-
-
- {!isMobile && ((desktopViewMode !== 'apps' && desktopViewMode !== 'dev') || isOpenSideViewGroups) && (
-
- )}
+ {!isMobile &&
+ ((desktopViewMode !== 'apps' && desktopViewMode !== 'dev') ||
+ isOpenSideViewGroups) && (
+
+ )}
- {!isMobile && desktopViewMode === 'chat' && desktopSideView !== 'directs' && renderGroups()}
- {!isMobile && desktopViewMode === 'chat' && desktopSideView === 'directs' && renderDirects()}
+ {!isMobile &&
+ desktopViewMode === 'chat' &&
+ desktopSideView !== 'directs' &&
+ renderGroups()}
+ {!isMobile &&
+ desktopViewMode === 'chat' &&
+ desktopSideView === 'directs' &&
+ renderDirects()}
-
{newChat && (
<>
- {isMobile && (
-
{
- close()
+ close();
}}
>
-
+
- {
- setSelectedDirect(null)
- setMobileViewModeKeepOpen('')
+ setSelectedDirect(null);
+ setMobileViewModeKeepOpen('');
}}
>
-
+
- )}
+ )}
-
- No group selected
-
-
- )}
-
-
- {!isMobile && (
-
-
-
- )}
-
-
-
-
- {triedToFetchSecretKey && (
-
+
+ )}
+
+
+ {!isMobile && (
+
+ )}
+
+
+ {triedToFetchSecretKey && (
+
+ )}
+ {isPrivate &&
+ firstSecretKeyInCreation &&
+ triedToFetchSecretKey &&
+ !secretKeyPublishDate && (
+
+ {' '}
+
+ The group's first common encryption key is in the process
+ of creation. Please wait a few minutes for it to be
+ retrieved by the network. Checking every 2 minutes...
+
+
+ )}
+ {isPrivate &&
+ !admins.includes(myAddress) &&
+ !secretKey &&
+ triedToFetchSecretKey ? (
+ <>
+ {secretKeyPublishDate ||
+ (!secretKeyPublishDate && !firstSecretKeyInCreation) ? (
+
+ {' '}
+
+ You are not part of the encrypted group of members. Wait
+ until an admin re-encrypts the keys.
+
+
+
+
+ Only unencrypted messages will be displayed.
+
+
+
+
+ Try notifying an admin from the list of admins below:
+
+
+ {adminsWithNames.map((admin) => {
+ return (
+
+ {admin?.name}
+ notifyAdmin(admin)}
+ >
+ Notify
+
+
+ );
+ })}
+
+ ) : null}
+ >
+ ) : admins.includes(myAddress) &&
+ !secretKey &&
+ isPrivate &&
+ triedToFetchSecretKey ? null : !triedToFetchSecretKey ? null : (
+ <>
+
+
+ {groupSection === 'adminSpace' && (
+
+ )}
+ >
+ )}
+
+
+ {((isPrivate &&
+ admins.includes(myAddress) &&
+ shouldReEncrypt &&
+ triedToFetchSecretKey &&
+ !firstSecretKeyInCreation &&
+ !hideCommonKeyPopup) ||
+ isForceShowCreationKeyPopup) && (
+
)}
- {isPrivate && firstSecretKeyInCreation &&
- triedToFetchSecretKey &&
- !secretKeyPublishDate && (
-
- {" "}
-
- The group's first common encryption key is in the
- process of creation. Please wait a few minutes for it to
- be retrieved by the network. Checking every 2 minutes...
-
-
- )}
- {isPrivate && !admins.includes(myAddress) &&
- !secretKey &&
- triedToFetchSecretKey ? (
- <>
- {secretKeyPublishDate ||
- (!secretKeyPublishDate && !firstSecretKeyInCreation) ? (
-
- {" "}
-
- You are not part of the encrypted group of members.
- Wait until an admin re-encrypts the keys.
-
-
-
- Only unencrypted messages will be displayed.
-
-
-
- Try notifying an admin from the list of admins below:
-
-
- {adminsWithNames.map((admin) => {
- return (
-
- {admin?.name}
- notifyAdmin(admin)}
- >
- Notify
-
-
- );
- })}
-
- ) : null}
- >
- ) : admins.includes(myAddress) &&
- (!secretKey && isPrivate) &&
- triedToFetchSecretKey ? null : !triedToFetchSecretKey ? null : (
- <>
-
-
- {groupSection === "adminSpace" && (
-
- )}
-
- >
- )}
-
-
- {((isPrivate && admins.includes(myAddress) &&
- shouldReEncrypt &&
- triedToFetchSecretKey &&
- !firstSecretKeyInCreation &&
- !hideCommonKeyPopup) || isForceShowCreationKeyPopup) && (
-
- )}
-
- {openManageMembers && (
-
- )}
-
- {isOpenBlockedUserModal && (
-
{
- setIsOpenBlockedUserModal(false)
- }} />
- )}
+
+ {openManageMembers && (
+
+ )}
+
+
{selectedDirect && !newChat && (
<>
>
)}
-
- {!isMobile && (
-
- )}
- {!isMobile && (
-
- )}
-
-
- {!isMobile && (
-
-
-
- )}
+ {!isMobile && (
+
+ )}
+ {!isMobile && (
+
+ )}
-
+ {!isMobile && (
+
+ )}
-
+
-
-
+ >
@@ -2586,5 +2719,3 @@ export const Group = ({
>
);
};
-
-
diff --git a/src/components/Group/useBlockUsers.tsx b/src/components/Group/useBlockUsers.tsx
index 05cbe90..eeb5361 100644
--- a/src/components/Group/useBlockUsers.tsx
+++ b/src/components/Group/useBlockUsers.tsx
@@ -19,7 +19,7 @@ export const useBlockedAddresses = () => {
const isUserBlocked = useCallback((address, name)=> {
try {
if(!address) return false
- if(userBlockedRef.current[address] || userNamesBlockedRef.current[name]) return true
+ if(userBlockedRef.current[address]) return true
return false
@@ -90,43 +90,13 @@ export const useBlockedAddresses = () => {
}, [])
const removeBlockFromList = useCallback(async (address, name)=> {
- await new Promise((res, rej) => {
- window.sendMessage("listActions", {
-
- type: 'remove',
- items: name ? [name] : [address],
- listName: name ? 'blockedNames' : 'blockedAddresses'
-
- })
- .then((response) => {
- if (response.error) {
- rej(response?.message);
- return;
- } else {
- if(!name){
- const copyObject = {...userBlockedRef.current}
- delete copyObject[address]
- userBlockedRef.current = copyObject
- } else {
- const copyObject = {...userNamesBlockedRef.current}
- delete copyObject[name]
- userNamesBlockedRef.current = copyObject
- }
-
- res(response);
- }
- })
- .catch((error) => {
- console.error("Failed qortalRequest", error);
- });
- })
- if(name && userBlockedRef.current[address]){
+ if(name){
await new Promise((res, rej) => {
window.sendMessage("listActions", {
type: 'remove',
- items: !name ? [name] : [address],
- listName: !name ? 'blockedNames' : 'blockedAddresses'
+ items: [name] ,
+ listName: 'blockedNames'
})
.then((response) => {
@@ -134,9 +104,12 @@ export const useBlockedAddresses = () => {
rej(response?.message);
return;
} else {
- const copyObject = {...userBlockedRef.current}
- delete copyObject[address]
- userBlockedRef.current = copyObject
+
+ const copyObject = {...userNamesBlockedRef.current}
+ delete copyObject[name]
+ userNamesBlockedRef.current = copyObject
+
+
res(response);
}
})
@@ -145,42 +118,95 @@ export const useBlockedAddresses = () => {
});
})
}
+
+ if(address){
+ await new Promise((res, rej) => {
+ window.sendMessage("listActions", {
+
+ type: 'remove',
+ items: [address],
+ listName: 'blockedAddresses'
+
+ })
+ .then((response) => {
+ if (response.error) {
+ rej(response?.message);
+ return;
+ } else {
+
+ const copyObject = {...userBlockedRef.current}
+ delete copyObject[address]
+ userBlockedRef.current = copyObject
+
+
+ res(response);
+ }
+ })
+ .catch((error) => {
+ console.error("Failed qortalRequest", error);
+ });
+ })
+ }
+
}, [])
const addToBlockList = useCallback(async (address, name)=> {
- await new Promise((res, rej) => {
- window.sendMessage("listActions", {
-
- type: 'add',
- items: name ? [name] : [address],
- listName: name ? 'blockedNames' : 'blockedAddresses'
-
- })
- .then((response) => {
- if (response.error) {
- rej(response?.message);
- return;
- } else {
- if(name){
-
- const copyObject = {...userNamesBlockedRef.current}
- copyObject[name] = true
- userNamesBlockedRef.current = copyObject
- }else {
- const copyObject = {...userBlockedRef.current}
- copyObject[address] = true
- userBlockedRef.current = copyObject
-
- }
+ if(name){
+ await new Promise((res, rej) => {
+ window.sendMessage("listActions", {
- res(response);
- }
+ type: 'add',
+ items: [name],
+ listName: 'blockedNames'
+
+ })
+ .then((response) => {
+ if (response.error) {
+ rej(response?.message);
+ return;
+ } else {
+ const copyObject = {...userNamesBlockedRef.current}
+ copyObject[name] = true
+ userNamesBlockedRef.current = copyObject
+
+
+ res(response);
+ }
+ })
+ .catch((error) => {
+ console.error("Failed qortalRequest", error);
+ });
})
- .catch((error) => {
- console.error("Failed qortalRequest", error);
- });
- })
+ }
+ if(address){
+ await new Promise((res, rej) => {
+ window.sendMessage("listActions", {
+
+ type: 'add',
+ items: [address],
+ listName: 'blockedAddresses'
+
+ })
+ .then((response) => {
+ if (response.error) {
+ rej(response?.message);
+ return;
+ } else {
+
+ const copyObject = {...userBlockedRef.current}
+ copyObject[address] = true
+ userBlockedRef.current = copyObject
+
+ res(response);
+ }
+ })
+ .catch((error) => {
+ console.error("Failed qortalRequest", error);
+ });
+ })
+ }
+
}, [])
return {
diff --git a/src/components/Minting/Minting.tsx b/src/components/Minting/Minting.tsx
index af63ece..4a9eeb3 100644
--- a/src/components/Minting/Minting.tsx
+++ b/src/components/Minting/Minting.tsx
@@ -13,29 +13,29 @@ import {
InputLabel,
Snackbar,
Typography,
-} from "@mui/material";
+} from '@mui/material';
import React, {
useCallback,
useContext,
useEffect,
useMemo,
useState,
-} from "react";
-import CloseIcon from "@mui/icons-material/Close";
-import { MyContext, getBaseApiReact } from "../../App";
+} from 'react';
+import CloseIcon from '@mui/icons-material/Close';
+import { MyContext, getBaseApiReact } from '../../App';
import {
executeEvent,
subscribeToEvent,
unsubscribeFromEvent,
-} from "../../utils/events";
-import { getFee, getNameOrAddress } from "../../background";
-import CopyToClipboard from "react-copy-to-clipboard";
-import { AddressBox } from "../../App-styles";
-import { Spacer } from "../../common/Spacer";
-import Copy from "../../assets/svgs/Copy.svg";
-import { Loader } from "../Loader";
-import { FidgetSpinner } from "react-loader-spinner";
-import { useModal } from "../../common/useModal";
+} from '../../utils/events';
+import { getFee, getNameOrAddress } from '../../background';
+import CopyToClipboard from 'react-copy-to-clipboard';
+import { AddressBox } from '../../styles/App-styles';
+import { Spacer } from '../../common/Spacer';
+import Copy from '../../assets/svgs/Copy.svg';
+import { Loader } from '../Loader';
+import { FidgetSpinner } from 'react-loader-spinner';
+import { useModal } from '../../common/useModal';
export const Minting = ({
setIsOpenMinting,
@@ -47,30 +47,30 @@ export const Minting = ({
}) => {
const [mintingAccounts, setMintingAccounts] = useState([]);
const [accountInfo, setAccountInfo] = useState(null);
- const [rewardSharePublicKey, setRewardSharePublicKey] = useState("");
- const [mintingKey, setMintingKey] = useState("");
- const [rewardsharekey, setRewardsharekey] = useState("");
+ const [rewardSharePublicKey, setRewardSharePublicKey] = useState('');
+ const [mintingKey, setMintingKey] = useState('');
+ const [rewardsharekey, setRewardsharekey] = useState('');
const [rewardShares, setRewardShares] = useState([]);
const [nodeInfos, setNodeInfos] = useState({});
const [openSnack, setOpenSnack] = useState(false);
const [isLoading, setIsLoading] = useState(false);
- const { show: showKey, message } = useModal();
- const { isShow: isShowNext, onOk, show: showNext } = useModal();
+ const { show: showKey, message } = useModal();
+ const { isShow: isShowNext, onOk, show: showNext } = useModal();
const [info, setInfo] = useState(null);
const [names, setNames] = useState({});
const [accountInfos, setAccountInfos] = useState({});
- const [showWaitDialog, setShowWaitDialog] = useState(false)
+ const [showWaitDialog, setShowWaitDialog] = useState(false);
const isPartOfMintingGroup = useMemo(() => {
if (groups?.length === 0) return false;
- return !!groups?.find((item) => item?.groupId?.toString() === "694");
+ return !!groups?.find((item) => item?.groupId?.toString() === '694');
}, [groups]);
const getMintingAccounts = useCallback(async () => {
try {
const url = `${getBaseApiReact()}/admin/mintingaccounts`;
const response = await fetch(url);
if (!response.ok) {
- throw new Error("network error");
+ throw new Error('network error');
}
const data = await response.json();
setMintingAccounts(data);
@@ -117,7 +117,7 @@ export const Minting = ({
const url = `${getBaseApiReact()}/addresses/${address}`;
const response = await fetch(url);
if (!response.ok) {
- throw new Error("network error");
+ throw new Error('network error');
}
const data = await response.json();
if (others) {
@@ -144,10 +144,10 @@ export const Minting = ({
};
useEffect(() => {
- subscribeToEvent("refresh-rewardshare-list", refreshRewardShare);
+ subscribeToEvent('refresh-rewardshare-list', refreshRewardShare);
return () => {
- unsubscribeFromEvent("refresh-rewardshare-list", refreshRewardShare);
+ unsubscribeFromEvent('refresh-rewardshare-list', refreshRewardShare);
};
}, [myAddress]);
@@ -177,15 +177,15 @@ export const Minting = ({
try {
const url = `${getBaseApiReact()}/admin/status`;
const response = await fetch(url, {
- method: "GET",
+ method: 'GET',
headers: {
- "Content-Type": "application/json",
+ 'Content-Type': 'application/json',
},
});
const data = await response.json();
setNodeInfos(data);
} catch (error) {
- console.error("Request failed", error);
+ console.error('Request failed', error);
}
};
@@ -194,11 +194,11 @@ export const Minting = ({
const url = `${getBaseApiReact()}/addresses/rewardshares?involving=${address}`;
const response = await fetch(url);
if (!response.ok) {
- throw new Error("network error");
+ throw new Error('network error');
}
const data = await response.json();
setRewardShares(data);
- return data
+ return data;
} catch (error) {}
}, []);
@@ -208,10 +208,10 @@ export const Minting = ({
return await new Promise((res, rej) => {
window
.sendMessage(
- "ADMIN_ACTION",
+ 'ADMIN_ACTION',
{
- type: "addmintingaccount",
+ type: 'addmintingaccount',
value: val,
},
180000,
@@ -220,7 +220,7 @@ export const Minting = ({
.then((response) => {
if (!response?.error) {
res(response);
- setMintingKey("");
+ setMintingKey('');
setTimeout(() => {
getMintingAccounts();
}, 300);
@@ -229,13 +229,13 @@ export const Minting = ({
rej({ message: response.error });
})
.catch((error) => {
- rej({ message: error.message || "An error occurred" });
+ rej({ message: error.message || 'An error occurred' });
});
});
} catch (error) {
setInfo({
- type: "error",
- message: error?.message || "Unable to add minting account",
+ type: 'error',
+ message: error?.message || 'Unable to add minting account',
});
setOpenSnack(true);
} finally {
@@ -249,10 +249,10 @@ export const Minting = ({
return await new Promise((res, rej) => {
window
.sendMessage(
- "ADMIN_ACTION",
+ 'ADMIN_ACTION',
{
- type: "removemintingaccount",
+ type: 'removemintingaccount',
value: val,
},
180000,
@@ -270,13 +270,13 @@ export const Minting = ({
rej({ message: response.error });
})
.catch((error) => {
- rej({ message: error.message || "An error occurred" });
+ rej({ message: error.message || 'An error occurred' });
});
});
} catch (error) {
setInfo({
- type: "error",
- message: error?.message || "Unable to remove minting account",
+ type: 'error',
+ message: error?.message || 'Unable to remove minting account',
});
setOpenSnack(true);
} finally {
@@ -285,14 +285,14 @@ export const Minting = ({
}, []);
const createRewardShare = useCallback(async (publicKey, recipient) => {
- const fee = await getFee("REWARD_SHARE");
+ const fee = await getFee('REWARD_SHARE');
await show({
- message: "Would you like to perform an REWARD_SHARE transaction?",
- publishFee: fee.fee + " QORT",
+ message: 'Would you like to perform an REWARD_SHARE transaction?',
+ publishFee: fee.fee + ' QORT',
});
return await new Promise((res, rej) => {
window
- .sendMessage("createRewardShare", {
+ .sendMessage('createRewardShare', {
recipientPublicKey: publicKey,
})
.then((response) => {
@@ -301,7 +301,7 @@ export const Minting = ({
{
recipient,
...response,
- type: "add-rewardShare",
+ type: 'add-rewardShare',
label: `Add rewardshare: awaiting confirmation`,
labelDone: `Add rewardshare: success!`,
done: false,
@@ -314,7 +314,7 @@ export const Minting = ({
rej({ message: response.error });
})
.catch((error) => {
- rej({ message: error.message || "An error occurred" });
+ rej({ message: error.message || 'An error occurred' });
});
});
}, []);
@@ -322,7 +322,7 @@ export const Minting = ({
const getRewardSharePrivateKey = useCallback(async (publicKey) => {
return await new Promise((res, rej) => {
window
- .sendMessage("getRewardSharePrivateKey", {
+ .sendMessage('getRewardSharePrivateKey', {
recipientPublicKey: publicKey,
})
.then((response) => {
@@ -333,7 +333,7 @@ export const Minting = ({
rej({ message: response.error });
})
.catch((error) => {
- rej({ message: error.message || "An error occurred" });
+ rej({ message: error.message || 'An error occurred' });
});
});
}, []);
@@ -341,26 +341,24 @@ export const Minting = ({
const waitUntilRewardShareIsConfirmed = async (timeoutMs = 600000) => {
const pollingInterval = 30000;
const startTime = Date.now();
-
+
const sleep = (ms) => new Promise((res) => setTimeout(res, ms));
-
+
while (Date.now() - startTime < timeoutMs) {
-
- const rewardShares = await getRewardShares(myAddress);
- const findRewardShare = rewardShares?.find(
- (item) =>
- item?.recipient === myAddress && item?.mintingAccount === myAddress
- );
-
- if (findRewardShare) {
- return true; // Exit early if found
- }
-
-
+ const rewardShares = await getRewardShares(myAddress);
+ const findRewardShare = rewardShares?.find(
+ (item) =>
+ item?.recipient === myAddress && item?.mintingAccount === myAddress
+ );
+
+ if (findRewardShare) {
+ return true; // Exit early if found
+ }
+
await sleep(pollingInterval); // Wait before the next poll
}
-
- throw new Error("Timeout waiting for reward share confirmation");
+
+ throw new Error('Timeout waiting for reward share confirmation');
};
const startMinting = async () => {
@@ -377,23 +375,22 @@ export const Minting = ({
addMintingAccount(privateRewardShare);
} else {
await createRewardShare(accountInfo?.publicKey, myAddress);
- setShowWaitDialog(true)
- await waitUntilRewardShareIsConfirmed()
+ setShowWaitDialog(true);
+ await waitUntilRewardShareIsConfirmed();
await showNext({
- message: ''
- })
+ message: '',
+ });
const privateRewardShare = await getRewardSharePrivateKey(
accountInfo?.publicKey
);
- setShowWaitDialog(false)
+ setShowWaitDialog(false);
addMintingAccount(privateRewardShare);
-
}
} catch (error) {
- setShowWaitDialog(false)
+ setShowWaitDialog(false);
setInfo({
- type: "error",
- message: error?.message || "Unable to start minting",
+ type: 'error',
+ message: error?.message || 'Unable to start minting',
});
setOpenSnack(true);
} finally {
@@ -412,13 +409,13 @@ export const Minting = ({
const url = `${getBaseApiReact()}/groups/member/${address}`;
const response = await fetch(url);
const data = await response.json();
- return !!data?.find((grp) => grp?.groupId?.toString() === "694");
+ return !!data?.find((grp) => grp?.groupId?.toString() === '694');
};
const removeRewardShare = useCallback(async (rewardShare) => {
return await new Promise((res, rej) => {
window
- .sendMessage("removeRewardShare", {
+ .sendMessage('removeRewardShare', {
rewardShareKeyPairPublicKey: rewardShare.rewardSharePublicKey,
recipient: rewardShare.recipient,
percentageShare: -1,
@@ -430,7 +427,7 @@ export const Minting = ({
{
...rewardShare,
...response,
- type: "remove-rewardShare",
+ type: 'remove-rewardShare',
label: `Remove rewardshare: awaiting confirmation`,
labelDone: `Remove rewardshare: success!`,
done: false,
@@ -442,7 +439,7 @@ export const Minting = ({
rej({ message: response.error });
})
.catch((error) => {
- rej({ message: error.message || "An error occurred" });
+ rej({ message: error.message || 'An error occurred' });
});
});
}, []);
@@ -454,8 +451,8 @@ export const Minting = ({
const privateRewardShare = await removeRewardShare(rewardShare);
} catch (error) {
setInfo({
- type: "error",
- message: error?.message || "Unable to remove reward share",
+ type: 'error',
+ message: error?.message || 'Unable to remove reward share',
});
setOpenSnack(true);
} finally {
@@ -468,9 +465,9 @@ export const Minting = ({
setIsLoading(true);
const confirmReceiver = await getNameOrAddress(receiver);
if (confirmReceiver.error)
- throw new Error("Invalid receiver address or name");
+ throw new Error('Invalid receiver address or name');
const isInMinterGroup = await checkIfMinterGroup(confirmReceiver);
- if (!isInMinterGroup) throw new Error("Account not in Minter Group");
+ if (!isInMinterGroup) throw new Error('Account not in Minter Group');
const publicKey = await getPublicKeyFromAddress(confirmReceiver);
const findRewardShare = rewardShares?.find(
(item) =>
@@ -487,8 +484,8 @@ export const Minting = ({
}
} catch (error) {
setInfo({
- type: "error",
- message: error?.message || "Unable to create reward share",
+ type: 'error',
+ message: error?.message || 'Unable to create reward share',
});
setOpenSnack(true);
} finally {
@@ -550,11 +547,9 @@ export const Minting = ({
(accountInfo?.blocksMinted + accountInfo?.blocksMintedAdjustment);
let countBlocksString = countBlocks.toString();
- return "" + countBlocksString;
+ return '' + countBlocksString;
};
-
-
return (
- {"Manage your minting"}
+ {'Manage your minting'}
{isLoading && (
Account: {handleNames(accountInfo?.address)}
@@ -631,11 +626,11 @@ export const Minting = ({
{isPartOfMintingGroup && !accountIsMinting && (
1}
sx={{
- backgroundColor: "var(--green)",
- color: "black",
- fontWeight: "bold",
+ backgroundColor: 'var(--green)',
+ color: 'black',
+ fontWeight: 'bold',
opacity: 0.7,
- maxWidth: "90%",
- width: "200px",
- "&:hover": {
- backgroundColor: "var(--green)",
- color: "black",
+ maxWidth: '90%',
+ width: '200px',
+ '&:hover': {
+ backgroundColor: 'var(--green)',
+ color: 'black',
opacity: 1,
},
}}
@@ -675,16 +670,16 @@ export const Minting = ({
)}
{accountIsMinting && (
@@ -698,9 +693,9 @@ export const Minting = ({
@@ -709,15 +704,15 @@ export const Minting = ({
@@ -768,22 +763,22 @@ export const Minting = ({
{
- executeEvent("addTab", {
- data: { service: "APP", name: "q-mintership" },
+ executeEvent('addTab', {
+ data: { service: 'APP', name: 'q-mintership' },
});
- executeEvent("open-apps-mode", {});
+ executeEvent('open-apps-mode', {});
setIsOpenMinting(false);
}}
variant="contained"
@@ -801,29 +796,32 @@ export const Minting = ({
aria-describedby="alert-dialog-description"
>
- {isShowNext ? "Confirmed" : "Please Wait"}
+ {isShowNext ? 'Confirmed' : 'Please Wait'}
{!isShowNext && (
- Confirming creation of rewardshare on chain. Please be patient, this could take up to 90 seconds.
-
+ Confirming creation of rewardshare on chain. Please be
+ patient, this could take up to 90 seconds.
+
)}
{isShowNext && (
- Rewardshare confirmed. Please click Next.
-
+ Rewardshare confirmed. Please click Next.
+
)}
-
-
-
-
+
+
+
Next
-
-
)}
@@ -837,7 +835,7 @@ export const Minting = ({
{info?.message}
diff --git a/src/components/PasswordField/PasswordField.tsx b/src/components/PasswordField/PasswordField.tsx
index 0c3e8b7..31f0a49 100644
--- a/src/components/PasswordField/PasswordField.tsx
+++ b/src/components/PasswordField/PasswordField.tsx
@@ -4,56 +4,59 @@ import {
TextField,
TextFieldProps,
styled,
-} from "@mui/material";
-import { forwardRef, useState } from "react";
-import VisibilityOffIcon from "@mui/icons-material/VisibilityOff";
-import VisibilityIcon from "@mui/icons-material/Visibility";
+ useTheme,
+} from '@mui/material';
+import { forwardRef, useState } from 'react';
+import VisibilityOffIcon from '@mui/icons-material/VisibilityOff';
+import VisibilityIcon from '@mui/icons-material/Visibility';
export const CustomInput = styled(TextField)(({ theme }) => ({
- width: "183px",
- borderRadius: "5px",
- backgroundColor: theme.palette.background.paper,
- outline: "none",
- input: {
- fontSize: 10,
- fontFamily: "Inter",
- fontWeight: 400,
- color: theme.palette.text.primary,
- "&::placeholder": {
- fontSize: 16,
- color: theme.palette.text.disabled,
- },
- outline: "none",
- padding: "10px",
+ width: '183px',
+ borderRadius: '5px',
+ backgroundColor: theme.palette.background.paper,
+ outline: 'none',
+ input: {
+ fontSize: 10,
+ fontFamily: 'Inter',
+ fontWeight: 400,
+ color: theme.palette.text.primary,
+ '&::placeholder': {
+ fontSize: 16,
+ color: theme.palette.text.disabled,
},
- "& .MuiOutlinedInput-root": {
- "& fieldset": {
- border: `0.5px solid ${theme.palette.divider}`,
- },
- "&:hover fieldset": {
- border: `0.5px solid ${theme.palette.divider}`,
- },
- "&.Mui-focused fieldset": {
- border: `0.5px solid ${theme.palette.divider}`,
- },
+ outline: 'none',
+ padding: '10px',
+ },
+ '& .MuiOutlinedInput-root': {
+ '& fieldset': {
+ border: `0.5px solid ${theme.palette.divider}`,
},
- "& .MuiInput-underline:before": {
- borderBottom: "none",
+ '&:hover fieldset': {
+ border: `0.5px solid ${theme.palette.divider}`,
},
- "& .MuiInput-underline:hover:not(.Mui-disabled):before": {
- borderBottom: "none",
+ '&.Mui-focused fieldset': {
+ border: `0.5px solid ${theme.palette.divider}`,
},
- "& .MuiInput-underline:after": {
- borderBottom: "none",
- },
- }));
+ },
+ '& .MuiInput-underline:before': {
+ borderBottom: 'none',
+ },
+ '& .MuiInput-underline:hover:not(.Mui-disabled):before': {
+ borderBottom: 'none',
+ },
+ '& .MuiInput-underline:after': {
+ borderBottom: 'none',
+ },
+}));
export const PasswordField = forwardRef(
({ ...props }, ref) => {
const [canViewPassword, setCanViewPassword] = useState(false);
+ const theme = useTheme();
+
return (
(
data-testid="plain-text-indicator"
sx={{ minWidth: 0, p: 0 }}
>
-
+
) : (
-
+
)}
diff --git a/src/components/QMailStatus.tsx b/src/components/QMailStatus.tsx
index cb1642a..0485240 100644
--- a/src/components/QMailStatus.tsx
+++ b/src/components/QMailStatus.tsx
@@ -1,31 +1,43 @@
-import React, { useMemo } from 'react'
-import QMailLogo from '../assets/QMailLogo.png'
-import { useRecoilState } from 'recoil'
-import { mailsAtom, qMailLastEnteredTimestampAtom } from '../atoms/global'
-import { isLessThanOneWeekOld } from './Group/QMailMessages'
-import { ButtonBase, Tooltip } from '@mui/material'
-import { executeEvent } from '../utils/events'
-export const QMailStatus = () => {
- const [lastEnteredTimestamp, setLastEnteredTimestamp] = useRecoilState(qMailLastEnteredTimestampAtom)
- const [mails, setMails] = useRecoilState(mailsAtom)
+import { useMemo } from 'react';
+import QMailLogo from '../assets/QMailLogo.png';
+import { useRecoilState } from 'recoil';
+import { mailsAtom, qMailLastEnteredTimestampAtom } from '../atoms/global';
+import { isLessThanOneWeekOld } from './Group/QMailMessages';
+import { ButtonBase, Tooltip } from '@mui/material';
+import { executeEvent } from '../utils/events';
- const hasNewMail = useMemo(()=> {
- if(mails?.length === 0) return false
- const latestMail = mails[0]
- if(!lastEnteredTimestamp && isLessThanOneWeekOld(latestMail?.created)) return true
- if((lastEnteredTimestamp < latestMail?.created) && isLessThanOneWeekOld(latestMail?.created)) return true
- return false
- }, [lastEnteredTimestamp, mails])
+export const QMailStatus = () => {
+ const [lastEnteredTimestamp, setLastEnteredTimestamp] = useRecoilState(
+ qMailLastEnteredTimestampAtom
+ );
+ const [mails, setMails] = useRecoilState(mailsAtom);
+
+ const hasNewMail = useMemo(() => {
+ if (mails?.length === 0) return false;
+ const latestMail = mails[0];
+ if (!lastEnteredTimestamp && isLessThanOneWeekOld(latestMail?.created))
+ return true;
+ if (
+ lastEnteredTimestamp < latestMail?.created &&
+ isLessThanOneWeekOld(latestMail?.created)
+ )
+ return true;
+ return false;
+ }, [lastEnteredTimestamp, mails]);
return (
- {
- executeEvent("addTab", { data: { service: 'APP', name: 'q-mail' } });
- executeEvent("open-apps-mode", { });
- setLastEnteredTimestamp(Date.now())
- }} style={{
- position: 'relative'
- }}>
+ {
+ executeEvent('addTab', { data: { service: 'APP', name: 'q-mail' } });
+ executeEvent('open-apps-mode', {});
+ setLastEnteredTimestamp(Date.now());
+ }}
+ style={{
+ position: 'relative',
+ }}
+ >
{hasNewMail && (
- {
height: '15px',
width: '15px',
borderRadius: '50%',
- outline: '1px solid white'
- }} />
+ outline: '1px solid white',
+ }}
+ />
)}
Q-MAIL}
+ title={
+
+ Q-MAIL
+
+ }
placement="left"
arrow
- sx={{ fontSize: "24" }}
+ sx={{ fontSize: '24' }}
slotProps={{
tooltip: {
sx: {
- color: "#ffffff",
- backgroundColor: "#444444",
+ color: '#ffffff',
+ backgroundColor: '#444444',
},
},
arrow: {
sx: {
- color: "#444444",
+ color: '#444444',
},
},
}}
>
-
- )
-}
+
+ );
+};
diff --git a/src/components/QortPayment.tsx b/src/components/QortPayment.tsx
index 6add9b2..ec68533 100644
--- a/src/components/QortPayment.tsx
+++ b/src/components/QortPayment.tsx
@@ -1,167 +1,170 @@
import { Box, CircularProgress } from '@mui/material';
-import React, { useEffect, useState } from 'react'
-import { CustomButton, CustomInput, CustomLabel, TextP } from '../App-styles';
+import React, { useEffect, useState } from 'react';
+import {
+ CustomButton,
+ CustomInput,
+ CustomLabel,
+ TextP,
+} from '../styles/App-styles';
import { Spacer } from '../common/Spacer';
import BoundedNumericTextField from '../common/BoundedNumericTextField';
import { PasswordField } from './PasswordField/PasswordField';
import { ErrorText } from './ErrorText/ErrorText';
import { getFee } from '../background';
-export const QortPayment = ({balance, show, onSuccess, defaultPaymentTo}) => {
- const [paymentTo, setPaymentTo] = useState
(defaultPaymentTo);
- const [paymentAmount, setPaymentAmount] = useState(0);
- const [paymentPassword, setPaymentPassword] = useState("");
- const [sendPaymentError, setSendPaymentError] = useState("");
- const [sendPaymentSuccess, setSendPaymentSuccess] = useState("");
- const [isLoadingSendCoin, setIsLoadingSendCoin] = useState(false);
+export const QortPayment = ({ balance, show, onSuccess, defaultPaymentTo }) => {
+ const [paymentTo, setPaymentTo] = useState(defaultPaymentTo);
+ const [paymentAmount, setPaymentAmount] = useState(0);
+ const [paymentPassword, setPaymentPassword] = useState('');
+ const [sendPaymentError, setSendPaymentError] = useState('');
+ const [sendPaymentSuccess, setSendPaymentSuccess] = useState('');
+ const [isLoadingSendCoin, setIsLoadingSendCoin] = useState(false);
+ const sendCoinFunc = async () => {
+ try {
+ setSendPaymentError('');
+ setSendPaymentSuccess('');
+ if (!paymentTo) {
+ setSendPaymentError('Please enter a recipient');
+ return;
+ }
+ if (!paymentAmount) {
+ setSendPaymentError('Please enter an amount greater than 0');
+ return;
+ }
+ if (!paymentPassword) {
+ setSendPaymentError('Please enter your wallet password');
+ return;
+ }
+ const fee = await getFee('PAYMENT');
-
- const sendCoinFunc = async() => {
- try {
- setSendPaymentError("");
- setSendPaymentSuccess("");
- if (!paymentTo) {
- setSendPaymentError("Please enter a recipient");
- return;
+ await show({
+ message: `Would you like to transfer ${Number(paymentAmount)} QORT?`,
+ paymentFee: fee.fee + ' QORT',
+ });
+ setIsLoadingSendCoin(true);
+ window
+ .sendMessage('sendCoin', {
+ amount: Number(paymentAmount),
+ receiver: paymentTo.trim(),
+ password: paymentPassword,
+ })
+ .then((response) => {
+ if (response?.error) {
+ setSendPaymentError(response.error);
+ } else {
+ onSuccess();
}
- if (!paymentAmount) {
- setSendPaymentError("Please enter an amount greater than 0");
- return;
- }
- if (!paymentPassword) {
- setSendPaymentError("Please enter your wallet password");
- return;
- }
- const fee = await getFee('PAYMENT')
-
- await show({
- message: `Would you like to transfer ${Number(paymentAmount)} QORT?` ,
- paymentFee: fee.fee + ' QORT'
- })
- setIsLoadingSendCoin(true);
- window
- .sendMessage("sendCoin", {
- amount: Number(paymentAmount),
- receiver: paymentTo.trim(),
- password: paymentPassword,
- })
- .then((response) => {
- if (response?.error) {
- setSendPaymentError(response.error);
- } else {
- onSuccess()
-
- }
- setIsLoadingSendCoin(false);
- })
- .catch((error) => {
- console.error("Failed to send coin:", error);
- setIsLoadingSendCoin(false);
- });
- } catch (error) {
- // error
- }
- };
+ setIsLoadingSendCoin(false);
+ })
+ .catch((error) => {
+ console.error('Failed to send coin:', error);
+ setIsLoadingSendCoin(false);
+ });
+ } catch (error) {
+ // error
+ }
+ };
return (
<>
-
- Transfer QORT
-
-
-
- Balance:
-
-
- {balance?.toFixed(2)} QORT
-
-
-
+ sx={{
+ display: 'flex',
+ flexDirection: 'column',
+ alignItems: 'flex-start',
+ }}
+ >
+
+ Transfer QORT
+
+
+
+ Balance:
+
+
+ {balance?.toFixed(2)} QORT
+
+
+
-
- To
-
- setPaymentTo(e.target.value)}
- autoComplete="off"
- />
-
-
- Amount
-
-
- setPaymentAmount(+e)}
- />
-
-
- Confirm Wallet Password
-
-
- setPaymentPassword(e.target.value)}
- autoComplete="off"
- />
-
-
- {sendPaymentError}
- {/* {sendPaymentSuccess} */}
-
-
+ To
+
+ setPaymentTo(e.target.value)}
+ autoComplete="off"
+ />
+
+ Amount
+
+ setPaymentAmount(+e)}
+ />
+
+
+ Confirm Wallet Password
+
+
+ setPaymentPassword(e.target.value)}
+ autoComplete="off"
+ />
+
+
+ {sendPaymentError}
+ {/* {sendPaymentSuccess} */}
+
+ {
+ if (isLoadingSendCoin) return;
+ sendCoinFunc();
+ }}
+ >
+ {isLoadingSendCoin && (
+ {
- if(isLoadingSendCoin) return
- sendCoinFunc();
- }}
- >
- {isLoadingSendCoin && (
-
- )}
- Send
-
+ />
+ )}
+ Send
+
>
- )
-}
+ );
+};
diff --git a/src/components/Theme/ThemeContext.tsx b/src/components/Theme/ThemeContext.tsx
index e21ab9f..e64c183 100644
--- a/src/components/Theme/ThemeContext.tsx
+++ b/src/components/Theme/ThemeContext.tsx
@@ -1,24 +1,19 @@
import { createContext, useContext, useState, useMemo } from 'react';
-import { createTheme, ThemeProvider as MuiThemeProvider } from '@mui/material/styles';
+import { ThemeProvider as MuiThemeProvider } from '@mui/material/styles';
+import { darkTheme, lightTheme } from '../../styles/theme';
-const darkTheme = createTheme({
- palette: {
- mode: 'dark',
- },
+const ThemeContext = createContext({
+ themeMode: 'light',
+ toggleTheme: () => {},
});
-const lightTheme = createTheme({
- palette: {
- mode: 'light',
- },
-});
-
-const ThemeContext = createContext({ themeMode: 'light', toggleTheme: () => {} });
-
export const ThemeProvider = ({ children }: { children: React.ReactNode }) => {
const [themeMode, setThemeMode] = useState('light');
- const theme = useMemo(() => (themeMode === 'light' ? lightTheme : darkTheme), [themeMode]);
+ const theme = useMemo(
+ () => (themeMode === 'light' ? lightTheme : darkTheme),
+ [themeMode]
+ );
const toggleTheme = () => {
setThemeMode((prevMode) => (prevMode === 'light' ? 'dark' : 'light'));
@@ -31,4 +26,4 @@ export const ThemeProvider = ({ children }: { children: React.ReactNode }) => {
);
};
-export const useThemeContext = () => useContext(ThemeContext);
\ No newline at end of file
+export const useThemeContext = () => useContext(ThemeContext);
diff --git a/src/components/Theme/ThemeSelector.tsx b/src/components/Theme/ThemeSelector.tsx
index 5b55f53..dbf9d90 100644
--- a/src/components/Theme/ThemeSelector.tsx
+++ b/src/components/Theme/ThemeSelector.tsx
@@ -1,58 +1,58 @@
-import { useThemeContext } from "./ThemeContext";
-import { styled, Switch } from "@mui/material";
+import { useThemeContext } from './ThemeContext';
+import { styled, Switch } from '@mui/material';
const ThemeSwitch = styled(Switch)(({ theme }) => ({
width: 62,
height: 34,
padding: 7,
- "& .MuiSwitch-switchBase": {
+ '& .MuiSwitch-switchBase': {
margin: 1,
padding: 0,
- transform: "translateX(6px)",
- "&.Mui-checked": {
- color: "#fff",
- transform: "translateX(22px)",
- "& .MuiSwitch-thumb:before": {
+ transform: 'translateX(6px)',
+ '&.Mui-checked': {
+ color: '#fff',
+ transform: 'translateX(22px)',
+ '& .MuiSwitch-thumb:before': {
backgroundImage: `url('data:image/svg+xml;utf8, ')`,
},
- "& + .MuiSwitch-track": {
+ '& + .MuiSwitch-track': {
opacity: 1,
- backgroundColor: "#aab4be",
- ...theme.applyStyles("dark", {
- backgroundColor: "#8796A5",
+ backgroundColor: '#aab4be',
+ ...theme.applyStyles('dark', {
+ backgroundColor: '#8796A5',
}),
},
},
},
- "& .MuiSwitch-thumb": {
- backgroundColor: "#001e3c",
+ '& .MuiSwitch-thumb': {
+ backgroundColor: '#fde402',
width: 32,
height: 32,
- "&::before": {
+ '&::before': {
content: "''",
- position: "absolute",
- width: "100%",
- height: "100%",
+ position: 'absolute',
+ width: '100%',
+ height: '100%',
left: 0,
top: 0,
- backgroundRepeat: "no-repeat",
- backgroundPosition: "center",
+ backgroundRepeat: 'no-repeat',
+ backgroundPosition: 'center',
backgroundImage: `url('data:image/svg+xml;utf8, ')`,
},
- ...theme.applyStyles("dark", {
- backgroundColor: "#003892",
+ ...theme.applyStyles('dark', {
+ backgroundColor: '#003892',
}),
},
- "& .MuiSwitch-track": {
+ '& .MuiSwitch-track': {
opacity: 1,
- backgroundColor: "#aab4be",
+ backgroundColor: '#aab4be',
borderRadius: 20 / 2,
- ...theme.applyStyles("dark", {
- backgroundColor: "#8796A5",
+ ...theme.applyStyles('dark', {
+ backgroundColor: '#8796A5',
}),
},
}));
@@ -62,14 +62,14 @@ const ThemeSelector = ({ style }) => {
return (
-
+
);
};
diff --git a/src/components/WrapperUserAction.tsx b/src/components/WrapperUserAction.tsx
index a3bcc3f..c074c16 100644
--- a/src/components/WrapperUserAction.tsx
+++ b/src/components/WrapperUserAction.tsx
@@ -169,12 +169,15 @@ useEffect(()=> {
onClick={async () => {
try {
setIsLoading(true)
- if(isAlreadyBlocked === true){
- await removeBlockFromList(address, name)
- } else if(isAlreadyBlocked === false) {
- await addToBlockList(address, name)
- }
- executeEvent('updateChatMessagesWithBlocks', true)
+ executeEvent("blockUserFromOutside", {
+ user: address
+ })
+ // if(isAlreadyBlocked === true){
+ // await removeBlockFromList(address, name)
+ // } else if(isAlreadyBlocked === false) {
+ // await addToBlockList(address, name)
+ // }
+ // executeEvent('updateChatMessagesWithBlocks', true)
} catch (error) {
console.error(error)
} finally {
diff --git a/src/main.tsx b/src/main.tsx
index 881d4c1..3f04c89 100644
--- a/src/main.tsx
+++ b/src/main.tsx
@@ -1,13 +1,12 @@
-import React from "react";
-import ReactDOM from "react-dom/client";
-import App from "./App.tsx";
-import "./index.css";
-import "./messaging/messagesToBackground";
-import { MessageQueueProvider } from "./MessageQueueContext.tsx";
-import { RecoilRoot } from "recoil";
-import { ThemeProvider } from "./components/Theme/ThemeContext.tsx";
+import ReactDOM from 'react-dom/client';
+import App from './App.tsx';
+import '../src/styles/index.css';
+import './messaging/messagesToBackground';
+import { MessageQueueProvider } from './MessageQueueContext.tsx';
+import { RecoilRoot } from 'recoil';
+import { ThemeProvider } from './components/Theme/ThemeContext.tsx';
-ReactDOM.createRoot(document.getElementById("root")!).render(
+ReactDOM.createRoot(document.getElementById('root')!).render(
<>
diff --git a/src/styles/App-styles.ts b/src/styles/App-styles.ts
new file mode 100644
index 0000000..9774f06
--- /dev/null
+++ b/src/styles/App-styles.ts
@@ -0,0 +1,260 @@
+import { Typography, Box, TextField, InputLabel } from '@mui/material';
+import { styled } from '@mui/system';
+
+export const AppContainer = styled(Box)(({ theme }) => ({
+ display: 'flex',
+ alignItems: 'center',
+ flexDirection: 'column',
+ width: '100vw',
+ height: '100vh',
+ radius: '15px',
+ backgroundColor: theme.palette.background.default,
+ color: theme.palette.text.primary,
+ overflow: 'hidden',
+}));
+
+export const AuthenticatedContainer = styled(Box)(({ theme }) => ({
+ display: 'flex',
+ width: '100%',
+ height: '100%',
+ justifyContent: 'space-between',
+ backgroundColor: theme.palette.background.default,
+ color: theme.palette.text.primary,
+}));
+
+export const AuthenticatedContainerInnerLeft = styled(Box)(({ theme }) => ({
+ display: 'flex',
+ alignItems: 'center',
+ flexDirection: 'column',
+ height: '100%',
+ width: '100%',
+ backgroundColor: theme.palette.background.default,
+ color: theme.palette.text.primary,
+}));
+
+export const AuthenticatedContainerInnerRight = styled(Box)(({ theme }) => ({
+ display: 'flex',
+ alignItems: 'center',
+ flexDirection: 'column',
+ width: '60px',
+ height: '100%',
+ backgroundColor: theme.palette.background.default,
+ color: theme.palette.text.primary,
+}));
+
+export const AuthenticatedContainerInnerTop = styled(Box)(({ theme }) => ({
+ display: 'flex',
+ alignItems: 'center',
+ justifyContent: 'flex-start',
+ width: '100%px',
+ height: '60px',
+ padding: '20px',
+ backgroundColor: theme.palette.background.default,
+ color: theme.palette.text.primary,
+}));
+
+export const TextP = styled(Typography)(({ theme }) => ({
+ fontSize: '13px',
+ fontWeight: 600,
+ fontFamily: 'Inter',
+ backgroundColor: theme.palette.background.default,
+ color: theme.palette.text.primary,
+}));
+
+export const TextItalic = styled('span')(({ theme }) => ({
+ fontSize: '13px',
+ fontWeight: 600,
+ fontFamily: 'Inter',
+ fontStyle: 'italic',
+ backgroundColor: theme.palette.background.default,
+ color: theme.palette.text.primary,
+}));
+
+export const TextSpan = styled('span')(({ theme }) => ({
+ fontSize: '13px',
+ fontFamily: 'Inter',
+ fontWeight: 800,
+ backgroundColor: theme.palette.background.default,
+ color: theme.palette.text.primary,
+}));
+
+export const AddressBox = styled(Box)(({ theme }) => ({
+ display: 'flex',
+ border: `1px solid ${
+ theme.palette.mode === 'dark'
+ ? 'rgba(255, 255, 255, 0.5)'
+ : 'rgba(0, 0, 0, 0.3)'
+ }`,
+ justifyContent: 'space-between',
+ alignItems: 'center',
+ width: 'auto',
+ height: '25px',
+ padding: '5px 15px',
+ gap: '5px',
+ borderRadius: '100px',
+ fontFamily: 'Inter',
+ fontSize: '12px',
+ fontWeight: 600,
+ lineHeight: '14.52px',
+ textAlign: 'left',
+ backgroundColor: theme.palette.background.default,
+ color: theme.palette.text.primary,
+ cursor: 'pointer',
+ transition: 'all 0.2s',
+
+ '&:hover': {
+ backgroundColor:
+ theme.palette.mode === 'dark'
+ ? 'rgba(41, 41, 43, 1)'
+ : 'rgba(240, 240, 240, 1)',
+ color: theme.palette.mode === 'dark' ? '#fff' : '#000',
+
+ 'svg path': {
+ fill: theme.palette.mode === 'dark' ? '#fff' : '#000',
+ },
+ },
+}));
+
+export const CustomButton = styled(Box)(({ theme }) => ({
+ boxSizing: 'border-box',
+ padding: '15px 20px',
+ gap: '10px',
+
+ border: `0.5px solid ${
+ theme.palette.mode === 'dark'
+ ? 'rgba(255, 255, 255, 0.5)'
+ : 'rgba(0, 0, 0, 0.3)'
+ }`,
+ filter: 'drop-shadow(1px 4px 10.5px rgba(0, 0, 0, 0.3))',
+ borderRadius: '5px',
+
+ display: 'inline-flex',
+ justifyContent: 'center',
+ alignItems: 'center',
+
+ width: 'fit-content',
+ minWidth: '160px',
+ cursor: 'pointer',
+ transition: 'all 0.2s',
+
+ fontWeight: 600,
+ fontFamily: 'Inter',
+ textAlign: 'center',
+ backgroundColor: theme.palette.background.default,
+ color: theme.palette.text.primary,
+
+ '&:hover': {
+ backgroundColor:
+ theme.palette.mode === 'dark'
+ ? 'rgba(41, 41, 43, 1)'
+ : 'rgba(230, 230, 230, 1)',
+ color: '#fff',
+
+ 'svg path': {
+ fill: '#fff',
+ },
+ },
+}));
+
+interface CustomButtonProps {
+ bgColor?: string;
+ color?: string;
+}
+
+export const CustomButtonAccept = styled(Box)(
+ ({ bgColor, color, theme }) => ({
+ boxSizing: 'border-box',
+ padding: '15px 20px',
+ gap: '10px',
+ border: `0.5px solid ${
+ theme.palette.mode === 'dark'
+ ? 'rgba(255, 255, 255, 0.5)'
+ : 'rgba(0, 0, 0, 0.3)'
+ }`,
+ filter: 'drop-shadow(1px 4px 10.5px rgba(0,0,0,0.3))',
+ borderRadius: 5,
+ display: 'inline-flex',
+ justifyContent: 'center',
+ alignItems: 'center',
+ width: 'fit-content',
+ transition: 'all 0.2s',
+ minWidth: 160,
+ cursor: 'pointer',
+ fontWeight: 600,
+ fontFamily: 'Inter',
+ textAlign: 'center',
+ opacity: 0.7,
+
+ // Color and backgroundColor with fallbacks
+ backgroundColor:
+ bgColor || (theme.palette.mode === 'dark' ? '#1d1d1d' : '#f5f5f5'),
+ color: color || (theme.palette.mode === 'dark' ? '#fff' : '#000'),
+
+ '&:hover': {
+ opacity: 1,
+ backgroundColor:
+ bgColor ||
+ (theme.palette.mode === 'dark'
+ ? 'rgba(41, 41, 43, 1)'
+ : 'rgba(230, 230, 230, 1)'),
+ color: color || '#fff',
+ svg: {
+ path: {
+ fill: color || '#fff',
+ },
+ },
+ },
+ })
+);
+
+export const CustomInput = styled(TextField)(({ theme }) => ({
+ width: '183px', // Adjust the width as needed
+ borderRadius: '5px',
+ // backgroundColor: "rgba(30, 30, 32, 1)",
+ outline: 'none',
+ backgroundColor: theme.palette.background.default,
+ color: theme.palette.text.primary,
+ input: {
+ fontSize: 10,
+ fontFamily: 'Inter',
+ fontWeight: 400,
+ color: 'white',
+ '&::placeholder': {
+ fontSize: 16,
+ color: 'rgba(255, 255, 255, 0.2)',
+ },
+ outline: 'none',
+ padding: '10px',
+ },
+ '& .MuiOutlinedInput-root': {
+ '& fieldset': {
+ border: '0.5px solid rgba(255, 255, 255, 0.5)',
+ },
+ '&:hover fieldset': {
+ border: '0.5px solid rgba(255, 255, 255, 0.5)',
+ },
+ '&.Mui-focused fieldset': {
+ border: '0.5px solid rgba(255, 255, 255, 0.5)',
+ },
+ },
+ '& .MuiInput-underline:before': {
+ borderBottom: 'none',
+ },
+ '& .MuiInput-underline:hover:not(.Mui-disabled):before': {
+ borderBottom: 'none',
+ },
+ '& .MuiInput-underline:after': {
+ borderBottom: 'none',
+ },
+}));
+
+export const CustomLabel = styled(InputLabel)(({ theme }) => ({
+ fontWeight: 400,
+ fontFamily: 'Inter',
+ fontSize: '10px',
+ lineHeight: '12px',
+ color:
+ theme.palette.mode === 'dark'
+ ? 'rgba(255, 255, 255, 0.5)'
+ : 'rgba(0, 0, 0, 0.5)',
+}));
diff --git a/src/components/CoreSyncStatus.css b/src/styles/CoreSyncStatus.css
similarity index 87%
rename from src/components/CoreSyncStatus.css
rename to src/styles/CoreSyncStatus.css
index 6624845..0f60c2b 100644
--- a/src/components/CoreSyncStatus.css
+++ b/src/styles/CoreSyncStatus.css
@@ -9,25 +9,32 @@
}
.tooltip .bottom {
- min-width: 225px;
- max-width: 250px;
- top: 35px;
- right: 0px;
- /* transform: translate(-50%, 0); */
- padding: 10px 10px;
- color: var(--black);
- background-color: var(--bg-2);
- font-weight: normal;
- font-size: 13px;
border-radius: 8px;
- position: absolute;
- z-index: 99999999;
- box-sizing: border-box;
- box-shadow: 0 1px 8px rgba(0, 0, 0, 0.5);
border: 1px solid var(--black);
- visibility: hidden;
+ box-shadow: 0 1px 8px rgba(0, 0, 0, 0.5);
+ box-sizing: border-box;
+ font-size: 13px;
+ font-weight: normal;
+ max-width: 250px;
+ min-width: 225px;
opacity: 0;
+ padding: 10px 10px;
+ position: absolute;
+ right: 0px;
+ top: 35px;
transition: opacity 0.2s;
+ visibility: hidden;
+ z-index: 99999999;
+}
+
+.tooltip[data-theme='light'] .bottom {
+ background-color: #f1f1f1;
+ color: #000000;
+}
+
+.tooltip[data-theme='dark'] .bottom {
+ background-color: var(--bg-2);
+ color: var(--black);
}
.tooltip:hover .bottom {
@@ -47,13 +54,13 @@
}
.tooltip .bottom i::after {
- content: "";
- position: absolute;
- width: 12px;
- height: 12px;
- left: 50%;
- transform: translate(-50%, 50%) rotate(45deg);
background-color: var(--white);
border: 1px solid var(--black);
box-shadow: 0 1px 8px rgba(0, 0, 0, 0.5);
+ content: '';
+ height: 12px;
+ left: 50%;
+ position: absolute;
+ transform: translate(-50%, 50%) rotate(45deg);
+ width: 12px;
}
diff --git a/src/index.css b/src/styles/index.css
similarity index 85%
rename from src/index.css
rename to src/styles/index.css
index 6b24232..3fd5ed7 100644
--- a/src/index.css
+++ b/src/styles/index.css
@@ -1,21 +1,21 @@
@font-face {
- font-family: "Inter";
- src: url("./styles/fonts/Inter-SemiBold.ttf") format("truetype");
+ font-family: 'Inter';
+ src: url('./styles/fonts/Inter-SemiBold.ttf') format('truetype');
font-weight: 600;
}
@font-face {
- font-family: "Inter";
- src: url("./styles/fonts/Inter-ExtraBold.ttf") format("truetype");
+ font-family: 'Inter';
+ src: url('./styles/fonts/Inter-ExtraBold.ttf') format('truetype');
font-weight: 800;
}
@font-face {
- font-family: "Inter";
- src: url("./styles/fonts/Inter-Bold.ttf") format("truetype");
+ font-family: 'Inter';
+ src: url('./styles/fonts/Inter-Bold.ttf') format('truetype');
font-weight: 700;
}
@font-face {
- font-family: "Inter";
- src: url("./styles/fonts/Inter-Regular.ttf") format("truetype");
+ font-family: 'Inter';
+ src: url('./styles/fonts/Inter-Regular.ttf') format('truetype');
font-weight: 400;
}
@@ -89,7 +89,7 @@ body {
}
@property --var1 {
- syntax: "";
+ syntax: '';
inherits: true;
initial-value: transparent;
}
diff --git a/src/styles/theme.ts b/src/styles/theme.ts
index feb0367..6ea83cc 100644
--- a/src/styles/theme.ts
+++ b/src/styles/theme.ts
@@ -1,54 +1,50 @@
-import { createTheme } from '@mui/material/styles'
-
+import { createTheme } from '@mui/material/styles';
// Extend the Theme interface
-
const commonThemeOptions = {
typography: {
- fontFamily: [
- 'Roboto'
- ].join(','),
+ fontFamily: ['Roboto'].join(','),
h1: {
fontSize: '2rem',
- fontWeight: 600
+ fontWeight: 600,
},
h2: {
fontSize: '1.75rem',
- fontWeight: 500
+ fontWeight: 500,
},
h3: {
fontSize: '1.5rem',
- fontWeight: 500
+ fontWeight: 500,
},
h4: {
fontSize: '1.25rem',
- fontWeight: 500
+ fontWeight: 500,
},
h5: {
fontSize: '1rem',
- fontWeight: 500
+ fontWeight: 500,
},
h6: {
fontSize: '0.875rem',
- fontWeight: 500
+ fontWeight: 500,
},
body1: {
fontSize: '23px',
fontWeight: 400,
lineHeight: 1.5,
- letterSpacing: '0.5px'
+ letterSpacing: 'normal',
},
body2: {
fontSize: '18px',
fontWeight: 400,
lineHeight: 1.4,
- letterSpacing: '0.2px'
- }
+ letterSpacing: '0.2px',
+ },
},
spacing: 8,
shape: {
- borderRadius: 4
+ borderRadius: 4,
},
breakpoints: {
values: {
@@ -56,8 +52,8 @@ const commonThemeOptions = {
sm: 600,
md: 900,
lg: 1200,
- xl: 1536
- }
+ xl: 1536,
+ },
},
components: {
MuiButton: {
@@ -66,25 +62,24 @@ const commonThemeOptions = {
backgroundColor: 'inherit',
transition: 'filter 0.3s ease-in-out',
'&:hover': {
- filter: 'brightness(1.1)'
- }
- }
+ filter: 'brightness(1.1)',
+ },
+ },
},
defaultProps: {
disableElevation: true,
- disableRipple: true
- }
+ disableRipple: true,
+ },
},
MuiModal: {
styleOverrides: {
root: {
zIndex: 50000,
},
- }
-
- }
- }
-}
+ },
+ },
+ },
+};
const lightTheme = createTheme({
...commonThemeOptions,
@@ -93,46 +88,46 @@ const lightTheme = createTheme({
primary: {
main: '#f4f4fb',
dark: '#eaecf4',
- light: '#f9f9fd'
+ light: '#f9f9fd',
},
secondary: {
- main: '#1EAAF1'
+ main: '#c2deec',
},
background: {
default: '#fafafa',
- paper: '#f0f0f0'
+ paper: '#f0f0f0',
},
text: {
primary: '#000000',
- secondary: '#525252'
- }
+ secondary: '#525252',
+ },
},
-
components: {
MuiCard: {
styleOverrides: {
root: {
boxShadow:
- 'rgba(0, 0, 0, 0.1) 0px 1px 3px 0px, rgba(0, 0, 0, 0.06) 0px 1px 2px 0px;',
+ 'rgba(0, 0, 0, 0.1) 0px 1px 3px 0px, rgba(230, 200, 200, 0.06) 0px 1px 2px 0px;',
borderRadius: '8px',
transition: 'all 0.3s ease-in-out',
'&:hover': {
cursor: 'pointer',
boxShadow:
- 'rgba(0, 0, 0, 0.1) 0px 4px 6px -1px, rgba(0, 0, 0, 0.06) 0px 2px 4px -1px;'
- }
- }
- }
+ 'rgba(0, 0, 0, 0.1) 0px 4px 6px -1px, rgba(0, 0, 0, 0.06) 0px 2px 4px -1px;',
+ },
+ },
+ },
},
MuiIcon: {
defaultProps: {
style: {
- color: '#000000'
- }
- }
- }
+ color: '#000000',
+ opacity: 0.5,
+ },
+ },
+ },
},
-})
+});
const darkTheme = createTheme({
...commonThemeOptions,
@@ -140,45 +135,46 @@ const darkTheme = createTheme({
mode: 'dark',
primary: {
main: '#2e3d60',
- dark: "#1a2744",
- light: "#3f4b66",
+ dark: '#1a2744',
+ light: '#3f4b66',
},
secondary: {
- main: '#45adff'
+ main: '#45adff',
},
background: {
default: '#313338',
- paper: "#1e1e20"
+ paper: '#1e1e20',
},
text: {
primary: '#ffffff',
- secondary: '#b3b3b3'
- }
+ secondary: '#b3b3b3',
+ },
},
components: {
MuiCard: {
styleOverrides: {
root: {
- boxShadow: "none",
+ boxShadow: 'none',
borderRadius: '8px',
transition: 'all 0.3s ease-in-out',
'&:hover': {
cursor: 'pointer',
boxShadow:
- ' 0px 3px 4px 0px hsla(0,0%,0%,0.14), 0px 3px 3px -2px hsla(0,0%,0%,0.12), 0px 1px 8px 0px hsla(0,0%,0%,0.2);'
- }
- }
- }
+ ' 0px 3px 4px 0px hsla(0,0%,0%,0.14), 0px 3px 3px -2px hsla(0,0%,0%,0.12), 0px 1px 8px 0px hsla(0,0%,0%,0.2);',
+ },
+ },
+ },
},
MuiIcon: {
defaultProps: {
style: {
- color: '#ffffff'
- }
- }
- }
+ color: '#ffffff',
+ opacity: 0.5,
+ },
+ },
+ },
},
-})
+});
-export { lightTheme, darkTheme }
+export { lightTheme, darkTheme };