diff --git a/public/content-script.js b/public/content-script.js index fd2b902..28c717b 100644 --- a/public/content-script.js +++ b/public/content-script.js @@ -23,7 +23,7 @@ document.addEventListener('qortalExtensionRequests', async (event) => { })); return } - chrome.runtime.sendMessage({ action: "userInfo" }, (response) => { + chrome?.runtime?.sendMessage({ action: "userInfo" }, (response) => { if (response.error) { document.dispatchEvent(new CustomEvent('qortalExtensionResponses', { detail: { type: "USER_INFO", data: { @@ -38,7 +38,7 @@ document.addEventListener('qortalExtensionRequests', async (event) => { } }); } else if (type === 'REQUEST_IS_INSTALLED') { - chrome.runtime.sendMessage({ action: "version" }, (response) => { + chrome?.runtime?.sendMessage({ action: "version" }, (response) => { if (response.error) { console.error("Error:", response.error); } else { @@ -51,7 +51,7 @@ document.addEventListener('qortalExtensionRequests', async (event) => { } else if (type === 'REQUEST_CONNECTION') { console.log('REQUEST_CONNECTION') const hostname = window.location.hostname - chrome.runtime.sendMessage({ action: "connection", payload: { + chrome?.runtime?.sendMessage({ action: "connection", payload: { hostname }, timeout }, (response) => { if (response.error) { @@ -75,7 +75,7 @@ document.addEventListener('qortalExtensionRequests', async (event) => { return } - chrome.runtime.sendMessage({ action: "oauth", payload: { + chrome?.runtime?.sendMessage({ action: "oauth", payload: { nodeBaseUrl: payload.nodeBaseUrl, senderAddress: payload.senderAddress, senderPublicKey: payload.senderPublicKey, timestamp: payload.timestamp @@ -105,7 +105,7 @@ document.addEventListener('qortalExtensionRequests', async (event) => { return } - chrome.runtime.sendMessage({ action: "buyOrder", payload: { + chrome?.runtime?.sendMessage({ action: "buyOrder", payload: { qortalAtAddress: payload.qortalAtAddress, hostname @@ -136,7 +136,7 @@ document.addEventListener('qortalExtensionRequests', async (event) => { })); return } - chrome.runtime.sendMessage({ action: "ltcBalance", payload: { + chrome?.runtime?.sendMessage({ action: "ltcBalance", payload: { hostname }, timeout }, (response) => { @@ -164,7 +164,7 @@ document.addEventListener('qortalExtensionRequests', async (event) => { })); return } - chrome.runtime.sendMessage({ action: "authentication", payload: { + chrome?.runtime?.sendMessage({ action: "authentication", payload: { hostname }, timeout }, (response) => { if (response.error) { @@ -191,7 +191,7 @@ document.addEventListener('qortalExtensionRequests', async (event) => { })); return } - chrome.runtime.sendMessage({ action: "sendQort", payload: { + chrome?.runtime?.sendMessage({ action: "sendQort", payload: { hostname, amount: payload.amount, description: payload.description, @@ -221,7 +221,7 @@ document.addEventListener('qortalExtensionRequests', async (event) => { })); return } - chrome.runtime.sendMessage({ action: "closePopup" }, (response) => { + chrome?.runtime?.sendMessage({ action: "closePopup" }, (response) => { if (response.error) { document.dispatchEvent(new CustomEvent('qortalExtensionResponses', { @@ -241,7 +241,7 @@ document.addEventListener('qortalExtensionRequests', async (event) => { }); -chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) { +chrome.runtime?.onMessage.addListener(function(message, sender, sendResponse) { if (message.type === "LOGOUT") { // Notify the web page window.postMessage({ diff --git a/src/App.tsx b/src/App.tsx index 940fa7c..f9d06b0 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -41,6 +41,8 @@ import Logout from "./assets/svgs/Logout.svg"; import Return from "./assets/svgs/Return.svg"; import Success from "./assets/svgs/Success.svg"; import Info from "./assets/svgs/Info.svg"; +import CloseIcon from '@mui/icons-material/Close'; + import { createAccount, generateRandomSentence, @@ -67,7 +69,7 @@ import { Spacer } from "./common/Spacer"; import { Loader } from "./components/Loader"; import { PasswordField, ErrorText } from "./components"; import { ChatGroup } from "./components/Chat/ChatGroup"; -import { Group, requestQueueMemberNames } from "./components/Group/Group"; +import { Group, requestQueueMemberNames } from "./components/Group/Group"; import { TaskManger } from "./components/TaskManager/TaskManger"; import { useModal } from "./common/useModal"; import { LoadingButton } from "@mui/lab"; @@ -83,6 +85,7 @@ import { import { executeEvent } from "./utils/events"; import { requestQueueCommentCount, requestQueuePublishedAccouncements } from "./components/Chat/GroupAnnouncements"; import { requestQueueGroupJoinRequests } from "./components/Group/GroupJoinRequests"; +import { DrawerComponent } from "./components/Drawer/Drawer"; type extStates = | "not-authenticated" @@ -126,6 +129,28 @@ const defaultValues: MyContextInterface = { message: "", }, }; +export let isMobile = false + +const isMobileDevice = () => { + const userAgent = navigator.userAgent || navigator.vendor || window.opera; + + if (/android/i.test(userAgent)) { + return true; // Android device + } + + if (/iPad|iPhone|iPod/.test(userAgent) && !window.MSStream) { + return true; // iOS device + } + + return false; +}; + +if (isMobileDevice()) { + isMobile = true + console.log("Running on a mobile device"); +} else { + console.log("Running on a desktop"); +} export const allQueues = { requestQueueCommentCount: requestQueueCommentCount, @@ -160,7 +185,7 @@ export const clearAllQueues = () => { export const pauseAllQueues = () => { controlAllQueues('pause'); - chrome.runtime.sendMessage( + chrome?.runtime?.sendMessage( { action: "pauseAllQueues", payload: { @@ -171,7 +196,7 @@ export const pauseAllQueues = () => { } export const resumeAllQueues = () => { controlAllQueues('resume'); - chrome.runtime.sendMessage( + chrome?.runtime?.sendMessage( { action: "resumeAllQueues", payload: { @@ -266,11 +291,33 @@ function App() { const [openAdvancedSettings, setOpenAdvancedSettings] = useState(false); const [useLocalNode, setUseLocalNode] = useState(false); const [confirmUseOfLocal, setConfirmUseOfLocal] = useState(false); - + const [isOpenDrawerProfile, setIsOpenDrawerProfile] = useState(false); const [apiKey, setApiKey] = useState(""); useEffect(() => { - chrome.runtime.sendMessage({ action: "getApiKey" }, (response) => { + if(!isMobile) return + // Function to set the height of the app to the viewport height + const resetHeight = () => { + const height = window.visualViewport ? window.visualViewport.height : window.innerHeight; + // Set the height to the root element (usually #root) + document.getElementById('root').style.height = height + "px"; + }; + + // Set the initial height + resetHeight(); + + // Add event listeners for resize and visualViewport changes + window.addEventListener('resize', resetHeight); + window.visualViewport?.addEventListener('resize', resetHeight); + + // Clean up the event listeners when the component unmounts + return () => { + window.removeEventListener('resize', resetHeight); + window.visualViewport?.removeEventListener('resize', resetHeight); + }; + }, []); + useEffect(() => { + chrome?.runtime?.sendMessage({ action: "getApiKey" }, (response) => { if (response) { globalApiKey = response; @@ -405,7 +452,7 @@ function App() { }; const storeWalletInfo = (wallet: any) => { - chrome.runtime.sendMessage( + chrome?.runtime?.sendMessage( { action: "storeWalletInfo", wallet }, (response) => { if (response) { @@ -427,7 +474,7 @@ function App() { const getBalanceFunc = () => { setQortBalanceLoading(true); - chrome.runtime.sendMessage({ action: "balance" }, (response) => { + chrome?.runtime?.sendMessage({ action: "balance" }, (response) => { if (!response?.error && !isNaN(+response)) { setBalance(response); } @@ -436,7 +483,7 @@ function App() { }; const getLtcBalanceFunc = () => { setLtcBalanceLoading(true); - chrome.runtime.sendMessage({ action: "ltcBalance" }, (response) => { + chrome?.runtime?.sendMessage({ action: "ltcBalance" }, (response) => { if (!response?.error && !isNaN(+response)) { setLtcBalance(response); } @@ -459,7 +506,7 @@ function App() { return; } setIsLoading(true); - chrome.runtime.sendMessage( + chrome?.runtime?.sendMessage( { action: "sendCoin", payload: { @@ -487,7 +534,7 @@ function App() { useEffect(() => { // Listen for messages from the background script - chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { + chrome.runtime?.onMessage.addListener((message, sender, sendResponse) => { // Check if the message is to update the state if ( message.action === "UPDATE_STATE_CONFIRM_SEND_QORT" && @@ -563,7 +610,7 @@ function App() { //param = isDecline const confirmPayment = (isDecline: boolean) => { if (isDecline) { - chrome.runtime.sendMessage( + chrome?.runtime?.sendMessage( { action: "sendQortConfirmation", payload: { @@ -586,7 +633,7 @@ function App() { } setIsLoading(true); - chrome.runtime.sendMessage( + chrome?.runtime?.sendMessage( { action: "sendQortConfirmation", payload: { @@ -613,7 +660,7 @@ function App() { const confirmBuyOrder = (isDecline: boolean) => { if (isDecline) { - chrome.runtime.sendMessage( + chrome?.runtime?.sendMessage( { action: "buyOrderConfirmation", payload: { @@ -630,7 +677,7 @@ function App() { } setIsLoading(true); - chrome.runtime.sendMessage( + chrome?.runtime?.sendMessage( { action: "buyOrderConfirmation", payload: { @@ -657,7 +704,7 @@ function App() { hostname: string, interactionId: string ) => { - chrome.runtime.sendMessage( + chrome?.runtime?.sendMessage( { action: "responseToConnectionRequest", payload: { isOkay, hostname, interactionId }, @@ -679,7 +726,7 @@ function App() { useEffect(() => { try { setIsLoading(true); - chrome.runtime.sendMessage({ action: "getWalletInfo" }, (response) => { + chrome?.runtime?.sendMessage({ action: "getWalletInfo" }, (response) => { if (response && response?.walletInfo) { setRawWallet(response?.walletInfo); if ( @@ -708,7 +755,7 @@ function App() { }, 10000); }); } - chrome.runtime.sendMessage({ action: "userInfo" }, (response) => { + chrome?.runtime?.sendMessage({ action: "userInfo" }, (response) => { if (response && !response.error) { setUserInfo(response); } @@ -799,7 +846,7 @@ function App() { crypto.kdfThreads, () => {} ); - chrome.runtime.sendMessage( + chrome?.runtime?.sendMessage( { action: "decryptWallet", payload: { @@ -814,7 +861,7 @@ function App() { wallet, qortAddress: wallet.address0, }); - chrome.runtime.sendMessage({ action: "userInfo" }, (response2) => { + chrome?.runtime?.sendMessage({ action: "userInfo" }, (response2) => { setIsLoading(false); if (response2 && !response2.error) { setUserInfo(response); @@ -835,7 +882,7 @@ function App() { const logoutFunc = () => { try { - chrome.runtime.sendMessage({ action: "logout" }, (response) => { + chrome?.runtime?.sendMessage({ action: "logout" }, (response) => { if (response) { resetAllStates(); executeEvent("logout-event", {}); @@ -898,7 +945,7 @@ function App() { res(); }, 250); }); - chrome.runtime.sendMessage( + chrome?.runtime?.sendMessage( { action: "decryptWallet", payload: { @@ -911,14 +958,14 @@ function App() { setAuthenticatePassword(""); setExtstate("authenticated"); setWalletToBeDecryptedError(""); - chrome.runtime.sendMessage({ action: "userInfo" }, (response) => { + chrome?.runtime?.sendMessage({ action: "userInfo" }, (response) => { setIsLoading(false); if (response && !response.error) { setUserInfo(response); } }); getBalanceFunc(); - chrome.runtime.sendMessage( + chrome?.runtime?.sendMessage( { action: "getWalletInfo" }, (response) => { if (response && response?.walletInfo) { @@ -1023,7 +1070,7 @@ function App() { }); setIsLoadingRegisterName(true); new Promise((res, rej) => { - chrome.runtime.sendMessage( + chrome?.runtime?.sendMessage( { action: "registerName", payload: { @@ -1076,8 +1123,224 @@ function App() { } }; + const renderProfile = ()=> { + return ( + + {isMobile && ( + { + setIsOpenDrawerProfile(false) + }} sx={{ + cursor: 'pointer', + color: 'white' + }} /> + )} + + + + + {authenticatedMode === "ltc" ? ( + <> + + + + + {rawWallet?.ltcAddress?.slice(0, 6)}... + {rawWallet?.ltcAddress?.slice(-4)} + + + + {ltcBalanceLoading && ( + + )} + {!isNaN(+ltcBalance) && !ltcBalanceLoading && ( + + + {ltcBalance} LTC + + + + )} + + ) : ( + <> + + + + {userInfo?.name} + + + + + {rawWallet?.address0?.slice(0, 6)}... + {rawWallet?.address0?.slice(-4)} + + + + {qortBalanceLoading && ( + + )} + {!qortBalanceLoading && balance >= 0 && ( + + + {balance?.toFixed(2)} QORT + + + + )} + + + {userInfo && !userInfo?.name && ( + { + setOpenRegisterName(true); + }} + > + REGISTER NAME + + )} + + { + setExtstate("send-qort"); + }} + > + Transfer QORT + + + )} + { + chrome.tabs.create({ url: "https://www.qort.trade" }); + }} + > + Get QORT at qort.trade + + + + + { + setExtstate("download-wallet"); + }} + src={Download} + style={{ + cursor: "pointer", + }} + /> + + + + {authenticatedMode === "qort" && ( + { + setAuthenticatedMode("ltc"); + }} + src={ltcLogo} + style={{ + cursor: "pointer", + width: "20px", + height: "auto", + }} + /> + )} + {authenticatedMode === "ltc" && ( + { + setAuthenticatedMode("qort"); + }} + src={qortLogo} + style={{ + cursor: "pointer", + width: "20px", + height: "auto", + }} + /> + )} + + + ) + } + return ( - + {/* {extState === 'group' && ( )} */} @@ -1230,7 +1493,7 @@ function App() { onClick={() => { const valueToSet = !confirmUseOfLocal const payload = valueToSet ? apiKey : null - chrome.runtime.sendMessage( + chrome?.runtime?.sendMessage( { action: "setApiKey", payload }, (response) => { if (response) { @@ -1266,7 +1529,7 @@ function App() { {/* {extState !== "not-authenticated" && ( )} */} - {extState === "authenticated" && isMainWindow && ( + {extState === "authenticated" && ( - - - - - {authenticatedMode === "ltc" ? ( - <> - - - - - {rawWallet?.ltcAddress?.slice(0, 6)}... - {rawWallet?.ltcAddress?.slice(-4)} - - - - {ltcBalanceLoading && ( - - )} - {!isNaN(+ltcBalance) && !ltcBalanceLoading && ( - - - {ltcBalance} LTC - - - - )} - - ) : ( - <> - - - - {userInfo?.name} - - - - - {rawWallet?.address0?.slice(0, 6)}... - {rawWallet?.address0?.slice(-4)} - - - - {qortBalanceLoading && ( - - )} - {!qortBalanceLoading && balance >= 0 && ( - - - {balance?.toFixed(2)} QORT - - - - )} - - - {userInfo && !userInfo?.name && ( - { - setOpenRegisterName(true); - }} - > - REGISTER NAME - - )} - - { - setExtstate("send-qort"); - }} - > - Transfer QORT - - - )} - { - chrome.tabs.create({ url: "https://www.qort.trade" }); - }} - > - Get QORT at qort.trade - - - - - { - setExtstate("download-wallet"); - }} - src={Download} - style={{ - cursor: "pointer", - }} - /> - - - - {authenticatedMode === "qort" && ( - { - setAuthenticatedMode("ltc"); - }} - src={ltcLogo} - style={{ - cursor: "pointer", - width: "20px", - height: "auto", - }} - /> - )} - {authenticatedMode === "ltc" && ( - { - setAuthenticatedMode("qort"); - }} - src={qortLogo} - style={{ - cursor: "pointer", - width: "20px", - height: "auto", - }} - /> - )} - - + {!isMobile && renderProfile()} + + {renderProfile()} ); } diff --git a/src/background.ts b/src/background.ts index 9539e5b..7413cd3 100644 --- a/src/background.ts +++ b/src/background.ts @@ -2341,7 +2341,7 @@ if (res?.[key]) { throw new Error("No Chatheads saved"); } } -chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { +chrome?.runtime?.onMessage.addListener((request, sender, sendResponse) => { if (request) { switch (request.action) { case "version": @@ -3581,7 +3581,7 @@ const restoreWindowBounds = (callback) => { }); }; -chrome.action.onClicked.addListener((tab) => { +chrome.action?.onClicked?.addListener((tab) => { const popupUrl = chrome.runtime.getURL("index.html?main=true"); chrome.windows.getAll( { populate: true, windowTypes: ["popup"] }, @@ -3716,7 +3716,7 @@ const checkActiveChatsForNotifications = async ()=> { } } -chrome.notifications.onClicked.addListener( (notificationId) => { +chrome.notifications?.onClicked?.addListener( (notificationId) => { const popupUrl = chrome.runtime.getURL("index.html?main=true"); const isDirect = notificationId.includes('_type=direct_'); @@ -3839,14 +3839,14 @@ chrome.notifications.onClicked.addListener( (notificationId) => { }); // Reconnect when service worker wakes up -chrome.runtime.onStartup.addListener(() => { +chrome.runtime?.onStartup.addListener(() => { console.log("Service worker started up, reconnecting WebSocket..."); // initWebsocketMessageGroup(); // listenForNewGroupAnnouncements() // listenForThreadUpdates() }); -chrome.runtime.onInstalled.addListener((details) => { +chrome.runtime?.onInstalled.addListener((details) => { if (details.reason === chrome.runtime.OnInstalledReason.INSTALL) { console.log('Extension Installed'); // Perform tasks that should only happen on extension installation @@ -3866,14 +3866,14 @@ chrome.runtime.onInstalled.addListener((details) => { }); // Check if the alarm already exists before creating it -chrome.alarms.get("checkForNotifications", (existingAlarm) => { +chrome.alarms?.get("checkForNotifications", (existingAlarm) => { if (!existingAlarm) { // If the alarm does not exist, create it chrome.alarms.create("checkForNotifications", { periodInMinutes: 4 }); } }); -chrome.alarms.onAlarm.addListener(async (alarm) => { +chrome.alarms?.onAlarm.addListener(async (alarm) => { try { if (alarm.name === "checkForNotifications") { diff --git a/src/components/Chat/AnnouncementDiscussion.tsx b/src/components/Chat/AnnouncementDiscussion.tsx index 7a4bb9c..00c7691 100644 --- a/src/components/Chat/AnnouncementDiscussion.tsx +++ b/src/components/Chat/AnnouncementDiscussion.tsx @@ -10,7 +10,7 @@ import { decryptPublishes, getTempPublish, saveTempPublish } from "./GroupAnnoun import { AnnouncementList } from "./AnnouncementList"; import { Spacer } from "../../common/Spacer"; import ArrowBackIcon from '@mui/icons-material/ArrowBack'; -import { getBaseApiReact, pauseAllQueues, resumeAllQueues } from "../../App"; +import { getBaseApiReact, isMobile, pauseAllQueues, resumeAllQueues } from "../../App"; const tempKey = 'accouncement-comment' @@ -66,7 +66,7 @@ export const AnnouncementDiscussion = ({ if (!selectedAnnouncement) return; return new Promise((res, rej) => { - chrome.runtime.sendMessage( + chrome?.runtime?.sendMessage( { action: "publishGroupEncryptedResource", payload: { @@ -245,7 +245,7 @@ export const AnnouncementDiscussion = ({ return (
{ try { return new Promise((res, rej)=> { - chrome.runtime.sendMessage({ action: "decryptDirect", payload: { + chrome?.runtime?.sendMessage({ action: "decryptDirect", payload: { data: encryptedMessages, involvingAddress: selectedDirect?.address }}, (response) => { @@ -146,7 +146,7 @@ const sendChatDirect = async ({ chatReference = undefined, messageText}: any)=> if(!directTo) return return new Promise((res, rej)=> { - chrome.runtime.sendMessage({ action: "sendChatDirect", payload: { + chrome?.runtime?.sendMessage({ action: "sendChatDirect", payload: { directTo, chatReference, messageText }}, async (response) => { @@ -167,7 +167,7 @@ const sendChatDirect = async ({ chatReference = undefined, messageText}: any)=> "senderName": myName }) setNewChat(null) - chrome.runtime.sendMessage({ + chrome?.runtime?.sendMessage({ action: "addTimestampEnterChat", payload: { timestamp: Date.now(), diff --git a/src/components/Chat/ChatGroup.tsx b/src/components/Chat/ChatGroup.tsx index d0c8887..4420d94 100644 --- a/src/components/Chat/ChatGroup.tsx +++ b/src/components/Chat/ChatGroup.tsx @@ -10,7 +10,7 @@ import Tiptap from './TipTap' import { CustomButton } from '../../App-styles' import CircularProgress from '@mui/material/CircularProgress'; import { LoadingSnackbar } from '../Snackbar/LoadingSnackbar' -import { getBaseApiReactSocket, pauseAllQueues, resumeAllQueues } from '../../App' +import { getBaseApiReactSocket, isMobile, pauseAllQueues, resumeAllQueues } from '../../App' import { CustomizedSnackbars } from '../Snackbar/Snackbar' import { PUBLIC_NOTIFICATION_CODE_FIRST_SECRET_KEY } from '../../constants/codes' import { useMessageQueue } from '../../MessageQueueContext' @@ -85,7 +85,7 @@ export const ChatGroup = ({selectedGroup, secretKey, setSecretKey, getSecretKey, return } return new Promise((res, rej)=> { - chrome.runtime.sendMessage({ action: "decryptSingle", payload: { + chrome?.runtime?.sendMessage({ action: "decryptSingle", payload: { data: encryptedMessages, secretKeyObject: secretKey }}, (response) => { @@ -233,7 +233,7 @@ export const ChatGroup = ({selectedGroup, secretKey, setSecretKey, getSecretKey, const encryptChatMessage = async (data: string, secretKeyObject: any)=> { try { return new Promise((res, rej)=> { - chrome.runtime.sendMessage({ action: "encryptSingle", payload: { + chrome?.runtime?.sendMessage({ action: "encryptSingle", payload: { data, secretKeyObject }}, (response) => { @@ -252,7 +252,7 @@ export const ChatGroup = ({selectedGroup, secretKey, setSecretKey, getSecretKey, const sendChatGroup = async ({groupId, typeMessage = undefined, chatReference = undefined, messageText}: any)=> { try { return new Promise((res, rej)=> { - chrome.runtime.sendMessage({ action: "sendChatGroup", payload: { + chrome?.runtime?.sendMessage({ action: "sendChatGroup", payload: { groupId, typeMessage, chatReference, messageText }}, (response) => { @@ -336,7 +336,7 @@ const clearEditorContent = () => { return (
{ @@ -142,7 +142,7 @@ export const CreateCommonSecret = ({groupId, secretKey, isOwner, myAddress, sec flexDirection: 'column', gap: '25px', maxWidth: '350px', - background: '#4444' + background: '#444444' }}> Re-encyrpt key {noSecretKey ? ( diff --git a/src/components/Chat/GroupAnnouncements.tsx b/src/components/Chat/GroupAnnouncements.tsx index 9f8b91f..bf94e1c 100644 --- a/src/components/Chat/GroupAnnouncements.tsx +++ b/src/components/Chat/GroupAnnouncements.tsx @@ -28,7 +28,7 @@ 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 { MyContext, getBaseApiReact, pauseAllQueues, resumeAllQueues } from "../../App"; +import { MyContext, getBaseApiReact, isMobile, pauseAllQueues, resumeAllQueues } from "../../App"; import { RequestQueueWithPromise } from "../../utils/queue/queue"; import { CustomizedSnackbars } from "../Snackbar/Snackbar"; @@ -39,7 +39,7 @@ export const saveTempPublish = async ({ data, key }: any) => { return new Promise((res, rej) => { - chrome.runtime.sendMessage( + chrome?.runtime?.sendMessage( { action: "saveTempPublish", payload: { @@ -62,7 +62,7 @@ export const getTempPublish = async () => { return new Promise((res, rej) => { - chrome.runtime.sendMessage( + chrome?.runtime?.sendMessage( { action: "getTempPublish", payload: { @@ -81,7 +81,7 @@ export const getTempPublish = async () => { export const decryptPublishes = async (encryptedMessages: any[], secretKey) => { try { return await new Promise((res, rej) => { - chrome.runtime.sendMessage( + chrome?.runtime?.sendMessage( { action: "decryptSingleForPublishes", payload: { @@ -182,7 +182,7 @@ export const GroupAnnouncements = ({ const encryptChatMessage = async (data: string, secretKeyObject: any) => { try { return new Promise((res, rej) => { - chrome.runtime.sendMessage( + chrome?.runtime?.sendMessage( { action: "encryptSingle", payload: { @@ -206,7 +206,7 @@ export const GroupAnnouncements = ({ return new Promise((res, rej) => { - chrome.runtime.sendMessage( + chrome?.runtime?.sendMessage( { action: "publishGroupEncryptedResource", payload: { @@ -460,7 +460,7 @@ export const GroupAnnouncements = ({ return (
{ + + const toggleDrawer = (newOpen: boolean) => () => { + setOpen(newOpen); + }; + + + return ( +
+ + + + {children} + + +
+ ); +} diff --git a/src/components/Group/AddGroup.tsx b/src/components/Group/AddGroup.tsx index 47bbf0e..ed27d35 100644 --- a/src/components/Group/AddGroup.tsx +++ b/src/components/Group/AddGroup.tsx @@ -103,7 +103,7 @@ export const AddGroup = ({ address, open, setOpen }) => { }) await new Promise((res, rej) => { - chrome.runtime.sendMessage( + chrome?.runtime?.sendMessage( { action: "createGroup", payload: { diff --git a/src/components/Group/AddGroupList.tsx b/src/components/Group/AddGroupList.tsx index d0b8772..2eb9495 100644 --- a/src/components/Group/AddGroupList.tsx +++ b/src/components/Group/AddGroupList.tsx @@ -108,7 +108,7 @@ export const AddGroupList = ({ setInfoSnack, setOpenSnack }) => { }) setIsLoading(true); await new Promise((res, rej) => { - chrome.runtime.sendMessage( + chrome?.runtime?.sendMessage( { action: "joinGroup", payload: { diff --git a/src/components/Group/Forum/GroupMail.tsx b/src/components/Group/Forum/GroupMail.tsx index d962347..48bc62e 100644 --- a/src/components/Group/Forum/GroupMail.tsx +++ b/src/components/Group/Forum/GroupMail.tsx @@ -123,7 +123,7 @@ export const GroupMail = ({ const updateThreadActivity = async ({threadId, qortalName, groupId, thread}) => { try { await new Promise((res, rej) => { - chrome.runtime.sendMessage( + chrome?.runtime?.sendMessage( { action: "updateThreadActivity", payload: { @@ -656,6 +656,11 @@ export const GroupMail = ({ thread?.threadData?.createdAt < hasViewedRecent?.timestamp; return ( { setCurrentThread(thread); if(thread?.threadId && thread?.threadData?.name){ diff --git a/src/components/Group/Forum/NewThread.tsx b/src/components/Group/Forum/NewThread.tsx index f4a088b..a716823 100644 --- a/src/components/Group/Forum/NewThread.tsx +++ b/src/components/Group/Forum/NewThread.tsx @@ -94,7 +94,7 @@ export const publishGroupEncryptedResource = async ({ identifier, }) => { return new Promise((res, rej) => { - chrome.runtime.sendMessage( + chrome?.runtime?.sendMessage( { action: "publishGroupEncryptedResource", payload: { @@ -117,7 +117,7 @@ export const publishGroupEncryptedResource = async ({ export const encryptSingleFunc = async (data: string, secretKeyObject: any) => { try { return new Promise((res, rej) => { - chrome.runtime.sendMessage( + chrome?.runtime?.sendMessage( { action: "encryptSingle", payload: { diff --git a/src/components/Group/Forum/ReusableModal.tsx b/src/components/Group/Forum/ReusableModal.tsx index b61e83e..d081293 100644 --- a/src/components/Group/Forum/ReusableModal.tsx +++ b/src/components/Group/Forum/ReusableModal.tsx @@ -1,5 +1,6 @@ import React from 'react' import { Box, Modal, useTheme } from '@mui/material' +import { isMobile } from '../../../App' interface MyModalProps { open: boolean @@ -40,7 +41,7 @@ export const ReusableModal: React.FC = ({ top: '50%', left: '50%', transform: 'translate(-50%, -50%)', - width: '75%', + width: isMobile ? '95%' : '75%', bgcolor: theme.palette.primary.main, boxShadow: 24, p: 4, diff --git a/src/components/Group/Group.tsx b/src/components/Group/Group.tsx index 7edab6c..aeed4b3 100644 --- a/src/components/Group/Group.tsx +++ b/src/components/Group/Group.tsx @@ -2,6 +2,7 @@ import { Avatar, Box, Button, + Grid, IconButton, List, ListItem, @@ -29,7 +30,9 @@ import MarkUnreadChatAltIcon from "@mui/icons-material/MarkUnreadChatAlt"; import AddCircleOutlineIcon from "@mui/icons-material/AddCircleOutline"; import CreateIcon from "@mui/icons-material/Create"; import RefreshIcon from "@mui/icons-material/Refresh"; - +import AnnouncementsIcon from '@mui/icons-material/Notifications'; +import GroupIcon from '@mui/icons-material/Group'; +import PersonIcon from '@mui/icons-material/Person'; import { AuthenticatedContainerInnerRight, CustomButton, @@ -39,13 +42,21 @@ import { Spacer } from "../../common/Spacer"; import PeopleIcon from "@mui/icons-material/People"; import { ManageMembers } from "./ManageMembers"; import MarkChatUnreadIcon from "@mui/icons-material/MarkChatUnread"; -import { MyContext, clearAllQueues, getBaseApiReact, pauseAllQueues, resumeAllQueues } from "../../App"; +import { + MyContext, + clearAllQueues, + getBaseApiReact, + 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"; import HomeIcon from "@mui/icons-material/Home"; +import CloseIcon from '@mui/icons-material/Close'; import { ThingsToDoInitial } from "./ThingsToDoInitial"; import { GroupJoinRequests } from "./GroupJoinRequests"; @@ -61,6 +72,29 @@ import { RequestQueueWithPromise } from "../../utils/queue/queue"; import { WebSocketActive } from "./WebsocketActive"; import { flushSync } from "react-dom"; import { useMessageQueue } from "../../MessageQueueContext"; +import { DrawerComponent } from "../Drawer/Drawer"; + +// let touchStartY = 0; +// let disablePullToRefresh = false; + +// // Detect when the user touches the screen +// window.addEventListener('touchstart', function(event) { +// if (event.touches.length !== 1) return; // Ignore multi-touch events + +// touchStartY = event.touches[0].clientY; +// disablePullToRefresh = window.scrollY === 0; // Only disable if at the top +// }); + +// // Detect when the user moves their finger on the screen +// window.addEventListener('touchmove', function(event) { +// let touchY = event.touches[0].clientY; + +// // If pulling down from the top of the page, prevent the default behavior +// if (disablePullToRefresh && touchY > touchStartY) { +// event.preventDefault(); +// } +// }); + interface GroupProps { myAddress: string; @@ -75,7 +109,7 @@ const timeDifferenceForNotificationChats = 900000; export const requestQueueMemberNames = new RequestQueueWithPromise(5); export const requestQueueAdminMemberNames = new RequestQueueWithPromise(5); -const audio = new Audio(chrome.runtime.getURL("msg-not1.wav")); +const audio = new Audio(chrome.runtime?.getURL("msg-not1.wav")); export const getGroupAdimnsAddress = async (groupNumber: number) => { // const validApi = await findUsableApi(); @@ -151,7 +185,7 @@ export const getGroupMembers = async (groupNumber: number) => { export const decryptResource = async (data: string) => { try { return new Promise((res, rej) => { - chrome.runtime.sendMessage( + chrome?.runtime?.sendMessage( { action: "decryptGroupEncryption", payload: { @@ -159,7 +193,6 @@ export const decryptResource = async (data: string) => { }, }, (response) => { - if (!response?.error) { res(response); } @@ -276,10 +309,11 @@ export const Group = ({ isMain, userInfo, balance, + isOpenDrawerProfile, setIsOpenDrawerProfile }: GroupProps) => { const [secretKey, setSecretKey] = useState(null); const [secretKeyPublishDate, setSecretKeyPublishDate] = useState(null); - const lastFetchedSecretKey = useRef(null) + const lastFetchedSecretKey = useRef(null); const [secretKeyDetails, setSecretKeyDetails] = useState(null); const [newEncryptionNotification, setNewEncryptionNotification] = useState(null); @@ -310,11 +344,14 @@ export const Group = ({ const [isLoadingNotifyAdmin, setIsLoadingNotifyAdmin] = React.useState(false); const [isLoadingGroups, setIsLoadingGroups] = React.useState(false); const [isLoadingGroup, setIsLoadingGroup] = React.useState(false); - const [firstSecretKeyInCreation, setFirstSecretKeyInCreation] = React.useState(false) + const [firstSecretKeyInCreation, setFirstSecretKeyInCreation] = + React.useState(false); const [groupSection, setGroupSection] = React.useState("home"); const [groupAnnouncements, setGroupAnnouncements] = React.useState({}); const [defaultThread, setDefaultThread] = React.useState(null); + const [isOpenDrawer, setIsOpenDrawer] = React.useState(false); + const [drawerMode, setDrawerMode] = React.useState('groups'); const isFocusedRef = useRef(true); const selectedGroupRef = useRef(null); const selectedDirectRef = useRef(null); @@ -325,6 +362,9 @@ export const Group = ({ const settimeoutForRefetchSecretKey = useRef(null); const { clearStatesMessageQueueProvider } = useMessageQueue(); + // useEffect(()=> { + // setFullHeight() + // }, []) useEffect(() => { isFocusedRef.current = isFocused; @@ -341,12 +381,10 @@ export const Group = ({ selectedDirectRef.current = selectedDirect; }, [selectedDirect]); - - const getTimestampEnterChat = async () => { try { return new Promise((res, rej) => { - chrome.runtime.sendMessage( + chrome?.runtime?.sendMessage( { action: "getTimestampEnterChat", }, @@ -371,12 +409,11 @@ export const Group = ({ const getGroupAnnouncements = async () => { try { return new Promise((res, rej) => { - chrome.runtime.sendMessage( + chrome?.runtime?.sendMessage( { action: "getGroupNotificationTimestamp", }, (response) => { - if (!response?.error) { setGroupAnnouncements(response); res(response); @@ -390,11 +427,10 @@ export const Group = ({ const getGroupOwner = async (groupId) => { try { - const url = `${getBaseApiReact()}/groups/${groupId}`; const response = await fetch(url); let data = await response.json(); - + const name = await getNameInfo(data?.owner); if (name) { data.name = name; @@ -475,11 +511,11 @@ export const Group = ({ selectedGroup?.groupId }&exactmatchnames=true&limit=0&reverse=true&${queryString}`; const response = await fetch(url); - if(!response.ok){ - throw new Error('network error') + if (!response.ok) { + throw new Error("network error"); } const adminData = await response.json(); - + const filterId = adminData.filter( (data: any) => data.identifier === `symmetric-qchat-group-${selectedGroup?.groupId}` @@ -491,18 +527,27 @@ export const Group = ({ // Get the most recent date for both a and b const dateA = a.updated ? new Date(a.updated) : new Date(a.created); const dateB = b.updated ? new Date(b.updated) : new Date(b.created); - + // Sort by most recent return dateB.getTime() - dateA.getTime(); }); - + return sortedData[0]; }; - const getSecretKey = async (loadingGroupParam?: boolean, secretKeyToPublish?: boolean) => { + const getSecretKey = async ( + loadingGroupParam?: boolean, + secretKeyToPublish?: boolean + ) => { try { - pauseAllQueues() - - if(secretKeyToPublish && secretKey && lastFetchedSecretKey.current && Date.now() - lastFetchedSecretKey.current < 1800000) return secretKey + pauseAllQueues(); + + if ( + secretKeyToPublish && + secretKey && + lastFetchedSecretKey.current && + Date.now() - lastFetchedSecretKey.current < 1800000 + ) + return secretKey; if (loadingGroupParam) { setIsLoadingGroup(true); } @@ -515,12 +560,12 @@ export const Group = ({ const prevGroupId = selectedGroupRef.current.groupId; // const validApi = await findUsableApi(); const groupAdmins = await getGroupAdimns(selectedGroup?.groupId); - setAdmins(groupAdmins) - if(!groupAdmins.length){ - throw new Error('Network error') + setAdmins(groupAdmins); + if (!groupAdmins.length) { + throw new Error("Network error"); } const publish = await getPublishesFromAdmins(groupAdmins); - + if (prevGroupId !== selectedGroupRef.current.groupId) { if (settimeoutForRefetchSecretKey.current) { clearTimeout(settimeoutForRefetchSecretKey.current); @@ -535,49 +580,45 @@ export const Group = ({ return false; } setSecretKeyPublishDate(publish?.updated || publish?.created); - + const res = await fetch( `${getBaseApiReact()}/arbitrary/DOCUMENT_PRIVATE/${publish.name}/${ publish.identifier }?encoding=base64` ); const data = await res.text(); - + const decryptedKey: any = await decryptResource(data); - + const dataint8Array = base64ToUint8Array(decryptedKey.data); const decryptedKeyToObject = uint8ArrayToObject(dataint8Array); - + if (!validateSecretKey(decryptedKeyToObject)) throw new Error("SecretKey is not valid"); setSecretKeyDetails(publish); setSecretKey(decryptedKeyToObject); - lastFetchedSecretKey.current = Date.now() + lastFetchedSecretKey.current = Date.now(); setMemberCountFromSecretKeyData(decryptedKey.count); if (decryptedKeyToObject) { setTriedToFetchSecretKey(true); - setFirstSecretKeyInCreation(false) + setFirstSecretKeyInCreation(false); return decryptedKeyToObject; } else { setTriedToFetchSecretKey(true); } - } catch (error) { - if(error === 'Unable to decrypt data'){ + if (error === "Unable to decrypt data") { setTriedToFetchSecretKey(true); settimeoutForRefetchSecretKey.current = setTimeout(() => { getSecretKey(); }, 120000); } - } finally { setIsLoadingGroup(false); - if(!secretKeyToPublish){ + if (!secretKeyToPublish) { await getAdmins(selectedGroup?.groupId); - } - resumeAllQueues() - + resumeAllQueues(); } }; @@ -596,7 +637,7 @@ export const Group = ({ // } // const newActiveChats= data // const oldActiveChats = await new Promise((res, rej) => { - // chrome.runtime.sendMessage( + // chrome?.runtime?.sendMessage( // { // action: "getChatHeads", // }, @@ -627,7 +668,7 @@ export const Group = ({ // if(results?.length > 0){ // if (!lastGroupNotification.current || (Date.now() - lastGroupNotification.current >= 60000)) { // console.log((Date.now() - lastGroupNotification.current >= 60000), lastGroupNotification.current) - // chrome.runtime.sendMessage( + // chrome?.runtime?.sendMessage( // { // action: "notification", // payload: { @@ -650,7 +691,7 @@ export const Group = ({ // } catch (error) { // console.log('error not', error) // if(!isFocusedRef.current){ - // chrome.runtime.sendMessage( + // chrome?.runtime?.sendMessage( // { // action: "notification", // payload: { @@ -670,7 +711,7 @@ export const Group = ({ // } finally { - // chrome.runtime.sendMessage( + // chrome?.runtime?.sendMessage( // { // action: "setChatHeads", // payload: { @@ -693,16 +734,15 @@ export const Group = ({ useEffect(() => { // Listen for messages from the background script - chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { - + chrome?.runtime?.onMessage.addListener((message, sender, sendResponse) => { if (message.action === "SET_GROUPS") { // Update the component state with the received 'sendqort' state setGroups(message.payload); - + setMemberGroups(message.payload); if (selectedGroupRef.current && groupSectionRef.current === "chat") { - chrome.runtime.sendMessage({ + chrome?.runtime?.sendMessage({ action: "addTimestampEnterChat", payload: { timestamp: Date.now(), @@ -711,7 +751,7 @@ export const Group = ({ }); } if (selectedDirectRef.current) { - chrome.runtime.sendMessage({ + chrome?.runtime?.sendMessage({ action: "addTimestampEnterChat", payload: { timestamp: Date.now(), @@ -731,7 +771,7 @@ export const Group = ({ selectedGroupRef.current && groupSectionRef.current === "announcement" ) { - chrome.runtime.sendMessage({ + chrome?.runtime?.sendMessage({ action: "addGroupNotificationTimestamp", payload: { timestamp: Date.now(), @@ -748,7 +788,7 @@ export const Group = ({ setDirects(message.payload); // if (selectedGroupRef.current) { - // chrome.runtime.sendMessage({ + // chrome?.runtime?.sendMessage({ // action: "addTimestampEnterChat", // payload: { // timestamp: Date.now(), @@ -775,16 +815,15 @@ export const Group = ({ ) return; - chrome.runtime.sendMessage({ action: "setupGroupWebsocket" }); + chrome?.runtime?.sendMessage({ action: "setupGroupWebsocket" }); hasInitializedWebsocket.current = true; }, [myAddress, groups]); - const getMembers = async (groupId) => { try { const res = await getGroupMembers(groupId); - if(groupId !== selectedGroupRef.current?.groupId) return + if (groupId !== selectedGroupRef.current?.groupId) return; setMembers(res); } catch (error) {} }; @@ -795,8 +834,6 @@ export const Group = ({ } }, [selectedGroup?.groupId]); - - const shouldReEncrypt = useMemo(() => { if (triedToFetchSecretKey && !secretKeyPublishDate) return true; if ( @@ -809,13 +846,13 @@ export const Group = ({ memberCountFromSecretKeyData !== members?.memberCount && newEncryptionNotification?.text?.data?.numberOfMembers !== members?.memberCount; - + if (isDiffMemberNumber) return true; const latestJoined = members?.members.reduce((maxJoined, current) => { return current.joined > maxJoined ? current.joined : maxJoined; }, members?.members[0].joined); - + if ( secretKeyPublishDate < latestJoined && newEncryptionNotification?.data?.timestamp < latestJoined @@ -835,7 +872,7 @@ export const Group = ({ try { setIsLoadingNotifyAdmin(true); await new Promise((res, rej) => { - chrome.runtime.sendMessage( + chrome?.runtime?.sendMessage( { action: "notifyAdminRegenerateSecretKey", payload: { @@ -844,7 +881,6 @@ export const Group = ({ }, }, (response) => { - if (!response?.error) { res(response); } @@ -882,7 +918,6 @@ export const Group = ({ }, [timestampEnterData, selectedGroup]); const isUnread = useMemo(() => { - if (!selectedGroup) return false; return ( groupAnnouncements?.[selectedGroup?.groupId]?.seentimestamp === false @@ -893,7 +928,7 @@ export const Group = ({ if (isLoadingOpenSectionFromNotification.current) return; isLoadingOpenSectionFromNotification.current = true; const directAddress = e.detail?.from; - + const findDirect = directs?.find( (direct) => direct?.address === directAddress ); @@ -908,7 +943,7 @@ export const Group = ({ setNewChat(false); - chrome.runtime.sendMessage({ + chrome?.runtime?.sendMessage({ action: "addTimestampEnterChat", payload: { timestamp: Date.now(), @@ -937,7 +972,7 @@ export const Group = ({ const resetAllStatesAndRefs = () => { // Reset all useState values to their initial states setSecretKey(null); - lastFetchedSecretKey.current = null + lastFetchedSecretKey.current = null; setSecretKeyPublishDate(null); setSecretKeyDetails(null); setNewEncryptionNotification(null); @@ -954,7 +989,7 @@ export const Group = ({ setOpenAddGroup(false); setIsInitialGroups(false); setOpenManageMembers(false); - setMemberGroups([]); // Assuming you're clearing the context here as well + setMemberGroups([]); // Assuming you're clearing the context here as well setTimestampEnterData({}); setChatMode("groups"); setNewChat(false); @@ -967,7 +1002,7 @@ export const Group = ({ setGroupSection("home"); setGroupAnnouncements({}); setDefaultThread(null); - + // Reset all useRef values to their initial states hasInitialized.current = false; hasInitializedWebsocket.current = false; @@ -981,12 +1016,11 @@ export const Group = ({ setupGroupWebsocketInterval.current = null; settimeoutForRefetchSecretKey.current = null; }; - - const logoutEventFunc = ()=> { - resetAllStatesAndRefs() - clearStatesMessageQueueProvider() - } + const logoutEventFunc = () => { + resetAllStatesAndRefs(); + clearStatesMessageQueueProvider(); + }; useEffect(() => { subscribeToEvent("logout-event", logoutEventFunc); @@ -1013,7 +1047,7 @@ export const Group = ({ setNewChat(false); setSecretKey(null); - lastFetchedSecretKey.current = null + lastFetchedSecretKey.current = null; setSecretKeyPublishDate(null); setAdmins([]); setSecretKeyDetails(null); @@ -1021,10 +1055,10 @@ export const Group = ({ setMembers([]); setMemberCountFromSecretKeyData(null); setTriedToFetchSecretKey(false); - setFirstSecretKeyInCreation(false) + setFirstSecretKeyInCreation(false); setGroupSection("chat"); - chrome.runtime.sendMessage({ + chrome?.runtime?.sendMessage({ action: "addTimestampEnterChat", payload: { timestamp: Date.now(), @@ -1052,7 +1086,6 @@ export const Group = ({ }, [groups, selectedGroup]); const openGroupAnnouncementFromNotification = (e) => { - const groupId = e.detail?.from; const findGroup = groups?.find((group) => +group?.groupId === +groupId); @@ -1061,7 +1094,7 @@ export const Group = ({ setChatMode("groups"); setSelectedGroup(null); setSecretKey(null); - lastFetchedSecretKey.current = null + lastFetchedSecretKey.current = null; setSecretKeyPublishDate(null); setAdmins([]); setSecretKeyDetails(null); @@ -1069,9 +1102,9 @@ export const Group = ({ setMembers([]); setMemberCountFromSecretKeyData(null); setTriedToFetchSecretKey(false); - setFirstSecretKeyInCreation(false) + setFirstSecretKeyInCreation(false); setGroupSection("announcement"); - chrome.runtime.sendMessage({ + chrome?.runtime?.sendMessage({ action: "addGroupNotificationTimestamp", payload: { timestamp: Date.now(), @@ -1118,7 +1151,7 @@ export const Group = ({ setChatMode("groups"); setSelectedGroup(null); setSecretKey(null); - lastFetchedSecretKey.current = null + lastFetchedSecretKey.current = null; setSecretKeyPublishDate(null); setAdmins([]); setSecretKeyDetails(null); @@ -1126,7 +1159,7 @@ export const Group = ({ setMembers([]); setMemberCountFromSecretKeyData(null); setTriedToFetchSecretKey(false); - setFirstSecretKeyInCreation(false) + setFirstSecretKeyInCreation(false); setGroupSection("forum"); setDefaultThread(data); @@ -1146,15 +1179,431 @@ export const Group = ({ }; }, [groups, selectedGroup]); - const handleSecretKeyCreationInProgress = ()=> { - setFirstSecretKeyInCreation(true) + const handleSecretKeyCreationInProgress = () => { + setFirstSecretKeyInCreation(true); + }; + + const goToHome = async ()=> { + setGroupSection("default"); + clearAllQueues(); + await new Promise((res) => { + setTimeout(() => { + res(null); + }, 200); + }); + setGroupSection("home"); + setSelectedGroup(null); + setNewChat(false); + setSelectedDirect(null); + setSecretKey(null); + lastFetchedSecretKey.current = null; + setSecretKeyPublishDate(null); + setAdmins([]); + setSecretKeyDetails(null); + setAdminsWithNames([]); + setMembers([]); + setMemberCountFromSecretKeyData(null); + setTriedToFetchSecretKey(false); + setFirstSecretKeyInCreation(false); } + const goToAnnouncements = async ()=> { + setGroupSection("default"); + await new Promise((res) => { + setTimeout(() => { + res(null); + }, 200); + }); + setGroupSection("announcement"); + chrome?.runtime?.sendMessage({ + action: "addGroupNotificationTimestamp", + payload: { + timestamp: Date.now(), + groupId: selectedGroupRef.current.groupId, + }, + }); + setTimeout(() => { + getGroupAnnouncements(); + }, 200); + } + const goToChat = async ()=> { + setGroupSection("default"); + await new Promise((res) => { + setTimeout(() => { + res(null); + }, 200); + }); + setGroupSection("chat"); + if (selectedGroupRef.current) { + chrome?.runtime?.sendMessage({ + action: "addTimestampEnterChat", + payload: { + timestamp: Date.now(), + groupId: selectedGroupRef.current.groupId, + }, + }); + + setTimeout(() => { + getTimestampEnterChat(); + }, 200); + } + } + + const renderGroups = ()=> { + return ( +
+
+ {isMobile && ( + { + setIsOpenDrawer(false) + }} sx={{ + cursor: 'pointer', + color: 'white' + }} /> + )} + { + setChatMode((prev) => + prev === "directs" ? "groups" : "directs" + ); + setNewChat(false); + setSelectedDirect(null); + setSelectedGroup(null); + setGroupSection("default"); + }} + > + {chatMode === "groups" && ( + <> + + + )} + {chatMode === "directs" ? "Switch to groups" : "Direct msgs"} + +
+
+ {directs.map((direct: any) => ( + + + // + // + // } + onClick={() => { + setSelectedDirect(null); + setNewChat(false); + setSelectedGroup(null); + setIsOpenDrawer(false) + chrome?.runtime?.sendMessage({ + action: "addTimestampEnterChat", + payload: { + timestamp: Date.now(), + groupId: direct.address, + }, + }); + setTimeout(() => { + setSelectedDirect(direct); + + getTimestampEnterChat(); + }, 200); + }} + sx={{ + display: "flex", + width: "100%", + flexDirection: "column", + cursor: "pointer", + border: "1px #232428 solid", + padding: "2px", + borderRadius: "2px", + background: + direct?.address === selectedDirect?.address && "white", + }} + > + + + + {(direct?.name || direct?.address)?.charAt(0)} + + + + {direct?.sender !== myAddress && + direct?.timestamp && + ((!timestampEnterData[direct?.address] && + Date.now() - direct?.timestamp < + timeDifferenceForNotificationChats) || + timestampEnterData[direct?.address] < + direct?.timestamp) && ( + + )} + + + + ))} +
+
+ {groups.map((group: any) => ( + + + // + // + // } + onClick={() => { + clearAllQueues(); + setSelectedDirect(null); + + setNewChat(false); + setSelectedGroup(null); + setSecretKey(null); + lastFetchedSecretKey.current = null; + setSecretKeyPublishDate(null); + setAdmins([]); + setSecretKeyDetails(null); + setAdminsWithNames([]); + setMembers([]); + setMemberCountFromSecretKeyData(null); + setTriedToFetchSecretKey(false); + setFirstSecretKeyInCreation(false); + setGroupSection("announcement"); + setIsOpenDrawer(false) + setTimeout(() => { + setSelectedGroup(group); + + getTimestampEnterChat(); + }, 200); + + if (groupSectionRef.current === "announcement") { + chrome?.runtime?.sendMessage({ + action: "addGroupNotificationTimestamp", + payload: { + timestamp: Date.now(), + groupId: group.groupId, + }, + }); + } + + setTimeout(() => { + getGroupAnnouncements(); + }, 600); + }} + sx={{ + display: "flex", + width: "100%", + flexDirection: "column", + cursor: "pointer", + border: "1px #232428 solid", + padding: "2px", + borderRadius: "2px", + background: + group?.groupId === selectedGroup?.groupId && "white", + }} + > + + + + {group.groupName?.charAt(0)} + + + + {groupAnnouncements[group?.groupId] && + !groupAnnouncements[group?.groupId]?.seentimestamp && ( + + )} + {group?.sender !== myAddress && + group?.timestamp && + ((!timestampEnterData[group?.groupId] && + Date.now() - group?.timestamp < + timeDifferenceForNotificationChats) || + timestampEnterData[group?.groupId] < + group?.timestamp) && ( + + )} + + + + ))} +
+
+ {chatMode === "groups" && ( + { + setOpenAddGroup(true); + }} + > + + Add Group + + )} + {chatMode === "directs" && ( + { + setNewChat(true); + setSelectedDirect(null); + setSelectedGroup(null); + }} + > + + New Chat + + )} +
+
+ ) + } return ( <> - + -
-
- { - setChatMode((prev) => - prev === "directs" ? "groups" : "directs" - ); - setNewChat(false); - setSelectedDirect(null); - setSelectedGroup(null); - setGroupSection("default"); - }} - > - {chatMode === "groups" && ( - <> - - - )} - {chatMode === "directs" ? "Switch to groups" : "Direct msgs"} - -
-
- {directs.map((direct: any) => ( - - - // - // - // } - onClick={() => { - setSelectedDirect(null); - setNewChat(false); - setSelectedGroup(null); - chrome.runtime.sendMessage({ - action: "addTimestampEnterChat", - payload: { - timestamp: Date.now(), - groupId: direct.address, - }, - }); - setTimeout(() => { - setSelectedDirect(direct); - - getTimestampEnterChat(); - }, 200); - }} - sx={{ - display: "flex", - width: "100%", - flexDirection: "column", - cursor: "pointer", - border: "1px #232428 solid", - padding: "2px", - borderRadius: "2px", - background: - direct?.address === selectedDirect?.address && "white", - }} - > - - - - {(direct?.name || direct?.address)?.charAt(0)} - - - - {direct?.sender !== myAddress && - direct?.timestamp && - ((!timestampEnterData[direct?.address] && - Date.now() - direct?.timestamp < - timeDifferenceForNotificationChats) || - timestampEnterData[direct?.address] < - direct?.timestamp) && ( - - )} - - - - ))} -
-
- {groups.map((group: any) => ( - - - // - // - // } - onClick={() => { - clearAllQueues() - setSelectedDirect(null); - - setNewChat(false); - setSelectedGroup(null); - setSecretKey(null); - lastFetchedSecretKey.current = null - setSecretKeyPublishDate(null); - setAdmins([]); - setSecretKeyDetails(null); - setAdminsWithNames([]); - setMembers([]); - setMemberCountFromSecretKeyData(null); - setTriedToFetchSecretKey(false); - setFirstSecretKeyInCreation(false) - setGroupSection("announcement"); - - setTimeout(() => { - setSelectedGroup(group); - - getTimestampEnterChat(); - }, 200); - - if (groupSectionRef.current === "announcement") { - chrome.runtime.sendMessage({ - action: "addGroupNotificationTimestamp", - payload: { - timestamp: Date.now(), - groupId: group.groupId, - }, - }); - } - - setTimeout(() => { - getGroupAnnouncements(); - }, 600); - }} - sx={{ - display: "flex", - width: "100%", - flexDirection: "column", - cursor: "pointer", - border: "1px #232428 solid", - padding: "2px", - borderRadius: "2px", - background: - group?.groupId === selectedGroup?.groupId && "white", - }} - > - - - - {group.groupName?.charAt(0)} - - - - {groupAnnouncements[group?.groupId] && - !groupAnnouncements[group?.groupId]?.seentimestamp && ( - - )} - {group?.sender !== myAddress && - group?.timestamp && - ((!timestampEnterData[group?.groupId] && - Date.now() - group?.timestamp < - timeDifferenceForNotificationChats) || - timestampEnterData[group?.groupId] < - group?.timestamp) && ( - - )} - - - - ))} -
-
- {chatMode === "groups" && ( - { - setOpenAddGroup(true); - }} - > - - Add Group - - )} - {chatMode === "directs" && ( - { - setNewChat(true); - setSelectedDirect(null); - setSelectedGroup(null); - }} - > - - New Chat - - )} -
-
+ {!isMobile && renderGroups()} - {triedToFetchSecretKey && ( + {triedToFetchSecretKey && ( + myAddress={myAddress} + selectedGroup={selectedGroup?.groupId} + getSecretKey={getSecretKey} + secretKey={secretKey} + setSecretKey={setSecretKey} + handleNewEncryptionNotification={setNewEncryptionNotification} + hide={groupSection !== "chat" || !secretKey} + handleSecretKeyCreationInProgress={ + handleSecretKeyCreationInProgress + } + triedToFetchSecretKey={triedToFetchSecretKey} + myName={userInfo?.name} + /> )} - {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... - -
- )} - {!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. + 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... - - - Try notifying an admin from the list of admins below: - - - {adminsWithNames.map((admin) => { - - return ( - - {admin?.name} - notifyAdmin(admin)} - > - Notify - - - ); - })}
- ) : null} + )} + {!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. + + + + Try notifying an admin from the list of admins below: + + + {adminsWithNames.map((admin) => { + return ( + + {admin?.name} + notifyAdmin(admin)} + > + Notify + + + ); + })} +
+ ) : null} - ) : admins.includes(myAddress) && !secretKey && triedToFetchSecretKey ? null : !triedToFetchSecretKey ? null : ( <> - - {admins.includes(myAddress) && shouldReEncrypt && - triedToFetchSecretKey && !firstSecretKeyInCreation && ( + triedToFetchSecretKey && + !firstSecretKeyInCreation && ( )} @@ -1686,8 +1808,6 @@ export const Group = ({ isOwner={groupOwner?.owner === myAddress} /> )} - - )} @@ -1721,6 +1841,8 @@ export const Group = ({ width: "100%", flexDirection: "column", gap: "20px", + height: '100%', + overflow: 'auto' }} > )} - + + + + + Home + + + {selectedGroup && ( + <> { - setGroupSection("default"); - clearAllQueues() - await new Promise((res) => { - setTimeout(() => { - res(null); - }, 200); - }); - setGroupSection("home"); - setSelectedGroup(null); - setNewChat(false); - setSelectedDirect(null); - setSecretKey(null); - lastFetchedSecretKey.current = null - setSecretKeyPublishDate(null); - setAdmins([]); - setSecretKeyDetails(null); - setAdminsWithNames([]); - setMembers([]); - setMemberCountFromSecretKeyData(null); - setTriedToFetchSecretKey(false); - setFirstSecretKeyInCreation(false) - }} - > - - - Home - - - {selectedGroup && ( - <> - - { - setGroupSection("default"); - await new Promise((res) => { - setTimeout(() => { - res(null); - }, 200); - }); - setGroupSection("announcement"); - chrome.runtime.sendMessage({ - action: "addGroupNotificationTimestamp", - payload: { - timestamp: Date.now(), - groupId: selectedGroupRef.current.groupId, - }, - }); - setTimeout(() => { - getGroupAnnouncements(); - }, 200); + cursor: "pointer", }} + onClick={goToAnnouncements} > Announcements @@ -1899,33 +1981,11 @@ export const Group = ({ alignItems: "center", justifyContent: "flex-start", width: "100%", - cursor: 'pointer' - }} - onClick={async () => { - setGroupSection("default"); - await new Promise((res) => { - setTimeout(() => { - res(null); - }, 200); - }); - setGroupSection("chat"); - if (selectedGroupRef.current) { - chrome.runtime.sendMessage({ - action: "addTimestampEnterChat", - payload: { - timestamp: Date.now(), - groupId: selectedGroupRef.current.groupId, - }, - }); - - setTimeout(() => { - getTimestampEnterChat(); - }, 200); - } + cursor: "pointer", }} + onClick={goToChat} > Chat @@ -1959,14 +2019,13 @@ export const Group = ({ alignItems: "center", justifyContent: "flex-start", width: "100%", - cursor: 'pointer' + cursor: "pointer", }} onClick={() => { setGroupSection("forum"); }} > setOpenManageMembers(true)} + onClick={() => setOpenManageMembers(true)} sx={{ display: "flex", gap: "3px", alignItems: "center", justifyContent: "flex-start", width: "100%", - cursor: 'pointer' + cursor: "pointer", }} > - - + Members - - )} - - {/* + )} + + {/* */} - + -
+ {renderGroups()} + + + + {isMobile && ( + + + {selectedGroup && ( + <> + + + + + + + + + + + + + + )} + + {/* Second row: Groups, Home, Profile */} + + + + + + + + + + setIsOpenDrawerProfile(true)} + > + + + + + + +)} + + ); }; diff --git a/src/components/Group/InviteMember.tsx b/src/components/Group/InviteMember.tsx index 5a22678..12efdda 100644 --- a/src/components/Group/InviteMember.tsx +++ b/src/components/Group/InviteMember.tsx @@ -26,7 +26,7 @@ export const InviteMember = ({ groupId, setInfoSnack, setOpenSnack, show }) => { setIsLoadingInvite(true) if (!expiryTime || !value) return; new Promise((res, rej) => { - chrome.runtime.sendMessage( + chrome?.runtime?.sendMessage( { action: "inviteToGroup", payload: { diff --git a/src/components/Group/ListOfBans.tsx b/src/components/Group/ListOfBans.tsx index 6cd1236..b25d21e 100644 --- a/src/components/Group/ListOfBans.tsx +++ b/src/components/Group/ListOfBans.tsx @@ -74,7 +74,7 @@ export const ListOfBans = ({ groupId, setInfoSnack, setOpenSnack, show }) => { }) setIsLoadingUnban(true) new Promise((res, rej)=> { - chrome.runtime.sendMessage({ action: "cancelBan", payload: { + chrome?.runtime?.sendMessage({ action: "cancelBan", payload: { groupId, qortalAddress: address, }}, (response) => { diff --git a/src/components/Group/ListOfInvites.tsx b/src/components/Group/ListOfInvites.tsx index b6a9734..ff6359e 100644 --- a/src/components/Group/ListOfInvites.tsx +++ b/src/components/Group/ListOfInvites.tsx @@ -75,7 +75,7 @@ export const ListOfInvites = ({ groupId, setInfoSnack, setOpenSnack, show }) => }) setIsLoadingCancelInvite(true) await new Promise((res, rej)=> { - chrome.runtime.sendMessage({ action: "cancelInvitationToGroup", payload: { + chrome?.runtime?.sendMessage({ action: "cancelInvitationToGroup", payload: { groupId, qortalAddress: address, }}, (response) => { diff --git a/src/components/Group/ListOfJoinRequests.tsx b/src/components/Group/ListOfJoinRequests.tsx index 160a7ca..cb47ab9 100644 --- a/src/components/Group/ListOfJoinRequests.tsx +++ b/src/components/Group/ListOfJoinRequests.tsx @@ -74,7 +74,7 @@ export const ListOfJoinRequests = ({ groupId, setInfoSnack, setOpenSnack, show } }) setIsLoadingAccept(true) await new Promise((res, rej)=> { - chrome.runtime.sendMessage({ action: "inviteToGroup", payload: { + chrome?.runtime?.sendMessage({ action: "inviteToGroup", payload: { groupId, qortalAddress: address, inviteTime: 10800, diff --git a/src/components/Group/ListOfMembers.tsx b/src/components/Group/ListOfMembers.tsx index 3662a91..6a81cf0 100644 --- a/src/components/Group/ListOfMembers.tsx +++ b/src/components/Group/ListOfMembers.tsx @@ -63,7 +63,7 @@ const ListOfMembers = ({ setIsLoadingKick(true); new Promise((res, rej) => { - chrome.runtime.sendMessage( + chrome?.runtime?.sendMessage( { action: "kickFromGroup", payload: { @@ -107,7 +107,7 @@ const ListOfMembers = ({ }); setIsLoadingBan(true); await new Promise((res, rej) => { - chrome.runtime.sendMessage( + chrome?.runtime?.sendMessage( { action: "banFromGroup", payload: { @@ -153,7 +153,7 @@ const ListOfMembers = ({ }); setIsLoadingMakeAdmin(true); await new Promise((res, rej) => { - chrome.runtime.sendMessage( + chrome?.runtime?.sendMessage( { action: "makeAdmin", payload: { @@ -198,7 +198,7 @@ const ListOfMembers = ({ }); setIsLoadingRemoveAdmin(true); await new Promise((res, rej) => { - chrome.runtime.sendMessage( + chrome?.runtime?.sendMessage( { action: "removeAdmin", payload: { diff --git a/src/components/Group/ListOfThreadPostsWatched.tsx b/src/components/Group/ListOfThreadPostsWatched.tsx index ed8e7d9..b22be24 100644 --- a/src/components/Group/ListOfThreadPostsWatched.tsx +++ b/src/components/Group/ListOfThreadPostsWatched.tsx @@ -23,7 +23,7 @@ export const ListOfThreadPostsWatched = () => { const getPosts = async ()=> { try { await new Promise((res, rej) => { - chrome.runtime.sendMessage( + chrome?.runtime?.sendMessage( { action: "getThreadActivity", payload: { diff --git a/src/components/Group/ManageMembers.tsx b/src/components/Group/ManageMembers.tsx index aebb3fb..57e5712 100644 --- a/src/components/Group/ManageMembers.tsx +++ b/src/components/Group/ManageMembers.tsx @@ -77,7 +77,7 @@ export const ManageMembers = ({ }) await new Promise((res, rej) => { - chrome.runtime.sendMessage( + chrome?.runtime?.sendMessage( { action: "leaveGroup", payload: { diff --git a/src/components/Group/UserListOfInvites.tsx b/src/components/Group/UserListOfInvites.tsx index d126024..98f37f1 100644 --- a/src/components/Group/UserListOfInvites.tsx +++ b/src/components/Group/UserListOfInvites.tsx @@ -85,7 +85,7 @@ export const UserListOfInvites = ({myAddress, setInfoSnack, setOpenSnack}) => { setIsLoading(true); await new Promise((res, rej)=> { - chrome.runtime.sendMessage({ action: "joinGroup", payload: { + chrome?.runtime?.sendMessage({ action: "joinGroup", payload: { groupId, }}, (response) => { diff --git a/src/components/Group/WebsocketActive.tsx b/src/components/Group/WebsocketActive.tsx index 055f590..33a6dca 100644 --- a/src/components/Group/WebsocketActive.tsx +++ b/src/components/Group/WebsocketActive.tsx @@ -74,7 +74,7 @@ export const WebSocketActive = ({ myAddress, setIsLoadingGroups }) => { ).sort((a, b) => (b.timestamp || 0) - (a.timestamp || 0)); - chrome.runtime.sendMessage({ + chrome?.runtime?.sendMessage({ action: 'handleActiveGroupDataFromSocket', payload: { groups: sortedGroups, diff --git a/src/index.css b/src/index.css index 853afa4..543bec2 100644 --- a/src/index.css +++ b/src/index.css @@ -80,4 +80,8 @@ body { .group-list::-webkit-scrollbar-thumb:hover { background-color: whitesmoke; +} + +html, body { + overscroll-behavior:none !important; } \ No newline at end of file