diff --git a/src/App.tsx b/src/App.tsx index 777c25e..6678580 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -47,6 +47,7 @@ import Info from "./assets/svgs/Info.svg"; import CloseIcon from "@mui/icons-material/Close"; import './utils/seedPhrase/RandomSentenceGenerator'; import EngineeringIcon from '@mui/icons-material/Engineering'; +import AccountBalanceWalletIcon from '@mui/icons-material/AccountBalanceWallet'; import { createAccount, generateRandomSentence, @@ -1698,13 +1699,46 @@ function App() { /> + + { + executeEvent('openWalletsApp', {}) + }} + > + WALLETS} + placement="left" + arrow + sx={{ fontSize: "24" }} + slotProps={{ + tooltip: { + sx: { + color: "#ffffff", + backgroundColor: "#444444", + }, + }, + arrow: { + sx: { + color: "#444444", + }, + }, + }} + > + + + + {desktopViewMode !== 'home' && ( <> WALLET} + title={YOUR ACCOUNT} placement="left" arrow sx={{ fontSize: "24" }} @@ -1733,75 +1767,7 @@ function App() { )} - {/* {authenticatedMode === "qort" && ( - LITECOIN WALLET} - placement="left" - arrow - sx={{ fontSize: "24" }} - slotProps={{ - tooltip: { - sx: { - color: "#ffffff", - backgroundColor: "#444444", - }, - }, - arrow: { - sx: { - color: "#444444", - }, - }, - }} - > - { - if(desktopViewMode !== 'home'){ - setIsOpenDrawerProfile((prev)=> !prev) - } - setAuthenticatedMode("ltc"); - }} - src={ltcLogo} - style={{ - cursor: "pointer", - width: "20px", - height: "auto", - }} - /> - - )} - {authenticatedMode === "ltc" && ( - QORTAL WALLET} - placement="left" - arrow - sx={{ fontSize: "24" }} - slotProps={{ - tooltip: { - sx: { - color: "#ffffff", - backgroundColor: "#444444", - }, - }, - arrow: { - sx: { - color: "#444444", - }, - }, - }} - > - { - setAuthenticatedMode("qort"); - }} - src={qortLogo} - style={{ - cursor: "pointer", - width: "20px", - height: "auto", - }} - /> - - )} */} + diff --git a/src/atoms/global.ts b/src/atoms/global.ts index f1946ef..d546bf0 100644 --- a/src/atoms/global.ts +++ b/src/atoms/global.ts @@ -38,6 +38,10 @@ export const sortablePinnedAppsAtom = atom({ { name: 'Q-Mintership', service: 'APP' + }, + { + name: 'Q-Wallets', + service: 'APP' } ], }); diff --git a/src/components/Apps/AppViewer.tsx b/src/components/Apps/AppViewer.tsx index 902c6d8..cd9cf94 100644 --- a/src/components/Apps/AppViewer.tsx +++ b/src/components/Apps/AppViewer.tsx @@ -11,11 +11,11 @@ import { useQortalMessageListener } from "./useQortalMessageListener"; -export const AppViewer = React.forwardRef(({ app , hide, isDevMode}, iframeRef) => { +export const AppViewer = React.forwardRef(({ app , hide, isDevMode, skipAuth}, iframeRef) => { const { rootHeight } = useContext(MyContext); // const iframeRef = useRef(null); const { document, window: frameWindow } = useFrame(); - const {path, history, changeCurrentIndex, resetHistory} = useQortalMessageListener(frameWindow, iframeRef, app?.tabId, isDevMode, app?.name, app?.service) + const {path, history, changeCurrentIndex, resetHistory} = useQortalMessageListener(frameWindow, iframeRef, app?.tabId, isDevMode, app?.name, app?.service, skipAuth) const [url, setUrl] = useState('') diff --git a/src/components/Apps/AppViewerContainer.tsx b/src/components/Apps/AppViewerContainer.tsx index 674a9a7..f258848 100644 --- a/src/components/Apps/AppViewerContainer.tsx +++ b/src/components/Apps/AppViewerContainer.tsx @@ -3,7 +3,7 @@ import { AppViewer } from './AppViewer'; import Frame from 'react-frame-component'; import { MyContext, isMobile } from '../../App'; -const AppViewerContainer = React.forwardRef(({ app, isSelected, hide, isDevMode, customHeight }, ref) => { +const AppViewerContainer = React.forwardRef(({ app, isSelected, hide, isDevMode, customHeight, skipAuth }, ref) => { const { rootHeight } = useContext(MyContext); @@ -42,7 +42,7 @@ const AppViewerContainer = React.forwardRef(({ app, isSelected, hide, isDevMode, overflow: 'hidden', }} > - + ); }); diff --git a/src/components/Apps/AppsCategory.tsx b/src/components/Apps/AppsCategory.tsx index 725ff1d..d1a1420 100644 --- a/src/components/Apps/AppsCategory.tsx +++ b/src/components/Apps/AppsCategory.tsx @@ -40,7 +40,8 @@ const officialAppList = [ "q-shop", "q-trade", "q-support", - "q-manager" + "q-manager", + "q-wallets" ]; const ScrollerStyled = styled('div')({ diff --git a/src/components/Apps/AppsCategoryDesktop.tsx b/src/components/Apps/AppsCategoryDesktop.tsx index d41207a..f6ba48d 100644 --- a/src/components/Apps/AppsCategoryDesktop.tsx +++ b/src/components/Apps/AppsCategoryDesktop.tsx @@ -48,7 +48,8 @@ const officialAppList = [ "q-shop", "q-trade", "q-support", - "q-manager" + "q-manager", + "q-wallets" ]; const ScrollerStyled = styled("div")({ diff --git a/src/components/Apps/AppsLibrary.tsx b/src/components/Apps/AppsLibrary.tsx index 26e7d81..f9b58ea 100644 --- a/src/components/Apps/AppsLibrary.tsx +++ b/src/components/Apps/AppsLibrary.tsx @@ -42,7 +42,8 @@ const officialAppList = [ "q-shop", "q-trade", "q-support", - "q-manager" + "q-manager", + "q-wallets" ]; const ScrollerStyled = styled('div')({ diff --git a/src/components/Apps/AppsLibraryDesktop.tsx b/src/components/Apps/AppsLibraryDesktop.tsx index b836ac8..de356d4 100644 --- a/src/components/Apps/AppsLibraryDesktop.tsx +++ b/src/components/Apps/AppsLibraryDesktop.tsx @@ -58,7 +58,8 @@ const officialAppList = [ "q-trade", "q-support", "q-manager", - "q-mintership" + "q-mintership", + "q-wallets" ]; const ScrollerStyled = styled("div")({ diff --git a/src/components/Apps/useQortalMessageListener.tsx b/src/components/Apps/useQortalMessageListener.tsx index 508d5bc..6ff79ab 100644 --- a/src/components/Apps/useQortalMessageListener.tsx +++ b/src/components/Apps/useQortalMessageListener.tsx @@ -507,7 +507,7 @@ export const UIQortalRequests = [ return obj; // Updated object with references to stored files } -export const useQortalMessageListener = (frameWindow, iframeRef, tabId, isDevMode, appName, appService) => { +export const useQortalMessageListener = (frameWindow, iframeRef, tabId, isDevMode, appName, appService, skipAuth) => { const [path, setPath] = useState('') const [history, setHistory] = useState({ customQDNHistoryPaths: [], @@ -564,7 +564,7 @@ isDOMContentLoaded: false const sendMessageToRuntime = (message, eventPort) => { window.sendMessage(message.action, message.payload, 300000, message.isExtension, { name: appName, service: appService - }) + }, skipAuth) .then((response) => { if (response.error) { eventPort.postMessage({ @@ -633,6 +633,8 @@ isDOMContentLoaded: false window.sendMessage("addEnteredQmailTimestamp").catch((error) => { // error }); + } else if(appName?.toLowerCase() === 'q-wallets'){ + executeEvent('setLastEnteredTimestampPaymentEvent', {}) } } else if(event?.data?.action === 'NAVIGATION_HISTORY'){ if(event?.data?.payload?.isDOMContentLoaded){ diff --git a/src/components/Explore/Explore.tsx b/src/components/Explore/Explore.tsx index 7cc96a0..61037d7 100644 --- a/src/components/Explore/Explore.tsx +++ b/src/components/Explore/Explore.tsx @@ -4,6 +4,9 @@ import ChatIcon from "@mui/icons-material/Chat"; import qTradeLogo from "../../assets/Icons/q-trade-logo.webp"; import AppsIcon from "@mui/icons-material/Apps"; import { executeEvent } from "../../utils/events"; +import AccountBalanceWalletIcon from '@mui/icons-material/AccountBalanceWallet'; + + export const Explore = ({setDesktopViewMode}) => { return ( { General Chat + { + executeEvent("openWalletsApp", { + + }); + }} + > + + + Wallets + + ); }; diff --git a/src/components/GeneralNotifications.tsx b/src/components/GeneralNotifications.tsx index 532c0e6..c7336dc 100644 --- a/src/components/GeneralNotifications.tsx +++ b/src/components/GeneralNotifications.tsx @@ -13,6 +13,7 @@ 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); @@ -35,11 +36,31 @@ export const GeneralNotifications = ({ address }) => { }} style={{}} > + PAYMENT NOTIFICATION} + placement="left" + arrow + sx={{ fontSize: "24" }} + slotProps={{ + tooltip: { + sx: { + color: "#ffffff", + backgroundColor: "#444444", + }, + }, + arrow: { + sx: { + color: "#444444", + }, + }, + }} + > + { width: "100%", alignItems: "flex-start", textWrap: "auto", - cursor: 'default' }} - onClick={(e) => { - // executeEvent("addTab", { data: { service: 'APP', name: 'q-mail' } }); - // executeEvent("open-apps-mode", { }); + onClick={() => { + setAnchorEl(null) + executeEvent('openWalletsApp', {}) }} > { @@ -2579,6 +2580,7 @@ export const Group = ({ message: "Setting up groups... please wait.", }} /> + ); diff --git a/src/components/Group/WalletsAppWrapper.tsx b/src/components/Group/WalletsAppWrapper.tsx new file mode 100644 index 0000000..00218a7 --- /dev/null +++ b/src/components/Group/WalletsAppWrapper.tsx @@ -0,0 +1,163 @@ +import { Box, ButtonBase, Divider, Typography } from "@mui/material"; +import React, { + useCallback, + useEffect, + useMemo, + useRef, + useState, +} from "react"; +import CloseIcon from "@mui/icons-material/Close"; +import AppViewerContainer from "../Apps/AppViewerContainer"; +import { + executeEvent, + subscribeToEvent, + unsubscribeFromEvent, +} from "../../utils/events"; +import { useRecoilState } from "recoil"; +import { navigationControllerAtom } from "../../atoms/global"; +import { AppsNavBarLeft, AppsNavBarParent } from "../Apps/Apps-styles"; +import NavBack from "../../assets/svgs/NavBack.svg"; +import RefreshIcon from "@mui/icons-material/Refresh"; + +export const WalletsAppWrapper = () => { + const iframeRef = useRef(null); + const [isOpen, setIsOpen] = useState(false); + const [navigationController, setNavigationController] = useRecoilState( + navigationControllerAtom + ); + const [selectedTab, setSelectedTab] = useState({ + tabId: "5558589", + name: "Q-Wallets", + service: "APP", + path: '/qortal' + }); + + const isDisableBackButton = useMemo(() => { + if (selectedTab && navigationController[selectedTab?.tabId]?.hasBack) + return false; + if (selectedTab && !navigationController[selectedTab?.tabId]?.hasBack) + return true; + return false; + }, [navigationController, selectedTab]); + + const openWalletsAppFunc = useCallback( + (e) => { + setIsOpen(true); + }, + [setIsOpen] + ); + + useEffect(() => { + subscribeToEvent("openWalletsApp", openWalletsAppFunc); + + return () => { + unsubscribeFromEvent("openWalletsApp", openWalletsAppFunc); + }; + }, [openWalletsAppFunc]); + + const handleClose = ()=> { + setIsOpen(false); + iframeRef.current = null + } + + return ( + <> + {isOpen && ( + + + + Q-Wallets + + + + + + + + + { + executeEvent(`navigateBackApp-${selectedTab?.tabId}`, {}); + }} + disabled={isDisableBackButton} + sx={{ + opacity: !isDisableBackButton ? 1 : 0.1, + cursor: !isDisableBackButton ? "pointer" : "default", + }} + > + + + { + if (selectedTab?.refreshFunc) { + selectedTab.refreshFunc(selectedTab?.tabId); + + } else { + executeEvent("refreshApp", { + tabId: selectedTab?.tabId, + }); + } + + + }}> + + + + + + + )} + + ); +}; diff --git a/src/hooks/useHandlePaymentNotification.tsx b/src/hooks/useHandlePaymentNotification.tsx index cfed663..b5df816 100644 --- a/src/hooks/useHandlePaymentNotification.tsx +++ b/src/hooks/useHandlePaymentNotification.tsx @@ -4,6 +4,7 @@ import { getData, storeData } from '../utils/chromeStorage'; import { checkDifference, getNameInfoForOthers } from '../background'; import { useRecoilState } from 'recoil'; import { lastPaymentSeenTimestampAtom } from '../atoms/global'; +import { subscribeToEvent, unsubscribeFromEvent } from '../utils/events'; export const useHandlePaymentNotification = (address) => { const [latestTx, setLatestTx] = useState(null); @@ -106,6 +107,21 @@ export const useHandlePaymentNotification = (address) => { window.removeEventListener("message", messageHandler); }; }, [getLastSeenData]); + + const setLastEnteredTimestampPaymentEventFunc = useCallback( + (e) => { + setLastEnteredTimestampPayment(Date.now) + }, + [setLastEnteredTimestampPayment] + ); + + useEffect(() => { + subscribeToEvent("setLastEnteredTimestampPaymentEvent", setLastEnteredTimestampPaymentEventFunc); + + return () => { + unsubscribeFromEvent("setLastEnteredTimestampPaymentEvent", setLastEnteredTimestampPaymentEventFunc); + }; + }, [setLastEnteredTimestampPaymentEventFunc]); return { latestTx, getNameOrAddressOfSenderMiddle, diff --git a/src/messaging/messagesToBackground.tsx b/src/messaging/messagesToBackground.tsx index 7da16d4..0ba8f71 100644 --- a/src/messaging/messagesToBackground.tsx +++ b/src/messaging/messagesToBackground.tsx @@ -24,13 +24,13 @@ window.addEventListener("message", (event) => { } }); -export const sendMessageBackground = (action, data = {}, timeout = 180000, isExtension, appInfo) => { +export const sendMessageBackground = (action, data = {}, timeout = 180000, isExtension, appInfo, skipAuth) => { return new Promise((resolve, reject) => { const requestId = generateRequestId(); // Unique ID for each request callbackMap.set(requestId, { resolve, reject }); // Store both resolve and reject callbacks const targetOrigin = window.location.origin // Send the message with `backgroundMessage` type - window.postMessage({ type: "backgroundMessage", action, requestId, payload: data, isExtension, appInfo }, targetOrigin); + window.postMessage({ type: "backgroundMessage", action, requestId, payload: data, isExtension, appInfo, skipAuth }, targetOrigin); // Set up a timeout to automatically reject if no response is received const timeoutId = setTimeout(() => { diff --git a/src/qortalRequests.ts b/src/qortalRequests.ts index b2848c4..18457da 100644 --- a/src/qortalRequests.ts +++ b/src/qortalRequests.ts @@ -70,6 +70,7 @@ export const isRunningGateway = async ()=> { // Ensure the message is from a trusted source const isFromExtension = request?.isExtension; const appInfo = request?.appInfo; + const skipAuth = request?.skipAuth || false if (request?.type !== "backgroundMessage") return; // Only process messages of type 'backgroundMessage' @@ -77,7 +78,7 @@ export const isRunningGateway = async ()=> { switch (request.action) { case "GET_USER_ACCOUNT": { try { - const res = await getUserAccount({isFromExtension, appInfo}); + const res = await getUserAccount({isFromExtension, appInfo, skipAuth}); event.source.postMessage({ requestId: request.requestId, action: request.action, diff --git a/src/qortalRequests/get.ts b/src/qortalRequests/get.ts index 66e3006..30fd805 100644 --- a/src/qortalRequests/get.ts +++ b/src/qortalRequests/get.ts @@ -371,7 +371,7 @@ async function getUserPermission(payload, isFromExtension) { }); } -export const getUserAccount = async ({ isFromExtension, appInfo }) => { +export const getUserAccount = async ({ isFromExtension, appInfo, skipAuth }) => { try { const value = (await getPermission(`qAPPAutoAuth-${appInfo?.name}`)) || false; @@ -379,6 +379,9 @@ export const getUserAccount = async ({ isFromExtension, appInfo }) => { if (value) { skip = true; } + if(skipAuth){ + skip = true + } let resPermission; if (!skip) { resPermission = await getUserPermission(