From 534301294e4de307637981154718b15ce08d191c Mon Sep 17 00:00:00 2001 From: PhilReact Date: Fri, 11 Apr 2025 15:56:46 +0300 Subject: [PATCH 01/55] give more info on block users --- src/atoms/global.ts | 5 + src/components/Group/BlockedUsersModal.tsx | 284 ++++++++++++++++----- src/components/Group/Group.tsx | 15 +- src/components/Group/useBlockUsers.tsx | 160 +++++++----- src/components/WrapperUserAction.tsx | 15 +- 5 files changed, 338 insertions(+), 141 deletions(-) diff --git a/src/atoms/global.ts b/src/atoms/global.ts index f05da75..443d833 100644 --- a/src/atoms/global.ts +++ b/src/atoms/global.ts @@ -177,4 +177,9 @@ export const mailsAtom = atom({ export const groupsPropertiesAtom = atom({ key: 'groupsPropertiesAtom', default: {}, +}); + +export const isOpenBlockedModalAtom = atom({ + key: 'isOpenBlockedModalAtom', + default: false, }); \ No newline at end of file diff --git a/src/components/Group/BlockedUsersModal.tsx b/src/components/Group/BlockedUsersModal.tsx index 84fa3fa..e81d207 100644 --- a/src/components/Group/BlockedUsersModal.tsx +++ b/src/components/Group/BlockedUsersModal.tsx @@ -10,15 +10,23 @@ import { Typography, } from "@mui/material"; import React, { useContext, useEffect, useState } from "react"; -import { MyContext } from "../../App"; +import { getBaseApiReact, MyContext } from "../../App"; import { Spacer } from "../../common/Spacer"; -import { executeEvent } from "../../utils/events"; - -export const BlockedUsersModal = ({ close }) => { +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 } = + useContext(MyContext); const [blockedUsers, setBlockedUsers] = useState({ addresses: {}, names: {}, @@ -28,60 +36,157 @@ 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) { + console.error(error); + } + }; + 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); + > + - - - + > + { + setValue(e.target.value); + }} + /> + + + {Object.entries(blockedUsers?.addresses).length > 0 && ( <> - Blocked Users for Chat ( addresses ) + Blocked addresses- blocks processing of txs + + )} - + {Object.entries(blockedUsers?.addresses || {})?.map( ([key, value]) => { return ( @@ -90,18 +195,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} + + + + {"Decide what to block"} + + + + Blocking {message?.userName || message?.userAddress} + + + Choose "block txs" or "all" to block chat messages + + + + + + + + ); }; diff --git a/src/components/Group/Group.tsx b/src/components/Group/Group.tsx index 64dc541..9f95a3a 100644 --- a/src/components/Group/Group.tsx +++ b/src/components/Group/Group.tsx @@ -75,9 +75,9 @@ 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 { addressInfoControllerAtom, groupsPropertiesAtom, isOpenBlockedModalAtom, selectedGroupIdAtom } from "../../atoms/global"; import { sortArrayByTimestampAndGroupName } from "../../utils/time"; -import BlockIcon from '@mui/icons-material/Block'; +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"; @@ -421,7 +421,7 @@ export const Group = ({ 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(""); @@ -2035,7 +2035,7 @@ export const Group = ({ padding: '10px' }} > - )} - {isOpenBlockedUserModal && ( - { - setIsOpenBlockedUserModal(false) - }} /> - )} + + {selectedDirect && !newChat && ( <> 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/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 { From 8f8b7fc0cdc4825705fdceb5c1581a95b1d086be Mon Sep 17 00:00:00 2001 From: PhilReact Date: Fri, 11 Apr 2025 20:19:03 +0300 Subject: [PATCH 02/55] error snack for blocked user --- src/components/Group/BlockedUsersModal.tsx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/components/Group/BlockedUsersModal.tsx b/src/components/Group/BlockedUsersModal.tsx index e81d207..24b3f01 100644 --- a/src/components/Group/BlockedUsersModal.tsx +++ b/src/components/Group/BlockedUsersModal.tsx @@ -25,7 +25,7 @@ export const BlockedUsersModal = () => { const [value, setValue] = useState(""); const [addressesWithNames, setAddressesWithNames] = useState({}) const { isShow, onCancel, onOk, show, message } = useModal(); - const { getAllBlockedUsers, removeBlockFromList, addToBlockList } = + const { getAllBlockedUsers, removeBlockFromList, addToBlockList, setOpenSnackGlobal, setInfoSnackCustom } = useContext(MyContext); const [blockedUsers, setBlockedUsers] = useState({ addresses: {}, @@ -115,7 +115,12 @@ export const BlockedUsersModal = () => { executeEvent('updateChatMessagesWithBlocks', true) } } catch (error) { - console.error(error); + setOpenSnackGlobal(true); + + setInfoSnackCustom({ + type: "error", + message: error?.message || "Unable to block user", + }); } }; const blockUserFromOutsideModalFunc = (e) => { From eb822cbcb470df9b861a4d63e0e5617308f597a1 Mon Sep 17 00:00:00 2001 From: PhilReact Date: Sun, 13 Apr 2025 18:10:09 +0300 Subject: [PATCH 03/55] added q-nodecontrol as default --- src/atoms/global.ts | 101 +++++++++++--------- src/components/Apps/AppsCategory.tsx | 3 +- src/components/Apps/AppsCategoryDesktop.tsx | 3 +- src/components/Apps/AppsLibrary.tsx | 25 ++--- src/components/Apps/AppsLibraryDesktop.tsx | 27 +++--- 5 files changed, 86 insertions(+), 73 deletions(-) diff --git a/src/atoms/global.ts b/src/atoms/global.ts index 443d833..7d0b3fc 100644 --- a/src/atoms/global.ts +++ b/src/atoms/global.ts @@ -2,52 +2,61 @@ import { atom, selectorFamily } from 'recoil'; export const sortablePinnedAppsAtom = atom({ - key: 'sortablePinnedAppsFromAtom', - default: [{ - name: 'Q-Tube', - service: 'APP' - }, { - name: 'Q-Mail', - service: 'APP' - }, { - name: 'Q-Share', - service: 'APP' - }, { - name: 'Q-Fund', - service: 'APP' - }, { - name: 'Q-Shop', - service: 'APP' - }, - { - name: 'Q-Trade', - service: 'APP' - }, - { - name: 'Q-Support', - service: 'APP' - }, - { - name: 'Q-Manager', - service: 'APP' - }, - { - name: 'Q-Blog', - service: 'APP' - }, - { - name: 'Q-Mintership', - service: 'APP' - }, - { - name: 'Q-Wallets', - service: 'APP' - }, - { - name: 'Q-Search', - service: 'APP' - }, -], + key: 'sortablePinnedAppsFromAtom', + default: [ + { + name: 'Q-Tube', + service: 'APP', + }, + { + name: 'Q-Mail', + service: 'APP', + }, + { + name: 'Q-Share', + service: 'APP', + }, + { + name: 'Q-Fund', + service: 'APP', + }, + { + name: 'Q-Shop', + service: 'APP', + }, + { + name: 'Q-Trade', + service: 'APP', + }, + { + name: 'Q-Support', + service: 'APP', + }, + { + name: 'Q-Manager', + service: 'APP', + }, + { + name: 'Q-Blog', + service: 'APP', + }, + { + name: 'Q-Mintership', + service: 'APP', + }, + { + name: 'Q-Wallets', + service: 'APP', + }, + { + name: 'Q-Search', + service: 'APP', + }, + { + name: 'Q-Nodecontrol', + service: 'APP' + } + ], }); export const canSaveSettingToQdnAtom = atom({ diff --git a/src/components/Apps/AppsCategory.tsx b/src/components/Apps/AppsCategory.tsx index c1fa0a0..e96391f 100644 --- a/src/components/Apps/AppsCategory.tsx +++ b/src/components/Apps/AppsCategory.tsx @@ -42,7 +42,8 @@ const officialAppList = [ "q-support", "q-manager", "q-wallets", - "q-search" + "q-search", + "q-nodecontrol" ]; const ScrollerStyled = styled('div')({ diff --git a/src/components/Apps/AppsCategoryDesktop.tsx b/src/components/Apps/AppsCategoryDesktop.tsx index 55cdc4f..ea08998 100644 --- a/src/components/Apps/AppsCategoryDesktop.tsx +++ b/src/components/Apps/AppsCategoryDesktop.tsx @@ -50,7 +50,8 @@ const officialAppList = [ "q-support", "q-manager", "q-wallets", - "q-search" + "q-search", + "q-nodecontrol" ]; const ScrollerStyled = styled("div")({ diff --git a/src/components/Apps/AppsLibrary.tsx b/src/components/Apps/AppsLibrary.tsx index 5601626..0902d9a 100644 --- a/src/components/Apps/AppsLibrary.tsx +++ b/src/components/Apps/AppsLibrary.tsx @@ -33,18 +33,19 @@ import { Virtuoso } from "react-virtuoso"; import { executeEvent } from "../../utils/events"; import { ComposeP, MailIconImg, ShowMessageReturnButton } from "../Group/Forum/Mail-styles"; const officialAppList = [ - "q-tube", - "q-blog", - "q-share", - "q-support", - "q-mail", - "q-fund", - "q-shop", - "q-trade", - "q-support", - "q-manager", - "q-wallets", - "q-search" + 'q-tube', + 'q-blog', + 'q-share', + 'q-support', + 'q-mail', + 'q-fund', + 'q-shop', + 'q-trade', + 'q-support', + 'q-manager', + 'q-wallets', + 'q-search', + "q-nodecontrol" ]; const ScrollerStyled = styled('div')({ diff --git a/src/components/Apps/AppsLibraryDesktop.tsx b/src/components/Apps/AppsLibraryDesktop.tsx index 851267b..a0a15e1 100644 --- a/src/components/Apps/AppsLibraryDesktop.tsx +++ b/src/components/Apps/AppsLibraryDesktop.tsx @@ -48,19 +48,20 @@ import { AppsNavBarDesktop } from "./AppsNavBarDesktop"; import ReturnSVG from '../../assets/svgs/Return.svg' import { ComposeP, MailIconImg, ShowMessageReturnButton } from "../Group/Forum/Mail-styles"; const officialAppList = [ - "q-tube", - "q-blog", - "q-share", - "q-support", - "q-mail", - "q-fund", - "q-shop", - "q-trade", - "q-support", - "q-manager", - "q-mintership", - "q-wallets", - "q-search" + 'q-tube', + 'q-blog', + 'q-share', + 'q-support', + 'q-mail', + 'q-fund', + 'q-shop', + 'q-trade', + 'q-support', + 'q-manager', + 'q-mintership', + 'q-wallets', + 'q-search', + "q-nodecontrol" ]; const ScrollerStyled = styled("div")({ From 7e98c33c11c2bfda33b78957bdfd5ca488d4f3cc Mon Sep 17 00:00:00 2001 From: Nicola Benaglia Date: Sun, 13 Apr 2025 21:52:05 +0200 Subject: [PATCH 04/55] Remove unused imports --- src/components/Group/QMailMessages.tsx | 475 +++++++++++++------------ 1 file changed, 245 insertions(+), 230 deletions(-) diff --git a/src/components/Group/QMailMessages.tsx b/src/components/Group/QMailMessages.tsx index c2d7370..504e766 100644 --- a/src/components/Group/QMailMessages.tsx +++ b/src/components/Group/QMailMessages.tsx @@ -1,14 +1,12 @@ -import React, { useCallback, useEffect, useMemo, useState } from 'react' -import List from "@mui/material/List"; -import ListItem from "@mui/material/ListItem"; -import ListItemButton from "@mui/material/ListItemButton"; -import ListItemIcon from "@mui/material/ListItemIcon"; -import ListItemText from "@mui/material/ListItemText"; -import moment from 'moment' -import { Box, ButtonBase, Collapse, Typography } from "@mui/material"; -import { Spacer } from "../../common/Spacer"; -import { getBaseApiReact, isMobile } from "../../App"; -import { MessagingIcon } from '../../assets/Icons/MessagingIcon'; +import { useCallback, useEffect, useMemo, useState } from 'react'; +import List from '@mui/material/List'; +import ListItem from '@mui/material/ListItem'; +import ListItemButton from '@mui/material/ListItemButton'; +import ListItemIcon from '@mui/material/ListItemIcon'; +import ListItemText from '@mui/material/ListItemText'; +import moment from 'moment'; +import { Box, ButtonBase, Collapse, Typography } from '@mui/material'; +import { getBaseApiReact, isMobile } from '../../App'; import MailIcon from '@mui/icons-material/Mail'; import MailOutlineIcon from '@mui/icons-material/MailOutline'; import { executeEvent } from '../../utils/events'; @@ -18,262 +16,279 @@ import { mailsAtom, qMailLastEnteredTimestampAtom } from '../../atoms/global'; import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; import ExpandLessIcon from '@mui/icons-material/ExpandLess'; import MarkEmailUnreadIcon from '@mui/icons-material/MarkEmailUnread'; + export const isLessThanOneWeekOld = (timestamp) => { // Current time in milliseconds const now = Date.now(); - + // One week ago in milliseconds (7 days * 24 hours * 60 minutes * 60 seconds * 1000 milliseconds) - const oneWeekAgo = now - (7 * 24 * 60 * 60 * 1000); - + const oneWeekAgo = now - 7 * 24 * 60 * 60 * 1000; + // Check if the timestamp is newer than one week ago return timestamp > oneWeekAgo; }; + export function formatEmailDate(timestamp: number) { - const date = moment(timestamp); - const now = moment(); + const date = moment(timestamp); + const now = moment(); - if (date.isSame(now, 'day')) { - // If the email was received today, show the time - return date.format('h:mm A'); - } else if (date.isSame(now, 'year')) { - // If the email was received this year, show the month and day - return date.format('MMM D'); - } else { - // For older emails, show the full date - return date.format('MMM D, YYYY'); - } + if (date.isSame(now, 'day')) { + // If the email was received today, show the time + return date.format('h:mm A'); + } else if (date.isSame(now, 'year')) { + // If the email was received this year, show the month and day + return date.format('MMM D'); + } else { + // For older emails, show the full date + return date.format('MMM D, YYYY'); + } } -export const QMailMessages = ({userName, userAddress}) => { - const [isExpanded, setIsExpanded] = useState(false) - const [mails, setMails] = useRecoilState(mailsAtom) - const [lastEnteredTimestamp, setLastEnteredTimestamp] = useRecoilState(qMailLastEnteredTimestampAtom) - const [loading, setLoading] = useState(true) - const getMails = useCallback(async () => { - try { - setLoading(true) - const query = `qortal_qmail_${userName.slice( - 0, - 20 - )}_${userAddress.slice(-6)}_mail_` - const response = await fetch(`${getBaseApiReact()}/arbitrary/resources/search?service=MAIL_PRIVATE&query=${query}&limit=10&includemetadata=false&offset=0&reverse=true&excludeblocked=true&mode=ALL`); - const mailData = await response.json(); - - - setMails(mailData); - } catch (error) { - console.error(error); - } finally { - setLoading(false) +export const QMailMessages = ({ userName, userAddress }) => { + const [isExpanded, setIsExpanded] = useState(false); + const [mails, setMails] = useRecoilState(mailsAtom); + const [lastEnteredTimestamp, setLastEnteredTimestamp] = useRecoilState( + qMailLastEnteredTimestampAtom + ); + const [loading, setLoading] = useState(true); - } - }, []) + const getMails = useCallback(async () => { + try { + setLoading(true); + const query = `qortal_qmail_${userName.slice( + 0, + 20 + )}_${userAddress.slice(-6)}_mail_`; + const response = await fetch( + `${getBaseApiReact()}/arbitrary/resources/search?service=MAIL_PRIVATE&query=${query}&limit=10&includemetadata=false&offset=0&reverse=true&excludeblocked=true&mode=ALL` + ); + const mailData = await response.json(); - const getTimestamp = async () => { - try { - return new Promise((res, rej) => { - window.sendMessage("getEnteredQmailTimestamp") - .then((response) => { - if (!response?.error) { - if(response?.timestamp){ - setLastEnteredTimestamp(response?.timestamp) - } + setMails(mailData); + } catch (error) { + console.error(error); + } finally { + setLoading(false); + } + }, []); + + const getTimestamp = async () => { + try { + return new Promise((res, rej) => { + window + .sendMessage('getEnteredQmailTimestamp') + .then((response) => { + if (!response?.error) { + if (response?.timestamp) { + setLastEnteredTimestamp(response?.timestamp); } - rej(response.error); - }) - .catch((error) => { - rej(error.message || "An error occurred"); - }); - + } + rej(response.error); + }) + .catch((error) => { + rej(error.message || 'An error occurred'); }); - } catch (error) {} - }; - - useEffect(() => { - getTimestamp() - if(!userName || !userAddress) return - getMails(); + }); + } catch (error) {} + }; - const interval = setInterval(() => { - getTimestamp() - getMails(); - }, 300000); - - return () => clearInterval(interval); - - }, [getMails, userName, userAddress]); + useEffect(() => { + getTimestamp(); + if (!userName || !userAddress) return; + getMails(); - const anyUnread = useMemo(()=> { - let unread = false - - mails.forEach((mail)=> { - if(!lastEnteredTimestamp && isLessThanOneWeekOld(mail?.created) || (lastEnteredTimestamp && isLessThanOneWeekOld(mail?.created) && lastEnteredTimestamp < mail?.created)){ - unread = true - } - }) - return unread - }, [mails, lastEnteredTimestamp]) + const interval = setInterval(() => { + getTimestamp(); + getMails(); + }, 300000); + + return () => clearInterval(interval); + }, [getMails, userName, userAddress]); + + const anyUnread = useMemo(() => { + let unread = false; + + mails.forEach((mail) => { + if ( + (!lastEnteredTimestamp && isLessThanOneWeekOld(mail?.created)) || + (lastEnteredTimestamp && + isLessThanOneWeekOld(mail?.created) && + lastEnteredTimestamp < mail?.created) + ) { + unread = true; + } + }); + return unread; + }, [mails, lastEnteredTimestamp]); return ( - - setIsExpanded((prev)=> !prev)} > - setIsExpanded((prev) => !prev)} > - Latest Q-Mails - - - {isExpanded ? : ( - - )} - - - - {loading && mails.length === 0 && ( - + Latest Q-Mails + + + {isExpanded ? ( + - - + /> + ) : ( + )} - {!loading && mails.length === 0 && ( - - + + + {loading && mails.length === 0 && ( + - Nothing to display - - - )} - - - {mails?.map((mail)=> { - return ( - { - executeEvent("addTab", { data: { service: 'APP', name: 'q-mail' } }); - executeEvent("open-apps-mode", { }); - setLastEnteredTimestamp(Date.now()) + + + )} + {!loading && mails.length === 0 && ( + + + Nothing to display + + + )} + + {mails?.map((mail) => { + return ( + { + executeEvent('addTab', { + data: { service: 'APP', name: 'q-mail' }, + }); + executeEvent('open-apps-mode', {}); + setLastEnteredTimestamp(Date.now()); + }} + > + - + - - - {!lastEnteredTimestamp && isLessThanOneWeekOld(mail?.created) ? ( - - ) : !lastEnteredTimestamp ? ( - - ): (lastEnteredTimestamp < mail?.created) && isLessThanOneWeekOld(mail?.created) ? ( - - ) : ( - - ) - } - - - - - - - ) + {!lastEnteredTimestamp && + isLessThanOneWeekOld(mail?.created) ? ( + + ) : !lastEnteredTimestamp ? ( + + ) : lastEnteredTimestamp < mail?.created && + isLessThanOneWeekOld(mail?.created) ? ( + + ) : ( + + )} + + + + ); })} - - - - - + + + - - - ) -} + ); +}; From 2e55c16f419907176bfbacb0b2e16bb19e2ff3a0 Mon Sep 17 00:00:00 2001 From: PhilReact Date: Wed, 16 Apr 2025 18:57:31 +0300 Subject: [PATCH 05/55] fixes --- src/background.ts | 8 +--- src/qortalRequests/get.ts | 82 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 81 insertions(+), 9 deletions(-) diff --git a/src/background.ts b/src/background.ts index 87a6416..5bd922b 100644 --- a/src/background.ts +++ b/src/background.ts @@ -2391,13 +2391,7 @@ export async function buyName({ privateKey: uint8PrivateKey, publicKey: uint8PublicKey, }; - console.log('tester', { - fee: feeres.fee, - name, - sellPrice, - recipient: sellerAddress, - lastReference: lastReference, - }) + const tx = await createTransaction(7, keyPair, { fee: feeres.fee, name, diff --git a/src/qortalRequests/get.ts b/src/qortalRequests/get.ts index c0206b2..4ae357f 100644 --- a/src/qortalRequests/get.ts +++ b/src/qortalRequests/get.ts @@ -4105,6 +4105,12 @@ export const registerNameRequest = async (data, isFromExtension) => { missingFields.push(field); } }); + + if (missingFields.length > 0) { + const missingFieldsString = missingFields.join(", "); + const errorMsg = `Missing fields: ${missingFieldsString}`; + throw new Error(errorMsg); + } const fee = await getFee("REGISTER_NAME"); const resPermission = await getUserPermission( { @@ -4118,7 +4124,7 @@ export const registerNameRequest = async (data, isFromExtension) => { const { accepted } = resPermission; if (accepted) { const name = data.name - const description = data?.description + const description = data?.description || "" const response = await registerName({ name, description }); return response @@ -4135,9 +4141,14 @@ export const updateNameRequest = async (data, isFromExtension) => { missingFields.push(field); } }); + if (missingFields.length > 0) { + const missingFieldsString = missingFields.join(", "); + const errorMsg = `Missing fields: ${missingFieldsString}`; + throw new Error(errorMsg); + } const oldName = data.oldName const newName = data.newName - const description = data?.description + const description = data?.description || "" const fee = await getFee("UPDATE_NAME"); const resPermission = await getUserPermission( { @@ -4166,6 +4177,11 @@ export const leaveGroupRequest = async (data, isFromExtension) => { missingFields.push(field); } }); + if (missingFields.length > 0) { + const missingFieldsString = missingFields.join(", "); + const errorMsg = `Missing fields: ${missingFieldsString}`; + throw new Error(errorMsg); + } const groupId = data.groupId let groupInfo = null; try { @@ -4206,6 +4222,11 @@ export const inviteToGroupRequest = async (data, isFromExtension) => { missingFields.push(field); } }); + if (missingFields.length > 0) { + const missingFieldsString = missingFields.join(", "); + const errorMsg = `Missing fields: ${missingFieldsString}`; + throw new Error(errorMsg); + } const groupId = data.groupId const qortalAddress = data?.inviteeAddress const inviteTime = data?.inviteTime @@ -4255,6 +4276,11 @@ export const kickFromGroupRequest = async (data, isFromExtension) => { missingFields.push(field); } }); + if (missingFields.length > 0) { + const missingFieldsString = missingFields.join(", "); + const errorMsg = `Missing fields: ${missingFieldsString}`; + throw new Error(errorMsg); + } const groupId = data.groupId const qortalAddress = data?.qortalAddress const reason = data?.reason @@ -4304,6 +4330,11 @@ export const banFromGroupRequest = async (data, isFromExtension) => { missingFields.push(field); } }); + if (missingFields.length > 0) { + const missingFieldsString = missingFields.join(", "); + const errorMsg = `Missing fields: ${missingFieldsString}`; + throw new Error(errorMsg); + } const groupId = data.groupId const qortalAddress = data?.qortalAddress const rBanTime = data?.banTime @@ -4354,6 +4385,11 @@ export const cancelGroupBanRequest = async (data, isFromExtension) => { missingFields.push(field); } }); + if (missingFields.length > 0) { + const missingFieldsString = missingFields.join(", "); + const errorMsg = `Missing fields: ${missingFieldsString}`; + throw new Error(errorMsg); + } const groupId = data.groupId const qortalAddress = data?.qortalAddress @@ -4401,6 +4437,11 @@ export const addGroupAdminRequest = async (data, isFromExtension) => { missingFields.push(field); } }); + if (missingFields.length > 0) { + const missingFieldsString = missingFields.join(", "); + const errorMsg = `Missing fields: ${missingFieldsString}`; + throw new Error(errorMsg); + } const groupId = data.groupId const qortalAddress = data?.qortalAddress @@ -4448,6 +4489,11 @@ export const removeGroupAdminRequest = async (data, isFromExtension) => { missingFields.push(field); } }); + if (missingFields.length > 0) { + const missingFieldsString = missingFields.join(", "); + const errorMsg = `Missing fields: ${missingFieldsString}`; + throw new Error(errorMsg); + } const groupId = data.groupId const qortalAddress = data?.qortalAddress @@ -4495,6 +4541,11 @@ export const cancelGroupInviteRequest = async (data, isFromExtension) => { missingFields.push(field); } }); + if (missingFields.length > 0) { + const missingFieldsString = missingFields.join(", "); + const errorMsg = `Missing fields: ${missingFieldsString}`; + throw new Error(errorMsg); + } const groupId = data.groupId const qortalAddress = data?.qortalAddress @@ -4543,6 +4594,11 @@ export const createGroupRequest = async (data, isFromExtension) => { missingFields.push(field); } }); + if (missingFields.length > 0) { + const missingFieldsString = missingFields.join(", "); + const errorMsg = `Missing fields: ${missingFieldsString}`; + throw new Error(errorMsg); + } const groupName = data.groupName const description = data?.description || "" const type = +data.type @@ -4585,6 +4641,11 @@ export const updateGroupRequest = async (data, isFromExtension) => { missingFields.push(field); } }); + if (missingFields.length > 0) { + const missingFieldsString = missingFields.join(", "); + const errorMsg = `Missing fields: ${missingFieldsString}`; + throw new Error(errorMsg); + } const groupId = +data.groupId const newOwner = data.newOwner const description = data?.description || "" @@ -4644,6 +4705,8 @@ export const decryptAESGCMRequest = async (data, isFromExtension) => { } }); + + const encryptedData = data.encryptedData; const iv = data.iv; const senderPublicKeyBase58 = data.senderPublicKey; @@ -4700,6 +4763,11 @@ export const sellNameRequest = async (data, isFromExtension) => { missingFields.push(field); } }); + if (missingFields.length > 0) { + const missingFieldsString = missingFields.join(", "); + const errorMsg = `Missing fields: ${missingFieldsString}`; + throw new Error(errorMsg); + } const name = data.nameForSale const sellPrice = +data.salePrice @@ -4740,6 +4808,11 @@ export const cancelSellNameRequest = async (data, isFromExtension) => { missingFields.push(field); } }); + if (missingFields.length > 0) { + const missingFieldsString = missingFields.join(", "); + const errorMsg = `Missing fields: ${missingFieldsString}`; + throw new Error(errorMsg); + } const name = data.nameForSale const validApi = await getBaseApi(); @@ -4776,6 +4849,11 @@ export const buyNameRequest = async (data, isFromExtension) => { missingFields.push(field); } }); + if (missingFields.length > 0) { + const missingFieldsString = missingFields.join(", "); + const errorMsg = `Missing fields: ${missingFieldsString}`; + throw new Error(errorMsg); + } const name = data.nameForSale const validApi = await getBaseApi(); From 6621527e82fb8c31cadc85a32900612a45fa89c7 Mon Sep 17 00:00:00 2001 From: Nicola Benaglia Date: Wed, 16 Apr 2025 20:45:24 +0200 Subject: [PATCH 06/55] Refactor button style in wallets --- src/Wallets.tsx | 8 +- src/common/Spacer.tsx | 26 +- src/components/Group/AddGroup.tsx | 634 ++++++++++++++------------- src/components/Snackbar/Snackbar.tsx | 31 +- src/styles/App-styles.ts | 4 +- 5 files changed, 361 insertions(+), 342 deletions(-) diff --git a/src/Wallets.tsx b/src/Wallets.tsx index 8faf005..240ca40 100644 --- a/src/Wallets.tsx +++ b/src/Wallets.tsx @@ -16,6 +16,7 @@ import { DialogTitle, IconButton, Input, + useTheme, } from '@mui/material'; import { CustomButton } from './styles/App-styles'; import { useDropzone } from 'react-dropzone'; @@ -266,6 +267,7 @@ export const Wallets = ({ setExtState, setRawWallet, rawWallet }) => { onClick={handleSetSeedValue} sx={{ padding: '10px', + display: 'inline', }} > Add seed-phrase @@ -401,6 +403,7 @@ const WalletItem = ({ wallet, updateWalletItem, idx, setSelectedWallet }) => { const [name, setName] = useState(''); const [note, setNote] = useState(''); const [isEdit, setIsEdit] = useState(false); + const theme = useTheme(); useEffect(() => { if (wallet?.name) { @@ -423,10 +426,10 @@ const WalletItem = ({ wallet, updateWalletItem, idx, setSelectedWallet }) => { > { } /> + { - return ( - - ); - }; \ No newline at end of file + return ( + + ); +}; diff --git a/src/components/Group/AddGroup.tsx b/src/components/Group/AddGroup.tsx index 1cf86fe..28ffa7b 100644 --- a/src/components/Group/AddGroup.tsx +++ b/src/components/Group/AddGroup.tsx @@ -1,19 +1,15 @@ -import * as React from "react"; -import Button from "@mui/material/Button"; -import Dialog from "@mui/material/Dialog"; -import ListItemText from "@mui/material/ListItemText"; -import ListItemButton from "@mui/material/ListItemButton"; -import List from "@mui/material/List"; -import Divider from "@mui/material/Divider"; -import AppBar from "@mui/material/AppBar"; -import Toolbar from "@mui/material/Toolbar"; -import IconButton from "@mui/material/IconButton"; -import Typography from "@mui/material/Typography"; -import CloseIcon from "@mui/icons-material/Close"; -import ExpandLess from "@mui/icons-material/ExpandLess"; -import ExpandMore from "@mui/icons-material/ExpandMore"; -import Slide from "@mui/material/Slide"; -import { TransitionProps } from "@mui/material/transitions"; +import * as React from 'react'; +import Button from '@mui/material/Button'; +import Dialog from '@mui/material/Dialog'; +import AppBar from '@mui/material/AppBar'; +import Toolbar from '@mui/material/Toolbar'; +import IconButton from '@mui/material/IconButton'; +import Typography from '@mui/material/Typography'; +import CloseIcon from '@mui/icons-material/Close'; +import ExpandLess from '@mui/icons-material/ExpandLess'; +import ExpandMore from '@mui/icons-material/ExpandMore'; +import Slide from '@mui/material/Slide'; +import { TransitionProps } from '@mui/material/transitions'; import { Box, Collapse, @@ -24,15 +20,15 @@ import { Tab, Tabs, styled, -} from "@mui/material"; -import { AddGroupList } from "./AddGroupList"; -import { UserListOfInvites } from "./UserListOfInvites"; -import { CustomizedSnackbars } from "../Snackbar/Snackbar"; -import { getFee } from "../../background"; -import { MyContext, isMobile } from "../../App"; -import { subscribeToEvent, unsubscribeFromEvent } from "../../utils/events"; +} from '@mui/material'; +import { AddGroupList } from './AddGroupList'; +import { UserListOfInvites } from './UserListOfInvites'; +import { CustomizedSnackbars } from '../Snackbar/Snackbar'; +import { getFee } from '../../background'; +import { MyContext, isMobile } from '../../App'; +import { subscribeToEvent, unsubscribeFromEvent } from '../../utils/events'; -export const Label = styled("label")( +export const Label = styled('label')( ({ theme }) => ` font-family: 'IBM Plex Sans', sans-serif; font-size: 14px; @@ -51,17 +47,15 @@ const Transition = React.forwardRef(function Transition( }); export const AddGroup = ({ address, open, setOpen }) => { - const {show, setTxList} = React.useContext(MyContext) - - const [tab, setTab] = React.useState("create"); + const { show, setTxList } = React.useContext(MyContext); + const [tab, setTab] = React.useState('create'); const [openAdvance, setOpenAdvance] = React.useState(false); - - const [name, setName] = React.useState(""); - const [description, setDescription] = React.useState(""); - const [groupType, setGroupType] = React.useState("1"); - const [approvalThreshold, setApprovalThreshold] = React.useState("40"); - const [minBlock, setMinBlock] = React.useState("5"); - const [maxBlock, setMaxBlock] = React.useState("21600"); + const [name, setName] = React.useState(''); + const [description, setDescription] = React.useState(''); + const [groupType, setGroupType] = React.useState('1'); + const [approvalThreshold, setApprovalThreshold] = React.useState('40'); + const [minBlock, setMinBlock] = React.useState('5'); + const [maxBlock, setMaxBlock] = React.useState('21600'); const [value, setValue] = React.useState(0); const [openSnack, setOpenSnack] = React.useState(false); const [infoSnack, setInfoSnack] = React.useState(null); @@ -69,6 +63,7 @@ export const AddGroup = ({ address, open, setOpen }) => { const handleChange = (event: React.SyntheticEvent, newValue: number) => { setValue(newValue); }; + const handleClose = () => { setOpen(false); }; @@ -89,58 +84,57 @@ export const AddGroup = ({ address, open, setOpen }) => { setMaxBlock(event.target.value as string); }; - - const handleCreateGroup = async () => { try { - if(!name) throw new Error('Please provide a name') - if(!description) throw new Error('Please provide a description') + if (!name) throw new Error('Please provide a name'); + if (!description) throw new Error('Please provide a description'); - const fee = await getFee('CREATE_GROUP') + const fee = await getFee('CREATE_GROUP'); await show({ - message: "Would you like to perform an CREATE_GROUP transaction?" , - publishFee: fee.fee + ' QORT' - }) + message: 'Would you like to perform an CREATE_GROUP transaction?', + publishFee: fee.fee + ' QORT', + }); - await new Promise((res, rej) => { - window.sendMessage("createGroup", { - groupName: name, - groupDescription: description, - groupType: +groupType, - groupApprovalThreshold: +approvalThreshold, - minBlock: +minBlock, - maxBlock: +maxBlock, - }) - .then((response) => { - if (!response?.error) { - setInfoSnack({ - type: "success", - message: "Successfully created group. It may take a couple of minutes for the changes to propagate", - }); - setOpenSnack(true); - setTxList((prev) => [ - { - ...response, - type: 'created-group', - label: `Created group ${name}: awaiting confirmation`, - labelDone: `Created group ${name}: success!`, - done: false, - }, - ...prev, - ]); - res(response); - return; - } - rej({ message: response.error }); - }) - .catch((error) => { - rej({ message: error.message || "An error occurred" }); - }); - + await new Promise((res, rej) => { + window + .sendMessage('createGroup', { + groupName: name, + groupDescription: description, + groupType: +groupType, + groupApprovalThreshold: +approvalThreshold, + minBlock: +minBlock, + maxBlock: +maxBlock, + }) + .then((response) => { + if (!response?.error) { + setInfoSnack({ + type: 'success', + message: + 'Successfully created group. It may take a couple of minutes for the changes to propagate', + }); + setOpenSnack(true); + setTxList((prev) => [ + { + ...response, + type: 'created-group', + label: `Created group ${name}: awaiting confirmation`, + labelDone: `Created group ${name}: success!`, + done: false, + }, + ...prev, + ]); + res(response); + return; + } + rej({ message: response.error }); + }) + .catch((error) => { + rej({ message: error.message || 'An error occurred' }); + }); }); } catch (error) { setInfoSnack({ - type: "error", + type: 'error', message: error?.message, }); setOpenSnack(true); @@ -166,20 +160,22 @@ export const AddGroup = ({ address, open, setOpen }) => { function a11yProps(index: number) { return { id: `simple-tab-${index}`, - "aria-controls": `simple-tabpanel-${index}`, + 'aria-controls': `simple-tabpanel-${index}`, }; } - - const openGroupInvitesRequestFunc = ()=> { - setValue(2) - } + const openGroupInvitesRequestFunc = () => { + setValue(2); + }; React.useEffect(() => { - subscribeToEvent("openGroupInvitesRequest", openGroupInvitesRequestFunc); + subscribeToEvent('openGroupInvitesRequest', openGroupInvitesRequestFunc); return () => { - unsubscribeFromEvent("openGroupInvitesRequest", openGroupInvitesRequestFunc); + unsubscribeFromEvent( + 'openGroupInvitesRequest', + openGroupInvitesRequestFunc + ); }; }, []); @@ -191,7 +187,7 @@ export const AddGroup = ({ address, open, setOpen }) => { onClose={handleClose} TransitionComponent={Transition} > - + Group Mgmt @@ -213,275 +209,289 @@ export const AddGroup = ({ address, open, setOpen }) => { - - - - - - + + + + + + - + {value === 0 && ( - - - setName(e.target.value)} - /> - - - - - setDescription(e.target.value)} - /> - - - - - - setOpenAdvance((prev) => !prev)} - > - Advanced options - - {openAdvance ? : } - - - + + setName(e.target.value)} + /> + + + + + setDescription(e.target.value)} + /> + + + setOpenAdvance((prev) => !prev)} > - - + Advanced options + + {openAdvance ? : } + + + + + + + + + + + + + + - - + Create Group + - - - - )} {value === 1 && ( - - - + + - )} - - {value === 2 && ( - - - - )} - + {value === 2 && ( + + + + )} - + ); diff --git a/src/components/Snackbar/Snackbar.tsx b/src/components/Snackbar/Snackbar.tsx index 59fa295..d79677e 100644 --- a/src/components/Snackbar/Snackbar.tsx +++ b/src/components/Snackbar/Snackbar.tsx @@ -1,31 +1,36 @@ import * as React from 'react'; -import Button from '@mui/material/Button'; import Snackbar, { SnackbarCloseReason } from '@mui/material/Snackbar'; import Alert from '@mui/material/Alert'; -export const CustomizedSnackbars = ({open, setOpen, info, setInfo, duration}) => { - - - +export const CustomizedSnackbars = ({ + open, + setOpen, + info, + setInfo, + duration, +}) => { const handleClose = ( event?: React.SyntheticEvent | Event, - reason?: SnackbarCloseReason, + reason?: SnackbarCloseReason ) => { if (reason === 'clickaway') { return; } - setOpen(false); - setInfo(null) + setInfo(null); }; - if(!open) return null + if (!open) return null; + return (
- +
); -} \ No newline at end of file +}; diff --git a/src/styles/App-styles.ts b/src/styles/App-styles.ts index 9774f06..da2b8c1 100644 --- a/src/styles/App-styles.ts +++ b/src/styles/App-styles.ts @@ -146,8 +146,8 @@ export const CustomButton = styled(Box)(({ theme }) => ({ '&:hover': { backgroundColor: theme.palette.mode === 'dark' - ? 'rgba(41, 41, 43, 1)' - : 'rgba(230, 230, 230, 1)', + ? 'rgb(136, 130, 130)' + : 'rgb(173, 173, 180)', color: '#fff', 'svg path': { From b64784cf450161842fa7e3a0098f23023d3ac239 Mon Sep 17 00:00:00 2001 From: Nicola Benaglia Date: Fri, 18 Apr 2025 09:20:29 +0200 Subject: [PATCH 07/55] Add theme dark/light --- src/components/Group/Settings.tsx | 144 ++++++++++++++---------------- 1 file changed, 67 insertions(+), 77 deletions(-) diff --git a/src/components/Group/Settings.tsx b/src/components/Group/Settings.tsx index 2aba6f6..d3ff1f7 100644 --- a/src/components/Group/Settings.tsx +++ b/src/components/Group/Settings.tsx @@ -1,37 +1,20 @@ -import * as React from "react"; -import Button from "@mui/material/Button"; -import Dialog from "@mui/material/Dialog"; -import ListItemText from "@mui/material/ListItemText"; -import ListItemButton from "@mui/material/ListItemButton"; -import List from "@mui/material/List"; -import Divider from "@mui/material/Divider"; -import AppBar from "@mui/material/AppBar"; -import Toolbar from "@mui/material/Toolbar"; -import IconButton from "@mui/material/IconButton"; -import Typography from "@mui/material/Typography"; -import CloseIcon from "@mui/icons-material/Close"; -import Slide from "@mui/material/Slide"; -import { TransitionProps } from "@mui/material/transitions"; -import ListOfMembers from "./ListOfMembers"; -import { InviteMember } from "./InviteMember"; -import { ListOfInvites } from "./ListOfInvites"; -import { ListOfBans } from "./ListOfBans"; -import { ListOfJoinRequests } from "./ListOfJoinRequests"; -import { Box, FormControlLabel, Switch, Tab, Tabs, styled } from "@mui/material"; -import { CustomizedSnackbars } from "../Snackbar/Snackbar"; -import { MyContext, isMobile } from "../../App"; -import { getGroupMembers, getNames } from "./Group"; -import { LoadingSnackbar } from "../Snackbar/LoadingSnackbar"; -import { getFee } from "../../background"; -import { LoadingButton } from "@mui/lab"; -import { subscribeToEvent, unsubscribeFromEvent } from "../../utils/events"; -import { enabledDevModeAtom } from "../../atoms/global"; -import { useRecoilState } from "recoil"; +import * as React from 'react'; +import Dialog from '@mui/material/Dialog'; +import AppBar from '@mui/material/AppBar'; +import Toolbar from '@mui/material/Toolbar'; +import IconButton from '@mui/material/IconButton'; +import Typography from '@mui/material/Typography'; +import CloseIcon from '@mui/icons-material/Close'; +import Slide from '@mui/material/Slide'; +import { TransitionProps } from '@mui/material/transitions'; +import { Box, FormControlLabel, Switch, styled, useTheme } from '@mui/material'; +import { enabledDevModeAtom } from '../../atoms/global'; +import { useRecoilState } from 'recoil'; function a11yProps(index: number) { return { id: `simple-tab-${index}`, - "aria-controls": `simple-tabpanel-${index}`, + 'aria-controls': `simple-tabpanel-${index}`, }; } @@ -49,13 +32,13 @@ const LocalNodeSwitch = styled(Switch)(({ theme }) => ({ }, '&::before': { backgroundImage: `url('data:image/svg+xml;utf8,')`, left: 12, }, '&::after': { backgroundImage: `url('data:image/svg+xml;utf8,')`, right: 12, }, @@ -77,35 +60,34 @@ const Transition = React.forwardRef(function Transition( return ; }); -export const Settings = ({ - address, - open, - setOpen, -}) => { +export const Settings = ({ address, open, setOpen }) => { const [checked, setChecked] = React.useState(false); - const [isEnabledDevMode, setIsEnabledDevMode] = useRecoilState(enabledDevModeAtom) - - + const [isEnabledDevMode, setIsEnabledDevMode] = + useRecoilState(enabledDevModeAtom); + const theme = useTheme(); const handleChange = (event: React.ChangeEvent) => { setChecked(event.target.checked); - window.sendMessage("addUserSettings", { - keyValue: { - key: 'disable-push-notifications', - value: event.target.checked, - }, - }) + window + .sendMessage('addUserSettings', { + keyValue: { + key: 'disable-push-notifications', + value: event.target.checked, + }, + }) .then((response) => { if (response?.error) { - console.error("Error adding user settings:", response.error); + console.error('Error adding user settings:', response.error); } else { - console.log("User settings added successfully"); + console.log('User settings added successfully'); } }) .catch((error) => { - console.error("Failed to add user settings:", error.message || "An error occurred"); + console.error( + 'Failed to add user settings:', + error.message || 'An error occurred' + ); }); - }; const handleClose = () => { @@ -115,9 +97,10 @@ export const Settings = ({ const getUserSettings = async () => { try { return new Promise((res, rej) => { - window.sendMessage("getUserSettings", { - key: "disable-push-notifications", - }) + window + .sendMessage('getUserSettings', { + key: 'disable-push-notifications', + }) .then((response) => { if (!response?.error) { setChecked(response || false); @@ -127,12 +110,11 @@ export const Settings = ({ 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); } }; @@ -140,8 +122,6 @@ export const Settings = ({ getUserSettings(); }, []); - - return ( - + - + General Settings + + @@ -188,17 +172,23 @@ export const Settings = ({ /> {window?.electronAPI && ( { - setIsEnabledDevMode(e.target.checked) - localStorage.setItem('isEnabledDevMode', JSON.stringify(e.target.checked)) - }} /> - } - label="Enable dev mode" - /> + sx={{ + color: 'white', + }} + control={ + { + setIsEnabledDevMode(e.target.checked); + localStorage.setItem( + 'isEnabledDevMode', + JSON.stringify(e.target.checked) + ); + }} + /> + } + label="Enable dev mode" + /> )} From 12a3dff029278da21065d32be5455bacea4a8712 Mon Sep 17 00:00:00 2001 From: Nicola Benaglia Date: Fri, 18 Apr 2025 09:32:03 +0200 Subject: [PATCH 08/55] Split themes into separate files --- src/components/Theme/ThemeContext.tsx | 3 +- src/main.tsx | 2 + src/styles/index.css | 29 +---- src/styles/theme-common.ts | 85 ++++++++++++ src/styles/theme-dark.ts | 83 ++++++++++++ src/styles/theme-light.ts | 84 ++++++++++++ src/styles/theme.ts | 180 -------------------------- 7 files changed, 258 insertions(+), 208 deletions(-) create mode 100644 src/styles/theme-common.ts create mode 100644 src/styles/theme-dark.ts create mode 100644 src/styles/theme-light.ts delete mode 100644 src/styles/theme.ts diff --git a/src/components/Theme/ThemeContext.tsx b/src/components/Theme/ThemeContext.tsx index e64c183..5a5abb8 100644 --- a/src/components/Theme/ThemeContext.tsx +++ b/src/components/Theme/ThemeContext.tsx @@ -1,6 +1,7 @@ import { createContext, useContext, useState, useMemo } from 'react'; import { ThemeProvider as MuiThemeProvider } from '@mui/material/styles'; -import { darkTheme, lightTheme } from '../../styles/theme'; +import { darkTheme } from '../../styles/theme-dark'; +import { lightTheme } from '../../styles/theme-light'; const ThemeContext = createContext({ themeMode: 'light', diff --git a/src/main.tsx b/src/main.tsx index 3f04c89..69e8901 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -5,10 +5,12 @@ import './messaging/messagesToBackground'; import { MessageQueueProvider } from './MessageQueueContext.tsx'; import { RecoilRoot } from 'recoil'; import { ThemeProvider } from './components/Theme/ThemeContext.tsx'; +import { CssBaseline } from '@mui/material'; ReactDOM.createRoot(document.getElementById('root')!).render( <> + diff --git a/src/styles/index.css b/src/styles/index.css index 3fd5ed7..f8b8090 100644 --- a/src/styles/index.css +++ b/src/styles/index.css @@ -19,29 +19,6 @@ font-weight: 400; } -:root { - padding: 0px; - margin: 0px; - box-sizing: border-box !important; - word-break: break-word; - --color-instance: #1e1e20; - --color-instance-popover-bg: #222222; - --Mail-Background: rgba(49, 51, 56, 1); - --new-message-text: black; - --bg-primary: rgba(31, 32, 35, 1); - --bg-2: #27282c; - --bg-3: rgba(0, 0, 0, 0.1); - --unread: #4297e2; - --danger: #b14646; - --apps-circle: #1f2023; - --green: #5eb049; -} - -body { - margin: 0px; - overflow: hidden; -} - .image-container { position: relative; } @@ -68,6 +45,7 @@ body { ::-webkit-scrollbar-track { background-color: transparent; } + ::-webkit-scrollbar-track:hover { background-color: transparent; } @@ -84,6 +62,7 @@ body { border: 4px solid transparent; transition: 0.3s background-color; } + ::-webkit-scrollbar-thumb:hover { background-color: #363636; } @@ -131,7 +110,3 @@ html, body { overscroll-behavior: none !important; } - -.swiper { - width: 100%; -} diff --git a/src/styles/theme-common.ts b/src/styles/theme-common.ts new file mode 100644 index 0000000..600b6da --- /dev/null +++ b/src/styles/theme-common.ts @@ -0,0 +1,85 @@ +// Extend the Theme interface +const commonThemeOptions = { + typography: { + fontFamily: ['Inter'].join(','), + h1: { + fontSize: '2rem', + fontWeight: 600, + }, + h2: { + fontSize: '1.75rem', + fontWeight: 500, + }, + h3: { + fontSize: '1.5rem', + fontWeight: 500, + }, + h4: { + fontSize: '1.25rem', + fontWeight: 500, + }, + h5: { + fontSize: '1rem', + fontWeight: 500, + }, + h6: { + fontSize: '0.875rem', + fontWeight: 500, + }, + body: { + margin: '0px', + overflow: 'hidden', + }, + body1: { + fontSize: '16px', + fontWeight: 400, + lineHeight: 1.5, + letterSpacing: 'normal', + }, + body2: { + fontSize: '18px', + fontWeight: 400, + lineHeight: 1.4, + letterSpacing: '0.2px', + }, + }, + spacing: 8, + shape: { + borderRadius: 4, + }, + breakpoints: { + values: { + xs: 0, + sm: 600, + md: 900, + lg: 1200, + xl: 1536, + }, + }, + components: { + MuiButton: { + styleOverrides: { + root: { + backgroundColor: 'inherit', + transition: 'filter 0.3s ease-in-out', + '&:hover': { + filter: 'brightness(1.1)', + }, + }, + }, + defaultProps: { + disableElevation: true, + disableRipple: true, + }, + }, + MuiModal: { + styleOverrides: { + root: { + zIndex: 50000, + }, + }, + }, + }, +}; + +export { commonThemeOptions }; diff --git a/src/styles/theme-dark.ts b/src/styles/theme-dark.ts new file mode 100644 index 0000000..0fa1e48 --- /dev/null +++ b/src/styles/theme-dark.ts @@ -0,0 +1,83 @@ +import { createTheme } from '@mui/material/styles'; +import { commonThemeOptions } from './theme-common'; + +const darkTheme = createTheme({ + ...commonThemeOptions, + palette: { + mode: 'dark', + primary: { + main: '#2e3d60', + dark: '#1a2744', + light: '#3f4b66', + }, + secondary: { + main: '#45adff', + }, + background: { + default: '#313338', + paper: '#1e1e20', + }, + text: { + primary: '#ffffff', + secondary: '#b3b3b3', + }, + }, + components: { + MuiCard: { + styleOverrides: { + root: { + 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);', + }, + }, + }, + }, + MuiIcon: { + defaultProps: { + style: { + color: '#ffffff', + opacity: 0.5, + }, + }, + }, + MuiCssBaseline: { + styleOverrides: { + ':root': { + '--color-instance': '#1e1e20', + '--color-instance-popover-bg': '#222222', + '--Mail-Background': 'rgb(101, 248, 174)', + '--new-message-text': 'black', + '--bg-primary': 'rgba(31, 32, 35, 1)', + '--bg-2': '#27282c', + '--bg-3': 'rgba(0, 0, 0, 0.1)', + '--unread': '#4297e2', + '--danger': '#b14646', + '--apps-circle': '#1f2023', + '--green': '#5eb049', + '--gallo': 'gallo', + }, + '*, *::before, *::after': { + boxSizing: 'border-box', + }, + html: { + padding: 0, + margin: 0, + }, + body: { + padding: 0, + margin: 0, + wordBreak: 'break-word', + backgroundColor: 'var(--bg-primary)', + color: 'var(--new-message-text)', + }, + }, + }, + }, +}); + +export { darkTheme }; diff --git a/src/styles/theme-light.ts b/src/styles/theme-light.ts new file mode 100644 index 0000000..15257c3 --- /dev/null +++ b/src/styles/theme-light.ts @@ -0,0 +1,84 @@ +import { createTheme } from '@mui/material/styles'; +import { commonThemeOptions } from './theme-common'; + +const lightTheme = createTheme({ + ...commonThemeOptions, + palette: { + mode: 'light', + primary: { + main: '#f4f4fb', + dark: '#eaecf4', + light: '#f9f9fd', + }, + secondary: { + main: '#c2deec', + }, + background: { + default: '#fafafa', + paper: '#f0f0f0', + }, + text: { + primary: '#000000', + secondary: '#525252', + }, + }, + components: { + MuiCard: { + styleOverrides: { + root: { + boxShadow: + '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;', + }, + }, + }, + }, + MuiIcon: { + defaultProps: { + style: { + color: '#000000', + opacity: 0.5, + }, + }, + }, + MuiCssBaseline: { + styleOverrides: { + ':root': { + '--color-instance': '#1e1e20', + '--color-instance-popover-bg': '#222222', + '--Mail-Background': 'rgba(49, 51, 56, 1)', + '--new-message-text': 'black', + '--bg-primary': 'rgba(31, 32, 35, 1)', + '--bg-2': '#27282c', + '--bg-3': 'rgba(0, 0, 0, 0.1)', + '--unread': '#4297e2', + '--danger': '#b14646', + '--apps-circle': '#1f2023', + '--green': '#5eb049', + '--pollo': 'pollo', + }, + '*, *::before, *::after': { + boxSizing: 'border-box', + }, + html: { + padding: 0, + margin: 0, + }, + body: { + padding: 0, + margin: 0, + wordBreak: 'break-word', + backgroundColor: 'var(--bg-primary)', + color: 'var(--new-message-text)', + }, + }, + }, + }, +}); + +export { lightTheme }; diff --git a/src/styles/theme.ts b/src/styles/theme.ts deleted file mode 100644 index 6ea83cc..0000000 --- a/src/styles/theme.ts +++ /dev/null @@ -1,180 +0,0 @@ -import { createTheme } from '@mui/material/styles'; - -// Extend the Theme interface -const commonThemeOptions = { - typography: { - fontFamily: ['Roboto'].join(','), - h1: { - fontSize: '2rem', - fontWeight: 600, - }, - h2: { - fontSize: '1.75rem', - fontWeight: 500, - }, - h3: { - fontSize: '1.5rem', - fontWeight: 500, - }, - h4: { - fontSize: '1.25rem', - fontWeight: 500, - }, - h5: { - fontSize: '1rem', - fontWeight: 500, - }, - h6: { - fontSize: '0.875rem', - fontWeight: 500, - }, - body1: { - fontSize: '23px', - fontWeight: 400, - lineHeight: 1.5, - letterSpacing: 'normal', - }, - - body2: { - fontSize: '18px', - fontWeight: 400, - lineHeight: 1.4, - letterSpacing: '0.2px', - }, - }, - spacing: 8, - shape: { - borderRadius: 4, - }, - breakpoints: { - values: { - xs: 0, - sm: 600, - md: 900, - lg: 1200, - xl: 1536, - }, - }, - components: { - MuiButton: { - styleOverrides: { - root: { - backgroundColor: 'inherit', - transition: 'filter 0.3s ease-in-out', - '&:hover': { - filter: 'brightness(1.1)', - }, - }, - }, - defaultProps: { - disableElevation: true, - disableRipple: true, - }, - }, - MuiModal: { - styleOverrides: { - root: { - zIndex: 50000, - }, - }, - }, - }, -}; - -const lightTheme = createTheme({ - ...commonThemeOptions, - palette: { - mode: 'light', - primary: { - main: '#f4f4fb', - dark: '#eaecf4', - light: '#f9f9fd', - }, - secondary: { - main: '#c2deec', - }, - background: { - default: '#fafafa', - paper: '#f0f0f0', - }, - text: { - primary: '#000000', - secondary: '#525252', - }, - }, - components: { - MuiCard: { - styleOverrides: { - root: { - boxShadow: - '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;', - }, - }, - }, - }, - MuiIcon: { - defaultProps: { - style: { - color: '#000000', - opacity: 0.5, - }, - }, - }, - }, -}); - -const darkTheme = createTheme({ - ...commonThemeOptions, - palette: { - mode: 'dark', - primary: { - main: '#2e3d60', - dark: '#1a2744', - light: '#3f4b66', - }, - secondary: { - main: '#45adff', - }, - - background: { - default: '#313338', - paper: '#1e1e20', - }, - text: { - primary: '#ffffff', - secondary: '#b3b3b3', - }, - }, - components: { - MuiCard: { - styleOverrides: { - root: { - 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);', - }, - }, - }, - }, - MuiIcon: { - defaultProps: { - style: { - color: '#ffffff', - opacity: 0.5, - }, - }, - }, - }, -}); - -export { lightTheme, darkTheme }; From d4eb2ae8ff949527547d17bcb121d9a7f529cd7b Mon Sep 17 00:00:00 2001 From: Nicola Benaglia Date: Fri, 18 Apr 2025 15:20:45 +0200 Subject: [PATCH 09/55] Remove color property --- src/App.tsx | 22 +++------------------- src/Wallets.tsx | 6 +----- 2 files changed, 4 insertions(+), 24 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index ba2329b..f011c7e 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1333,9 +1333,7 @@ function App() { {authenticatedMode === 'qort' && ( + LITECOIN WALLET } @@ -1372,9 +1370,7 @@ function App() { {authenticatedMode === 'ltc' && ( + QORTAL WALLET } @@ -1447,7 +1443,6 @@ function App() { onClick={getLtcBalanceFunc} sx={{ fontSize: '16px', - color: 'white', cursor: 'pointer', }} /> @@ -1506,7 +1501,6 @@ function App() { onClick={getBalanceFunc} sx={{ fontSize: '16px', - color: 'white', cursor: 'pointer', }} /> @@ -1593,7 +1587,6 @@ function App() { }} sx={{ cursor: 'pointer', - color: 'white', }} />
@@ -1625,7 +1618,6 @@ function App() { title={ + BACKUP WALLET } diff --git a/src/Wallets.tsx b/src/Wallets.tsx index 240ca40..02fb10a 100644 --- a/src/Wallets.tsx +++ b/src/Wallets.tsx @@ -486,11 +486,7 @@ const WalletItem = ({ wallet, updateWalletItem, idx, setSelectedWallet }) => { edge="end" aria-label="edit" > - +
{isEdit && ( From 1dfad6371a2b9a01954c5eebc2f91172aba694c9 Mon Sep 17 00:00:00 2001 From: Nicola Benaglia Date: Fri, 18 Apr 2025 15:24:13 +0200 Subject: [PATCH 10/55] Remove unused imports --- src/hooks/useHandlePaymentNotification.tsx | 233 +- src/qortalRequests/get.ts | 2678 ++++++++++---------- 2 files changed, 1476 insertions(+), 1435 deletions(-) diff --git a/src/hooks/useHandlePaymentNotification.tsx b/src/hooks/useHandlePaymentNotification.tsx index b5df816..cc6e4e5 100644 --- a/src/hooks/useHandlePaymentNotification.tsx +++ b/src/hooks/useHandlePaymentNotification.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react' +import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { getBaseApiReact } from '../App'; import { getData, storeData } from '../utils/chromeStorage'; import { checkDifference, getNameInfoForOthers } from '../background'; @@ -7,126 +7,131 @@ import { lastPaymentSeenTimestampAtom } from '../atoms/global'; import { subscribeToEvent, unsubscribeFromEvent } from '../utils/events'; export const useHandlePaymentNotification = (address) => { - const [latestTx, setLatestTx] = useState(null); + const [latestTx, setLatestTx] = useState(null); - const nameAddressOfSender = useRef({}) - const isFetchingName = useRef({}) - - - const [lastEnteredTimestampPayment, setLastEnteredTimestampPayment] = - useRecoilState(lastPaymentSeenTimestampAtom); - - useEffect(() => { - if (lastEnteredTimestampPayment && address) { - storeData(`last-seen-payment-${address}`, Date.now()).catch((error) => { - console.error(error); - }); - } - }, [lastEnteredTimestampPayment, address]); - - const getNameOrAddressOfSender = useCallback(async(senderAddress)=> { - if(isFetchingName.current[senderAddress]) return senderAddress - try { - isFetchingName.current[senderAddress] = true - const res = await getNameInfoForOthers(senderAddress) - nameAddressOfSender.current[senderAddress] = res || senderAddress - } catch (error) { - console.error(error) - } finally { - isFetchingName.current[senderAddress] = false - } - - }, []) + const nameAddressOfSender = useRef({}); + const isFetchingName = useRef({}); - const getNameOrAddressOfSenderMiddle = useCallback(async(senderAddress)=> { - getNameOrAddressOfSender(senderAddress) - return senderAddress - - }, [getNameOrAddressOfSender]) - - const hasNewPayment = useMemo(() => { - if (!latestTx) return false; - if (!checkDifference(latestTx?.timestamp)) return false; - if ( - !lastEnteredTimestampPayment || - lastEnteredTimestampPayment < latestTx?.timestamp - ) - return true; - - return false; - }, [lastEnteredTimestampPayment, latestTx]); - - const getLastSeenData = useCallback(async () => { - try { - if (!address) return; - const key = `last-seen-payment-${address}`; - - const res = await getData(key).catch(() => null); - if (res) { - setLastEnteredTimestampPayment(res); - } - - const response = await fetch( - `${getBaseApiReact()}/transactions/search?txType=PAYMENT&address=${address}&confirmationStatus=CONFIRMED&limit=5&reverse=true` - ); - - const responseData = await response.json(); - - const latestTx = responseData.filter( - (tx) => tx?.creatorAddress !== address && tx?.recipient === address - )[0]; - if (!latestTx) { - return; // continue to the next group - } - - setLatestTx(latestTx); - } catch (error) { + const [lastEnteredTimestampPayment, setLastEnteredTimestampPayment] = + useRecoilState(lastPaymentSeenTimestampAtom); + + useEffect(() => { + if (lastEnteredTimestampPayment && address) { + storeData(`last-seen-payment-${address}`, Date.now()).catch((error) => { console.error(error); - } - }, [address, setLastEnteredTimestampPayment]); - - - useEffect(() => { - getLastSeenData(); - // Handler function for incoming messages - const messageHandler = (event) => { - if (event.origin !== window.location.origin) { - return; - } - const message = event.data; - if (message?.action === "SET_PAYMENT_ANNOUNCEMENT" && message?.payload) { - setLatestTx(message.payload); - } - }; - - // Attach the event listener - window.addEventListener("message", messageHandler); - - // Clean up the event listener on component unmount - return () => { - window.removeEventListener("message", messageHandler); - }; - }, [getLastSeenData]); + }); + } + }, [lastEnteredTimestampPayment, address]); - const setLastEnteredTimestampPaymentEventFunc = useCallback( - (e) => { - setLastEnteredTimestampPayment(Date.now) - }, - [setLastEnteredTimestampPayment] + const getNameOrAddressOfSender = useCallback(async (senderAddress) => { + if (isFetchingName.current[senderAddress]) return senderAddress; + try { + isFetchingName.current[senderAddress] = true; + const res = await getNameInfoForOthers(senderAddress); + nameAddressOfSender.current[senderAddress] = res || senderAddress; + } catch (error) { + console.error(error); + } finally { + isFetchingName.current[senderAddress] = false; + } + }, []); + + const getNameOrAddressOfSenderMiddle = useCallback( + async (senderAddress) => { + getNameOrAddressOfSender(senderAddress); + return senderAddress; + }, + [getNameOrAddressOfSender] + ); + + const hasNewPayment = useMemo(() => { + if (!latestTx) return false; + if (!checkDifference(latestTx?.timestamp)) return false; + if ( + !lastEnteredTimestampPayment || + lastEnteredTimestampPayment < latestTx?.timestamp + ) + return true; + + return false; + }, [lastEnteredTimestampPayment, latestTx]); + + const getLastSeenData = useCallback(async () => { + try { + if (!address) return; + const key = `last-seen-payment-${address}`; + + const res = await getData(key).catch(() => null); + if (res) { + setLastEnteredTimestampPayment(res); + } + + const response = await fetch( + `${getBaseApiReact()}/transactions/search?txType=PAYMENT&address=${address}&confirmationStatus=CONFIRMED&limit=5&reverse=true` ); - - useEffect(() => { - subscribeToEvent("setLastEnteredTimestampPaymentEvent", setLastEnteredTimestampPaymentEventFunc); - - return () => { - unsubscribeFromEvent("setLastEnteredTimestampPaymentEvent", setLastEnteredTimestampPaymentEventFunc); - }; - }, [setLastEnteredTimestampPaymentEventFunc]); + + const responseData = await response.json(); + + const latestTx = responseData.filter( + (tx) => tx?.creatorAddress !== address && tx?.recipient === address + )[0]; + if (!latestTx) { + return; // continue to the next group + } + + setLatestTx(latestTx); + } catch (error) { + console.error(error); + } + }, [address, setLastEnteredTimestampPayment]); + + useEffect(() => { + getLastSeenData(); + // Handler function for incoming messages + const messageHandler = (event) => { + if (event.origin !== window.location.origin) { + return; + } + const message = event.data; + if (message?.action === 'SET_PAYMENT_ANNOUNCEMENT' && message?.payload) { + setLatestTx(message.payload); + } + }; + + // Attach the event listener + window.addEventListener('message', messageHandler); + + // Clean up the event listener on component unmount + return () => { + 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, hasNewPayment, setLastEnteredTimestampPayment, - nameAddressOfSender - } -} + nameAddressOfSender, + }; +}; diff --git a/src/qortalRequests/get.ts b/src/qortalRequests/get.ts index 4ae357f..a160305 100644 --- a/src/qortalRequests/get.ts +++ b/src/qortalRequests/get.ts @@ -1,6 +1,5 @@ -import { Sha256 } from "asmcrypto.js"; +import { Sha256 } from 'asmcrypto.js'; import { - computePow, createEndpoint, getBalanceInfo, getFee, @@ -8,12 +7,10 @@ import { getLastRef, getSaveWallet, processTransactionVersion2, - removeDuplicateWindow, signChatFunc, joinGroup as joinGroupFunc, sendQortFee, sendCoin as sendCoinFunc, - isUsingLocal, createBuyOrderTx, performPowTask, parseErrorResponse, @@ -35,18 +32,24 @@ import { cancelSellName, buyName, getBaseApi, -} from "../background"; -import { getNameInfo, uint8ArrayToObject } from "../backgroundFunctions/encryption"; -import { showSaveFilePicker } from "../components/Apps/useQortalMessageListener"; -import { getPublishesFromAdminsAdminSpace } from "../components/Chat/AdminSpaceInner"; -import { extractComponents } from "../components/Chat/MessageDisplay"; -import { decryptResource, getGroupAdmins, getPublishesFromAdmins, validateSecretKey } from "../components/Group/Group"; -import { QORT_DECIMALS } from "../constants/constants"; -import Base58 from "../deps/Base58"; -import ed2curve from "../deps/ed2curve"; -import nacl from "../deps/nacl-fast"; - - +} from '../background'; +import { + getNameInfo, + uint8ArrayToObject, +} from '../backgroundFunctions/encryption'; +import { showSaveFilePicker } from '../components/Apps/useQortalMessageListener'; +import { getPublishesFromAdminsAdminSpace } from '../components/Chat/AdminSpaceInner'; +import { extractComponents } from '../components/Chat/MessageDisplay'; +import { + decryptResource, + getGroupAdmins, + getPublishesFromAdmins, + validateSecretKey, +} from '../components/Group/Group'; +import { QORT_DECIMALS } from '../constants/constants'; +import Base58 from '../deps/Base58'; +import ed2curve from '../deps/ed2curve'; +import nacl from '../deps/nacl-fast'; import { base64ToUint8Array, createSymmetricKeyAndNonce, @@ -59,49 +62,49 @@ import { objectToBase64, uint8ArrayStartsWith, uint8ArrayToBase64, -} from "../qdn/encryption/group-encryption"; -import { publishData } from "../qdn/publish/pubish"; +} from '../qdn/encryption/group-encryption'; +import { publishData } from '../qdn/publish/pubish'; import { getPermission, isRunningGateway, setPermission, -} from "../qortalRequests"; -import TradeBotCreateRequest from "../transactions/TradeBotCreateRequest"; -import DeleteTradeOffer from "../transactions/TradeBotDeleteRequest"; -import signTradeBotTransaction from "../transactions/signTradeBotTransaction"; -import { createTransaction } from "../transactions/transactions"; -import { executeEvent } from "../utils/events"; -import { fileToBase64 } from "../utils/fileReading"; -import { mimeToExtensionMap } from "../utils/memeTypes"; -import { RequestQueueWithPromise } from "../utils/queue/queue"; -import utils from "../utils/utils"; +} from '../qortalRequests'; +import TradeBotCreateRequest from '../transactions/TradeBotCreateRequest'; +import DeleteTradeOffer from '../transactions/TradeBotDeleteRequest'; +import signTradeBotTransaction from '../transactions/signTradeBotTransaction'; +import { createTransaction } from '../transactions/transactions'; +import { executeEvent } from '../utils/events'; +import { fileToBase64 } from '../utils/fileReading'; +import { mimeToExtensionMap } from '../utils/memeTypes'; +import { RequestQueueWithPromise } from '../utils/queue/queue'; +import utils from '../utils/utils'; export const requestQueueGetAtAddresses = new RequestQueueWithPromise(10); const sellerForeignFee = { LITECOIN: { - value: "~0.00005", - ticker: "LTC", + value: '~0.00005', + ticker: 'LTC', }, DOGECOIN: { - value: "~0.005", - ticker: "DOGE", + value: '~0.005', + ticker: 'DOGE', }, BITCOIN: { - value: "~0.0001", - ticker: "BTC", + value: '~0.0001', + ticker: 'BTC', }, DIGIBYTE: { - value: "~0.0005", - ticker: "DGB", + value: '~0.0005', + ticker: 'DGB', }, RAVENCOIN: { - value: "~0.006", - ticker: "RVN", + value: '~0.006', + ticker: 'RVN', }, PIRATECHAIN: { - value: "~0.0002", - ticker: "ARRR", + value: '~0.0002', + ticker: 'ARRR', }, }; @@ -113,24 +116,28 @@ const rvnFeePerByte = 0.00001125; const MAX_RETRIES = 3; // Set max number of retries - -export async function retryTransaction(fn, args, throwError, retries = MAX_RETRIES) { +export async function retryTransaction( + fn, + args, + throwError, + retries = MAX_RETRIES +) { let attempt = 0; while (attempt < retries) { try { - return await fn(...args); + return await fn(...args); } catch (error) { console.error(`Attempt ${attempt + 1} failed: ${error.message}`); attempt++; if (attempt === retries) { - console.error("Max retries reached. Skipping transaction."); - if(throwError){ - throw new Error(error?.message || "Unable to process transaction") + console.error('Max retries reached. Skipping transaction.'); + if (throwError) { + throw new Error(error?.message || 'Unable to process transaction'); } else { - throw new Error(error?.message || "Unable to process transaction") + throw new Error(error?.message || 'Unable to process transaction'); } } - await new Promise(res => setTimeout(res, 10000)); + await new Promise((res) => setTimeout(res, 10000)); } } } @@ -142,23 +149,24 @@ function roundUpToDecimals(number, decimals = 8) { export const _createPoll = async ( { pollName, pollDescription, options }, - isFromExtension, skipPermission + isFromExtension, + skipPermission ) => { - const fee = await getFee("CREATE_POLL"); - let resPermission = {} - if(!skipPermission){ - resPermission = await getUserPermission( + const fee = await getFee('CREATE_POLL'); + let resPermission = {}; + if (!skipPermission) { + resPermission = await getUserPermission( { - text1: "You are requesting to create the poll below:", + text1: 'You are requesting to create the poll below:', text2: `Poll: ${pollName}`, text3: `Description: ${pollDescription}`, - text4: `Options: ${options?.join(", ")}`, + text4: `Options: ${options?.join(', ')}`, fee: fee.fee, }, isFromExtension ); } - + const { accepted = false } = resPermission; if (accepted || skipPermission) { @@ -186,11 +194,11 @@ export const _createPoll = async ( const res = await processTransactionVersion2(signedBytes); if (!res?.signature) throw new Error( - res?.message || "Transaction was not able to be processed" + res?.message || 'Transaction was not able to be processed' ); return res; } else { - throw new Error("User declined request"); + throw new Error('User declined request'); } }; @@ -198,11 +206,11 @@ const _deployAt = async ( { name, description, tags, creationBytes, amount, assetId, atType }, isFromExtension ) => { - const fee = await getFee("DEPLOY_AT"); + const fee = await getFee('DEPLOY_AT'); const resPermission = await getUserPermission( { - text1: "Would you like to deploy this AT?", + text1: 'Would you like to deploy this AT?', text2: `Name: ${name}`, text3: `Description: ${description}`, fee: fee.fee, @@ -242,24 +250,25 @@ const _deployAt = async ( const res = await processTransactionVersion2(signedBytes); if (!res?.signature) throw new Error( - res?.message || "Transaction was not able to be processed" + res?.message || 'Transaction was not able to be processed' ); return res; } else { - throw new Error("User declined transaction"); + throw new Error('User declined transaction'); } }; export const _voteOnPoll = async ( { pollName, optionIndex, optionName }, - isFromExtension, skipPermission + isFromExtension, + skipPermission ) => { - const fee = await getFee("VOTE_ON_POLL"); - let resPermission = {} - if(!skipPermission){ + const fee = await getFee('VOTE_ON_POLL'); + let resPermission = {}; + if (!skipPermission) { resPermission = await getUserPermission( { - text1: "You are being requested to vote on the poll below:", + text1: 'You are being requested to vote on the poll below:', text2: `Poll: ${pollName}`, text3: `Option: ${optionName}`, fee: fee.fee, @@ -267,7 +276,7 @@ export const _voteOnPoll = async ( isFromExtension ); } - + const { accepted = false } = resPermission; if (accepted || skipPermission) { @@ -294,11 +303,11 @@ export const _voteOnPoll = async ( const res = await processTransactionVersion2(signedBytes); if (!res?.signature) throw new Error( - res?.message || "Transaction was not able to be processed" + res?.message || 'Transaction was not able to be processed' ); return res; } else { - throw new Error("User declined request"); + throw new Error('User declined request'); } }; @@ -309,7 +318,7 @@ const handleFileMessage = (event) => { const { action, requestId, result, error } = event.data; if ( - action === "getFileFromIndexedDBResponse" && + action === 'getFileFromIndexedDBResponse' && fileRequestResolvers.has(requestId) ) { const { resolve, reject } = fileRequestResolvers.get(requestId); @@ -318,12 +327,12 @@ const handleFileMessage = (event) => { if (result) { resolve(result); } else { - reject(error || "Failed to retrieve file"); + reject(error || 'Failed to retrieve file'); } } }; -window.addEventListener("message", handleFileMessage); +window.addEventListener('message', handleFileMessage); function getFileFromContentScript(fileId) { return new Promise((resolve, reject) => { @@ -334,14 +343,14 @@ function getFileFromContentScript(fileId) { // Send the request message window.postMessage( - { action: "getFileFromIndexedDB", fileId, requestId }, + { action: 'getFileFromIndexedDB', fileId, requestId }, targetOrigin ); // Timeout to handle no response scenario setTimeout(() => { if (fileRequestResolvers.has(requestId)) { - fileRequestResolvers.get(requestId).reject("Request timed out"); + fileRequestResolvers.get(requestId).reject('Request timed out'); fileRequestResolvers.delete(requestId); // Clean up on timeout } }, 10000); // 10-second timeout @@ -362,7 +371,7 @@ const handleMessage = (event) => { // Check if this is the expected response action and if we have a stored resolver if ( - action === "QORTAL_REQUEST_PERMISSION_RESPONSE" && + action === 'QORTAL_REQUEST_PERMISSION_RESPONSE' && responseResolvers.has(requestId) ) { // Resolve the stored promise with the result @@ -371,7 +380,7 @@ const handleMessage = (event) => { } }; -window.addEventListener("message", handleMessage); +window.addEventListener('message', handleMessage); async function getUserPermission(payload, isFromExtension) { return new Promise((resolve) => { @@ -382,7 +391,7 @@ async function getUserPermission(payload, isFromExtension) { // Send the request message window.postMessage( { - action: "QORTAL_REQUEST_PERMISSION", + action: 'QORTAL_REQUEST_PERMISSION', payload, requestId, isFromExtension, @@ -400,7 +409,11 @@ async function getUserPermission(payload, isFromExtension) { }); } -export const getUserAccount = async ({ isFromExtension, appInfo, skipAuth }) => { +export const getUserAccount = async ({ + isFromExtension, + appInfo, + skipAuth, +}) => { try { const value = (await getPermission(`qAPPAutoAuth-${appInfo?.name}`)) || false; @@ -408,17 +421,17 @@ export const getUserAccount = async ({ isFromExtension, appInfo, skipAuth }) => if (value) { skip = true; } - if(skipAuth){ - skip = true + if (skipAuth) { + skip = true; } let resPermission; if (!skip) { resPermission = await getUserPermission( { - text1: "Do you give this application permission to authenticate?", + text1: 'Do you give this application permission to authenticate?', checkbox1: { value: false, - label: "Always authenticate automatically", + label: 'Always authenticate automatically', }, }, isFromExtension @@ -438,10 +451,10 @@ export const getUserAccount = async ({ isFromExtension, appInfo, skipAuth }) => publicKey, }; } else { - throw new Error("User declined request"); + throw new Error('User declined request'); } } catch (error) { - throw new Error("Unable to fetch user account"); + throw new Error('Unable to fetch user account'); } }; @@ -452,7 +465,7 @@ export const encryptData = async (data, sender) => { data64 = await fileToBase64(data?.file || data?.blob); } if (!data64) { - throw new Error("Please include data to encrypt"); + throw new Error('Please include data to encrypt'); } const resKeyPair = await getKeyPair(); const parsedData = resKeyPair; @@ -468,195 +481,203 @@ export const encryptData = async (data, sender) => { if (encryptDataResponse) { return encryptDataResponse; } else { - throw new Error("Unable to encrypt"); + throw new Error('Unable to encrypt'); } }; export const encryptQortalGroupData = async (data, sender) => { let data64 = data?.data64 || data?.base64; - let groupId = data?.groupId - let isAdmins = data?.isAdmins - if(!groupId){ - throw new Error('Please provide a groupId') + let groupId = data?.groupId; + let isAdmins = data?.isAdmins; + if (!groupId) { + throw new Error('Please provide a groupId'); } if (data?.file || data?.blob) { data64 = await fileToBase64(data?.file || data?.blob); } if (!data64) { - throw new Error("Please include data to encrypt"); + throw new Error('Please include data to encrypt'); } - - let secretKeyObject - if(!isAdmins){ - if(groupSecretkeys[groupId] && groupSecretkeys[groupId].secretKeyObject && groupSecretkeys[groupId]?.timestamp && (Date.now() - groupSecretkeys[groupId]?.timestamp) < 1200000){ - secretKeyObject = groupSecretkeys[groupId].secretKeyObject - } - - if(!secretKeyObject){ - const { names } = - await getGroupAdmins(groupId) - - const publish = - await getPublishesFromAdmins(names, groupId); - if(publish === false) throw new Error('No group key found.') - const url = await createEndpoint(`/arbitrary/DOCUMENT_PRIVATE/${publish.name}/${ - publish.identifier - }?encoding=base64&rebuild=true`); - - const res = await fetch( -url - ); - const resData = await res.text(); - - const decryptedKey: any = await decryptResource(resData, true); - - const dataint8Array = base64ToUint8Array(decryptedKey.data); - const decryptedKeyToObject = uint8ArrayToObject(dataint8Array); - - if (!validateSecretKey(decryptedKeyToObject)) - throw new Error("SecretKey is not valid"); - secretKeyObject = decryptedKeyToObject - groupSecretkeys[groupId] = { - secretKeyObject, - timestamp: Date.now() + let secretKeyObject; + if (!isAdmins) { + if ( + groupSecretkeys[groupId] && + groupSecretkeys[groupId].secretKeyObject && + groupSecretkeys[groupId]?.timestamp && + Date.now() - groupSecretkeys[groupId]?.timestamp < 1200000 + ) { + secretKeyObject = groupSecretkeys[groupId].secretKeyObject; } - } -} else { - if(groupSecretkeys[`admins-${groupId}`] && groupSecretkeys[`admins-${groupId}`].secretKeyObject && groupSecretkeys[`admins-${groupId}`]?.timestamp && (Date.now() - groupSecretkeys[`admins-${groupId}`]?.timestamp) < 1200000){ - secretKeyObject = groupSecretkeys[`admins-${groupId}`].secretKeyObject - } + if (!secretKeyObject) { + const { names } = await getGroupAdmins(groupId); - if(!secretKeyObject){ - const { names } = - await getGroupAdmins(groupId) + const publish = await getPublishesFromAdmins(names, groupId); + if (publish === false) throw new Error('No group key found.'); + const url = await createEndpoint( + `/arbitrary/DOCUMENT_PRIVATE/${publish.name}/${ + publish.identifier + }?encoding=base64&rebuild=true` + ); - const publish = - await getPublishesFromAdminsAdminSpace(names, groupId); - if(publish === false) throw new Error('No group key found.') - const url = await createEndpoint(`/arbitrary/DOCUMENT_PRIVATE/${publish.name}/${ - publish.identifier - }?encoding=base64&rebuild=true`); + const res = await fetch(url); + const resData = await res.text(); - const res = await fetch( -url - ); - const resData = await res.text(); - const decryptedKey: any = await decryptResource(resData, true); - const dataint8Array = base64ToUint8Array(decryptedKey.data); - const decryptedKeyToObject = uint8ArrayToObject(dataint8Array); + const decryptedKey: any = await decryptResource(resData, true); - if (!validateSecretKey(decryptedKeyToObject)) - throw new Error("SecretKey is not valid"); - secretKeyObject = decryptedKeyToObject - groupSecretkeys[`admins-${groupId}`] = { - secretKeyObject, - timestamp: Date.now() + const dataint8Array = base64ToUint8Array(decryptedKey.data); + const decryptedKeyToObject = uint8ArrayToObject(dataint8Array); + + if (!validateSecretKey(decryptedKeyToObject)) + throw new Error('SecretKey is not valid'); + secretKeyObject = decryptedKeyToObject; + groupSecretkeys[groupId] = { + secretKeyObject, + timestamp: Date.now(), + }; + } + } else { + if ( + groupSecretkeys[`admins-${groupId}`] && + groupSecretkeys[`admins-${groupId}`].secretKeyObject && + groupSecretkeys[`admins-${groupId}`]?.timestamp && + Date.now() - groupSecretkeys[`admins-${groupId}`]?.timestamp < 1200000 + ) { + secretKeyObject = groupSecretkeys[`admins-${groupId}`].secretKeyObject; + } + + if (!secretKeyObject) { + const { names } = await getGroupAdmins(groupId); + + const publish = await getPublishesFromAdminsAdminSpace(names, groupId); + if (publish === false) throw new Error('No group key found.'); + const url = await createEndpoint( + `/arbitrary/DOCUMENT_PRIVATE/${publish.name}/${ + publish.identifier + }?encoding=base64&rebuild=true` + ); + + const res = await fetch(url); + const resData = await res.text(); + const decryptedKey: any = await decryptResource(resData, true); + const dataint8Array = base64ToUint8Array(decryptedKey.data); + const decryptedKeyToObject = uint8ArrayToObject(dataint8Array); + + if (!validateSecretKey(decryptedKeyToObject)) + throw new Error('SecretKey is not valid'); + secretKeyObject = decryptedKeyToObject; + groupSecretkeys[`admins-${groupId}`] = { + secretKeyObject, + timestamp: Date.now(), + }; } } + const resGroupEncryptedResource = encryptSingle({ + data64, + secretKeyObject: secretKeyObject, + }); - -} - - const resGroupEncryptedResource = encryptSingle({ - data64, secretKeyObject: secretKeyObject, - }) - if (resGroupEncryptedResource) { return resGroupEncryptedResource; } else { - throw new Error("Unable to encrypt"); + throw new Error('Unable to encrypt'); } }; export const decryptQortalGroupData = async (data, sender) => { let data64 = data?.data64 || data?.base64; - let groupId = data?.groupId - let isAdmins = data?.isAdmins - if(!groupId){ - throw new Error('Please provide a groupId') + let groupId = data?.groupId; + let isAdmins = data?.isAdmins; + if (!groupId) { + throw new Error('Please provide a groupId'); } if (!data64) { - throw new Error("Please include data to encrypt"); + throw new Error('Please include data to encrypt'); } - let secretKeyObject - if(!isAdmins){ - if(groupSecretkeys[groupId] && groupSecretkeys[groupId].secretKeyObject && groupSecretkeys[groupId]?.timestamp && (Date.now() - groupSecretkeys[groupId]?.timestamp) < 1200000){ - secretKeyObject = groupSecretkeys[groupId].secretKeyObject - } - if(!secretKeyObject){ - const { names } = - await getGroupAdmins(groupId) - - const publish = - await getPublishesFromAdmins(names, groupId); - if(publish === false) throw new Error('No group key found.') - const url = await createEndpoint(`/arbitrary/DOCUMENT_PRIVATE/${publish.name}/${ - publish.identifier - }?encoding=base64&rebuild=true`); - - const res = await fetch( -url - ); - const resData = await res.text(); - const decryptedKey: any = await decryptResource(resData, true); - - const dataint8Array = base64ToUint8Array(decryptedKey.data); - const decryptedKeyToObject = uint8ArrayToObject(dataint8Array); - if (!validateSecretKey(decryptedKeyToObject)) - throw new Error("SecretKey is not valid"); - secretKeyObject = decryptedKeyToObject - groupSecretkeys[groupId] = { - secretKeyObject, - timestamp: Date.now() + let secretKeyObject; + if (!isAdmins) { + if ( + groupSecretkeys[groupId] && + groupSecretkeys[groupId].secretKeyObject && + groupSecretkeys[groupId]?.timestamp && + Date.now() - groupSecretkeys[groupId]?.timestamp < 1200000 + ) { + secretKeyObject = groupSecretkeys[groupId].secretKeyObject; } - } -} else { - if(groupSecretkeys[`admins-${groupId}`] && groupSecretkeys[`admins-${groupId}`].secretKeyObject && groupSecretkeys[`admins-${groupId}`]?.timestamp && (Date.now() - groupSecretkeys[`admins-${groupId}`]?.timestamp) < 1200000){ - secretKeyObject = groupSecretkeys[`admins-${groupId}`].secretKeyObject - } - if(!secretKeyObject){ - const { names } = - await getGroupAdmins(groupId) + if (!secretKeyObject) { + const { names } = await getGroupAdmins(groupId); - const publish = - await getPublishesFromAdminsAdminSpace(names, groupId); - if(publish === false) throw new Error('No group key found.') - const url = await createEndpoint(`/arbitrary/DOCUMENT_PRIVATE/${publish.name}/${ - publish.identifier - }?encoding=base64&rebuild=true`); + const publish = await getPublishesFromAdmins(names, groupId); + if (publish === false) throw new Error('No group key found.'); + const url = await createEndpoint( + `/arbitrary/DOCUMENT_PRIVATE/${publish.name}/${ + publish.identifier + }?encoding=base64&rebuild=true` + ); - const res = await fetch( -url - ); - const resData = await res.text(); - const decryptedKey: any = await decryptResource(resData, true); + const res = await fetch(url); + const resData = await res.text(); + const decryptedKey: any = await decryptResource(resData, true); - const dataint8Array = base64ToUint8Array(decryptedKey.data); - const decryptedKeyToObject = uint8ArrayToObject(dataint8Array); - if (!validateSecretKey(decryptedKeyToObject)) - throw new Error("SecretKey is not valid"); - secretKeyObject = decryptedKeyToObject - groupSecretkeys[`admins-${groupId}`] = { - secretKeyObject, - timestamp: Date.now() + const dataint8Array = base64ToUint8Array(decryptedKey.data); + const decryptedKeyToObject = uint8ArrayToObject(dataint8Array); + if (!validateSecretKey(decryptedKeyToObject)) + throw new Error('SecretKey is not valid'); + secretKeyObject = decryptedKeyToObject; + groupSecretkeys[groupId] = { + secretKeyObject, + timestamp: Date.now(), + }; + } + } else { + if ( + groupSecretkeys[`admins-${groupId}`] && + groupSecretkeys[`admins-${groupId}`].secretKeyObject && + groupSecretkeys[`admins-${groupId}`]?.timestamp && + Date.now() - groupSecretkeys[`admins-${groupId}`]?.timestamp < 1200000 + ) { + secretKeyObject = groupSecretkeys[`admins-${groupId}`].secretKeyObject; + } + if (!secretKeyObject) { + const { names } = await getGroupAdmins(groupId); + + const publish = await getPublishesFromAdminsAdminSpace(names, groupId); + if (publish === false) throw new Error('No group key found.'); + const url = await createEndpoint( + `/arbitrary/DOCUMENT_PRIVATE/${publish.name}/${ + publish.identifier + }?encoding=base64&rebuild=true` + ); + + const res = await fetch(url); + const resData = await res.text(); + const decryptedKey: any = await decryptResource(resData, true); + + const dataint8Array = base64ToUint8Array(decryptedKey.data); + const decryptedKeyToObject = uint8ArrayToObject(dataint8Array); + if (!validateSecretKey(decryptedKeyToObject)) + throw new Error('SecretKey is not valid'); + secretKeyObject = decryptedKeyToObject; + groupSecretkeys[`admins-${groupId}`] = { + secretKeyObject, + timestamp: Date.now(), + }; } } - -} - - const resGroupDecryptResource = decryptSingle({ - data64, secretKeyObject: secretKeyObject, skipDecodeBase64: true - }) + const resGroupDecryptResource = decryptSingle({ + data64, + secretKeyObject: secretKeyObject, + skipDecodeBase64: true, + }); if (resGroupDecryptResource) { return resGroupDecryptResource; } else { - throw new Error("Unable to decrypt"); + throw new Error('Unable to decrypt'); } }; @@ -667,14 +688,14 @@ export const encryptDataWithSharingKey = async (data, sender) => { data64 = await fileToBase64(data?.file || data?.blob); } if (!data64) { - throw new Error("Please include data to encrypt"); + throw new Error('Please include data to encrypt'); } - const symmetricKey = createSymmetricKeyAndNonce() + const symmetricKey = createSymmetricKeyAndNonce(); const dataObject = { data: data64, - key:symmetricKey.messageKey - } - const dataObjectBase64 = await objectToBase64(dataObject) + key: symmetricKey.messageKey, + }; + const dataObjectBase64 = await objectToBase64(dataObject); const resKeyPair = await getKeyPair(); const parsedData = resKeyPair; @@ -686,70 +707,70 @@ export const encryptDataWithSharingKey = async (data, sender) => { publicKeys: publicKeys, privateKey, userPublicKey, - customSymmetricKey: symmetricKey.messageKey + customSymmetricKey: symmetricKey.messageKey, }); if (encryptDataResponse) { return encryptDataResponse; } else { - throw new Error("Unable to encrypt"); + throw new Error('Unable to encrypt'); } }; export const decryptDataWithSharingKey = async (data, sender) => { const { encryptedData, key } = data; - if (!encryptedData) { - throw new Error("Please include data to decrypt"); + throw new Error('Please include data to decrypt'); } - const decryptedData = await decryptGroupEncryptionWithSharingKey({data64EncryptedData: encryptedData, key}) - const base64ToObject = JSON.parse(atob(decryptedData)) - if(!base64ToObject.data) throw new Error('No data in the encrypted resource') - return base64ToObject.data + const decryptedData = await decryptGroupEncryptionWithSharingKey({ + data64EncryptedData: encryptedData, + key, + }); + const base64ToObject = JSON.parse(atob(decryptedData)); + if (!base64ToObject.data) + throw new Error('No data in the encrypted resource'); + return base64ToObject.data; }; export const getHostedData = async (data, isFromExtension) => { const isGateway = await isRunningGateway(); if (isGateway) { - throw new Error("This action cannot be done through a public node"); + throw new Error('This action cannot be done through a public node'); } const resPermission = await getUserPermission( { - text1: "Do you give this application permission to", + text1: 'Do you give this application permission to', text2: `Get a list of your hosted data?`, }, isFromExtension ); const { accepted } = resPermission; - if(accepted){ + if (accepted) { const limit = data?.limit ? data?.limit : 20; - const query = data?.query ? data?.query : "" - const offset = data?.offset ? data?.offset : 0 + const query = data?.query ? data?.query : ''; + const offset = data?.offset ? data?.offset : 0; - let urlPath = `/arbitrary/hosted/resources/?limit=${limit}&offset=${offset}` - if(query){ - urlPath = urlPath + `&query=${query}` + let urlPath = `/arbitrary/hosted/resources/?limit=${limit}&offset=${offset}`; + if (query) { + urlPath = urlPath + `&query=${query}`; } - - const url = await createEndpoint(urlPath); - const response = await fetch(url); - const dataResponse = await response.json(); - return dataResponse - - } else { - throw new Error("User declined to get list of hosted resources"); + const url = await createEndpoint(urlPath); + const response = await fetch(url); + const dataResponse = await response.json(); + return dataResponse; + } else { + throw new Error('User declined to get list of hosted resources'); } - }; export const deleteHostedData = async (data, isFromExtension) => { const isGateway = await isRunningGateway(); if (isGateway) { - throw new Error("This action cannot be done through a public node"); + throw new Error('This action cannot be done through a public node'); } - const requiredFields = ["hostedData"]; + const requiredFields = ['hostedData']; const missingFields: string[] = []; requiredFields.forEach((field) => { if (!data[field]) { @@ -758,35 +779,36 @@ export const deleteHostedData = async (data, isFromExtension) => { }); const resPermission = await getUserPermission( { - text1: "Do you give this application permission to", + text1: 'Do you give this application permission to', text2: `Delete ${data?.hostedData?.length} hosted resources?`, }, isFromExtension ); const { accepted } = resPermission; - if(accepted){ + if (accepted) { const { hostedData } = data; - for (const hostedDataItem of hostedData){ - try { - const url = await createEndpoint(`/arbitrary/resource/${hostedDataItem.service}/${hostedDataItem.name}/${hostedDataItem.identifier}`); - await fetch(url, { - method: "DELETE", - headers: { - "Content-Type": "application/json", - } - }); - } catch (error) { - //error + for (const hostedDataItem of hostedData) { + try { + const url = await createEndpoint( + `/arbitrary/resource/${hostedDataItem.service}/${hostedDataItem.name}/${hostedDataItem.identifier}` + ); + await fetch(url, { + method: 'DELETE', + headers: { + 'Content-Type': 'application/json', + }, + }); + } catch (error) { + //error + } } - } - return true + return true; } else { - throw new Error("User declined delete hosted resources"); + throw new Error('User declined delete hosted resources'); } - }; export const decryptData = async (data) => { const { encryptedData, publicKey } = data; @@ -800,7 +822,7 @@ export const decryptData = async (data) => { const uint8Array = base64ToUint8Array(encryptedData); const startsWithQortalEncryptedData = uint8ArrayStartsWith( uint8Array, - "qortalEncryptedData" + 'qortalEncryptedData' ); if (startsWithQortalEncryptedData) { if (!publicKey) { @@ -816,7 +838,7 @@ export const decryptData = async (data) => { } const startsWithQortalGroupEncryptedData = uint8ArrayStartsWith( uint8Array, - "qortalGroupEncryptedData" + 'qortalGroupEncryptedData' ); if (startsWithQortalGroupEncryptedData) { const decryptedData = decryptGroupDataQortalRequest( @@ -826,15 +848,15 @@ export const decryptData = async (data) => { const decryptedDataToBase64 = uint8ArrayToBase64(decryptedData); return decryptedDataToBase64; } - throw new Error("Unable to decrypt"); + throw new Error('Unable to decrypt'); }; export const getListItems = async (data, isFromExtension) => { const isGateway = await isRunningGateway(); if (isGateway) { - throw new Error("This action cannot be done through a public node"); + throw new Error('This action cannot be done through a public node'); } - const requiredFields = ["list_name"]; + const requiredFields = ['list_name']; const missingFields: string[] = []; requiredFields.forEach((field) => { if (!data[field]) { @@ -842,11 +864,11 @@ export const getListItems = async (data, isFromExtension) => { } }); if (missingFields.length > 0) { - const missingFieldsString = missingFields.join(", "); + const missingFieldsString = missingFields.join(', '); const errorMsg = `Missing fields: ${missingFieldsString}`; throw new Error(errorMsg); } - const value = (await getPermission("qAPPAutoLists")) || false; + const value = (await getPermission('qAPPAutoLists')) || false; let skip = false; if (value) { @@ -858,12 +880,12 @@ export const getListItems = async (data, isFromExtension) => { if (!skip) { resPermission = await getUserPermission( { - text1: "Do you give this application permission to", - text2: "Access the list", + text1: 'Do you give this application permission to', + text2: 'Access the list', highlightedText: data.list_name, checkbox1: { value: value, - label: "Always allow lists to be retrieved automatically", + label: 'Always allow lists to be retrieved automatically', }, }, isFromExtension @@ -871,27 +893,27 @@ export const getListItems = async (data, isFromExtension) => { const { accepted, checkbox1 } = resPermission; acceptedVar = accepted; checkbox1Var = checkbox1; - setPermission("qAPPAutoLists", checkbox1); + setPermission('qAPPAutoLists', checkbox1); } if (acceptedVar || skip) { const url = await createEndpoint(`/lists/${data.list_name}`); const response = await fetch(url); - if (!response.ok) throw new Error("Failed to fetch"); + if (!response.ok) throw new Error('Failed to fetch'); const list = await response.json(); return list; } else { - throw new Error("User declined to share list"); + throw new Error('User declined to share list'); } }; export const addListItems = async (data, isFromExtension) => { const isGateway = await isRunningGateway(); if (isGateway) { - throw new Error("This action cannot be done through a public node"); + throw new Error('This action cannot be done through a public node'); } - const requiredFields = ["list_name", "items"]; + const requiredFields = ['list_name', 'items']; const missingFields: string[] = []; requiredFields.forEach((field) => { if (!data[field]) { @@ -899,7 +921,7 @@ export const addListItems = async (data, isFromExtension) => { } }); if (missingFields.length > 0) { - const missingFieldsString = missingFields.join(", "); + const missingFieldsString = missingFields.join(', '); const errorMsg = `Missing fields: ${missingFieldsString}`; throw new Error(errorMsg); } @@ -909,9 +931,9 @@ export const addListItems = async (data, isFromExtension) => { const resPermission = await getUserPermission( { - text1: "Do you give this application permission to", + text1: 'Do you give this application permission to', text2: `Add the following to the list ${list_name}:`, - highlightedText: items.join(", "), + highlightedText: items.join(', '), }, isFromExtension ); @@ -924,14 +946,14 @@ export const addListItems = async (data, isFromExtension) => { }; const bodyToString = JSON.stringify(body); const response = await fetch(url, { - method: "POST", + method: 'POST', headers: { - "Content-Type": "application/json", + 'Content-Type': 'application/json', }, body: bodyToString, }); - if (!response.ok) throw new Error("Failed to add to list"); + if (!response.ok) throw new Error('Failed to add to list'); let res; try { res = await response.clone().json(); @@ -940,16 +962,16 @@ export const addListItems = async (data, isFromExtension) => { } return res; } else { - throw new Error("User declined add to list"); + throw new Error('User declined add to list'); } }; export const deleteListItems = async (data, isFromExtension) => { const isGateway = await isRunningGateway(); if (isGateway) { - throw new Error("This action cannot be done through a public node"); + throw new Error('This action cannot be done through a public node'); } - const requiredFields = ["list_name"]; + const requiredFields = ['list_name']; const missingFields: string[] = []; requiredFields.forEach((field) => { if (!data[field]) { @@ -957,20 +979,20 @@ export const deleteListItems = async (data, isFromExtension) => { } }); if (missingFields.length > 0) { - const missingFieldsString = missingFields.join(", "); + const missingFieldsString = missingFields.join(', '); const errorMsg = `Missing fields: ${missingFieldsString}`; throw new Error(errorMsg); } - if(!data?.item && !data?.items){ - throw new Error('Missing fields: items') + if (!data?.item && !data?.items) { + throw new Error('Missing fields: items'); } const item = data?.item; - const items = data?.items + const items = data?.items; const list_name = data.list_name; const resPermission = await getUserPermission( { - text1: "Do you give this application permission to", + text1: 'Do you give this application permission to', text2: `Remove the following from the list ${list_name}:`, highlightedText: items ? JSON.stringify(items) : item, }, @@ -985,14 +1007,14 @@ export const deleteListItems = async (data, isFromExtension) => { }; const bodyToString = JSON.stringify(body); const response = await fetch(url, { - method: "DELETE", + method: 'DELETE', headers: { - "Content-Type": "application/json", + 'Content-Type': 'application/json', }, body: bodyToString, }); - if (!response.ok) throw new Error("Failed to add to list"); + if (!response.ok) throw new Error('Failed to add to list'); let res; try { res = await response.clone().json(); @@ -1001,7 +1023,7 @@ export const deleteListItems = async (data, isFromExtension) => { } return res; } else { - throw new Error("User declined delete from list"); + throw new Error('User declined delete from list'); } }; @@ -1010,7 +1032,7 @@ export const publishQDNResource = async ( sender, isFromExtension ) => { - const requiredFields = ["service"]; + const requiredFields = ['service']; const missingFields: string[] = []; requiredFields.forEach((field) => { if (!data[field]) { @@ -1018,25 +1040,25 @@ export const publishQDNResource = async ( } }); if (missingFields.length > 0) { - const missingFieldsString = missingFields.join(", "); + const missingFieldsString = missingFields.join(', '); const errorMsg = `Missing fields: ${missingFieldsString}`; throw new Error(errorMsg); } if (!data.file && !data.data64 && !data.base64) { - throw new Error("No data or file was submitted"); + throw new Error('No data or file was submitted'); } // Use "default" if user hasn't specified an identifier const service = data.service; - const appFee = data?.appFee ? +data.appFee : undefined - const appFeeRecipient = data?.appFeeRecipient - let hasAppFee = false - if(appFee && appFee > 0 && appFeeRecipient){ - hasAppFee = true + const appFee = data?.appFee ? +data.appFee : undefined; + const appFeeRecipient = data?.appFeeRecipient; + let hasAppFee = false; + if (appFee && appFee > 0 && appFeeRecipient) { + hasAppFee = true; } const registeredName = await getNameInfo(); const name = registeredName; - if(!name){ - throw new Error('User has no Qortal name') + if (!name) { + throw new Error('User has no Qortal name'); } let identifier = data.identifier; let data64 = data.data64 || data.base64; @@ -1046,18 +1068,18 @@ export const publishQDNResource = async ( const category = data.category; const tags = data?.tags || []; -const result = {}; + const result = {}; -// Fill tags dynamically while maintaining backward compatibility -for (let i = 0; i < 5; i++) { - result[`tag${i + 1}`] = tags[i] || data[`tag${i + 1}`] || undefined; -} + // Fill tags dynamically while maintaining backward compatibility + for (let i = 0; i < 5; i++) { + result[`tag${i + 1}`] = tags[i] || data[`tag${i + 1}`] || undefined; + } -// Access tag1 to tag5 from result -const { tag1, tag2, tag3, tag4, tag5 } = result; + // Access tag1 to tag5 from result + const { tag1, tag2, tag3, tag4, tag5 } = result; if (data.identifier == null) { - identifier = "default"; + identifier = 'default'; } if (data?.file || data?.blob) { data64 = await fileToBase64(data?.file || data?.blob); @@ -1067,10 +1089,9 @@ const { tag1, tag2, tag3, tag4, tag5 } = result; (!data.publicKeys || (Array.isArray(data.publicKeys) && data.publicKeys.length === 0)) ) { - throw new Error("Encrypting data requires public keys"); + throw new Error('Encrypting data requires public keys'); } - if (data.encrypt) { try { const resKeyPair = await getKeyPair(); @@ -1088,46 +1109,45 @@ const { tag1, tag2, tag3, tag4, tag5 } = result; } } catch (error) { throw new Error( - error.message || "Upload failed due to failed encryption" + error.message || 'Upload failed due to failed encryption' ); } } - const fee = await getFee("ARBITRARY"); + const fee = await getFee('ARBITRARY'); - const handleDynamicValues = {} - if(hasAppFee){ - const feePayment = await getFee("PAYMENT"); + const handleDynamicValues = {}; + if (hasAppFee) { + const feePayment = await getFee('PAYMENT'); - handleDynamicValues['appFee'] = +appFee + +feePayment.fee, - handleDynamicValues['checkbox1'] = { - value: true, - label: "accept app fee", - } + (handleDynamicValues['appFee'] = +appFee + +feePayment.fee), + (handleDynamicValues['checkbox1'] = { + value: true, + label: 'accept app fee', + }); } - if(!!data?.encrypt){ - handleDynamicValues['highlightedText'] = `isEncrypted: ${!!data.encrypt}` + if (!!data?.encrypt) { + handleDynamicValues['highlightedText'] = `isEncrypted: ${!!data.encrypt}`; } const resPermission = await getUserPermission( { - text1: "Do you give this application permission to publish to QDN?", + text1: 'Do you give this application permission to publish to QDN?', text2: `service: ${service}`, text3: `identifier: ${identifier || null}`, fee: fee.fee, - ...handleDynamicValues + ...handleDynamicValues, }, isFromExtension ); const { accepted, checkbox1 = false } = resPermission; if (accepted) { - try { const resPublish = await publishData({ registeredName: encodeURIComponent(name), file: data64, service: service, identifier: encodeURIComponent(identifier), - uploadType: "file", + uploadType: 'file', isBase64: true, filename: filename, title, @@ -1141,18 +1161,21 @@ const { tag1, tag2, tag3, tag4, tag5 } = result; apiVersion: 2, withFee: true, }); - if(resPublish?.signature && hasAppFee && checkbox1){ - sendCoinFunc({ - amount: appFee, - receiver: appFeeRecipient - }, true) + if (resPublish?.signature && hasAppFee && checkbox1) { + sendCoinFunc( + { + amount: appFee, + receiver: appFeeRecipient, + }, + true + ); } return resPublish; } catch (error) { - throw new Error(error?.message || "Upload failed"); + throw new Error(error?.message || 'Upload failed'); } } else { - throw new Error("User declined request"); + throw new Error('User declined request'); } }; @@ -1162,9 +1185,9 @@ export const checkArrrSyncStatus = async (seed) => { while (tries < 36) { const response = await fetch(_url, { - method: "POST", + method: 'POST', headers: { - "Content-Type": "application/json", + 'Content-Type': 'application/json', }, body: seed, }); @@ -1176,7 +1199,7 @@ export const checkArrrSyncStatus = async (seed) => { res = await response.text(); } - if (res.indexOf('<') > -1 || res !== "Synchronized") { + if (res.indexOf('<') > -1 || res !== 'Synchronized') { // Wait 2 seconds before trying again await new Promise((resolve) => setTimeout(resolve, 2000)); tries += 1; @@ -1187,16 +1210,15 @@ export const checkArrrSyncStatus = async (seed) => { } // If we exceed 6 tries, throw an error - throw new Error("Failed to synchronize after 36 attempts"); + throw new Error('Failed to synchronize after 36 attempts'); }; - export const publishMultipleQDNResources = async ( data: any, sender, isFromExtension ) => { - const requiredFields = ["resources"]; + const requiredFields = ['resources']; const missingFields: string[] = []; let feeAmount = null; requiredFields.forEach((field) => { @@ -1205,32 +1227,32 @@ export const publishMultipleQDNResources = async ( } }); if (missingFields.length > 0) { - const missingFieldsString = missingFields.join(", "); + const missingFieldsString = missingFields.join(', '); const errorMsg = `Missing fields: ${missingFieldsString}`; throw new Error(errorMsg); } const resources = data.resources; if (!Array.isArray(resources)) { - throw new Error("Invalid data"); + throw new Error('Invalid data'); } if (resources.length === 0) { - throw new Error("No resources to publish"); + throw new Error('No resources to publish'); } - const encrypt = data?.encrypt + const encrypt = data?.encrypt; for (const resource of resources) { - const resourceEncrypt = encrypt && resource?.disableEncrypt !== true - if (!resourceEncrypt && resource?.service.endsWith("_PRIVATE")) { - const errorMsg = "Only encrypted data can go into private services"; - throw new Error(errorMsg) - } else if(resourceEncrypt && !resource?.service.endsWith("_PRIVATE")){ - const errorMsg = "For an encrypted publish please use a service that ends with _PRIVATE"; - throw new Error(errorMsg) + const resourceEncrypt = encrypt && resource?.disableEncrypt !== true; + if (!resourceEncrypt && resource?.service.endsWith('_PRIVATE')) { + const errorMsg = 'Only encrypted data can go into private services'; + throw new Error(errorMsg); + } else if (resourceEncrypt && !resource?.service.endsWith('_PRIVATE')) { + const errorMsg = + 'For an encrypted publish please use a service that ends with _PRIVATE'; + throw new Error(errorMsg); } } - - + // if ( // data.encrypt && // (!data.publicKeys || @@ -1238,35 +1260,35 @@ export const publishMultipleQDNResources = async ( // ) { // throw new Error("Encrypting data requires public keys"); // } - const fee = await getFee("ARBITRARY"); + const fee = await getFee('ARBITRARY'); const registeredName = await getNameInfo(); const name = registeredName; - if(!name){ - throw new Error('You need a Qortal name to publish.') + if (!name) { + throw new Error('You need a Qortal name to publish.'); } - const appFee = data?.appFee ? +data.appFee : undefined - const appFeeRecipient = data?.appFeeRecipient - let hasAppFee = false - if(appFee && appFee > 0 && appFeeRecipient){ - hasAppFee = true + const appFee = data?.appFee ? +data.appFee : undefined; + const appFeeRecipient = data?.appFeeRecipient; + let hasAppFee = false; + if (appFee && appFee > 0 && appFeeRecipient) { + hasAppFee = true; } - const handleDynamicValues = {} - if(hasAppFee){ - const feePayment = await getFee("PAYMENT"); + const handleDynamicValues = {}; + if (hasAppFee) { + const feePayment = await getFee('PAYMENT'); - handleDynamicValues['appFee'] = +appFee + +feePayment.fee, - handleDynamicValues['checkbox1'] = { - value: true, - label: "accept app fee", - } + (handleDynamicValues['appFee'] = +appFee + +feePayment.fee), + (handleDynamicValues['checkbox1'] = { + value: true, + label: 'accept app fee', + }); } - if(data?.encrypt){ - handleDynamicValues['highlightedText'] = `isEncrypted: ${!!data.encrypt}` + if (data?.encrypt) { + handleDynamicValues['highlightedText'] = `isEncrypted: ${!!data.encrypt}`; } const resPermission = await getUserPermission( { - text1: "Do you give this application permission to publish to QDN?", + text1: 'Do you give this application permission to publish to QDN?', html: `
+ + + + \ No newline at end of file diff --git a/src/assets/svgs/Mail.tsx b/src/assets/svgs/Mail.tsx new file mode 100644 index 0000000..601c0aa --- /dev/null +++ b/src/assets/svgs/Mail.tsx @@ -0,0 +1,39 @@ +import { useTheme } from '@mui/material'; +import { SVGProps } from './interfaces'; + +export const Logout: React.FC = ({ color, opacity, ...children }) => { + const theme = useTheme(); + + const setColor = color ? color : theme.palette.text.primary; + const setOpacity = opacity ? opacity : 1; + + return ( + + + + ); +}; diff --git a/src/components/QMailStatus.tsx b/src/components/QMailStatus.tsx index 6c6783a..c760751 100644 --- a/src/components/QMailStatus.tsx +++ b/src/components/QMailStatus.tsx @@ -1,12 +1,15 @@ import { useMemo } from 'react'; -import QMailLogo from '../assets/QMailLogo.png'; +import EmailIcon from '@mui/icons-material/Email'; import { useRecoilState } from 'recoil'; import { mailsAtom, qMailLastEnteredTimestampAtom } from '../atoms/global'; import { isLessThanOneWeekOld } from './Group/QMailMessages'; -import { ButtonBase, Tooltip } from '@mui/material'; +import { ButtonBase, Tooltip, useTheme } from '@mui/material'; import { executeEvent } from '../utils/events'; +import { Mail } from '@mui/icons-material'; export const QMailStatus = () => { + const theme = useTheme(); + const [lastEnteredTimestamp, setLastEnteredTimestamp] = useRecoilState( qMailLastEnteredTimestampAtom ); @@ -39,21 +42,27 @@ export const QMailStatus = () => { {hasNewMail && (
)} + Q-MAIL } @@ -63,18 +72,18 @@ export const QMailStatus = () => { slotProps={{ tooltip: { sx: { - color: '#ffffff', - backgroundColor: '#444444', + color: theme.palette.text.primary, + backgroundColor: theme.palette.background.default, }, }, arrow: { sx: { - color: '#444444', + color: theme.palette.text.primary, }, }, }} > - + ); From a2c0e3af25a35be2f8bf80d86923cf8f9303c463 Mon Sep 17 00:00:00 2001 From: Nicola Benaglia Date: Sat, 19 Apr 2025 16:26:34 +0200 Subject: [PATCH 33/55] Remove unused files --- src/assets/svgs/Mail.svg | 25 ------------------------- src/assets/svgs/Mail.tsx | 39 --------------------------------------- 2 files changed, 64 deletions(-) delete mode 100644 src/assets/svgs/Mail.svg delete mode 100644 src/assets/svgs/Mail.tsx diff --git a/src/assets/svgs/Mail.svg b/src/assets/svgs/Mail.svg deleted file mode 100644 index 89ec974..0000000 --- a/src/assets/svgs/Mail.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/src/assets/svgs/Mail.tsx b/src/assets/svgs/Mail.tsx deleted file mode 100644 index 601c0aa..0000000 --- a/src/assets/svgs/Mail.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import { useTheme } from '@mui/material'; -import { SVGProps } from './interfaces'; - -export const Logout: React.FC = ({ color, opacity, ...children }) => { - const theme = useTheme(); - - const setColor = color ? color : theme.palette.text.primary; - const setOpacity = opacity ? opacity : 1; - - return ( - - - - ); -}; From 46e52ec738af4eb240304b23aadb7dfaff32f5b4 Mon Sep 17 00:00:00 2001 From: Nicola Benaglia Date: Sat, 19 Apr 2025 16:48:23 +0200 Subject: [PATCH 34/55] Move qortal icon from right bar to top-left bar --- src/App.tsx | 4 - src/assets/Icons/AppsIcon.tsx | 2 +- src/assets/Icons/HomeIcon.tsx | 2 +- src/components/Apps/AppsDesktop.tsx | 233 ++++++++++++----------- src/components/Apps/AppsDevMode.tsx | 12 +- src/components/CoreSyncStatus.tsx | 3 +- src/components/Desktop/DesktopFooter.tsx | 34 ++-- src/components/DesktopSideBar.tsx | 55 +++--- 8 files changed, 182 insertions(+), 163 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index b20b6d5..1814032 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1817,10 +1817,6 @@ function App() { - - - - diff --git a/src/assets/Icons/AppsIcon.tsx b/src/assets/Icons/AppsIcon.tsx index d2ad47c..3f58604 100644 --- a/src/assets/Icons/AppsIcon.tsx +++ b/src/assets/Icons/AppsIcon.tsx @@ -1,4 +1,4 @@ -import { useTheme } from "@mui/material"; +import { useTheme } from '@mui/material'; export const AppsIcon = ({ height = 31, width = 31 }) => { const theme = useTheme(); diff --git a/src/assets/Icons/HomeIcon.tsx b/src/assets/Icons/HomeIcon.tsx index 7659119..0d3c4fe 100644 --- a/src/assets/Icons/HomeIcon.tsx +++ b/src/assets/Icons/HomeIcon.tsx @@ -1,4 +1,4 @@ -import { useTheme } from "@mui/material"; +import { useTheme } from '@mui/material'; export const HomeIcon = ({ height = 20, width = 23 }) => { const theme = useTheme(); diff --git a/src/components/Apps/AppsDesktop.tsx b/src/components/Apps/AppsDesktop.tsx index c17521f..6952be4 100644 --- a/src/components/Apps/AppsDesktop.tsx +++ b/src/components/Apps/AppsDesktop.tsx @@ -1,34 +1,29 @@ -import React, { - useContext, - useEffect, - useMemo, - useRef, - useState, -} from "react"; -import { AppsHomeDesktop } from "./AppsHomeDesktop"; -import { Spacer } from "../../common/Spacer"; -import { GlobalContext, getBaseApiReact } from "../../App"; -import { AppInfo } from "./AppInfo"; +import React, { useContext, useEffect, useMemo, useRef, useState } from 'react'; +import { AppsHomeDesktop } from './AppsHomeDesktop'; +import { Spacer } from '../../common/Spacer'; +import { GlobalContext, getBaseApiReact } from '../../App'; +import { AppInfo } from './AppInfo'; import { executeEvent, subscribeToEvent, unsubscribeFromEvent, -} from "../../utils/events"; -import { AppsParent } from "./Apps-styles"; -import AppViewerContainer from "./AppViewerContainer"; -import ShortUniqueId from "short-unique-id"; -import { AppPublish } from "./AppPublish"; -import { AppsLibraryDesktop } from "./AppsLibraryDesktop"; -import { AppsCategoryDesktop } from "./AppsCategoryDesktop"; -import { AppsNavBarDesktop } from "./AppsNavBarDesktop"; -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"; +} from '../../utils/events'; +import { AppsParent } from './Apps-styles'; +import AppViewerContainer from './AppViewerContainer'; +import ShortUniqueId from 'short-unique-id'; +import { AppPublish } from './AppPublish'; +import { AppsLibraryDesktop } from './AppsLibraryDesktop'; +import { AppsCategoryDesktop } from './AppsCategoryDesktop'; +import { AppsNavBarDesktop } from './AppsNavBarDesktop'; +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 { CoreSyncStatus } from '../CoreSyncStatus'; const uid = new ShortUniqueId({ length: 8 }); @@ -58,25 +53,25 @@ export const AppsDesktop = ({ const myApp = useMemo(() => { return availableQapps.find( - (app) => app.name === myName && app.service === "APP" + (app) => app.name === myName && app.service === 'APP' ); }, [myName, availableQapps]); const myWebsite = useMemo(() => { return availableQapps.find( - (app) => app.name === myName && app.service === "WEBSITE" + (app) => app.name === myName && app.service === 'WEBSITE' ); }, [myName, availableQapps]); useEffect(() => { if (show) { - showTutorial("qapps"); + showTutorial('qapps'); } }, [show]); useEffect(() => { setTimeout(() => { - executeEvent("setTabsToNav", { + executeEvent('setTabsToNav', { data: { tabs: tabs, selectedTab: selectedTab, @@ -91,9 +86,9 @@ export const AppsDesktop = ({ const url = `${getBaseApiReact()}/arbitrary/categories`; const response = await fetch(url, { - method: "GET", + method: 'GET', headers: { - "Content-Type": "application/json", + 'Content-Type': 'application/json', }, }); if (!response?.ok) return; @@ -115,9 +110,9 @@ export const AppsDesktop = ({ const url = `${getBaseApiReact()}/arbitrary/resources/search?service=APP&mode=ALL&limit=0&includestatus=true&includemetadata=true`; const response = await fetch(url, { - method: "GET", + method: 'GET', headers: { - "Content-Type": "application/json", + 'Content-Type': 'application/json', }, }); if (!response?.ok) return; @@ -125,9 +120,9 @@ export const AppsDesktop = ({ const urlWebsites = `${getBaseApiReact()}/arbitrary/resources/search?service=WEBSITE&mode=ALL&limit=0&includestatus=true&includemetadata=true`; const responseWebsites = await fetch(urlWebsites, { - method: "GET", + method: 'GET', headers: { - "Content-Type": "application/json", + 'Content-Type': 'application/json', }, }); if (!responseWebsites?.ok) return; @@ -150,9 +145,12 @@ export const AppsDesktop = ({ useEffect(() => { getQapps(); - const interval = setInterval(() => { - getQapps(); - }, 20 * 60 * 1000); // 20 minutes in milliseconds + const interval = setInterval( + () => { + getQapps(); + }, + 20 * 60 * 1000 + ); // 20 minutes in milliseconds return () => clearInterval(interval); }, [getQapps]); @@ -160,29 +158,29 @@ export const AppsDesktop = ({ const selectedAppInfoFunc = (e) => { const data = e.detail?.data; setSelectedAppInfo(data); - setMode("appInfo"); + setMode('appInfo'); }; useEffect(() => { - subscribeToEvent("selectedAppInfo", selectedAppInfoFunc); + subscribeToEvent('selectedAppInfo', selectedAppInfoFunc); return () => { - unsubscribeFromEvent("selectedAppInfo", selectedAppInfoFunc); + unsubscribeFromEvent('selectedAppInfo', selectedAppInfoFunc); }; }, []); const selectedAppInfoCategoryFunc = (e) => { const data = e.detail?.data; setSelectedAppInfo(data); - setMode("appInfo-from-category"); + setMode('appInfo-from-category'); }; useEffect(() => { - subscribeToEvent("selectedAppInfoCategory", selectedAppInfoCategoryFunc); + subscribeToEvent('selectedAppInfoCategory', selectedAppInfoCategoryFunc); return () => { unsubscribeFromEvent( - "selectedAppInfoCategory", + 'selectedAppInfoCategory', selectedAppInfoCategoryFunc ); }; @@ -191,43 +189,43 @@ export const AppsDesktop = ({ const selectedCategoryFunc = (e) => { const data = e.detail?.data; setSelectedCategory(data); - setMode("category"); + setMode('category'); }; useEffect(() => { - subscribeToEvent("selectedCategory", selectedCategoryFunc); + subscribeToEvent('selectedCategory', selectedCategoryFunc); return () => { - unsubscribeFromEvent("selectedCategory", selectedCategoryFunc); + unsubscribeFromEvent('selectedCategory', selectedCategoryFunc); }; }, []); const navigateBackFunc = (e) => { if ( [ - "category", - "appInfo-from-category", - "appInfo", - "library", - "publish", + 'category', + 'appInfo-from-category', + 'appInfo', + 'library', + 'publish', ].includes(mode) ) { // Handle the various modes as needed - if (mode === "category") { - setMode("library"); + if (mode === 'category') { + setMode('library'); setSelectedCategory(null); - } else if (mode === "appInfo-from-category") { - setMode("category"); - } else if (mode === "appInfo") { - setMode("library"); - } else if (mode === "library") { + } else if (mode === 'appInfo-from-category') { + setMode('category'); + } else if (mode === 'appInfo') { + setMode('library'); + } else if (mode === 'library') { if (isNewTabWindow) { - setMode("viewer"); + setMode('viewer'); } else { - setMode("home"); + setMode('home'); } - } else if (mode === "publish") { - setMode("library"); + } else if (mode === 'publish') { + setMode('library'); } } else if (selectedTab?.tabId) { executeEvent(`navigateBackApp-${selectedTab?.tabId}`, {}); @@ -235,10 +233,10 @@ export const AppsDesktop = ({ }; useEffect(() => { - subscribeToEvent("navigateBack", navigateBackFunc); + subscribeToEvent('navigateBack', navigateBackFunc); return () => { - unsubscribeFromEvent("navigateBack", navigateBackFunc); + unsubscribeFromEvent('navigateBack', navigateBackFunc); }; }, [mode, selectedTab]); @@ -250,16 +248,16 @@ export const AppsDesktop = ({ }; setTabs((prev) => [...prev, newTab]); setSelectedTab(newTab); - setMode("viewer"); + setMode('viewer'); setIsNewTabWindow(false); }; useEffect(() => { - subscribeToEvent("addTab", addTabFunc); + subscribeToEvent('addTab', addTabFunc); return () => { - unsubscribeFromEvent("addTab", addTabFunc); + unsubscribeFromEvent('addTab', addTabFunc); }; }, [tabs]); const setSelectedTabFunc = (e) => { @@ -268,7 +266,7 @@ export const AppsDesktop = ({ setSelectedTab(data); setTimeout(() => { - executeEvent("setTabsToNav", { + executeEvent('setTabsToNav', { data: { tabs: tabs, selectedTab: data, @@ -280,10 +278,10 @@ export const AppsDesktop = ({ }; useEffect(() => { - subscribeToEvent("setSelectedTab", setSelectedTabFunc); + subscribeToEvent('setSelectedTab', setSelectedTabFunc); return () => { - unsubscribeFromEvent("setSelectedTab", setSelectedTabFunc); + unsubscribeFromEvent('setSelectedTab', setSelectedTabFunc); }; }, [tabs, isNewTabWindow]); @@ -291,14 +289,14 @@ export const AppsDesktop = ({ const data = e.detail?.data; const copyTabs = [...tabs].filter((tab) => tab?.tabId !== data?.tabId); if (copyTabs?.length === 0) { - setMode("home"); + setMode('home'); } else { setSelectedTab(copyTabs[0]); } setTabs(copyTabs); setSelectedTab(copyTabs[0]); setTimeout(() => { - executeEvent("setTabsToNav", { + executeEvent('setTabsToNav', { data: { tabs: copyTabs, selectedTab: copyTabs[0], @@ -308,10 +306,10 @@ export const AppsDesktop = ({ }; useEffect(() => { - subscribeToEvent("removeTab", removeTabFunc); + subscribeToEvent('removeTab', removeTabFunc); return () => { - unsubscribeFromEvent("removeTab", removeTabFunc); + unsubscribeFromEvent('removeTab', removeTabFunc); }; }, [tabs]); @@ -321,10 +319,10 @@ export const AppsDesktop = ({ }; useEffect(() => { - subscribeToEvent("newTabWindow", setNewTabWindowFunc); + subscribeToEvent('newTabWindow', setNewTabWindowFunc); return () => { - unsubscribeFromEvent("newTabWindow", setNewTabWindowFunc); + unsubscribeFromEvent('newTabWindow', setNewTabWindowFunc); }; }, [tabs]); @@ -333,24 +331,33 @@ export const AppsDesktop = ({ sx={{ position: !show && 'fixed', left: !show && '-200vw', - flexDirection: 'row' + flexDirection: 'row', }} > + + + + { goToHome(); @@ -361,7 +368,7 @@ export const AppsDesktop = ({ { - setDesktopViewMode("apps"); + setDesktopViewMode('apps'); }} > @@ -371,13 +378,13 @@ export const AppsDesktop = ({ { - setDesktopViewMode("chat"); + setDesktopViewMode('chat'); }} > @@ -434,7 +441,7 @@ export const AppsDesktop = ({ {isEnabledDevMode && ( { - setDesktopViewMode("dev"); + setDesktopViewMode('dev'); }} > @@ -442,21 +449,21 @@ export const AppsDesktop = ({ )} - {mode !== "home" && ( + {mode !== 'home' && ( )} - {mode === "home" && ( + {mode === 'home' && ( @@ -471,7 +478,7 @@ export const AppsDesktop = ({ )} - {mode === "appInfo" && !selectedTab && ( + {mode === 'appInfo' && !selectedTab && ( )} - {mode === "appInfo-from-category" && !selectedTab && ( + {mode === 'appInfo-from-category' && !selectedTab && ( )} - {mode === "publish" && !selectedTab && ( + {mode === 'publish' && !selectedTab && ( )} {tabs.map((tab) => { @@ -511,15 +518,15 @@ export const AppsDesktop = ({ ); })} - {isNewTabWindow && mode === "viewer" && ( + {isNewTabWindow && mode === 'viewer' && ( <> diff --git a/src/components/Apps/AppsDevMode.tsx b/src/components/Apps/AppsDevMode.tsx index a01f6d7..6301286 100644 --- a/src/components/Apps/AppsDevMode.tsx +++ b/src/components/Apps/AppsDevMode.tsx @@ -31,6 +31,7 @@ import { HubsIcon } from '../../assets/Icons/HubsIcon'; import { AppsDevModeNavBar } from './AppsDevModeNavBar'; import { AppsIcon } from '../../assets/Icons/AppsIcon'; import { IconWrapper } from '../Desktop/DesktopFooter'; +import { CoreSyncStatus } from '../CoreSyncStatus'; const uid = new ShortUniqueId({ length: 8 }); @@ -243,11 +244,20 @@ export const AppsDevMode = ({ gap: '25px', }} > + + + + { goToHome(); diff --git a/src/components/CoreSyncStatus.tsx b/src/components/CoreSyncStatus.tsx index e0e4692..66d16ec 100644 --- a/src/components/CoreSyncStatus.tsx +++ b/src/components/CoreSyncStatus.tsx @@ -73,6 +73,7 @@ export const CoreSyncStatus = () => { let imagePath = syncingImg; let message = `Synchronizing`; + if (isMintingPossible && !isUsingGateway) { imagePath = syncedMintingImg; message = `${isSynchronizing ? 'Synchronizing' : 'Synchronized'} ${'(Minting)'}`; @@ -101,7 +102,7 @@ export const CoreSyncStatus = () => { sync status diff --git a/src/components/Desktop/DesktopFooter.tsx b/src/components/Desktop/DesktopFooter.tsx index 3bcaad5..ebfbc6f 100644 --- a/src/components/Desktop/DesktopFooter.tsx +++ b/src/components/Desktop/DesktopFooter.tsx @@ -22,27 +22,27 @@ export const IconWrapper = ({ return ( {children} {label} @@ -68,18 +68,20 @@ export const DesktopFooter = ({ const [isEnabledDevMode, setIsEnabledDevMode] = useRecoilState(enabledDevModeAtom); + const theme = useTheme(); + if (hide) return; return ( @@ -141,8 +143,8 @@ export const DesktopFooter = ({ hasUnreadDirects ? 'var(--danger)' : isDirects - ? 'white' - : 'rgba(250, 250, 250, 0.5)' + ? theme.palette.text.primary + : theme.palette.text.secondary } /> diff --git a/src/components/DesktopSideBar.tsx b/src/components/DesktopSideBar.tsx index dce577b..d1c8a7a 100644 --- a/src/components/DesktopSideBar.tsx +++ b/src/components/DesktopSideBar.tsx @@ -7,6 +7,7 @@ import { useRecoilState } from 'recoil'; import { enabledDevModeAtom } from '../atoms/global'; import { AppsIcon } from '../assets/Icons/AppsIcon'; import ThemeSelector from './Theme/ThemeSelector'; +import { CoreSyncStatus } from './CoreSyncStatus'; export const DesktopSideBar = ({ goToHome, @@ -30,19 +31,28 @@ export const DesktopSideBar = ({ return ( + + + + { goToHome(); @@ -51,10 +61,13 @@ export const DesktopSideBar = ({ + { setDesktopViewMode('apps'); @@ -63,17 +76,22 @@ export const DesktopSideBar = ({ }} > + { setDesktopViewMode('chat'); @@ -98,24 +116,7 @@ export const DesktopSideBar = ({ /> - {/* { - setDesktopSideView("groups"); - toggleSideViewGroups() - }} - > - - - */} + {/* */} {isEnabledDevMode && ( @@ -126,7 +127,9 @@ export const DesktopSideBar = ({ > Date: Sat, 19 Apr 2025 17:04:03 +0200 Subject: [PATCH 35/55] Adjust position for CoreSync window --- src/components/CoreSyncStatus.tsx | 5 +++-- src/styles/CoreSyncStatus.css | 16 ++-------------- 2 files changed, 5 insertions(+), 16 deletions(-) diff --git a/src/components/CoreSyncStatus.tsx b/src/components/CoreSyncStatus.tsx index 66d16ec..585b2e0 100644 --- a/src/components/CoreSyncStatus.tsx +++ b/src/components/CoreSyncStatus.tsx @@ -106,11 +106,13 @@ export const CoreSyncStatus = () => { alt="sync status" /> +

Core Information

@@ -135,7 +137,6 @@ export const CoreSyncStatus = () => { {isUsingGateway?.toString()} -
); diff --git a/src/styles/CoreSyncStatus.css b/src/styles/CoreSyncStatus.css index 0f60c2b..0cacfec 100644 --- a/src/styles/CoreSyncStatus.css +++ b/src/styles/CoreSyncStatus.css @@ -44,23 +44,11 @@ } .tooltip .bottom i { - position: absolute; bottom: 100%; + height: 12px; left: 50%; margin-left: -12px; - width: 24px; - height: 12px; overflow: hidden; -} - -.tooltip .bottom i::after { - 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; + width: 24px; } From 2b3d2e23260919b9c0fc1bf83145db62ea7a1005 Mon Sep 17 00:00:00 2001 From: Nicola Benaglia Date: Sat, 19 Apr 2025 17:13:07 +0200 Subject: [PATCH 36/55] Set default value --- src/components/Chat/MessageItem.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Chat/MessageItem.tsx b/src/components/Chat/MessageItem.tsx index 11cc381..a40fca8 100644 --- a/src/components/Chat/MessageItem.tsx +++ b/src/components/Chat/MessageItem.tsx @@ -565,7 +565,7 @@ export const MessageItem = React.memo( } ); -export const ReplyPreview = ({ message, isEdit }) => { +export const ReplyPreview = ({ message, isEdit = false }) => { const theme = useTheme(); return ( From 1f59205f5eb680a57a0e818f2243a1892dbf887f Mon Sep 17 00:00:00 2001 From: PhilReact Date: Sat, 19 Apr 2025 22:22:13 +0300 Subject: [PATCH 37/55] added theme event --- src/components/Apps/AppViewer.tsx | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/components/Apps/AppViewer.tsx b/src/components/Apps/AppViewer.tsx index 11188a9..9302df7 100644 --- a/src/components/Apps/AppViewer.tsx +++ b/src/components/Apps/AppViewer.tsx @@ -1,12 +1,12 @@ import React, { useContext, useEffect, useMemo, useState } from "react"; -import { Avatar, Box, } from "@mui/material"; -import { Add } from "@mui/icons-material"; +import { Box, } from "@mui/material"; import { MyContext, getBaseApiReact, isMobile } from "../../App"; -import { executeEvent, subscribeToEvent, unsubscribeFromEvent } from "../../utils/events"; +import { subscribeToEvent, unsubscribeFromEvent } from "../../utils/events"; import { useFrame } from "react-frame-component"; import { useQortalMessageListener } from "./useQortalMessageListener"; +import { useThemeContext } from "../Theme/ThemeContext"; @@ -14,10 +14,10 @@ import { useQortalMessageListener } from "./useQortalMessageListener"; export const AppViewer = React.forwardRef(({ app , hide, isDevMode, skipAuth}, iframeRef) => { const { rootHeight } = useContext(MyContext); // const iframeRef = useRef(null); - const { document, window: frameWindow } = useFrame(); + const { window: frameWindow } = useFrame(); const {path, history, changeCurrentIndex, resetHistory} = useQortalMessageListener(frameWindow, iframeRef, app?.tabId, isDevMode, app?.name, app?.service, skipAuth) const [url, setUrl] = useState('') - + const { themeMode } = useThemeContext(); useEffect(()=> { if(app?.isPreview) return @@ -30,7 +30,7 @@ export const AppViewer = React.forwardRef(({ app , hide, isDevMode, skipAuth}, i hasQueryParam = true } - setUrl(`${getBaseApiReact()}/render/${app?.service}/${app?.name}${app?.path != null ? `/${app?.path}` : ''}${hasQueryParam ? "&": "?" }theme=dark&identifier=${(app?.identifier != null && app?.identifier != 'null') ? app?.identifier : ''}`) + setUrl(`${getBaseApiReact()}/render/${app?.service}/${app?.name}${app?.path != null ? `/${app?.path}` : ''}${hasQueryParam ? "&": "?" }theme=${themeMode}&identifier=${(app?.identifier != null && app?.identifier != 'null') ? app?.identifier : ''}`) }, [app?.service, app?.name, app?.identifier, app?.path, app?.isPreview]) useEffect(()=> { @@ -55,7 +55,7 @@ export const AppViewer = React.forwardRef(({ app , hide, isDevMode, skipAuth}, i return } - const constructUrl = `${getBaseApiReact()}/render/${app?.service}/${app?.name}${path != null ? path : ''}?theme=dark&identifier=${app?.identifier != null ? app?.identifier : ''}&time=${new Date().getMilliseconds()}` + const constructUrl = `${getBaseApiReact()}/render/${app?.service}/${app?.name}${path != null ? path : ''}?theme=${themeMode}&identifier=${app?.identifier != null ? app?.identifier : ''}&time=${new Date().getMilliseconds()}` setUrl(constructUrl) } }; @@ -68,6 +68,15 @@ export const AppViewer = React.forwardRef(({ app , hide, isDevMode, skipAuth}, i }; }, [app, path, isDevMode]); + useEffect(()=> { + if(!iframeRef?.current) return + const targetOrigin = iframeRef.current ? new URL(iframeRef.current.src).origin : "*"; + // Send the navigation command after setting up the listener and timeout + iframeRef.current.contentWindow.postMessage( + { action: 'THEME_CHANGED', theme: themeMode, requestedHandler: 'UI' }, targetOrigin + ); + }, [themeMode]) + const removeTrailingSlash = (str) => str.replace(/\/$/, ''); const copyLinkFunc = (e) => { const {tabId} = e.detail @@ -139,10 +148,10 @@ export const AppViewer = React.forwardRef(({ app , hide, isDevMode, skipAuth}, i await navigationPromise; } catch (error) { if(isDevMode){ - setUrl(`${url}${previousPath != null ? previousPath : ''}?theme=dark&time=${new Date().getMilliseconds()}&isManualNavigation=false`) + setUrl(`${url}${previousPath != null ? previousPath : ''}?theme=${themeMode}&time=${new Date().getMilliseconds()}&isManualNavigation=false`) return } - setUrl(`${getBaseApiReact()}/render/${app?.service}/${app?.name}${previousPath != null ? previousPath : ''}?theme=dark&identifier=${(app?.identifier != null && app?.identifier != 'null') ? app?.identifier : ''}&time=${new Date().getMilliseconds()}&isManualNavigation=false`) + setUrl(`${getBaseApiReact()}/render/${app?.service}/${app?.name}${previousPath != null ? previousPath : ''}?theme=${themeMode}&identifier=${(app?.identifier != null && app?.identifier != 'null') ? app?.identifier : ''}&time=${new Date().getMilliseconds()}&isManualNavigation=false`) // iframeRef.current.contentWindow.location.href = previousPath; // Fallback URL update } } else { From c5358abd36e1e24c91dfed01369bb5efa8d00514 Mon Sep 17 00:00:00 2001 From: Nicola Benaglia Date: Sat, 19 Apr 2025 21:54:01 +0200 Subject: [PATCH 38/55] Fix path --- src/styles/index.css | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/styles/index.css b/src/styles/index.css index f8b8090..02c897f 100644 --- a/src/styles/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'); + src: url('./fonts/Inter-SemiBold.ttf') format('truetype'); font-weight: 600; } @font-face { font-family: 'Inter'; - src: url('./styles/fonts/Inter-ExtraBold.ttf') format('truetype'); + src: url('./fonts/Inter-ExtraBold.ttf') format('truetype'); font-weight: 800; } @font-face { font-family: 'Inter'; - src: url('./styles/fonts/Inter-Bold.ttf') format('truetype'); + src: url('./fonts/Inter-Bold.ttf') format('truetype'); font-weight: 700; } @font-face { font-family: 'Inter'; - src: url('./styles/fonts/Inter-Regular.ttf') format('truetype'); + src: url('./fonts/Inter-Regular.ttf') format('truetype'); font-weight: 400; } From 5c93f27fce3b6cdf6fc5de979310a3c6e55f934f Mon Sep 17 00:00:00 2001 From: Nicola Benaglia Date: Sat, 19 Apr 2025 21:54:13 +0200 Subject: [PATCH 39/55] Revert to Inter font --- src/styles/theme-common.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/styles/theme-common.ts b/src/styles/theme-common.ts index e2b2b60..600b6da 100644 --- a/src/styles/theme-common.ts +++ b/src/styles/theme-common.ts @@ -1,7 +1,7 @@ // Extend the Theme interface const commonThemeOptions = { typography: { - fontFamily: ['Roboto'].join(','), + fontFamily: ['Inter'].join(','), h1: { fontSize: '2rem', fontWeight: 600, From c5c8d80693e8899d3a5fa4cb27480493c296c416 Mon Sep 17 00:00:00 2001 From: Nicola Benaglia Date: Sat, 19 Apr 2025 22:01:15 +0200 Subject: [PATCH 40/55] Refactor style --- src/components/Chat/MessageDisplay.tsx | 14 +++++++++++-- src/components/Chat/chat.css | 29 +++++++++++++------------- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/src/components/Chat/MessageDisplay.tsx b/src/components/Chat/MessageDisplay.tsx index 17a57ef..2bf3d6f 100644 --- a/src/components/Chat/MessageDisplay.tsx +++ b/src/components/Chat/MessageDisplay.tsx @@ -3,6 +3,7 @@ import DOMPurify from 'dompurify'; import './chat.css'; import { executeEvent } from '../../utils/events'; import { Embed } from '../Embeds/Embed'; +import { Box, useTheme } from '@mui/material'; export const extractComponents = (url) => { if (!url || !url.startsWith('qortal://')) { @@ -75,6 +76,8 @@ const linkify = (text) => { }; export const MessageDisplay = ({ htmlContent, isReply }) => { + const theme = useTheme(); + const sanitizedContent = useMemo(() => { return DOMPurify.sanitize(linkify(htmlContent), { ALLOWED_TAGS: [ @@ -188,13 +191,20 @@ export const MessageDisplay = ({ htmlContent, isReply }) => { } return ( - <> + {embedLink && }
- + ); }; diff --git a/src/components/Chat/chat.css b/src/components/Chat/chat.css index 73fa159..d563d85 100644 --- a/src/components/Chat/chat.css +++ b/src/components/Chat/chat.css @@ -1,6 +1,6 @@ .tiptap { margin-top: 0; - color: theme => theme.palette.text.primary; + color: var(--text-primary); width: 100%; } @@ -26,7 +26,7 @@ line-height: 1.1; margin-top: 2.5rem; text-wrap: pretty; - color: theme => theme.palette.text.primary; + color: var(--text-primary); } .tiptap h1, @@ -55,18 +55,18 @@ /* Code and preformatted text styles */ .tiptap code { - background-color: theme => theme.palette.background.default; + background-color: var(--background-default); border-radius: 0.4rem; - color: theme => theme.palette.text.primary; + color: var(--text-primary); font-size: 0.85rem; padding: 0.25em 0.3em; text-wrap: pretty; } .tiptap pre { - background: theme => theme.palette.background.default; + background: var(--background-default); border-radius: 0.5rem; - color: theme => theme.palette.text.primary; + color: var(--text-primary); font-family: 'JetBrainsMono', monospace; margin: 1.5rem 0; padding: 0.75rem 1rem; @@ -86,7 +86,7 @@ border-left: 3px solid var(--gray-3); margin: 1.5rem 0; padding-left: 1rem; - color: theme => theme.palette.text.primary; + color: var(--text-primary); text-wrap: pretty; } @@ -102,12 +102,12 @@ .tiptap p { font-size: 16px; - color: theme => theme.palette.text.primary; + color: var(--text-primary); margin: 0px; } .tiptap p.is-editor-empty:first-child::before { - color: theme => theme.palette.text.primary; + color: var(--text-primary); content: attr(data-placeholder); float: left; height: 0; @@ -134,14 +134,14 @@ .tiptap [data-type='mention'] { box-decoration-break: clone; - color: theme => theme.palette.text.secondary; + color: var(--text-secondary); padding: 0.1rem 0.3rem; } .unread-divider { - border-bottom: 1px solid white; + border-bottom: 1px solid var(--text-primary); border-radius: 2px; - color: theme => theme.palette.text.primary; + color: var(--text-primary); display: flex; justify-content: center; width: 90%; @@ -169,11 +169,10 @@ font-size: 16px; width: 100%; border: none; - color: theme => theme.palette.text.primary; - cursor: pointer; + color: var(--text-primary); &:hover, &:hover.is-selected { - background-color: theme => theme.palette.background.secondary; + background-color: var(--background-default); } } } From cf59bae3331afaf02e28dc00394774c2dadf20b4 Mon Sep 17 00:00:00 2001 From: Nicola Benaglia Date: Sun, 20 Apr 2025 09:13:36 +0200 Subject: [PATCH 41/55] Delete svg files now converted to tsx --- src/assets/svgs/Logout.svg | 3 --- src/assets/svgs/NavAdd.svg | 4 ---- src/assets/svgs/NavBack.svg | 10 ---------- src/assets/svgs/NavCloseTab.svg | 6 ------ src/assets/svgs/NavMoreMenu.svg | 10 ---------- 5 files changed, 33 deletions(-) delete mode 100644 src/assets/svgs/Logout.svg delete mode 100644 src/assets/svgs/NavAdd.svg delete mode 100644 src/assets/svgs/NavBack.svg delete mode 100644 src/assets/svgs/NavCloseTab.svg delete mode 100644 src/assets/svgs/NavMoreMenu.svg diff --git a/src/assets/svgs/Logout.svg b/src/assets/svgs/Logout.svg deleted file mode 100644 index 6ba462d..0000000 --- a/src/assets/svgs/Logout.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/assets/svgs/NavAdd.svg b/src/assets/svgs/NavAdd.svg deleted file mode 100644 index 1d38c05..0000000 --- a/src/assets/svgs/NavAdd.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/src/assets/svgs/NavBack.svg b/src/assets/svgs/NavBack.svg deleted file mode 100644 index 07df29e..0000000 --- a/src/assets/svgs/NavBack.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/src/assets/svgs/NavCloseTab.svg b/src/assets/svgs/NavCloseTab.svg deleted file mode 100644 index a4595df..0000000 --- a/src/assets/svgs/NavCloseTab.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/src/assets/svgs/NavMoreMenu.svg b/src/assets/svgs/NavMoreMenu.svg deleted file mode 100644 index f64cdab..0000000 --- a/src/assets/svgs/NavMoreMenu.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - From ecd75a6f6e3026c4f3bb355e6489dc4f98686538 Mon Sep 17 00:00:00 2001 From: Nicola Benaglia Date: Sun, 20 Apr 2025 09:15:35 +0200 Subject: [PATCH 42/55] Convert svg into tsx --- src/assets/svgs/NavAdd.tsx | 32 +++++++++++++++++++++++ src/assets/svgs/NavBack.tsx | 30 +++++++++++++++++++++ src/assets/svgs/NavCloseTab.tsx | 46 +++++++++++++++++++++++++++++++++ src/assets/svgs/NavMoreMenu.tsx | 30 +++++++++++++++++++++ 4 files changed, 138 insertions(+) create mode 100644 src/assets/svgs/NavAdd.tsx create mode 100644 src/assets/svgs/NavBack.tsx create mode 100644 src/assets/svgs/NavCloseTab.tsx create mode 100644 src/assets/svgs/NavMoreMenu.tsx diff --git a/src/assets/svgs/NavAdd.tsx b/src/assets/svgs/NavAdd.tsx new file mode 100644 index 0000000..dd45bad --- /dev/null +++ b/src/assets/svgs/NavAdd.tsx @@ -0,0 +1,32 @@ +import { useTheme } from '@mui/material'; +import { SVGProps } from './interfaces'; + +export const NavAdd: React.FC = ({ color, opacity, ...children }) => { + const theme = useTheme(); + + const setColor = color ? color : theme.palette.text.primary; + const setOpacity = opacity ? opacity : 1; + + return ( + + + + + ); +}; diff --git a/src/assets/svgs/NavBack.tsx b/src/assets/svgs/NavBack.tsx new file mode 100644 index 0000000..d5865f9 --- /dev/null +++ b/src/assets/svgs/NavBack.tsx @@ -0,0 +1,30 @@ +import { useTheme } from '@mui/material'; +import { SVGProps } from './interfaces'; + +export const NavBack: React.FC = ({ + color, + opacity, + ...children +}) => { + const theme = useTheme(); + + const setColor = color ? color : theme.palette.text.primary; + const setOpacity = opacity ? opacity : 1; + + return ( + + + + ); +}; diff --git a/src/assets/svgs/NavCloseTab.tsx b/src/assets/svgs/NavCloseTab.tsx new file mode 100644 index 0000000..8b2734e --- /dev/null +++ b/src/assets/svgs/NavCloseTab.tsx @@ -0,0 +1,46 @@ +import { useTheme } from '@mui/material'; +import { SVGProps } from './interfaces'; + +export const NavCloseTab: React.FC = ({ + color, + opacity, + ...children +}) => { + const theme = useTheme(); + + const setColor = color ? color : theme.palette.text.primary; + const setOpacity = opacity ? opacity : 1; + + return ( + + + + + + + ); +}; diff --git a/src/assets/svgs/NavMoreMenu.tsx b/src/assets/svgs/NavMoreMenu.tsx new file mode 100644 index 0000000..ca641ba --- /dev/null +++ b/src/assets/svgs/NavMoreMenu.tsx @@ -0,0 +1,30 @@ +import { useTheme } from '@mui/material'; +import { SVGProps } from './interfaces'; + +export const NavMoreMenu: React.FC = ({ + color, + opacity, + ...children +}) => { + const theme = useTheme(); + + const setColor = color ? color : theme.palette.text.primary; + const setOpacity = opacity ? opacity : 1; + + return ( + + + + ); +}; From df8f5fe787e40d239ea223fbeec8aab3e93c7604 Mon Sep 17 00:00:00 2001 From: Nicola Benaglia Date: Sun, 20 Apr 2025 09:16:09 +0200 Subject: [PATCH 43/55] Add space --- src/App.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/App.tsx b/src/App.tsx index 1814032..8da871d 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -2859,6 +2859,7 @@ function App() { {!walletToBeDownloaded && ( <> + Date: Sun, 20 Apr 2025 09:16:20 +0200 Subject: [PATCH 44/55] Format code --- src/assets/Icons/LogoutIcon.tsx | 30 ++++++++++++++++++------------ src/assets/Icons/ThreadsIcon.tsx | 31 ++++++++++++++++++------------- src/assets/Icons/TradingIcon.tsx | 27 ++++++++++++++++----------- 3 files changed, 52 insertions(+), 36 deletions(-) diff --git a/src/assets/Icons/LogoutIcon.tsx b/src/assets/Icons/LogoutIcon.tsx index 30334f4..d1a4408 100644 --- a/src/assets/Icons/LogoutIcon.tsx +++ b/src/assets/Icons/LogoutIcon.tsx @@ -1,12 +1,18 @@ -import React from 'react'; - -export const LogoutIcon= ({ color, height = 20, width = 18}) => { - return ( - - - - - - ); - }; - \ No newline at end of file +export const LogoutIcon = ({ color, height = 20, width = 18 }) => { + return ( + + + + ); +}; diff --git a/src/assets/Icons/ThreadsIcon.tsx b/src/assets/Icons/ThreadsIcon.tsx index 3cf02cc..ed45696 100644 --- a/src/assets/Icons/ThreadsIcon.tsx +++ b/src/assets/Icons/ThreadsIcon.tsx @@ -1,13 +1,18 @@ -import React from 'react'; - -export const ThreadsIcon= ({ color = 'white', height = 11, width = 15 }) => { - return ( - - - - - - - ); - }; - \ No newline at end of file +export const ThreadsIcon = ({ color = 'white', height = 11, width = 15 }) => { + return ( + + + + ); +}; diff --git a/src/assets/Icons/TradingIcon.tsx b/src/assets/Icons/TradingIcon.tsx index 2c72300..e6723da 100644 --- a/src/assets/Icons/TradingIcon.tsx +++ b/src/assets/Icons/TradingIcon.tsx @@ -1,11 +1,16 @@ -import React from 'react'; - -export const TradingIcon= ({ color, height, width }) => { - return ( - - - - - ); - }; - \ No newline at end of file +export const TradingIcon = ({ color, height, width }) => { + return ( + + + + ); +}; From e5c2e7387694c73c17b0a3d3a769e9e1f4543574 Mon Sep 17 00:00:00 2001 From: Nicola Benaglia Date: Sun, 20 Apr 2025 09:20:29 +0200 Subject: [PATCH 45/55] Remove copy --- src/qortalRequests copy.ts | 427 ------------------------------------- 1 file changed, 427 deletions(-) delete mode 100644 src/qortalRequests copy.ts diff --git a/src/qortalRequests copy.ts b/src/qortalRequests copy.ts deleted file mode 100644 index 6807fe9..0000000 --- a/src/qortalRequests copy.ts +++ /dev/null @@ -1,427 +0,0 @@ -import { addForeignServer, addListItems, createPoll, decryptData, deleteListItems, deployAt, encryptData, getCrossChainServerInfo, getDaySummary, getForeignFee, getListItems, getServerConnectionHistory, getTxActivitySummary, getUserAccount, getUserWallet, getUserWalletInfo, getWalletBalance, joinGroup, publishMultipleQDNResources, publishQDNResource, removeForeignServer, saveFile, sendChatMessage, sendCoin, setCurrentForeignServer, updateForeignFee, voteOnPoll } from "./qortalRequests/get"; - - - -// Promisify chrome.storage.local.get -function getLocalStorage(key) { - return new Promise((resolve, reject) => { - chrome.storage.local.get([key], function (result) { - if (chrome.runtime.lastError) { - return reject(chrome.runtime.lastError); - } - resolve(result[key]); - }); - }); - } - - // Promisify chrome.storage.local.set - function setLocalStorage(data) { - return new Promise((resolve, reject) => { - chrome.storage.local.set(data, function () { - if (chrome.runtime.lastError) { - return reject(chrome.runtime.lastError); - } - resolve(); - }); - }); - } - - - export async function setPermission(key, value) { - try { - // Get the existing qortalRequestPermissions object - const qortalRequestPermissions = (await getLocalStorage('qortalRequestPermissions')) || {}; - - // Update the permission - qortalRequestPermissions[key] = value; - - // Save the updated object back to storage - await setLocalStorage({ qortalRequestPermissions }); - - } catch (error) { - console.error('Error setting permission:', error); - } - } - - export async function getPermission(key) { - try { - // Get the qortalRequestPermissions object from storage - const qortalRequestPermissions = (await getLocalStorage('qortalRequestPermissions')) || {}; - - // Return the value for the given key, or null if it doesn't exist - return qortalRequestPermissions[key] || null; - } catch (error) { - console.error('Error getting permission:', error); - return null; - } - } - - - // TODO: GET_FRIENDS_LIST - // NOT SURE IF TO IMPLEMENT: LINK_TO_QDN_RESOURCE, QDN_RESOURCE_DISPLAYED, SET_TAB_NOTIFICATIONS - -chrome?.runtime?.onMessage.addListener((request, sender, sendResponse) => { - if (request) { - const isFromExtension = request?.isExtension - switch (request.action) { - case "GET_USER_ACCOUNT": { - getUserAccount() - .then((res) => { - sendResponse(res); - }) - .catch((error) => { - sendResponse({ error: "Unable to get user account" }); - }); - - break; - } - case "ENCRYPT_DATA": { - const data = request.payload; - - encryptData(data, sender) - .then((res) => { - sendResponse(res); - }) - .catch((error) => { - sendResponse({ error: error.message }); - }); - - break; - } - case "DECRYPT_DATA": { - const data = request.payload; - - decryptData(data) - .then((res) => { - sendResponse(res); - }) - .catch((error) => { - sendResponse({ error: error.message }); - }); - - break; - } - case "GET_LIST_ITEMS": { - const data = request.payload; - - getListItems(data, isFromExtension) - .then((res) => { - sendResponse(res); - }) - .catch((error) => { - sendResponse({ error: error.message }); - }); - - break; - } - case "ADD_LIST_ITEMS": { - const data = request.payload; - - addListItems(data, isFromExtension) - .then((res) => { - sendResponse(res); - }) - .catch((error) => { - sendResponse({ error: error.message }); - }); - - break; - } - case "DELETE_LIST_ITEM": { - const data = request.payload; - - deleteListItems(data, isFromExtension) - .then((res) => { - sendResponse(res); - }) - .catch((error) => { - sendResponse({ error: error.message }); - }); - - break; - } - case "PUBLISH_QDN_RESOURCE": { - const data = request.payload; - - publishQDNResource(data, sender, isFromExtension) - .then((res) => { - sendResponse(res); - }) - .catch((error) => { - sendResponse({ error: error.message }); - }); - - break; - } - case "PUBLISH_MULTIPLE_QDN_RESOURCES": { - const data = request.payload; - - publishMultipleQDNResources(data, sender, isFromExtension) - .then((res) => { - sendResponse(res); - }) - .catch((error) => { - sendResponse({ error: error.message }); - }); - - break; - } - case "VOTE_ON_POLL": { - const data = request.payload; - - voteOnPoll(data, isFromExtension) - .then((res) => { - sendResponse(res); - }) - .catch((error) => { - sendResponse({ error: error.message }); - }); - - break; - } - case "CREATE_POLL": { - const data = request.payload; - - createPoll(data, isFromExtension) - .then((res) => { - sendResponse(res); - }) - .catch((error) => { - sendResponse({ error: error.message }); - }); - - break; - } - case "SEND_CHAT_MESSAGE": { - const data = request.payload; - sendChatMessage(data, isFromExtension) - .then((res) => { - sendResponse(res); - }) - .catch((error) => { - sendResponse({ error: error.message }); - }); - - break; - } - case "JOIN_GROUP": { - const data = request.payload; - - joinGroup(data, isFromExtension) - .then((res) => { - sendResponse(res); - }) - .catch((error) => { - sendResponse({ error: error.message }); - }); - - break; - } - case "SAVE_FILE": { - const data = request.payload; - - saveFile(data, sender, isFromExtension) - .then((res) => { - sendResponse(res); - }) - .catch((error) => { - sendResponse({ error: error.message }); - }); - - break; - } - case "DEPLOY_AT": { - const data = request.payload; - - deployAt(data, isFromExtension) - .then((res) => { - sendResponse(res); - }) - .catch((error) => { - sendResponse({ error: error.message }); - }); - - break; - } - case "GET_USER_WALLET": { - const data = request.payload; - - getUserWallet(data, isFromExtension) - .then((res) => { - sendResponse(res); - }) - .catch((error) => { - sendResponse({ error: error.message }); - }); - - break; - } - case "GET_WALLET_BALANCE": { - const data = request.payload; - - getWalletBalance(data, false, isFromExtension) - .then((res) => { - sendResponse(res); - }) - .catch((error) => { - sendResponse({ error: error.message }); - }); - - break; - } - - case "GET_USER_WALLET_INFO": { - const data = request.payload; - - getUserWalletInfo(data, isFromExtension) - .then((res) => { - sendResponse(res); - }) - .catch((error) => { - sendResponse({ error: error.message }); - }); - - break; - } - case "GET_CROSSCHAIN_SERVER_INFO": { - const data = request.payload; - - getCrossChainServerInfo(data) - .then((res) => { - sendResponse(res); - }) - .catch((error) => { - sendResponse({ error: error.message }); - }); - - break; - } - case "GET_TX_ACTIVITY_SUMMARY": { - const data = request.payload; - - getTxActivitySummary(data) - .then((res) => { - sendResponse(res); - }) - .catch((error) => { - sendResponse({ error: error.message }); - }); - - break; - } - - case "GET_FOREIGN_FEE": { - const data = request.payload; - - getForeignFee(data) - .then((res) => { - sendResponse(res); - }) - .catch((error) => { - sendResponse({ error: error.message }); - }); - - break; - } - - case "UPDATE_FOREIGN_FEE": { - const data = request.payload; - - updateForeignFee(data) - .then((res) => { - sendResponse(res); - }) - .catch((error) => { - sendResponse({ error: error.message }); - }); - - break; - } - - case "GET_SERVER_CONNECTION_HISTORY": { - const data = request.payload; - - getServerConnectionHistory(data) - .then((res) => { - sendResponse(res); - }) - .catch((error) => { - sendResponse({ error: error.message }); - }); - - break; - } - - case "SET_CURRENT_FOREIGN_SERVER": { - const data = request.payload; - - setCurrentForeignServer(data) - .then((res) => { - sendResponse(res); - }) - .catch((error) => { - sendResponse({ error: error.message }); - }); - - break; - } - - case "ADD_FOREIGN_SERVER": { - const data = request.payload; - - addForeignServer(data) - .then((res) => { - sendResponse(res); - }) - .catch((error) => { - sendResponse({ error: error.message }); - }); - - break; - } - - case "REMOVE_FOREIGN_SERVER": { - const data = request.payload; - - removeForeignServer(data) - .then((res) => { - sendResponse(res); - }) - .catch((error) => { - sendResponse({ error: error.message }); - }); - - break; - } - - case "GET_DAY_SUMMARY": { - const data = request.payload; - - getDaySummary(data) - .then((res) => { - sendResponse(res); - }) - .catch((error) => { - sendResponse({ error: error.message }); - }); - - break; - } - - case "SEND_COIN": { - const data = request.payload; - - sendCoin(data, isFromExtension) - .then((res) => { - sendResponse(res); - }) - .catch((error) => { - sendResponse({ error: error.message }); - }); - - break; - } - } - } - return true; -}); From acfc641663fc91e6359bf267768254a40881c4f3 Mon Sep 17 00:00:00 2001 From: Nicola Benaglia Date: Sun, 20 Apr 2025 09:29:10 +0200 Subject: [PATCH 46/55] Add theme --- src/components/Apps/AppsNavBarDesktop.tsx | 296 +++++++++++----------- src/components/Apps/TabComponent.tsx | 45 ++-- 2 files changed, 176 insertions(+), 165 deletions(-) diff --git a/src/components/Apps/AppsNavBarDesktop.tsx b/src/components/Apps/AppsNavBarDesktop.tsx index 8873e1a..2a22efd 100644 --- a/src/components/Apps/AppsNavBarDesktop.tsx +++ b/src/components/Apps/AppsNavBarDesktop.tsx @@ -1,12 +1,12 @@ -import React, { useEffect, useMemo, useRef, useState } from "react"; +import { useEffect, useMemo, useRef, useState } from 'react'; import { AppsNavBarLeft, AppsNavBarParent, AppsNavBarRight, -} from "./Apps-styles"; -import NavBack from "../../assets/svgs/NavBack.svg"; -import NavAdd from "../../assets/svgs/NavAdd.svg"; -import NavMoreMenu from "../../assets/svgs/NavMoreMenu.svg"; +} from './Apps-styles'; +import { NavBack } from '../../assets/svgs/NavBack.tsx'; +import { NavAdd } from '../../assets/svgs/NavAdd.tsx'; +import { NavMoreMenu } from '../../assets/svgs/NavMoreMenu.tsx'; import ContentCopyIcon from '@mui/icons-material/ContentCopy'; import { ButtonBase, @@ -16,21 +16,22 @@ import { MenuItem, Tab, Tabs, -} from "@mui/material"; + useTheme, +} from '@mui/material'; import { executeEvent, subscribeToEvent, unsubscribeFromEvent, -} from "../../utils/events"; -import TabComponent from "./TabComponent"; -import PushPinIcon from "@mui/icons-material/PushPin"; -import RefreshIcon from "@mui/icons-material/Refresh"; -import { useRecoilState, useSetRecoilState } from "recoil"; +} from '../../utils/events'; +import TabComponent from './TabComponent'; +import PushPinIcon from '@mui/icons-material/PushPin'; +import RefreshIcon from '@mui/icons-material/Refresh'; +import { useRecoilState, useSetRecoilState } from 'recoil'; import { navigationControllerAtom, settingsLocalLastUpdatedAtom, sortablePinnedAppsAtom, -} from "../../atoms/global"; +} from '../../atoms/global'; export function saveToLocalStorage(key, subKey, newValue) { try { @@ -59,14 +60,17 @@ export function saveToLocalStorage(key, subKey, newValue) { const serializedValue = JSON.stringify(combinedData); localStorage.setItem(key, serializedValue); } catch (error) { - console.error("Error saving to localStorage:", error); + console.error('Error saving to localStorage:', error); } } -export const AppsNavBarDesktop = ({disableBack}) => { +export const AppsNavBarDesktop = ({ disableBack }) => { const [tabs, setTabs] = useState([]); const [selectedTab, setSelectedTab] = useState(null); - const [navigationController, setNavigationController] = useRecoilState(navigationControllerAtom) + const [navigationController, setNavigationController] = useRecoilState( + navigationControllerAtom + ); + const theme = useTheme(); const [isNewTabWindow, setIsNewTabWindow] = useState(false); const tabsRef = useRef(null); @@ -76,7 +80,6 @@ export const AppsNavBarDesktop = ({disableBack}) => { sortablePinnedAppsAtom ); - const setSettingsLocalLastUpdated = useSetRecoilState( settingsLocalLastUpdatedAtom ); @@ -92,29 +95,26 @@ export const AppsNavBarDesktop = ({disableBack}) => { useEffect(() => { // Scroll to the last tab whenever the tabs array changes (e.g., when a new tab is added) if (tabsRef.current) { - const tabElements = tabsRef.current.querySelectorAll(".MuiTab-root"); + const tabElements = tabsRef.current.querySelectorAll('.MuiTab-root'); if (tabElements.length > 0) { const lastTab = tabElements[tabElements.length - 1]; lastTab.scrollIntoView({ - behavior: "smooth", - block: "nearest", - inline: "end", + behavior: 'smooth', + block: 'nearest', + inline: 'end', }); } } }, [tabs.length]); // Dependency on the number of tabs - - - const isDisableBackButton = useMemo(()=> { - if(disableBack) return true - if(selectedTab && navigationController[selectedTab?.tabId]?.hasBack) return false - if(selectedTab && !navigationController[selectedTab?.tabId]?.hasBack) return true - return false - }, [navigationController, selectedTab, disableBack]) - - - + const isDisableBackButton = useMemo(() => { + if (disableBack) return true; + if (selectedTab && navigationController[selectedTab?.tabId]?.hasBack) + return false; + if (selectedTab && !navigationController[selectedTab?.tabId]?.hasBack) + return true; + return false; + }, [navigationController, selectedTab, disableBack]); const setTabsToNav = (e) => { const { tabs, selectedTab, isNewTabWindow } = e.detail?.data; @@ -124,57 +124,61 @@ export const AppsNavBarDesktop = ({disableBack}) => { }; useEffect(() => { - subscribeToEvent("setTabsToNav", setTabsToNav); + subscribeToEvent('setTabsToNav', setTabsToNav); return () => { - unsubscribeFromEvent("setTabsToNav", setTabsToNav); + unsubscribeFromEvent('setTabsToNav', setTabsToNav); }; }, []); - - - const isSelectedAppPinned = useMemo(()=> { - if(selectedTab?.isPrivate){ + const isSelectedAppPinned = useMemo(() => { + if (selectedTab?.isPrivate) { return !!sortablePinnedApps?.find( (item) => - item?.privateAppProperties?.name === selectedTab?.privateAppProperties?.name && item?.privateAppProperties?.service === selectedTab?.privateAppProperties?.service && item?.privateAppProperties?.identifier === selectedTab?.privateAppProperties?.identifier + item?.privateAppProperties?.name === + selectedTab?.privateAppProperties?.name && + item?.privateAppProperties?.service === + selectedTab?.privateAppProperties?.service && + item?.privateAppProperties?.identifier === + selectedTab?.privateAppProperties?.identifier ); } else { return !!sortablePinnedApps?.find( (item) => - item?.name === selectedTab?.name && item?.service === selectedTab?.service + item?.name === selectedTab?.name && + item?.service === selectedTab?.service ); } - }, [selectedTab,sortablePinnedApps]) + }, [selectedTab, sortablePinnedApps]); return ( { - executeEvent("navigateBack", selectedTab?.tabId); + executeEvent('navigateBack', selectedTab?.tabId); }} disabled={isDisableBackButton} sx={{ opacity: !isDisableBackButton ? 1 : 0.1, - cursor: !isDisableBackButton ? 'pointer': 'default' + cursor: !isDisableBackButton ? 'pointer' : 'default', }} > - + { variant="scrollable" // Make tabs scrollable scrollButtons={true} sx={{ - "& .MuiTabs-indicator": { - backgroundColor: "white", + '& .MuiTabs-indicator': { + backgroundColor: theme.palette.background.default, }, maxHeight: `320px`, // Ensure the tabs container fits within the available space - overflow: "hidden", // Prevents overflow on small screens + overflow: 'hidden', // Prevents overflow on small screens }} > {tabs?.map((tab) => ( @@ -202,84 +206,83 @@ export const AppsNavBarDesktop = ({disableBack}) => { /> } // Pass custom component sx={{ - "&.Mui-selected": { - color: "white", + '&.Mui-selected': { + color: theme.palette.text.primary, }, - padding: "0px", - margin: "0px", - minWidth: "0px", - width: "50px", + padding: '0px', + margin: '0px', + minWidth: '0px', + width: '50px', }} /> ))} + {selectedTab && ( - { - setSelectedTab(null); - executeEvent("newTabWindow", {}); + sx={{ + gap: '10px', + flexDirection: 'column', }} > - { + setSelectedTab(null); + executeEvent('newTabWindow', {}); }} - src={NavAdd} - /> - - { - if (!selectedTab) return; - handleClick(e); - }} - > - + + + { + if (!selectedTab) return; + handleClick(e); }} - src={NavMoreMenu} - /> - - + > + + + )} - + { if (isSelectedAppPinned) { // Remove the selected app if it is pinned - if(selectedTab?.isPrivate){ + if (selectedTab?.isPrivate) { updatedApps = prev.filter( (item) => !( - item?.privateAppProperties?.name === selectedTab?.privateAppProperties?.name && - item?.privateAppProperties?.service === selectedTab?.privateAppProperties?.service && - item?.privateAppProperties?.identifier === selectedTab?.privateAppProperties?.identifier + item?.privateAppProperties?.name === + selectedTab?.privateAppProperties?.name && + item?.privateAppProperties?.service === + selectedTab?.privateAppProperties?.service && + item?.privateAppProperties?.identifier === + selectedTab?.privateAppProperties?.identifier ) ); } else { @@ -309,21 +315,19 @@ export const AppsNavBarDesktop = ({disableBack}) => { ) ); } - } else { // Add the selected app if it is not pinned - if(selectedTab?.isPrivate){ + if (selectedTab?.isPrivate) { updatedApps = [ - ...prev, - { - isPreview: true, - isPrivate: true, - privateAppProperties: { - ...(selectedTab?.privateAppProperties || {}) - } - - }, - ]; + ...prev, + { + isPreview: true, + isPrivate: true, + privateAppProperties: { + ...(selectedTab?.privateAppProperties || {}), + }, + }, + ]; } else { updatedApps = [ ...prev, @@ -333,12 +337,11 @@ export const AppsNavBarDesktop = ({disableBack}) => { }, ]; } - } saveToLocalStorage( - "ext_saved_settings", - "sortablePinnedApps", + 'ext_saved_settings', + 'sortablePinnedApps', updatedApps ); return updatedApps; @@ -350,70 +353,74 @@ export const AppsNavBarDesktop = ({disableBack}) => { > { if (selectedTab?.refreshFunc) { selectedTab.refreshFunc(selectedTab?.tabId); - } else { - executeEvent("refreshApp", { + executeEvent('refreshApp', { tabId: selectedTab?.tabId, }); } - + handleClose(); }} > + {!selectedTab?.isPrivate && ( - { - executeEvent("copyLink", { + executeEvent('copyLink', { tabId: selectedTab?.tabId, }); handleClose(); @@ -421,23 +428,24 @@ export const AppsNavBarDesktop = ({disableBack}) => { > + { + const theme = useTheme(); + return ( { if (isSelected) { - executeEvent("removeTab", { + executeEvent('removeTab', { data: app, }); return; } - executeEvent("setSelectedTab", { + executeEvent('setSelectedTab', { data: app, }); }} > {isSelected && ( - )} {app?.isPrivate && !app?.privateAppProperties?.logo ? ( ) : ( { > center-icon Date: Sun, 20 Apr 2025 09:39:39 +0200 Subject: [PATCH 47/55] Format code --- src/qortalRequests.ts | 2571 +++++++++++++++++++++++++---------------- 1 file changed, 1545 insertions(+), 1026 deletions(-) diff --git a/src/qortalRequests.ts b/src/qortalRequests.ts index f034dbd..701c433 100644 --- a/src/qortalRequests.ts +++ b/src/qortalRequests.ts @@ -1,12 +1,73 @@ -import { gateways, getApiKeyFromStorage } from "./background"; -import { listOfAllQortalRequests } from "./components/Apps/useQortalMessageListener"; -import { addForeignServer, addGroupAdminRequest, addListItems, adminAction, banFromGroupRequest, cancelGroupBanRequest, cancelGroupInviteRequest, cancelSellOrder, createAndCopyEmbedLink, createBuyOrder, createGroupRequest, createPoll, createSellOrder, decryptAESGCMRequest, decryptData, decryptDataWithSharingKey, decryptQortalGroupData, deleteHostedData, deleteListItems, deployAt, encryptData, encryptDataWithSharingKey, encryptQortalGroupData, getCrossChainServerInfo, getDaySummary, getNodeInfo, getNodeStatus, getForeignFee, getHostedData, getListItems, getServerConnectionHistory, getTxActivitySummary, getUserAccount, getUserWallet, getUserWalletInfo, getUserWalletTransactions, getWalletBalance, inviteToGroupRequest, joinGroup, kickFromGroupRequest, leaveGroupRequest, openNewTab, publishMultipleQDNResources, publishQDNResource, registerNameRequest, removeForeignServer, removeGroupAdminRequest, saveFile, sendChatMessage, sendCoin, setCurrentForeignServer, signTransaction, updateForeignFee, updateNameRequest, voteOnPoll, getArrrSyncStatus, updateGroupRequest, buyNameRequest, sellNameRequest, cancelSellNameRequest } from "./qortalRequests/get"; -import { getData, storeData } from "./utils/chromeStorage"; -import { executeEvent } from "./utils/events"; +import { gateways, getApiKeyFromStorage } from './background'; +import { listOfAllQortalRequests } from './components/Apps/useQortalMessageListener'; +import { + addForeignServer, + addGroupAdminRequest, + addListItems, + adminAction, + banFromGroupRequest, + cancelGroupBanRequest, + cancelGroupInviteRequest, + cancelSellOrder, + createAndCopyEmbedLink, + createBuyOrder, + createGroupRequest, + createPoll, + createSellOrder, + decryptAESGCMRequest, + decryptData, + decryptDataWithSharingKey, + decryptQortalGroupData, + deleteHostedData, + deleteListItems, + deployAt, + encryptData, + encryptDataWithSharingKey, + encryptQortalGroupData, + getCrossChainServerInfo, + getDaySummary, + getNodeInfo, + getNodeStatus, + getForeignFee, + getHostedData, + getListItems, + getServerConnectionHistory, + getTxActivitySummary, + getUserAccount, + getUserWallet, + getUserWalletInfo, + getUserWalletTransactions, + getWalletBalance, + inviteToGroupRequest, + joinGroup, + kickFromGroupRequest, + leaveGroupRequest, + openNewTab, + publishMultipleQDNResources, + publishQDNResource, + registerNameRequest, + removeForeignServer, + removeGroupAdminRequest, + saveFile, + sendChatMessage, + sendCoin, + setCurrentForeignServer, + signTransaction, + updateForeignFee, + updateNameRequest, + voteOnPoll, + getArrrSyncStatus, + updateGroupRequest, + buyNameRequest, + sellNameRequest, + cancelSellNameRequest, +} from './qortalRequests/get'; +import { getData, storeData } from './utils/chromeStorage'; +import { executeEvent } from './utils/events'; function getLocalStorage(key) { return getData(key).catch((error) => { - console.error("Error retrieving data:", error); + console.error('Error retrieving data:', error); throw error; }); } @@ -14,1311 +75,1769 @@ function getLocalStorage(key) { // Promisify setting data in localStorage function setLocalStorage(key, data) { return storeData(key, data).catch((error) => { - console.error("Error saving data:", error); + console.error('Error saving data:', error); throw error; }); } -export const isRunningGateway = async ()=> { - let isGateway = true; - const apiKey = await getApiKeyFromStorage(); - if (apiKey && (apiKey?.url && !gateways.some(gateway => apiKey?.url?.includes(gateway)))) { - isGateway = false; - } +export const isRunningGateway = async () => { + let isGateway = true; + const apiKey = await getApiKeyFromStorage(); + if ( + apiKey && + apiKey?.url && + !gateways.some((gateway) => apiKey?.url?.includes(gateway)) + ) { + isGateway = false; + } - return isGateway + return isGateway; +}; + +export async function setPermission(key, value) { + try { + // Get the existing qortalRequestPermissions object + const qortalRequestPermissions = + (await getLocalStorage('qortalRequestPermissions')) || {}; + + // Update the permission + qortalRequestPermissions[key] = value; + + // Save the updated object back to storage + await setLocalStorage('qortalRequestPermissions', qortalRequestPermissions); + } catch (error) { + console.error('Error setting permission:', error); + } } - - export async function setPermission(key, value) { - try { - // Get the existing qortalRequestPermissions object - const qortalRequestPermissions = (await getLocalStorage('qortalRequestPermissions')) || {}; - - // Update the permission - qortalRequestPermissions[key] = value; - - // Save the updated object back to storage - await setLocalStorage('qortalRequestPermissions', qortalRequestPermissions ); - - } catch (error) { - console.error('Error setting permission:', error); - } +export async function getPermission(key) { + try { + // Get the qortalRequestPermissions object from storage + const qortalRequestPermissions = + (await getLocalStorage('qortalRequestPermissions')) || {}; + + // Return the value for the given key, or null if it doesn't exist + return qortalRequestPermissions[key] || null; + } catch (error) { + console.error('Error getting permission:', error); + return null; } +} - export async function getPermission(key) { - try { - // Get the qortalRequestPermissions object from storage - const qortalRequestPermissions = (await getLocalStorage('qortalRequestPermissions')) || {}; - - // Return the value for the given key, or null if it doesn't exist - return qortalRequestPermissions[key] || null; - } catch (error) { - console.error('Error getting permission:', error); - return null; - } - } +// TODO: GET_FRIENDS_LIST +// NOT SURE IF TO IMPLEMENT: LINK_TO_QDN_RESOURCE, QDN_RESOURCE_DISPLAYED, SET_TAB_NOTIFICATIONS +function setupMessageListenerQortalRequest() { + window.addEventListener('message', async (event) => { + const request = event.data; - // TODO: GET_FRIENDS_LIST - // NOT SURE IF TO IMPLEMENT: LINK_TO_QDN_RESOURCE, QDN_RESOURCE_DISPLAYED, SET_TAB_NOTIFICATIONS + // 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' - function setupMessageListenerQortalRequest() { - window.addEventListener("message", async (event) => { - const request = event.data; - - // 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' - - - // Handle actions based on the `request.action` value - switch (request.action) { - case "GET_USER_ACCOUNT": { - try { - const res = await getUserAccount({isFromExtension, appInfo, skipAuth}); - event.source.postMessage({ + // Handle actions based on the `request.action` value + switch (request.action) { + case 'GET_USER_ACCOUNT': { + try { + const res = await getUserAccount({ + isFromExtension, + appInfo, + skipAuth, + }); + event.source.postMessage( + { requestId: request.requestId, action: request.action, payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { requestId: request.requestId, action: request.action, - error: "Unable to get user account", - type: "backgroundMessageResponse", - }, event.origin); - } - break; + error: 'Unable to get user account', + type: 'backgroundMessageResponse', + }, + event.origin + ); } - - case "ENCRYPT_DATA": { - try { - const res = await encryptData(request.payload, event.source); - event.source.postMessage({ + break; + } + + case 'ENCRYPT_DATA': { + try { + const res = await encryptData(request.payload, event.source); + event.source.postMessage( + { requestId: request.requestId, action: request.action, payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { requestId: request.requestId, action: request.action, error: error?.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; + type: 'backgroundMessageResponse', + }, + event.origin + ); } + break; + } - case "ENCRYPT_QORTAL_GROUP_DATA": { - try { - const res = await encryptQortalGroupData(request.payload, event.source); - event.source.postMessage({ + case 'ENCRYPT_QORTAL_GROUP_DATA': { + try { + const res = await encryptQortalGroupData( + request.payload, + event.source + ); + event.source.postMessage( + { requestId: request.requestId, action: request.action, payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { requestId: request.requestId, action: request.action, error: error?.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; + type: 'backgroundMessageResponse', + }, + event.origin + ); } + break; + } - case "DECRYPT_QORTAL_GROUP_DATA": { - try { - const res = await decryptQortalGroupData(request.payload, event.source); - event.source.postMessage({ + case 'DECRYPT_QORTAL_GROUP_DATA': { + try { + const res = await decryptQortalGroupData( + request.payload, + event.source + ); + event.source.postMessage( + { requestId: request.requestId, action: request.action, payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { requestId: request.requestId, action: request.action, error: error?.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; - } - - case "DECRYPT_DATA": { - try { - const res = await decryptData(request.payload); - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - error: error.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; - } - - case "GET_LIST_ITEMS": { - try { - const res = await getListItems(request.payload, isFromExtension); - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - error: error.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; - } - - case "ADD_LIST_ITEMS": { - try { - const res = await addListItems(request.payload, isFromExtension); - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - error: error.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; - } - - case "DELETE_LIST_ITEM": { - try { - const res = await deleteListItems(request.payload, isFromExtension); - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - error: error.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; - } - - case "PUBLISH_QDN_RESOURCE": { - try { - const res = await publishQDNResource(request.payload, event.source, isFromExtension); - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - error: error.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; - } - - case "PUBLISH_MULTIPLE_QDN_RESOURCES": { - try { - const res = await publishMultipleQDNResources(request.payload, event.source, isFromExtension); - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - error: error.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; - } - - case "VOTE_ON_POLL": { - try { - const res = await voteOnPoll(request.payload, isFromExtension); - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - error: error.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; - } - - case "CREATE_POLL": { - try { - const res = await createPoll(request.payload, isFromExtension); - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - error: error.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; - } - - case "SEND_CHAT_MESSAGE": { - try { - const res = await sendChatMessage(request.payload, isFromExtension, appInfo); - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - error: error.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; - } - - case "JOIN_GROUP": { - try { - const res = await joinGroup(request.payload, isFromExtension); - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - error: error.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; + type: 'backgroundMessageResponse', + }, + event.origin + ); } + break; + } - case "DEPLOY_AT": { - try { - const res = await deployAt(request.payload, isFromExtension); - event.source.postMessage({ + case 'DECRYPT_DATA': { + try { + const res = await decryptData(request.payload); + event.source.postMessage( + { requestId: request.requestId, action: request.action, payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { requestId: request.requestId, action: request.action, error: error.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; - } - - case "GET_USER_WALLET": { - try { - const res = await getUserWallet(request.payload, isFromExtension, appInfo); - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - error: error.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; - } - - case "GET_WALLET_BALANCE": { - try { - const res = await getWalletBalance(request.payload, false, isFromExtension, appInfo); - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - error: error.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; - } - - case "GET_USER_WALLET_TRANSACTIONS": { - try { - const res = await getUserWalletTransactions(request.payload, isFromExtension, appInfo); - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - error: error.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; - } - - case "GET_USER_WALLET_INFO": { - try { - const res = await getUserWalletInfo(request.payload, isFromExtension, appInfo); - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - error: error.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; - } - - case "GET_CROSSCHAIN_SERVER_INFO": { - try { - const res = await getCrossChainServerInfo(request.payload); - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - error: error.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; - } - - case "GET_TX_ACTIVITY_SUMMARY": { - try { - const res = await getTxActivitySummary(request.payload); - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - error: error.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; - } - - case "GET_FOREIGN_FEE": { - try { - const res = await getForeignFee(request.payload); - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - error: error.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; - } - - case "UPDATE_FOREIGN_FEE": { - try { - const res = await updateForeignFee(request.payload); - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - error: error.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; - } - - case "GET_SERVER_CONNECTION_HISTORY": { - try { - const res = await getServerConnectionHistory(request.payload); - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - error: error.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; - } - - case "SET_CURRENT_FOREIGN_SERVER": { - try { - const res = await setCurrentForeignServer(request.payload); - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - error: error.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; - } - - case "ADD_FOREIGN_SERVER": { - try { - const res = await addForeignServer(request.payload); - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - error: error.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; - } - - case "REMOVE_FOREIGN_SERVER": { - try { - const res = await removeForeignServer(request.payload); - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - error: error.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; - } - - case "GET_DAY_SUMMARY": { - try { - const res = await getDaySummary(request.payload); - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - error: error.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; - } - - case "GET_NODE_INFO": { - try { - const res = await getNodeInfo(request.payload); - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - error: error.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; + type: 'backgroundMessageResponse', + }, + event.origin + ); } + break; + } - case "GET_NODE_STATUS": { - try { - const res = await getNodeStatus(request.payload); - event.source.postMessage({ + case 'GET_LIST_ITEMS': { + try { + const res = await getListItems(request.payload, isFromExtension); + event.source.postMessage( + { requestId: request.requestId, action: request.action, payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { requestId: request.requestId, action: request.action, error: error.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; + type: 'backgroundMessageResponse', + }, + event.origin + ); } + break; + } - case "SEND_COIN": { - try { - const res = await sendCoin(request.payload, isFromExtension); - event.source.postMessage({ + case 'ADD_LIST_ITEMS': { + try { + const res = await addListItems(request.payload, isFromExtension); + event.source.postMessage( + { requestId: request.requestId, action: request.action, payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { requestId: request.requestId, action: request.action, error: error.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; + type: 'backgroundMessageResponse', + }, + event.origin + ); } + break; + } - case "CREATE_TRADE_BUY_ORDER": { - try { - const res = await createBuyOrder(request.payload, isFromExtension); - event.source.postMessage({ + case 'DELETE_LIST_ITEM': { + try { + const res = await deleteListItems(request.payload, isFromExtension); + event.source.postMessage( + { requestId: request.requestId, action: request.action, payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { requestId: request.requestId, action: request.action, error: error.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; + type: 'backgroundMessageResponse', + }, + event.origin + ); } + break; + } - case "CREATE_TRADE_SELL_ORDER": { - try { - const res = await createSellOrder(request.payload, isFromExtension); - event.source.postMessage({ + case 'PUBLISH_QDN_RESOURCE': { + try { + const res = await publishQDNResource( + request.payload, + event.source, + isFromExtension + ); + event.source.postMessage( + { requestId: request.requestId, action: request.action, payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { requestId: request.requestId, action: request.action, error: error.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; + type: 'backgroundMessageResponse', + }, + event.origin + ); } + break; + } - case "CANCEL_TRADE_SELL_ORDER": { - try { - const res = await cancelSellOrder(request.payload, isFromExtension); - event.source.postMessage({ + case 'PUBLISH_MULTIPLE_QDN_RESOURCES': { + try { + const res = await publishMultipleQDNResources( + request.payload, + event.source, + isFromExtension + ); + event.source.postMessage( + { requestId: request.requestId, action: request.action, payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { requestId: request.requestId, action: request.action, error: error.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; + type: 'backgroundMessageResponse', + }, + event.origin + ); } + break; + } - case "IS_USING_PUBLIC_NODE": { - try { - let isGateway = await isRunningGateway() - event.source.postMessage({ + case 'VOTE_ON_POLL': { + try { + const res = await voteOnPoll(request.payload, isFromExtension); + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + payload: res, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + error: error.message, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } + break; + } + + case 'CREATE_POLL': { + try { + const res = await createPoll(request.payload, isFromExtension); + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + payload: res, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + error: error.message, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } + break; + } + + case 'SEND_CHAT_MESSAGE': { + try { + const res = await sendChatMessage( + request.payload, + isFromExtension, + appInfo + ); + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + payload: res, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + error: error.message, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } + break; + } + + case 'JOIN_GROUP': { + try { + const res = await joinGroup(request.payload, isFromExtension); + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + payload: res, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + error: error.message, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } + break; + } + + case 'DEPLOY_AT': { + try { + const res = await deployAt(request.payload, isFromExtension); + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + payload: res, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + error: error.message, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } + break; + } + + case 'GET_USER_WALLET': { + try { + const res = await getUserWallet( + request.payload, + isFromExtension, + appInfo + ); + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + payload: res, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + error: error.message, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } + break; + } + + case 'GET_WALLET_BALANCE': { + try { + const res = await getWalletBalance( + request.payload, + false, + isFromExtension, + appInfo + ); + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + payload: res, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + error: error.message, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } + break; + } + + case 'GET_USER_WALLET_TRANSACTIONS': { + try { + const res = await getUserWalletTransactions( + request.payload, + isFromExtension, + appInfo + ); + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + payload: res, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + error: error.message, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } + break; + } + + case 'GET_USER_WALLET_INFO': { + try { + const res = await getUserWalletInfo( + request.payload, + isFromExtension, + appInfo + ); + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + payload: res, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + error: error.message, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } + break; + } + + case 'GET_CROSSCHAIN_SERVER_INFO': { + try { + const res = await getCrossChainServerInfo(request.payload); + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + payload: res, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + error: error.message, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } + break; + } + + case 'GET_TX_ACTIVITY_SUMMARY': { + try { + const res = await getTxActivitySummary(request.payload); + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + payload: res, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + error: error.message, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } + break; + } + + case 'GET_FOREIGN_FEE': { + try { + const res = await getForeignFee(request.payload); + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + payload: res, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + error: error.message, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } + break; + } + + case 'UPDATE_FOREIGN_FEE': { + try { + const res = await updateForeignFee(request.payload); + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + payload: res, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + error: error.message, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } + break; + } + + case 'GET_SERVER_CONNECTION_HISTORY': { + try { + const res = await getServerConnectionHistory(request.payload); + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + payload: res, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + error: error.message, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } + break; + } + + case 'SET_CURRENT_FOREIGN_SERVER': { + try { + const res = await setCurrentForeignServer(request.payload); + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + payload: res, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + error: error.message, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } + break; + } + + case 'ADD_FOREIGN_SERVER': { + try { + const res = await addForeignServer(request.payload); + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + payload: res, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + error: error.message, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } + break; + } + + case 'REMOVE_FOREIGN_SERVER': { + try { + const res = await removeForeignServer(request.payload); + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + payload: res, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + error: error.message, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } + break; + } + + case 'GET_DAY_SUMMARY': { + try { + const res = await getDaySummary(request.payload); + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + payload: res, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + error: error.message, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } + break; + } + + case 'GET_NODE_INFO': { + try { + const res = await getNodeInfo(request.payload); + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + payload: res, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + error: error.message, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } + break; + } + + case 'GET_NODE_STATUS': { + try { + const res = await getNodeStatus(request.payload); + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + payload: res, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + error: error.message, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } + break; + } + + case 'SEND_COIN': { + try { + const res = await sendCoin(request.payload, isFromExtension); + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + payload: res, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + error: error.message, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } + break; + } + + case 'CREATE_TRADE_BUY_ORDER': { + try { + const res = await createBuyOrder(request.payload, isFromExtension); + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + payload: res, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + error: error.message, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } + break; + } + + case 'CREATE_TRADE_SELL_ORDER': { + try { + const res = await createSellOrder(request.payload, isFromExtension); + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + payload: res, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + error: error.message, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } + break; + } + + case 'CANCEL_TRADE_SELL_ORDER': { + try { + const res = await cancelSellOrder(request.payload, isFromExtension); + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + payload: res, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + error: error.message, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } + break; + } + + case 'IS_USING_PUBLIC_NODE': { + try { + let isGateway = await isRunningGateway(); + event.source.postMessage( + { requestId: request.requestId, action: request.action, payload: isGateway, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { requestId: request.requestId, action: request.action, error: error?.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; + type: 'backgroundMessageResponse', + }, + event.origin + ); } + break; + } - case "ADMIN_ACTION": { - try { - const res = await adminAction(request.payload, isFromExtension) - event.source.postMessage({ + case 'ADMIN_ACTION': { + try { + const res = await adminAction(request.payload, isFromExtension); + event.source.postMessage( + { requestId: request.requestId, action: request.action, payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { requestId: request.requestId, action: request.action, error: error?.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; + type: 'backgroundMessageResponse', + }, + event.origin + ); } + break; + } - case "SIGN_TRANSACTION": { - try { - const res = await signTransaction(request.payload, isFromExtension) - event.source.postMessage({ + case 'SIGN_TRANSACTION': { + try { + const res = await signTransaction(request.payload, isFromExtension); + event.source.postMessage( + { requestId: request.requestId, action: request.action, payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { requestId: request.requestId, action: request.action, error: error?.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; + type: 'backgroundMessageResponse', + }, + event.origin + ); } + break; + } - case "OPEN_NEW_TAB": { - try { - const res = await openNewTab(request.payload, isFromExtension) - event.source.postMessage({ + case 'OPEN_NEW_TAB': { + try { + const res = await openNewTab(request.payload, isFromExtension); + event.source.postMessage( + { requestId: request.requestId, action: request.action, payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { requestId: request.requestId, action: request.action, error: error?.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; + type: 'backgroundMessageResponse', + }, + event.origin + ); } + break; + } - case "CREATE_AND_COPY_EMBED_LINK": { - try { - const res = await createAndCopyEmbedLink(request.payload, isFromExtension) - event.source.postMessage({ + case 'CREATE_AND_COPY_EMBED_LINK': { + try { + const res = await createAndCopyEmbedLink( + request.payload, + isFromExtension + ); + event.source.postMessage( + { requestId: request.requestId, action: request.action, payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { requestId: request.requestId, action: request.action, error: error?.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; + type: 'backgroundMessageResponse', + }, + event.origin + ); } + break; + } - case "ENCRYPT_DATA_WITH_SHARING_KEY": { - try { - const res = await encryptDataWithSharingKey(request.payload, isFromExtension) - event.source.postMessage({ + case 'ENCRYPT_DATA_WITH_SHARING_KEY': { + try { + const res = await encryptDataWithSharingKey( + request.payload, + isFromExtension + ); + event.source.postMessage( + { requestId: request.requestId, action: request.action, payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { requestId: request.requestId, action: request.action, error: error?.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; + type: 'backgroundMessageResponse', + }, + event.origin + ); } + break; + } - case "DECRYPT_DATA_WITH_SHARING_KEY": { - try { - const res = await decryptDataWithSharingKey(request.payload, isFromExtension) - event.source.postMessage({ + case 'DECRYPT_DATA_WITH_SHARING_KEY': { + try { + const res = await decryptDataWithSharingKey( + request.payload, + isFromExtension + ); + event.source.postMessage( + { requestId: request.requestId, action: request.action, payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { requestId: request.requestId, action: request.action, error: error?.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; + type: 'backgroundMessageResponse', + }, + event.origin + ); } + break; + } - case "DELETE_HOSTED_DATA" : { - try { - const res = await deleteHostedData(request.payload, isFromExtension) - event.source.postMessage({ + case 'DELETE_HOSTED_DATA': { + try { + const res = await deleteHostedData(request.payload, isFromExtension); + event.source.postMessage( + { requestId: request.requestId, action: request.action, payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { requestId: request.requestId, action: request.action, error: error?.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; + type: 'backgroundMessageResponse', + }, + event.origin + ); } - case "GET_HOSTED_DATA" : { - try { - const res = await getHostedData(request.payload, isFromExtension) - event.source.postMessage({ + break; + } + case 'GET_HOSTED_DATA': { + try { + const res = await getHostedData(request.payload, isFromExtension); + event.source.postMessage( + { requestId: request.requestId, action: request.action, payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { requestId: request.requestId, action: request.action, error: error?.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; + type: 'backgroundMessageResponse', + }, + event.origin + ); } + break; + } - case "SHOW_ACTIONS" : { - try { - - event.source.postMessage({ + case 'SHOW_ACTIONS': { + try { + event.source.postMessage( + { requestId: request.requestId, action: request.action, payload: listOfAllQortalRequests, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { requestId: request.requestId, action: request.action, error: error?.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; + type: 'backgroundMessageResponse', + }, + event.origin + ); } + break; + } - case "REGISTER_NAME" : { - try { - const res = await registerNameRequest(request.payload, isFromExtension) - event.source.postMessage({ + case 'REGISTER_NAME': { + try { + const res = await registerNameRequest( + request.payload, + isFromExtension + ); + event.source.postMessage( + { requestId: request.requestId, action: request.action, payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { requestId: request.requestId, action: request.action, error: error?.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; + type: 'backgroundMessageResponse', + }, + event.origin + ); } + break; + } - case "UPDATE_NAME" : { - try { - const res = await updateNameRequest(request.payload, isFromExtension) - event.source.postMessage({ + case 'UPDATE_NAME': { + try { + const res = await updateNameRequest(request.payload, isFromExtension); + event.source.postMessage( + { requestId: request.requestId, action: request.action, payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { requestId: request.requestId, action: request.action, error: error?.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; + type: 'backgroundMessageResponse', + }, + event.origin + ); } + break; + } - case "LEAVE_GROUP" : { - try { - const res = await leaveGroupRequest(request.payload, isFromExtension) - event.source.postMessage({ + case 'LEAVE_GROUP': { + try { + const res = await leaveGroupRequest(request.payload, isFromExtension); + event.source.postMessage( + { requestId: request.requestId, action: request.action, payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { requestId: request.requestId, action: request.action, error: error?.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; + type: 'backgroundMessageResponse', + }, + event.origin + ); } + break; + } - case "INVITE_TO_GROUP" : { - try { - const res = await inviteToGroupRequest(request.payload, isFromExtension) - event.source.postMessage({ + case 'INVITE_TO_GROUP': { + try { + const res = await inviteToGroupRequest( + request.payload, + isFromExtension + ); + event.source.postMessage( + { requestId: request.requestId, action: request.action, payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { requestId: request.requestId, action: request.action, error: error?.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; + type: 'backgroundMessageResponse', + }, + event.origin + ); } + break; + } - case "KICK_FROM_GROUP" : { - try { - const res = await kickFromGroupRequest(request.payload, isFromExtension) - event.source.postMessage({ + case 'KICK_FROM_GROUP': { + try { + const res = await kickFromGroupRequest( + request.payload, + isFromExtension + ); + event.source.postMessage( + { requestId: request.requestId, action: request.action, payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { requestId: request.requestId, action: request.action, error: error?.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; + type: 'backgroundMessageResponse', + }, + event.origin + ); } + break; + } - case "BAN_FROM_GROUP" : { - try { - const res = await banFromGroupRequest(request.payload, isFromExtension) - event.source.postMessage({ + case 'BAN_FROM_GROUP': { + try { + const res = await banFromGroupRequest( + request.payload, + isFromExtension + ); + event.source.postMessage( + { requestId: request.requestId, action: request.action, payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { requestId: request.requestId, action: request.action, error: error?.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; + type: 'backgroundMessageResponse', + }, + event.origin + ); } + break; + } - case "CANCEL_GROUP_BAN" : { - try { - const res = await cancelGroupBanRequest(request.payload, isFromExtension) - event.source.postMessage({ + case 'CANCEL_GROUP_BAN': { + try { + const res = await cancelGroupBanRequest( + request.payload, + isFromExtension + ); + event.source.postMessage( + { requestId: request.requestId, action: request.action, payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { requestId: request.requestId, action: request.action, error: error?.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; + type: 'backgroundMessageResponse', + }, + event.origin + ); } + break; + } - case "ADD_GROUP_ADMIN" : { - try { - const res = await addGroupAdminRequest(request.payload, isFromExtension) + case 'ADD_GROUP_ADMIN': { + try { + const res = await addGroupAdminRequest( + request.payload, + isFromExtension + ); - event.source.postMessage({ + event.source.postMessage( + { requestId: request.requestId, action: request.action, payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { requestId: request.requestId, action: request.action, error: error?.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; + type: 'backgroundMessageResponse', + }, + event.origin + ); } + break; + } - case "DECRYPT_AESGCM" : { - try { - const res = await decryptAESGCMRequest(request.payload, isFromExtension) - event.source.postMessage({ + case 'DECRYPT_AESGCM': { + try { + const res = await decryptAESGCMRequest( + request.payload, + isFromExtension + ); + event.source.postMessage( + { requestId: request.requestId, action: request.action, payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { requestId: request.requestId, action: request.action, error: error?.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; + type: 'backgroundMessageResponse', + }, + event.origin + ); } + break; + } - case "REMOVE_GROUP_ADMIN" : { - try { - const res = await removeGroupAdminRequest(request.payload, isFromExtension) - event.source.postMessage({ + case 'REMOVE_GROUP_ADMIN': { + try { + const res = await removeGroupAdminRequest( + request.payload, + isFromExtension + ); + event.source.postMessage( + { requestId: request.requestId, action: request.action, payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { requestId: request.requestId, action: request.action, error: error?.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; + type: 'backgroundMessageResponse', + }, + event.origin + ); } + break; + } - case "CANCEL_GROUP_INVITE" : { - try { - const res = await cancelGroupInviteRequest(request.payload, isFromExtension) - event.source.postMessage({ + case 'CANCEL_GROUP_INVITE': { + try { + const res = await cancelGroupInviteRequest( + request.payload, + isFromExtension + ); + event.source.postMessage( + { requestId: request.requestId, action: request.action, payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { requestId: request.requestId, action: request.action, error: error?.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; + type: 'backgroundMessageResponse', + }, + event.origin + ); } + break; + } - case "CREATE_GROUP" : { - try { - const res = await createGroupRequest(request.payload, isFromExtension) - event.source.postMessage({ + case 'CREATE_GROUP': { + try { + const res = await createGroupRequest( + request.payload, + isFromExtension + ); + event.source.postMessage( + { requestId: request.requestId, action: request.action, payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { requestId: request.requestId, action: request.action, error: error?.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; + type: 'backgroundMessageResponse', + }, + event.origin + ); } - case "UPDATE_GROUP" : { - try { - const res = await updateGroupRequest(request.payload, isFromExtension) - event.source.postMessage({ + break; + } + case 'UPDATE_GROUP': { + try { + const res = await updateGroupRequest( + request.payload, + isFromExtension + ); + event.source.postMessage( + { requestId: request.requestId, action: request.action, payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { requestId: request.requestId, action: request.action, error: error?.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; + type: 'backgroundMessageResponse', + }, + event.origin + ); } + break; + } - case "GET_ARRR_SYNC_STATUS": { - try { - const res = await getArrrSyncStatus(request.payload); - event.source.postMessage({ + case 'GET_ARRR_SYNC_STATUS': { + try { + const res = await getArrrSyncStatus(request.payload); + event.source.postMessage( + { requestId: request.requestId, action: request.action, payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { requestId: request.requestId, action: request.action, error: error.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; + type: 'backgroundMessageResponse', + }, + event.origin + ); } - case "SHOW_PDF_READER" : { - try { - if(!request.payload?.blob){ - throw new Error('Missing blob') - } - if(request.payload?.blob?.type !== "application/pdf") throw new Error('blob type must be application/pdf') - executeEvent("openPdf", { blob: request.payload?.blob}); - event.source.postMessage({ + break; + } + case 'SHOW_PDF_READER': { + try { + if (!request.payload?.blob) { + throw new Error('Missing blob'); + } + if (request.payload?.blob?.type !== 'application/pdf') + throw new Error('blob type must be application/pdf'); + executeEvent('openPdf', { blob: request.payload?.blob }); + event.source.postMessage( + { requestId: request.requestId, action: request.action, payload: true, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { requestId: request.requestId, action: request.action, error: error?.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; + type: 'backgroundMessageResponse', + }, + event.origin + ); } - case "BUY_NAME": { - try { - const res = await buyNameRequest(request.payload, isFromExtension); - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - error: error.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; - } - case "SELL_NAME": { - try { - const res = await sellNameRequest(request.payload, isFromExtension); - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - error: error.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; - } - case "CANCEL_SELL_NAME": { - try { - const res = await cancelSellNameRequest(request.payload, isFromExtension); - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - payload: res, - type: "backgroundMessageResponse", - }, event.origin); - } catch (error) { - event.source.postMessage({ - requestId: request.requestId, - action: request.action, - error: error.message, - type: "backgroundMessageResponse", - }, event.origin); - } - break; - } - default: - break; + break; } - }); - } - - // Initialize the message listener - setupMessageListenerQortalRequest(); + case 'BUY_NAME': { + try { + const res = await buyNameRequest(request.payload, isFromExtension); + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + payload: res, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + error: error.message, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } + break; + } + case 'SELL_NAME': { + try { + const res = await sellNameRequest(request.payload, isFromExtension); + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + payload: res, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + error: error.message, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } + break; + } + case 'CANCEL_SELL_NAME': { + try { + const res = await cancelSellNameRequest( + request.payload, + isFromExtension + ); + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + payload: res, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } catch (error) { + event.source.postMessage( + { + requestId: request.requestId, + action: request.action, + error: error.message, + type: 'backgroundMessageResponse', + }, + event.origin + ); + } + break; + } + default: + break; + } + }); +} + +// Initialize the message listener +setupMessageListenerQortalRequest(); From 6e26f582d0f2c51570027d807809cbd2a5ae0c4f Mon Sep 17 00:00:00 2001 From: Nicola Benaglia Date: Sun, 20 Apr 2025 09:39:51 +0200 Subject: [PATCH 48/55] Format code --- src/components/Group/WalletsAppWrapper.tsx | 131 ++++++++++----------- 1 file changed, 63 insertions(+), 68 deletions(-) diff --git a/src/components/Group/WalletsAppWrapper.tsx b/src/components/Group/WalletsAppWrapper.tsx index 788a36a..64b89be 100644 --- a/src/components/Group/WalletsAppWrapper.tsx +++ b/src/components/Group/WalletsAppWrapper.tsx @@ -1,23 +1,17 @@ -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 { Box, ButtonBase, Divider, Typography } from '@mui/material'; +import { 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"; +} 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.tsx'; +import RefreshIcon from '@mui/icons-material/Refresh'; export const WalletsAppWrapper = () => { const iframeRef = useRef(null); @@ -26,10 +20,10 @@ export const WalletsAppWrapper = () => { navigationControllerAtom ); const [selectedTab, setSelectedTab] = useState({ - tabId: "5558589", - name: "Q-Wallets", - service: "APP", - path: 'qortal?authOnMount=true' + tabId: '5558589', + name: 'Q-Wallets', + service: 'APP', + path: 'qortal?authOnMount=true', }); const isDisableBackButton = useMemo(() => { @@ -48,64 +42,64 @@ export const WalletsAppWrapper = () => { ); useEffect(() => { - subscribeToEvent("openWalletsApp", openWalletsAppFunc); + subscribeToEvent('openWalletsApp', openWalletsAppFunc); return () => { - unsubscribeFromEvent("openWalletsApp", openWalletsAppFunc); + unsubscribeFromEvent('openWalletsApp', openWalletsAppFunc); }; }, [openWalletsAppFunc]); - const handleClose = ()=> { + const handleClose = () => { setIsOpen(false); - iframeRef.current = null - } + iframeRef.current = null; + }; return ( <> {isOpen && ( Q-Wallets - + + + { skipAuth={true} /> - + { executeEvent(`navigateBackApp-${selectedTab?.tabId}`, {}); @@ -124,31 +120,30 @@ export const WalletsAppWrapper = () => { disabled={isDisableBackButton} sx={{ opacity: !isDisableBackButton ? 1 : 0.1, - cursor: !isDisableBackButton ? "pointer" : "default", + cursor: !isDisableBackButton ? 'pointer' : 'default', }} > - + - { - if (selectedTab?.refreshFunc) { - selectedTab.refreshFunc(selectedTab?.tabId); - - } else { - executeEvent("refreshApp", { - tabId: selectedTab?.tabId, - }); - } - - - }}> - + { + if (selectedTab?.refreshFunc) { + selectedTab.refreshFunc(selectedTab?.tabId); + } else { + executeEvent('refreshApp', { + tabId: selectedTab?.tabId, + }); + } + }} + > + From 515379ab719c8297e070f7f956c77fc77b970521 Mon Sep 17 00:00:00 2001 From: Nicola Benaglia Date: Sun, 20 Apr 2025 09:40:26 +0200 Subject: [PATCH 49/55] Use txs instead of svg --- src/components/Apps/AppsDevModeTabComponent.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/components/Apps/AppsDevModeTabComponent.tsx b/src/components/Apps/AppsDevModeTabComponent.tsx index e25bf11..27dcbec 100644 --- a/src/components/Apps/AppsDevModeTabComponent.tsx +++ b/src/components/Apps/AppsDevModeTabComponent.tsx @@ -1,5 +1,5 @@ import { TabParent } from './Apps-styles'; -import NavCloseTab from '../../assets/svgs/NavCloseTab.svg'; +import { NavCloseTab } from '../../assets/svgs/NavCloseTab.tsx'; import { getBaseApiReact } from '../../App'; import { Avatar, ButtonBase } from '@mui/material'; import LogoSelected from '../../assets/svgs/LogoSelected.svg'; @@ -27,14 +27,13 @@ export const AppsDevModeTabComponent = ({ isSelected, app }) => { }} > {isSelected && ( - )} Date: Sun, 20 Apr 2025 09:40:44 +0200 Subject: [PATCH 50/55] Format code --- src/components/Apps/AppsDevModeNavBar.tsx | 187 ++++++++---------- src/components/Apps/AppsLibrary.tsx | 72 ++++--- src/components/Apps/AppsNavBar.tsx | 220 ++++++++++++---------- 3 files changed, 243 insertions(+), 236 deletions(-) diff --git a/src/components/Apps/AppsDevModeNavBar.tsx b/src/components/Apps/AppsDevModeNavBar.tsx index 983aef3..15c22ab 100644 --- a/src/components/Apps/AppsDevModeNavBar.tsx +++ b/src/components/Apps/AppsDevModeNavBar.tsx @@ -1,51 +1,34 @@ -import React, { useEffect, useMemo, useRef, useState } from "react"; +import { useEffect, useMemo, useRef, useState } from 'react'; import { AppsNavBarLeft, AppsNavBarParent, AppsNavBarRight, -} from "./Apps-styles"; -import NavBack from "../../assets/svgs/NavBack.svg"; -import NavAdd from "../../assets/svgs/NavAdd.svg"; -import NavMoreMenu from "../../assets/svgs/NavMoreMenu.svg"; -import { - ButtonBase, - ListItemIcon, - ListItemText, - Menu, - MenuItem, - Tab, - Tabs, -} from "@mui/material"; +} from './Apps-styles'; +import { NavBack } from '../../assets/svgs/NavBack.tsx'; +import { NavAdd } from '../../assets/svgs/NavAdd.tsx'; +import { ButtonBase, Tab, Tabs } from '@mui/material'; import { executeEvent, subscribeToEvent, unsubscribeFromEvent, -} from "../../utils/events"; -import TabComponent from "./TabComponent"; -import PushPinIcon from "@mui/icons-material/PushPin"; -import RefreshIcon from "@mui/icons-material/Refresh"; -import { useRecoilState, useSetRecoilState } from "recoil"; -import { - navigationControllerAtom, - settingsLocalLastUpdatedAtom, - sortablePinnedAppsAtom, -} from "../../atoms/global"; -import { AppsDevModeTabComponent } from "./AppsDevModeTabComponent"; - - +} from '../../utils/events'; +import RefreshIcon from '@mui/icons-material/Refresh'; +import { useRecoilState } from 'recoil'; +import { navigationControllerAtom } from '../../atoms/global'; +import { AppsDevModeTabComponent } from './AppsDevModeTabComponent'; export const AppsDevModeNavBar = () => { const [tabs, setTabs] = useState([]); const [selectedTab, setSelectedTab] = useState(null); - const [navigationController, setNavigationController] = useRecoilState(navigationControllerAtom) + const [navigationController, setNavigationController] = useRecoilState( + navigationControllerAtom + ); const [isNewTabWindow, setIsNewTabWindow] = useState(false); const tabsRef = useRef(null); const [anchorEl, setAnchorEl] = useState(null); const open = Boolean(anchorEl); - - const handleClick = (event) => { setAnchorEl(event.currentTarget); }; @@ -57,27 +40,25 @@ export const AppsDevModeNavBar = () => { useEffect(() => { // Scroll to the last tab whenever the tabs array changes (e.g., when a new tab is added) if (tabsRef.current) { - const tabElements = tabsRef.current.querySelectorAll(".MuiTab-root"); + const tabElements = tabsRef.current.querySelectorAll('.MuiTab-root'); if (tabElements.length > 0) { const lastTab = tabElements[tabElements.length - 1]; lastTab.scrollIntoView({ - behavior: "smooth", - block: "nearest", - inline: "end", + behavior: 'smooth', + block: 'nearest', + inline: 'end', }); } } }, [tabs.length]); // Dependency on the number of tabs - - const isDisableBackButton = useMemo(()=> { - if(selectedTab && navigationController[selectedTab?.tabId]?.hasBack) return false - if(selectedTab && !navigationController[selectedTab?.tabId]?.hasBack) return true - return false - }, [navigationController, selectedTab]) - - - + const isDisableBackButton = useMemo(() => { + if (selectedTab && navigationController[selectedTab?.tabId]?.hasBack) + return false; + if (selectedTab && !navigationController[selectedTab?.tabId]?.hasBack) + return true; + return false; + }, [navigationController, selectedTab]); const setTabsToNav = (e) => { const { tabs, selectedTab, isNewTabWindow } = e.detail?.data; @@ -88,45 +69,43 @@ export const AppsDevModeNavBar = () => { }; useEffect(() => { - subscribeToEvent("appsDevModeSetTabsToNav", setTabsToNav); + subscribeToEvent('appsDevModeSetTabsToNav', setTabsToNav); return () => { - unsubscribeFromEvent("appsDevModeSetTabsToNav", setTabsToNav); + unsubscribeFromEvent('appsDevModeSetTabsToNav', setTabsToNav); }; }, []); - - - return ( { - executeEvent("devModeNavigateBack", selectedTab?.tabId); + executeEvent('devModeNavigateBack', selectedTab?.tabId); }} disabled={isDisableBackButton} sx={{ opacity: !isDisableBackButton ? 1 : 0.1, - cursor: !isDisableBackButton ? 'pointer': 'default' + cursor: !isDisableBackButton ? 'pointer' : 'default', }} > - + + { variant="scrollable" // Make tabs scrollable scrollButtons={true} sx={{ - "& .MuiTabs-indicator": { - backgroundColor: "white", + '& .MuiTabs-indicator': { + backgroundColor: 'white', }, maxHeight: `320px`, // Ensure the tabs container fits within the available space - overflow: "hidden", // Prevents overflow on small screens + overflow: 'hidden', // Prevents overflow on small screens }} > {tabs?.map((tab) => ( @@ -153,65 +132,61 @@ export const AppsDevModeNavBar = () => { /> } // Pass custom component sx={{ - "&.Mui-selected": { - color: "white", + '&.Mui-selected': { + color: 'white', }, - padding: "0px", - margin: "0px", - minWidth: "0px", - width: "50px", + padding: '0px', + margin: '0px', + minWidth: '0px', + width: '50px', }} /> ))} + {selectedTab && ( - { - setSelectedTab(null); - executeEvent("devModeNewTabWindow", {}); + sx={{ + gap: '10px', + flexDirection: 'column', }} > - { + setSelectedTab(null); + executeEvent('devModeNewTabWindow', {}); }} - src={NavAdd} - /> - - - { - if(selectedTab?.refreshFunc){ - selectedTab.refreshFunc(selectedTab?.tabId) - } else { - executeEvent("refreshApp", { - tabId: selectedTab?.tabId, - }); - } - - }} - > - + - - + + + { + if (selectedTab?.refreshFunc) { + selectedTab.refreshFunc(selectedTab?.tabId); + } else { + executeEvent('refreshApp', { + tabId: selectedTab?.tabId, + }); + } + }} + > + + + )} - - ); }; diff --git a/src/components/Apps/AppsLibrary.tsx b/src/components/Apps/AppsLibrary.tsx index 42a8658..e5cac4a 100644 --- a/src/components/Apps/AppsLibrary.tsx +++ b/src/components/Apps/AppsLibrary.tsx @@ -1,11 +1,4 @@ -import React, { - useCallback, - useContext, - useEffect, - useMemo, - useRef, - useState, -} from 'react'; +import { useContext, useEffect, useMemo, useRef, useState } from 'react'; import { AppCircle, AppCircleContainer, @@ -13,7 +6,6 @@ import { AppLibrarySubTitle, AppsContainer, AppsLibraryContainer, - AppsParent, AppsSearchContainer, AppsSearchLeft, AppsSearchRight, @@ -24,16 +16,22 @@ import { PublishQAppCTARight, PublishQAppDotsBG, } from './Apps-styles'; -import { Avatar, Box, ButtonBase, InputBase, styled } from '@mui/material'; -import { Add } from '@mui/icons-material'; +import { + Avatar, + Box, + ButtonBase, + InputBase, + styled, + useTheme, +} from '@mui/material'; import { MyContext, getBaseApiReact } from '../../App'; import LogoSelected from '../../assets/svgs/LogoSelected.svg'; import IconSearch from '../../assets/svgs/Search.svg'; import IconClearInput from '../../assets/svgs/ClearInput.svg'; import qappDevelopText from '../../assets/svgs/qappDevelopText.svg'; import qappDots from '../../assets/svgs/qappDots.svg'; +// import { Return } from './assets/svgs/Return.tsx'; import ReturnSVG from '../../assets/svgs/Return.svg'; - import { Spacer } from '../../common/Spacer'; import { AppInfoSnippet } from './AppInfoSnippet'; import { Virtuoso } from 'react-virtuoso'; @@ -43,6 +41,7 @@ import { MailIconImg, ShowMessageReturnButton, } from '../Group/Forum/Mail-styles'; + const officialAppList = [ 'q-tube', 'q-blog', @@ -59,8 +58,6 @@ const officialAppList = [ 'q-nodecontrol', ]; -// TODO: apply dark/light style - const ScrollerStyled = styled('div')({ // Hide scrollbar for WebKit browsers (Chrome, Safari) '::-webkit-scrollbar': { @@ -76,10 +73,10 @@ const ScrollerStyled = styled('div')({ }); const StyledVirtuosoContainer = styled('div')({ - position: 'relative', - width: '100%', display: 'flex', flexDirection: 'column', + position: 'relative', + width: '100%', // Hide scrollbar for WebKit browsers (Chrome, Safari) '::-webkit-scrollbar': { @@ -148,6 +145,8 @@ export const AppsLibrary = ({ ); }; + const theme = useTheme(); + return ( + setSearchValue(e.target.value)} @@ -191,7 +191,9 @@ export const AppsLibrary = ({ + + - + // TODO return icon Return to Apps Dashboard + + {searchedList?.length > 0 ? ( Official Apps + + {officialApps?.map((qapp) => { return ( @@ -271,6 +277,7 @@ export const AppsLibrary = ({ /> + {qapp?.metadata?.title || qapp?.name} @@ -279,20 +286,27 @@ export const AppsLibrary = ({ ); })} + + {hasPublishApp ? 'Update Apps!' : 'Create Apps!'} + + + + + { setMode('publish'); @@ -301,13 +315,18 @@ export const AppsLibrary = ({ {hasPublishApp ? 'Update' : 'Publish'} + + + Categories + + {category?.name} diff --git a/src/components/Apps/AppsNavBar.tsx b/src/components/Apps/AppsNavBar.tsx index 67786db..5546962 100644 --- a/src/components/Apps/AppsNavBar.tsx +++ b/src/components/Apps/AppsNavBar.tsx @@ -1,12 +1,12 @@ -import React, { useEffect, useMemo, useRef, useState } from "react"; +import { useEffect, useMemo, useRef, useState } from 'react'; import { AppsNavBarLeft, AppsNavBarParent, AppsNavBarRight, -} from "./Apps-styles"; -import NavBack from "../../assets/svgs/NavBack.svg"; -import NavAdd from "../../assets/svgs/NavAdd.svg"; -import NavMoreMenu from "../../assets/svgs/NavMoreMenu.svg"; +} from './Apps-styles'; +import { NavBack } from '../../assets/svgs/NavBack.tsx'; +import { NavAdd } from '../../assets/svgs/NavAdd.tsx'; +import { NavMoreMenu } from '../../assets/svgs/NavMoreMenu.tsx'; import { ButtonBase, ListItemIcon, @@ -15,27 +15,33 @@ import { MenuItem, Tab, Tabs, -} from "@mui/material"; +} from '@mui/material'; import { executeEvent, subscribeToEvent, unsubscribeFromEvent, -} from "../../utils/events"; -import TabComponent from "./TabComponent"; -import PushPinIcon from "@mui/icons-material/PushPin"; -import RefreshIcon from "@mui/icons-material/Refresh"; -import { useRecoilState, useSetRecoilState } from "recoil"; +} from '../../utils/events'; +import TabComponent from './TabComponent'; +import PushPinIcon from '@mui/icons-material/PushPin'; +import RefreshIcon from '@mui/icons-material/Refresh'; +import { useRecoilState, useSetRecoilState } from 'recoil'; import { navigationControllerAtom, settingsLocalLastUpdatedAtom, sortablePinnedAppsAtom, -} from "../../atoms/global"; +} from '../../atoms/global'; -export function saveToLocalStorage(key, subKey, newValue, otherRootData = {}, deleteWholeKey) { +export function saveToLocalStorage( + key, + subKey, + newValue, + otherRootData = {}, + deleteWholeKey +) { try { - if(deleteWholeKey){ + if (deleteWholeKey) { localStorage.setItem(key, null); - return + return; } // Fetch existing data const existingData = localStorage.getItem(key); @@ -64,7 +70,7 @@ export function saveToLocalStorage(key, subKey, newValue, otherRootData = {}, de const serializedValue = JSON.stringify(combinedData); localStorage.setItem(key, serializedValue); } catch (error) { - console.error("Error saving to localStorage:", error); + console.error('Error saving to localStorage:', error); } } @@ -78,13 +84,17 @@ export const AppsNavBar = () => { const [sortablePinnedApps, setSortablePinnedApps] = useRecoilState( sortablePinnedAppsAtom ); - const [navigationController, setNavigationController] = useRecoilState(navigationControllerAtom) + const [navigationController, setNavigationController] = useRecoilState( + navigationControllerAtom + ); - const isDisableBackButton = useMemo(()=> { - if(selectedTab && navigationController[selectedTab?.tabId]?.hasBack) return false - if(selectedTab && !navigationController[selectedTab?.tabId]?.hasBack) return true - return false - }, [navigationController, selectedTab]) + const isDisableBackButton = useMemo(() => { + if (selectedTab && navigationController[selectedTab?.tabId]?.hasBack) + return false; + if (selectedTab && !navigationController[selectedTab?.tabId]?.hasBack) + return true; + return false; + }, [navigationController, selectedTab]); const setSettingsLocalLastUpdated = useSetRecoilState( settingsLocalLastUpdatedAtom @@ -101,13 +111,13 @@ export const AppsNavBar = () => { useEffect(() => { // Scroll to the last tab whenever the tabs array changes (e.g., when a new tab is added) if (tabsRef.current) { - const tabElements = tabsRef.current.querySelectorAll(".MuiTab-root"); + const tabElements = tabsRef.current.querySelectorAll('.MuiTab-root'); if (tabElements.length > 0) { const lastTab = tabElements[tabElements.length - 1]; lastTab.scrollIntoView({ - behavior: "smooth", - block: "nearest", - inline: "end", + behavior: 'smooth', + block: 'nearest', + inline: 'end', }); } } @@ -122,10 +132,10 @@ export const AppsNavBar = () => { }; useEffect(() => { - subscribeToEvent("setTabsToNav", setTabsToNav); + subscribeToEvent('setTabsToNav', setTabsToNav); return () => { - unsubscribeFromEvent("setTabsToNav", setTabsToNav); + unsubscribeFromEvent('setTabsToNav', setTabsToNav); }; }, []); @@ -137,28 +147,29 @@ export const AppsNavBar = () => { { - executeEvent("navigateBack", selectedTab?.tabId); + onClick={() => { + executeEvent('navigateBack', selectedTab?.tabId); }} disabled={isDisableBackButton} sx={{ - opacity: !isDisableBackButton ? 1 : 0.1, - cursor: !isDisableBackButton ? 'pointer': 'default' + opacity: !isDisableBackButton ? 1 : 0.3, + cursor: !isDisableBackButton ? 'pointer' : 'default', }} > - + + {tabs?.map((tab) => ( @@ -173,83 +184,83 @@ export const AppsNavBar = () => { /> } // Pass custom component sx={{ - "&.Mui-selected": { - color: "white", + '&.Mui-selected': { + color: 'white', }, - padding: "0px", - margin: "0px", - minWidth: "0px", - width: "50px", + padding: '0px', + margin: '0px', + minWidth: '0px', + width: '50px', }} /> ))} + {selectedTab && ( - - { - setSelectedTab(null); - executeEvent("newTabWindow", {}); - }} - > - - - { - if (!selectedTab) return; - handleClick(e); - }} - > - - - + + { + setSelectedTab(null); + executeEvent('newTabWindow', {}); + }} + > + + + + { + if (!selectedTab) return; + handleClick(e); + }} + > + + + )} - + { } saveToLocalStorage( - "ext_saved_settings", - "sortablePinnedApps", + 'ext_saved_settings', + 'sortablePinnedApps', updatedApps ); return updatedApps; @@ -293,31 +304,33 @@ export const AppsNavBar = () => { > + + { - executeEvent("refreshApp", { + executeEvent('refreshApp', { tabId: selectedTab?.tabId, }); handleClose(); @@ -325,23 +338,24 @@ export const AppsNavBar = () => { > + Date: Sun, 20 Apr 2025 09:44:43 +0200 Subject: [PATCH 51/55] Move tsx into proper folder --- src/App.tsx | 6 +- .../{svgs => Icons}/CreateThreadIcon.tsx | 0 src/assets/{svgs => Icons}/Download.tsx | 0 src/assets/{svgs => Icons}/Logout.tsx | 0 src/assets/{svgs => Icons}/NavAdd.tsx | 0 src/assets/{svgs => Icons}/NavBack.tsx | 0 src/assets/{svgs => Icons}/NavCloseTab.tsx | 0 src/assets/{svgs => Icons}/NavMoreMenu.tsx | 0 src/assets/{svgs => Icons}/Return.tsx | 0 src/assets/{svgs => Icons}/SaveIcon.tsx | 0 src/assets/{svgs => Icons}/SendNewMessage.tsx | 0 src/assets/{svgs => Icons}/StarEmpty.tsx | 0 src/assets/{svgs => Icons}/StarFilled.tsx | 0 src/assets/Icons/WalletIcon.tsx | 2 +- src/assets/{svgs => Icons}/interfaces.ts | 0 src/assets/svgs/Download.svg | 3 - src/components/Apps/AppRating.tsx | 184 +++++++------ src/components/Apps/AppsDevModeNavBar.tsx | 4 +- .../Apps/AppsDevModeTabComponent.tsx | 2 +- src/components/Apps/AppsNavBar.tsx | 6 +- src/components/Apps/AppsNavBarDesktop.tsx | 6 +- src/components/Apps/TabComponent.tsx | 2 +- src/components/Group/Forum/NewThread.tsx | 4 +- src/components/Group/WalletsAppWrapper.tsx | 2 +- src/components/Save/Save.tsx | 242 +++++++++--------- 25 files changed, 229 insertions(+), 234 deletions(-) rename src/assets/{svgs => Icons}/CreateThreadIcon.tsx (100%) rename src/assets/{svgs => Icons}/Download.tsx (100%) rename src/assets/{svgs => Icons}/Logout.tsx (100%) rename src/assets/{svgs => Icons}/NavAdd.tsx (100%) rename src/assets/{svgs => Icons}/NavBack.tsx (100%) rename src/assets/{svgs => Icons}/NavCloseTab.tsx (100%) rename src/assets/{svgs => Icons}/NavMoreMenu.tsx (100%) rename src/assets/{svgs => Icons}/Return.tsx (100%) rename src/assets/{svgs => Icons}/SaveIcon.tsx (100%) rename src/assets/{svgs => Icons}/SendNewMessage.tsx (100%) rename src/assets/{svgs => Icons}/StarEmpty.tsx (100%) rename src/assets/{svgs => Icons}/StarFilled.tsx (100%) rename src/assets/{svgs => Icons}/interfaces.ts (100%) delete mode 100644 src/assets/svgs/Download.svg diff --git a/src/App.tsx b/src/App.tsx index 8da871d..9bb5342 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -34,9 +34,9 @@ import ltcLogo from './assets/ltc.png'; import PersonSearchIcon from '@mui/icons-material/PersonSearch'; import qortLogo from './assets/qort.png'; import { CopyToClipboard } from 'react-copy-to-clipboard'; -import { Download } from './assets/svgs/Download.tsx'; -import { Logout } from './assets/svgs/Logout.tsx'; -import { Return } from './assets/svgs/Return.tsx'; +import { Download } from './assets/Icons/Download.tsx'; +import { Logout } from './assets/Icons/Logout.tsx'; +import { Return } from './assets/Icons/Return.tsx'; import WarningIcon from '@mui/icons-material/Warning'; import Success from './assets/svgs/Success.svg'; import './utils/seedPhrase/RandomSentenceGenerator'; diff --git a/src/assets/svgs/CreateThreadIcon.tsx b/src/assets/Icons/CreateThreadIcon.tsx similarity index 100% rename from src/assets/svgs/CreateThreadIcon.tsx rename to src/assets/Icons/CreateThreadIcon.tsx diff --git a/src/assets/svgs/Download.tsx b/src/assets/Icons/Download.tsx similarity index 100% rename from src/assets/svgs/Download.tsx rename to src/assets/Icons/Download.tsx diff --git a/src/assets/svgs/Logout.tsx b/src/assets/Icons/Logout.tsx similarity index 100% rename from src/assets/svgs/Logout.tsx rename to src/assets/Icons/Logout.tsx diff --git a/src/assets/svgs/NavAdd.tsx b/src/assets/Icons/NavAdd.tsx similarity index 100% rename from src/assets/svgs/NavAdd.tsx rename to src/assets/Icons/NavAdd.tsx diff --git a/src/assets/svgs/NavBack.tsx b/src/assets/Icons/NavBack.tsx similarity index 100% rename from src/assets/svgs/NavBack.tsx rename to src/assets/Icons/NavBack.tsx diff --git a/src/assets/svgs/NavCloseTab.tsx b/src/assets/Icons/NavCloseTab.tsx similarity index 100% rename from src/assets/svgs/NavCloseTab.tsx rename to src/assets/Icons/NavCloseTab.tsx diff --git a/src/assets/svgs/NavMoreMenu.tsx b/src/assets/Icons/NavMoreMenu.tsx similarity index 100% rename from src/assets/svgs/NavMoreMenu.tsx rename to src/assets/Icons/NavMoreMenu.tsx diff --git a/src/assets/svgs/Return.tsx b/src/assets/Icons/Return.tsx similarity index 100% rename from src/assets/svgs/Return.tsx rename to src/assets/Icons/Return.tsx diff --git a/src/assets/svgs/SaveIcon.tsx b/src/assets/Icons/SaveIcon.tsx similarity index 100% rename from src/assets/svgs/SaveIcon.tsx rename to src/assets/Icons/SaveIcon.tsx diff --git a/src/assets/svgs/SendNewMessage.tsx b/src/assets/Icons/SendNewMessage.tsx similarity index 100% rename from src/assets/svgs/SendNewMessage.tsx rename to src/assets/Icons/SendNewMessage.tsx diff --git a/src/assets/svgs/StarEmpty.tsx b/src/assets/Icons/StarEmpty.tsx similarity index 100% rename from src/assets/svgs/StarEmpty.tsx rename to src/assets/Icons/StarEmpty.tsx diff --git a/src/assets/svgs/StarFilled.tsx b/src/assets/Icons/StarFilled.tsx similarity index 100% rename from src/assets/svgs/StarFilled.tsx rename to src/assets/Icons/StarFilled.tsx diff --git a/src/assets/Icons/WalletIcon.tsx b/src/assets/Icons/WalletIcon.tsx index 9bb606b..84c6775 100644 --- a/src/assets/Icons/WalletIcon.tsx +++ b/src/assets/Icons/WalletIcon.tsx @@ -1,5 +1,5 @@ import { useTheme } from '@mui/material'; -import { SVGProps } from '../svgs/interfaces'; +import { SVGProps } from './interfaces'; export const WalletIcon: React.FC = ({ color, diff --git a/src/assets/svgs/interfaces.ts b/src/assets/Icons/interfaces.ts similarity index 100% rename from src/assets/svgs/interfaces.ts rename to src/assets/Icons/interfaces.ts diff --git a/src/assets/svgs/Download.svg b/src/assets/svgs/Download.svg deleted file mode 100644 index 4fb9e52..0000000 --- a/src/assets/svgs/Download.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/components/Apps/AppRating.tsx b/src/components/Apps/AppRating.tsx index a1f3c98..abf1bba 100644 --- a/src/components/Apps/AppRating.tsx +++ b/src/components/Apps/AppRating.tsx @@ -1,20 +1,14 @@ -import { Box, Rating, Typography } from "@mui/material"; -import React, { - useCallback, - useContext, - useEffect, - useRef, - useState, -} from "react"; -import { getFee } from "../../background"; -import { MyContext, getBaseApiReact } from "../../App"; -import { CustomizedSnackbars } from "../Snackbar/Snackbar"; -import { StarFilledIcon } from "../../assets/svgs/StarFilled"; -import { StarEmptyIcon } from "../../assets/svgs/StarEmpty"; -import { AppInfoUserName } from "./Apps-styles"; -import { Spacer } from "../../common/Spacer"; +import { Box, Rating } from '@mui/material'; +import { useCallback, useContext, useEffect, useRef, useState } from 'react'; +import { getFee } from '../../background'; +import { MyContext, getBaseApiReact } from '../../App'; +import { CustomizedSnackbars } from '../Snackbar/Snackbar'; +import { StarFilledIcon } from '../../assets/Icons/StarFilled'; +import { StarEmptyIcon } from '../../assets/Icons/StarEmpty'; +import { AppInfoUserName } from './Apps-styles'; +import { Spacer } from '../../common/Spacer'; -export const AppRating = ({ app, myName, ratingCountPosition = "right" }) => { +export const AppRating = ({ app, myName, ratingCountPosition = 'right' }) => { const [value, setValue] = useState(0); const { show } = useContext(MyContext); const [hasPublishedRating, setHasPublishedRating] = useState( @@ -33,14 +27,14 @@ export const AppRating = ({ app, myName, ratingCountPosition = "right" }) => { const url = `${getBaseApiReact()}/polls/${pollName}`; const response = await fetch(url, { - method: "GET", + method: 'GET', headers: { - "Content-Type": "application/json", + 'Content-Type': 'application/json', }, }); const responseData = await response.json(); - if (responseData?.message?.includes("POLL_NO_EXISTS")) { + if (responseData?.message?.includes('POLL_NO_EXISTS')) { setHasPublishedRating(false); } else if (responseData?.pollName) { setPollInfo(responseData); @@ -48,9 +42,9 @@ export const AppRating = ({ app, myName, ratingCountPosition = "right" }) => { const urlVotes = `${getBaseApiReact()}/polls/votes/${pollName}`; const responseVotes = await fetch(urlVotes, { - method: "GET", + method: 'GET', headers: { - "Content-Type": "application/json", + 'Content-Type': 'application/json', }, }); @@ -59,15 +53,15 @@ export const AppRating = ({ app, myName, ratingCountPosition = "right" }) => { const voteCount = responseDataVotes.voteCounts; // Include initial value vote in the calculation const ratingVotes = voteCount.filter( - (vote) => !vote.optionName.startsWith("initialValue-") + (vote) => !vote.optionName.startsWith('initialValue-') ); const initialValueVote = voteCount.find((vote) => - vote.optionName.startsWith("initialValue-") + vote.optionName.startsWith('initialValue-') ); if (initialValueVote) { // Convert "initialValue-X" to just "X" and add it to the ratingVotes array const initialRating = parseInt( - initialValueVote.optionName.split("-")[1], + initialValueVote.optionName.split('-')[1], 10 ); ratingVotes.push({ @@ -92,7 +86,7 @@ export const AppRating = ({ app, myName, ratingCountPosition = "right" }) => { setValue(averageRating); } } catch (error) { - if (error?.message?.includes("POLL_NO_EXISTS")) { + if (error?.message?.includes('POLL_NO_EXISTS')) { setHasPublishedRating(false); } } @@ -105,45 +99,47 @@ export const AppRating = ({ app, myName, ratingCountPosition = "right" }) => { const rateFunc = async (event, chosenValue, currentValue) => { try { - const newValue = chosenValue || currentValue - if (!myName) throw new Error("You need a name to rate."); + const newValue = chosenValue || currentValue; + if (!myName) throw new Error('You need a name to rate.'); if (!app?.name) return; - const fee = await getFee("CREATE_POLL"); + const fee = await getFee('CREATE_POLL'); await show({ message: `Would you like to rate this app a rating of ${newValue}?. It will create a POLL tx.`, - publishFee: fee.fee + " QORT", + publishFee: fee.fee + ' QORT', }); if (hasPublishedRating === false) { const pollName = `app-library-${app.service}-rating-${app.name}`; const pollOptions = [`1, 2, 3, 4, 5, initialValue-${newValue}`]; await new Promise((res, rej) => { - window.sendMessage("createPoll", { - - pollName: pollName, - pollDescription: `Rating for ${app.service} ${app.name}`, - pollOptions: pollOptions, - pollOwnerAddress: myName, - - }, 60000) - .then((response) => { - if (response.error) { - rej(response?.message); - return; - } else { - res(response); - setInfoSnack({ - type: "success", - message: - "Successfully rated. Please wait a couple minutes for the network to propogate the changes.", - }); - setOpenSnack(true); - } - }) - .catch((error) => { - console.error("Failed qortalRequest", error); - }); - + window + .sendMessage( + 'createPoll', + { + pollName: pollName, + pollDescription: `Rating for ${app.service} ${app.name}`, + pollOptions: pollOptions, + pollOwnerAddress: myName, + }, + 60000 + ) + .then((response) => { + if (response.error) { + rej(response?.message); + return; + } else { + res(response); + setInfoSnack({ + type: 'success', + message: + 'Successfully rated. Please wait a couple minutes for the network to propogate the changes.', + }); + setOpenSnack(true); + } + }) + .catch((error) => { + console.error('Failed qortalRequest', error); + }); }); } else { const pollName = `app-library-${app.service}-rating-${app.name}`; @@ -152,39 +148,41 @@ export const AppRating = ({ app, myName, ratingCountPosition = "right" }) => { (option) => +option.optionName === +newValue ); if (isNaN(optionIndex) || optionIndex === -1) - throw new Error("Cannot find rating option"); + throw new Error('Cannot find rating option'); await new Promise((res, rej) => { - window.sendMessage("voteOnPoll", { - - pollName: pollName, - optionIndex, - - }, 60000) - .then((response) => { - if (response.error) { - rej(response?.message); - return; - } else { - res(response); - setInfoSnack({ - type: "success", - message: - "Successfully rated. Please wait a couple minutes for the network to propogate the changes.", - }); - setOpenSnack(true); - } - }) - .catch((error) => { - console.error("Failed qortalRequest", error); - }); - + window + .sendMessage( + 'voteOnPoll', + { + pollName: pollName, + optionIndex, + }, + 60000 + ) + .then((response) => { + if (response.error) { + rej(response?.message); + return; + } else { + res(response); + setInfoSnack({ + type: 'success', + message: + 'Successfully rated. Please wait a couple minutes for the network to propogate the changes.', + }); + setOpenSnack(true); + } + }) + .catch((error) => { + console.error('Failed qortalRequest', error); + }); }); } } catch (error) { - console.log('error', error) + console.log('error', error); setInfoSnack({ - type: "error", - message: error?.message || "Unable to rate", + type: 'error', + message: error?.message || 'Unable to rate', }); setOpenSnack(true); } @@ -194,17 +192,17 @@ export const AppRating = ({ app, myName, ratingCountPosition = "right" }) => {
- {ratingCountPosition === "top" && ( + {ratingCountPosition === 'top' && ( <> {(votesInfo?.totalVotes ?? 0) + - (votesInfo?.voteCounts?.length === 6 ? 1 : 0)}{" "} - {" RATINGS"} + (votesInfo?.voteCounts?.length === 6 ? 1 : 0)}{' '} + {' RATINGS'} {value?.toFixed(1)} @@ -214,17 +212,17 @@ export const AppRating = ({ app, myName, ratingCountPosition = "right" }) => { rateFunc(event, rating, value)} + onChange={(event, rating) => rateFunc(event, rating, value)} precision={1} size="small" icon={} emptyIcon={} sx={{ - display: "flex", - gap: "2px", + display: 'flex', + gap: '2px', }} /> - {ratingCountPosition === "right" && ( + {ratingCountPosition === 'right' && ( {(votesInfo?.totalVotes ?? 0) + (votesInfo?.voteCounts?.length === 6 ? 1 : 0)} diff --git a/src/components/Apps/AppsDevModeNavBar.tsx b/src/components/Apps/AppsDevModeNavBar.tsx index 15c22ab..433ce9b 100644 --- a/src/components/Apps/AppsDevModeNavBar.tsx +++ b/src/components/Apps/AppsDevModeNavBar.tsx @@ -4,8 +4,8 @@ import { AppsNavBarParent, AppsNavBarRight, } from './Apps-styles'; -import { NavBack } from '../../assets/svgs/NavBack.tsx'; -import { NavAdd } from '../../assets/svgs/NavAdd.tsx'; +import { NavBack } from '../../assets/Icons/NavBack.tsx'; +import { NavAdd } from '../../assets/Icons/NavAdd.tsx'; import { ButtonBase, Tab, Tabs } from '@mui/material'; import { executeEvent, diff --git a/src/components/Apps/AppsDevModeTabComponent.tsx b/src/components/Apps/AppsDevModeTabComponent.tsx index 27dcbec..3e791c1 100644 --- a/src/components/Apps/AppsDevModeTabComponent.tsx +++ b/src/components/Apps/AppsDevModeTabComponent.tsx @@ -1,5 +1,5 @@ import { TabParent } from './Apps-styles'; -import { NavCloseTab } from '../../assets/svgs/NavCloseTab.tsx'; +import { NavCloseTab } from '../../assets/Icons/NavCloseTab.tsx'; import { getBaseApiReact } from '../../App'; import { Avatar, ButtonBase } from '@mui/material'; import LogoSelected from '../../assets/svgs/LogoSelected.svg'; diff --git a/src/components/Apps/AppsNavBar.tsx b/src/components/Apps/AppsNavBar.tsx index 5546962..9731bd5 100644 --- a/src/components/Apps/AppsNavBar.tsx +++ b/src/components/Apps/AppsNavBar.tsx @@ -4,9 +4,9 @@ import { AppsNavBarParent, AppsNavBarRight, } from './Apps-styles'; -import { NavBack } from '../../assets/svgs/NavBack.tsx'; -import { NavAdd } from '../../assets/svgs/NavAdd.tsx'; -import { NavMoreMenu } from '../../assets/svgs/NavMoreMenu.tsx'; +import { NavBack } from '../../assets/Icons/NavBack.tsx'; +import { NavAdd } from '../../assets/Icons/NavAdd.tsx'; +import { NavMoreMenu } from '../../assets/Icons/NavMoreMenu.tsx'; import { ButtonBase, ListItemIcon, diff --git a/src/components/Apps/AppsNavBarDesktop.tsx b/src/components/Apps/AppsNavBarDesktop.tsx index 2a22efd..890c297 100644 --- a/src/components/Apps/AppsNavBarDesktop.tsx +++ b/src/components/Apps/AppsNavBarDesktop.tsx @@ -4,9 +4,9 @@ import { AppsNavBarParent, AppsNavBarRight, } from './Apps-styles'; -import { NavBack } from '../../assets/svgs/NavBack.tsx'; -import { NavAdd } from '../../assets/svgs/NavAdd.tsx'; -import { NavMoreMenu } from '../../assets/svgs/NavMoreMenu.tsx'; +import { NavBack } from '../../assets/Icons/NavBack.tsx'; +import { NavAdd } from '../../assets/Icons/NavAdd.tsx'; +import { NavMoreMenu } from '../../assets/Icons/NavMoreMenu.tsx'; import ContentCopyIcon from '@mui/icons-material/ContentCopy'; import { ButtonBase, diff --git a/src/components/Apps/TabComponent.tsx b/src/components/Apps/TabComponent.tsx index 0e8f655..2558a9f 100644 --- a/src/components/Apps/TabComponent.tsx +++ b/src/components/Apps/TabComponent.tsx @@ -1,5 +1,5 @@ import { TabParent } from './Apps-styles'; -import { NavCloseTab } from '../../assets/svgs/NavCloseTab.tsx'; +import { NavCloseTab } from '../../assets/Icons/NavCloseTab.tsx'; import { getBaseApiReact } from '../../App'; import { Avatar, ButtonBase, useTheme } from '@mui/material'; import LogoSelected from '../../assets/svgs/LogoSelected.svg'; diff --git a/src/components/Group/Forum/NewThread.tsx b/src/components/Group/Forum/NewThread.tsx index dd4c83a..31b6592 100644 --- a/src/components/Group/Forum/NewThread.tsx +++ b/src/components/Group/Forum/NewThread.tsx @@ -33,8 +33,8 @@ import { import { ReusableModal } from './ReusableModal'; import { Spacer } from '../../../common/Spacer'; import { formatBytes } from '../../../utils/Size'; -import { CreateThreadIcon } from '../../../assets/svgs/CreateThreadIcon'; -import { SendNewMessage } from '../../../assets/svgs/SendNewMessage'; +import { CreateThreadIcon } from '../../../assets/Icons/CreateThreadIcon'; +import { SendNewMessage } from '../../../assets/Icons/SendNewMessage'; import { TextEditor } from './TextEditor'; import { MyContext, diff --git a/src/components/Group/WalletsAppWrapper.tsx b/src/components/Group/WalletsAppWrapper.tsx index 64b89be..c569425 100644 --- a/src/components/Group/WalletsAppWrapper.tsx +++ b/src/components/Group/WalletsAppWrapper.tsx @@ -10,7 +10,7 @@ import { import { useRecoilState } from 'recoil'; import { navigationControllerAtom } from '../../atoms/global'; import { AppsNavBarLeft, AppsNavBarParent } from '../Apps/Apps-styles'; -import { NavBack } from '../../assets/svgs/NavBack.tsx'; +import { NavBack } from '../../assets/Icons/NavBack.tsx'; import RefreshIcon from '@mui/icons-material/Refresh'; export const WalletsAppWrapper = () => { diff --git a/src/components/Save/Save.tsx b/src/components/Save/Save.tsx index 273da15..cf8dba6 100644 --- a/src/components/Save/Save.tsx +++ b/src/components/Save/Save.tsx @@ -1,6 +1,6 @@ -import React, { useContext, useEffect, useMemo, useState } from "react"; -import { useRecoilState, useSetRecoilState } from "recoil"; -import isEqual from "lodash/isEqual"; // Import deep comparison utility +import React, { useContext, useEffect, useMemo, useState } from 'react'; +import { useRecoilState, useSetRecoilState } from 'recoil'; +import isEqual from 'lodash/isEqual'; // Import deep comparison utility import { canSaveSettingToQdnAtom, hasSettingsChangedAtom, @@ -9,35 +9,35 @@ import { settingsLocalLastUpdatedAtom, settingsQDNLastUpdatedAtom, sortablePinnedAppsAtom, -} from "../../atoms/global"; -import { Box, Button, ButtonBase, Popover, Typography } from "@mui/material"; -import { objectToBase64 } from "../../qdn/encryption/group-encryption"; -import { MyContext } from "../../App"; -import { getFee } from "../../background"; -import { CustomizedSnackbars } from "../Snackbar/Snackbar"; -import { SaveIcon } from "../../assets/svgs/SaveIcon"; -import { IconWrapper } from "../Desktop/DesktopFooter"; -import { Spacer } from "../../common/Spacer"; -import { LoadingButton } from "@mui/lab"; -import { saveToLocalStorage } from "../Apps/AppsNavBar"; -import { decryptData, encryptData } from "../../qortalRequests/get"; -import { saveFileToDiskGeneric } from "../../utils/generateWallet/generateWallet"; +} from '../../atoms/global'; +import { Box, Button, ButtonBase, Popover, Typography } from '@mui/material'; +import { objectToBase64 } from '../../qdn/encryption/group-encryption'; +import { MyContext } from '../../App'; +import { getFee } from '../../background'; +import { CustomizedSnackbars } from '../Snackbar/Snackbar'; +import { SaveIcon } from '../../assets/Icons/SaveIcon'; +import { IconWrapper } from '../Desktop/DesktopFooter'; +import { Spacer } from '../../common/Spacer'; +import { LoadingButton } from '@mui/lab'; +import { saveToLocalStorage } from '../Apps/AppsNavBar'; +import { decryptData, encryptData } from '../../qortalRequests/get'; +import { saveFileToDiskGeneric } from '../../utils/generateWallet/generateWallet'; import { base64ToUint8Array, uint8ArrayToObject, -} from "../../backgroundFunctions/encryption"; +} from '../../backgroundFunctions/encryption'; export const handleImportClick = async () => { - const fileInput = document.createElement("input"); - fileInput.type = "file"; - fileInput.accept = ".base64,.txt"; + const fileInput = document.createElement('input'); + fileInput.type = 'file'; + fileInput.accept = '.base64,.txt'; // Create a promise to handle file selection and reading synchronously return await new Promise((resolve, reject) => { fileInput.onchange = () => { const file = fileInput.files[0]; if (!file) { - reject(new Error("No file selected")); + reject(new Error('No file selected')); return; } @@ -46,7 +46,7 @@ export const handleImportClick = async () => { resolve(e.target.result); // Resolve with the file content }; reader.onerror = () => { - reject(new Error("Error reading file")); + reject(new Error('Error reading file')); }; reader.readAsText(file); // Read the file as text (Base64 string) @@ -124,7 +124,7 @@ export const Save = ({ isDesktop, disableWidth, myName }) => { const encryptData = await new Promise((res, rej) => { window .sendMessage( - "ENCRYPT_DATA", + 'ENCRYPT_DATA', { data64, }, @@ -139,23 +139,23 @@ export const Save = ({ isDesktop, disableWidth, myName }) => { } }) .catch((error) => { - console.error("Failed qortalRequest", error); + console.error('Failed qortalRequest', error); }); }); if (encryptData && !encryptData?.error) { - const fee = await getFee("ARBITRARY"); + const fee = await getFee('ARBITRARY'); await show({ message: - "Would you like to publish your settings to QDN (encrypted) ?", - publishFee: fee.fee + " QORT", + 'Would you like to publish your settings to QDN (encrypted) ?', + publishFee: fee.fee + ' QORT', }); const response = await new Promise((res, rej) => { window - .sendMessage("publishOnQDN", { + .sendMessage('publishOnQDN', { data: encryptData, - identifier: "ext_saved_settings", - service: "DOCUMENT_PRIVATE", + identifier: 'ext_saved_settings', + service: 'DOCUMENT_PRIVATE', }) .then((response) => { if (!response?.error) { @@ -165,15 +165,15 @@ export const Save = ({ isDesktop, disableWidth, myName }) => { rej(response.error); }) .catch((error) => { - rej(error.message || "An error occurred"); + rej(error.message || 'An error occurred'); }); }); if (response?.identifier) { setOldPinnedApps(pinnedApps); setSettingsQdnLastUpdated(Date.now()); setInfoSnack({ - type: "success", - message: "Sucessfully published to QDN", + type: 'success', + message: 'Sucessfully published to QDN', }); setOpenSnack(true); setAnchorEl(null); @@ -181,8 +181,8 @@ export const Save = ({ isDesktop, disableWidth, myName }) => { } } catch (error) { setInfoSnack({ - type: "error", - message: error?.message || "Unable to save to QDN", + type: 'error', + message: error?.message || 'Unable to save to QDN', }); setOpenSnack(true); } finally { @@ -196,7 +196,7 @@ export const Save = ({ isDesktop, disableWidth, myName }) => { const revertChanges = () => { setPinnedApps(oldPinnedApps); - saveToLocalStorage("ext_saved_settings", "sortablePinnedApps", null); + saveToLocalStorage('ext_saved_settings', 'sortablePinnedApps', null); setAnchorEl(null); }; @@ -218,11 +218,11 @@ export const Save = ({ isDesktop, disableWidth, myName }) => { selected={false} > ) : ( - + )} { anchorEl={anchorEl} onClose={() => setAnchorEl(null)} // Close popover on click outside anchorOrigin={{ - vertical: "bottom", - horizontal: "center", + vertical: 'bottom', + horizontal: 'center', }} transformOrigin={{ - vertical: "top", - horizontal: "center", + vertical: 'top', + horizontal: 'center', }} sx={{ - width: "300px", - maxWidth: "90%", - maxHeight: "80%", - overflow: "auto", + width: '300px', + maxWidth: '90%', + maxHeight: '80%', + overflow: 'auto', }} > {isUsingImportExportSettings && ( You are using the export/import way of saving settings. @@ -274,8 +274,8 @@ export const Save = ({ isDesktop, disableWidth, myName }) => { size="small" onClick={() => { saveToLocalStorage( - "ext_saved_settings_import_export", - "sortablePinnedApps", + 'ext_saved_settings_import_export', + 'sortablePinnedApps', null, true ); @@ -283,13 +283,13 @@ export const Save = ({ isDesktop, disableWidth, myName }) => { }} variant="contained" sx={{ - backgroundColor: "var(--danger)", - color: "black", - fontWeight: "bold", + backgroundColor: 'var(--danger)', + color: 'black', + fontWeight: 'bold', opacity: 0.7, - "&:hover": { - backgroundColor: "var(--danger)", - color: "black", + '&:hover': { + backgroundColor: 'var(--danger)', + color: 'black', opacity: 1, }, }} @@ -302,25 +302,25 @@ export const Save = ({ isDesktop, disableWidth, myName }) => { {!isUsingImportExportSettings && ( {!myName ? ( You need a registered Qortal name to save your pinned apps to @@ -332,15 +332,15 @@ export const Save = ({ isDesktop, disableWidth, myName }) => { {hasChanged && ( You have unsaved changes to your pinned apps. Save them to @@ -349,13 +349,13 @@ export const Save = ({ isDesktop, disableWidth, myName }) => { { <> Don't like your current local changes? Would you @@ -385,13 +385,13 @@ export const Save = ({ isDesktop, disableWidth, myName }) => { onClick={revertChanges} variant="contained" sx={{ - backgroundColor: "var(--danger)", - color: "black", - fontWeight: "bold", + backgroundColor: 'var(--danger)', + color: 'black', + fontWeight: 'bold', opacity: 0.7, - "&:hover": { - backgroundColor: "var(--danger)", - color: "black", + '&:hover': { + backgroundColor: 'var(--danger)', + color: 'black', opacity: 1, }, }} @@ -405,7 +405,7 @@ export const Save = ({ isDesktop, disableWidth, myName }) => { <> Don't like your current local changes? Would you @@ -428,15 +428,15 @@ export const Save = ({ isDesktop, disableWidth, myName }) => { isUsingImportExportSettings !== true && ( The app was unable to download your existing QDN-saved @@ -449,13 +449,13 @@ export const Save = ({ isDesktop, disableWidth, myName }) => { onClick={saveToQdn} variant="contained" sx={{ - backgroundColor: "var(--danger)", - color: "black", - fontWeight: "bold", + backgroundColor: 'var(--danger)', + color: 'black', + fontWeight: 'bold', opacity: 0.7, - "&:hover": { - backgroundColor: "var(--danger)", - color: "black", + '&:hover': { + backgroundColor: 'var(--danger)', + color: 'black', opacity: 1, }, }} @@ -467,15 +467,15 @@ export const Save = ({ isDesktop, disableWidth, myName }) => { {!hasChanged && ( You currently do not have any changes to your pinned apps @@ -488,19 +488,19 @@ export const Save = ({ isDesktop, disableWidth, myName }) => { )} { ); if (Array.isArray(responseData)) { saveToLocalStorage( - "ext_saved_settings_import_export", - "sortablePinnedApps", + 'ext_saved_settings_import_export', + 'sortablePinnedApps', responseData, { isUsingImportExport: true, @@ -529,7 +529,7 @@ export const Save = ({ isDesktop, disableWidth, myName }) => { setIsUsingImportExportSettings(true); } } catch (error) { - console.log("error", error); + console.log('error', error); } }} > @@ -544,14 +544,14 @@ export const Save = ({ isDesktop, disableWidth, myName }) => { data64, }); const blob = new Blob([encryptedData], { - type: "text/plain", + type: 'text/plain', }); - const timestamp = new Date().toISOString().replace(/:/g, "-"); // Safe timestamp for filenames + const timestamp = new Date().toISOString().replace(/:/g, '-'); // Safe timestamp for filenames const filename = `qortal-new-ui-backup-settings-${timestamp}.txt`; await saveFileToDiskGeneric(blob, filename); } catch (error) { - console.log("error", error); + console.log('error', error); } }} > From fbf42076800c2327642256bf13ef24fffa9c2c5d Mon Sep 17 00:00:00 2001 From: Nicola Benaglia Date: Sun, 20 Apr 2025 09:51:57 +0200 Subject: [PATCH 52/55] Add theme --- src/components/Minting/Minting.tsx | 78 +++++++++++++++--------------- 1 file changed, 38 insertions(+), 40 deletions(-) diff --git a/src/components/Minting/Minting.tsx b/src/components/Minting/Minting.tsx index de16e09..84697c8 100644 --- a/src/components/Minting/Minting.tsx +++ b/src/components/Minting/Minting.tsx @@ -9,31 +9,20 @@ import { DialogTitle, Divider, IconButton, - InputBase, - InputLabel, Snackbar, Typography, + useTheme, } from '@mui/material'; -import React, { - useCallback, - useContext, - useEffect, - useMemo, - useState, -} from 'react'; +import { useCallback, useEffect, useMemo, useState } from 'react'; import CloseIcon from '@mui/icons-material/Close'; -import { MyContext, getBaseApiReact } from '../../App'; +import { 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 '../../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'; @@ -56,15 +45,18 @@ export const Minting = ({ const [isLoading, setIsLoading] = useState(false); const { show: showKey, message } = useModal(); const { isShow: isShowNext, onOk, show: showNext } = useModal(); + const theme = useTheme(); const [info, setInfo] = useState(null); const [names, setNames] = useState({}); const [accountInfos, setAccountInfos] = useState({}); const [showWaitDialog, setShowWaitDialog] = useState(false); + const isPartOfMintingGroup = useMemo(() => { if (groups?.length === 0) return false; return !!groups?.find((item) => item?.groupId?.toString() === '694'); }, [groups]); + const getMintingAccounts = useCallback(async () => { try { const url = `${getBaseApiReact()}/admin/mintingaccounts`; @@ -107,7 +99,7 @@ export const Minting = ({ }); } } catch (error) { - // error + console.log(error); } }; @@ -133,6 +125,7 @@ export const Minting = ({ setAccountInfo(data); } } catch (error) { + console.log(error); } finally { if (!others) { setIsLoading(false); @@ -254,7 +247,6 @@ export const Minting = ({ window .sendMessage( 'ADMIN_ACTION', - { type: 'removemintingaccount', value: val, @@ -358,7 +350,6 @@ export const Minting = ({ if (findRewardShare) { return true; // Exit early if found } - await sleep(pollingInterval); // Wait before the next poll } @@ -511,7 +502,7 @@ export const Minting = ({ const _blocksNeed = () => { if (accountInfo?.level === 0) { - return 7200; + return 7200; // TODO manage these magic numbers in a proper location } else if (accountInfo?.level === 1) { return 72000; } else if (accountInfo?.level === 2) { @@ -562,11 +553,11 @@ export const Minting = ({ fullScreen sx={{ '& .MuiDialog-paper': { + height: '100vh', margin: 0, maxWidth: '100%', - width: '100%', - height: '100vh', overflow: 'hidden', // Prevent scrollbars + width: '100%', }, }} > @@ -583,6 +574,7 @@ export const Minting = ({ > + )} Account: {handleNames(accountInfo?.address)} + Level: {accountInfo?.level} + blocks remaining until next level: {_levelUpBlocks()} + This node is minting: {nodeInfos?.isMintingPossible?.toString()} @@ -630,11 +625,11 @@ export const Minting = ({ {isPartOfMintingGroup && !accountIsMinting && ( + + ))} @@ -744,7 +741,7 @@ export const Minting = ({ {!isPartOfMintingGroup && ( @@ -768,7 +765,7 @@ export const Minting = ({ size="small" sx={{ backgroundColor: 'var(--green)', - color: 'black', + color: theme.palette.text.primary, fontWeight: 'bold', opacity: 0.7, @@ -802,6 +799,7 @@ export const Minting = ({ {isShowNext ? 'Confirmed' : 'Please Wait'} + {!isShowNext && ( From 88f4ce4e4d385e074ca0deb24f3ea6540dca3f00 Mon Sep 17 00:00:00 2001 From: Nicola Benaglia Date: Sun, 20 Apr 2025 09:57:22 +0200 Subject: [PATCH 53/55] Format code --- src/components/Apps/SortablePinnedApps.tsx | 422 ++++++++++++--------- 1 file changed, 234 insertions(+), 188 deletions(-) diff --git a/src/components/Apps/SortablePinnedApps.tsx b/src/components/Apps/SortablePinnedApps.tsx index 98c2287..30dcec7 100644 --- a/src/components/Apps/SortablePinnedApps.tsx +++ b/src/components/Apps/SortablePinnedApps.tsx @@ -1,205 +1,251 @@ -import React, { useContext, useEffect, useMemo, useRef, useState } from 'react'; +import { useMemo } from 'react'; import { DndContext, closestCenter } from '@dnd-kit/core'; -import { arrayMove, SortableContext, sortableKeyboardCoordinates, useSortable } from '@dnd-kit/sortable'; -import { KeyboardSensor, PointerSensor, TouchSensor, useSensor, useSensors } from '@dnd-kit/core'; +import { + arrayMove, + SortableContext, + sortableKeyboardCoordinates, + useSortable, +} from '@dnd-kit/sortable'; +import { + KeyboardSensor, + PointerSensor, + TouchSensor, + useSensor, + useSensors, +} from '@dnd-kit/core'; import { CSS } from '@dnd-kit/utilities'; import { Avatar, ButtonBase } from '@mui/material'; import { AppCircle, AppCircleContainer, AppCircleLabel } from './Apps-styles'; -import { getBaseApiReact, MyContext } from '../../App'; +import { getBaseApiReact } from '../../App'; import { executeEvent } from '../../utils/events'; -import { settingsLocalLastUpdatedAtom, sortablePinnedAppsAtom } from '../../atoms/global'; +import { + settingsLocalLastUpdatedAtom, + sortablePinnedAppsAtom, +} from '../../atoms/global'; import { useRecoilState, useSetRecoilState } from 'recoil'; import { saveToLocalStorage } from './AppsNavBar'; import { ContextMenuPinnedApps } from '../ContextMenuPinnedApps'; -import LockIcon from "@mui/icons-material/Lock"; +import LockIcon from '@mui/icons-material/Lock'; import { useHandlePrivateApps } from './useHandlePrivateApps'; + const SortableItem = ({ id, name, app, isDesktop }) => { - const {openApp} = useHandlePrivateApps() + const { openApp } = useHandlePrivateApps(); - const { attributes, listeners, setNodeRef, transform, transition } = useSortable({ id }); - const style = { - transform: CSS.Transform.toString(transform), - transition, - padding: '10px', - border: '1px solid #ccc', - marginBottom: '5px', - borderRadius: '4px', - backgroundColor: '#f9f9f9', - cursor: 'grab', - color: 'black' - }; + const { attributes, listeners, setNodeRef, transform, transition } = + useSortable({ id }); - return ( - - { - if(app?.isPrivate){ - try { - await openApp(app?.privateAppProperties) - } catch (error) { - console.error(error) - } - - } else { - executeEvent("addTab", { - data: app - }) - } - - }} - > - - - {app?.isPrivate && !app?.privateAppProperties?.logo ? ( - - ) : ( - - center-icon - - )} - - - {app?.isPrivate ? ( - - {`${app?.privateAppProperties?.appName || "Private"}`} - - ) : ( - - {app?.metadata?.title || app?.name} - - )} - - - - - ); -}; + const style = { + backgroundColor: '#f9f9f9', + border: '1px solid #ccc', + borderRadius: '4px', + color: 'black', + cursor: 'grab', + marginBottom: '5px', + padding: '10px', + transform: CSS.Transform.toString(transform), + transition, + }; -export const SortablePinnedApps = ({ isDesktop, myWebsite, myApp, availableQapps = [] }) => { - const [pinnedApps, setPinnedApps] = useRecoilState(sortablePinnedAppsAtom); - const setSettingsLocalLastUpdated = useSetRecoilState(settingsLocalLastUpdatedAtom); - - const transformPinnedApps = useMemo(() => { - - // Clone the existing pinned apps list - let pinned = [...pinnedApps]; - - // Function to add or update `isMine` property - const addOrUpdateIsMine = (pinnedList, appToCheck) => { - if (!appToCheck) return pinnedList; - - const existingIndex = pinnedList.findIndex( - (item) => item?.service === appToCheck?.service && item?.name === appToCheck?.name - ); - - if (existingIndex !== -1) { - // If the app is already in the list, update it with `isMine: true` - pinnedList[existingIndex] = { ...pinnedList[existingIndex], isMine: true }; + return ( + + { + if (app?.isPrivate) { + try { + await openApp(app?.privateAppProperties); + } catch (error) { + console.error(error); + } } else { - // If not in the list, add it with `isMine: true` at the beginning - pinnedList.unshift({ ...appToCheck, isMine: true }); + executeEvent('addTab', { + data: app, + }); } - - return pinnedList; - }; - - // Update or add `myWebsite` and `myApp` while preserving their positions - pinned = addOrUpdateIsMine(pinned, myWebsite); - pinned = addOrUpdateIsMine(pinned, myApp); - - // Update pinned list based on availableQapps - pinned = pinned.map((pin) => { - const findIndex = availableQapps?.findIndex( - (item) => item?.service === pin?.service && item?.name === pin?.name - ); - if (findIndex !== -1) return { - ...availableQapps[findIndex], - ...pin - } - - return pin; - }); - - return pinned; - }, [myApp, myWebsite, pinnedApps, availableQapps]); - - - const sensors = useSensors( - useSensor(PointerSensor, { - activationConstraint: { - distance: 10, // Set a distance to avoid triggering drag on small movements - }, - }), - useSensor(TouchSensor, { - activationConstraint: { - distance: 10, // Also apply to touch - }, - }), - useSensor(KeyboardSensor, { - coordinateGetter: sortableKeyboardCoordinates, - }) - ); - - const handleDragEnd = (event) => { - const { active, over } = event; - - if (!over) return; // Make sure the drop target exists - - if (active.id !== over.id) { - const oldIndex = transformPinnedApps.findIndex((item) => `${item?.service}-${item?.name}` === active.id); - const newIndex = transformPinnedApps.findIndex((item) => `${item?.service}-${item?.name}` === over.id); - - const newOrder = arrayMove(transformPinnedApps, oldIndex, newIndex); - setPinnedApps(newOrder); - saveToLocalStorage('ext_saved_settings','sortablePinnedApps', newOrder) - setSettingsLocalLastUpdated(Date.now()) - } - }; - return ( - - `${app?.service}-${app?.name}`)}> - {transformPinnedApps.map((app) => ( - - ))} - - - ); + }} + > + + + {app?.isPrivate && !app?.privateAppProperties?.logo ? ( + + ) : ( + + center-icon + + )} + + {app?.isPrivate ? ( + + {`${app?.privateAppProperties?.appName || 'Private'}`} + + ) : ( + {app?.metadata?.title || app?.name} + )} + + + + ); }; +export const SortablePinnedApps = ({ + isDesktop, + myWebsite, + myApp, + availableQapps = [], +}) => { + const [pinnedApps, setPinnedApps] = useRecoilState(sortablePinnedAppsAtom); + const setSettingsLocalLastUpdated = useSetRecoilState( + settingsLocalLastUpdatedAtom + ); + + const transformPinnedApps = useMemo(() => { + // Clone the existing pinned apps list + let pinned = [...pinnedApps]; + + // Function to add or update `isMine` property + const addOrUpdateIsMine = (pinnedList, appToCheck) => { + if (!appToCheck) return pinnedList; + + const existingIndex = pinnedList.findIndex( + (item) => + item?.service === appToCheck?.service && + item?.name === appToCheck?.name + ); + + if (existingIndex !== -1) { + // If the app is already in the list, update it with `isMine: true` + pinnedList[existingIndex] = { + ...pinnedList[existingIndex], + isMine: true, + }; + } else { + // If not in the list, add it with `isMine: true` at the beginning + pinnedList.unshift({ ...appToCheck, isMine: true }); + } + + return pinnedList; + }; + + // Update or add `myWebsite` and `myApp` while preserving their positions + pinned = addOrUpdateIsMine(pinned, myWebsite); + pinned = addOrUpdateIsMine(pinned, myApp); + + // Update pinned list based on availableQapps + pinned = pinned.map((pin) => { + const findIndex = availableQapps?.findIndex( + (item) => item?.service === pin?.service && item?.name === pin?.name + ); + if (findIndex !== -1) + return { + ...availableQapps[findIndex], + ...pin, + }; + + return pin; + }); + + return pinned; + }, [myApp, myWebsite, pinnedApps, availableQapps]); + + const sensors = useSensors( + useSensor(PointerSensor, { + activationConstraint: { + distance: 10, // Set a distance to avoid triggering drag on small movements + }, + }), + useSensor(TouchSensor, { + activationConstraint: { + distance: 10, // Also apply to touch + }, + }), + useSensor(KeyboardSensor, { + coordinateGetter: sortableKeyboardCoordinates, + }) + ); + + const handleDragEnd = (event) => { + const { active, over } = event; + + if (!over) return; // Make sure the drop target exists + + if (active.id !== over.id) { + const oldIndex = transformPinnedApps.findIndex( + (item) => `${item?.service}-${item?.name}` === active.id + ); + const newIndex = transformPinnedApps.findIndex( + (item) => `${item?.service}-${item?.name}` === over.id + ); + + const newOrder = arrayMove(transformPinnedApps, oldIndex, newIndex); + setPinnedApps(newOrder); + saveToLocalStorage('ext_saved_settings', 'sortablePinnedApps', newOrder); + setSettingsLocalLastUpdated(Date.now()); + } + }; + + return ( + + `${app?.service}-${app?.name}`)} + > + {transformPinnedApps.map((app) => ( + + ))} + + + ); +}; From 1797754283e4b1165cb4ab1e15adf616e29d578c Mon Sep 17 00:00:00 2001 From: Nicola Benaglia Date: Sun, 20 Apr 2025 10:10:51 +0200 Subject: [PATCH 54/55] Add style, remove dialog (useless) --- src/components/Apps/AppsPrivate.tsx | 240 ++++++++++++++++------------ 1 file changed, 134 insertions(+), 106 deletions(-) diff --git a/src/components/Apps/AppsPrivate.tsx b/src/components/Apps/AppsPrivate.tsx index d18fcad..e9696e0 100644 --- a/src/components/Apps/AppsPrivate.tsx +++ b/src/components/Apps/AppsPrivate.tsx @@ -1,6 +1,5 @@ -import React, { useContext, useMemo, useState } from "react"; +import React, { useContext, useMemo, useState } from 'react'; import { - Avatar, Box, Button, ButtonBase, @@ -13,14 +12,17 @@ import { Select, Tab, Tabs, - Typography, -} from "@mui/material"; -import { useDropzone } from "react-dropzone"; -import { useHandlePrivateApps } from "./useHandlePrivateApps"; -import { useRecoilState, useSetRecoilState } from "recoil"; -import { groupsPropertiesAtom, myGroupsWhereIAmAdminAtom } from "../../atoms/global"; -import { Label } from "../Group/AddGroup"; -import { Spacer } from "../../common/Spacer"; + useTheme, +} from '@mui/material'; +import { useDropzone } from 'react-dropzone'; +import { useHandlePrivateApps } from './useHandlePrivateApps'; +import { useRecoilState } from 'recoil'; +import { + groupsPropertiesAtom, + myGroupsWhereIAmAdminAtom, +} from '../../atoms/global'; +import { Label } from '../Group/AddGroup'; +import { Spacer } from '../../common/Spacer'; import { Add, AppCircle, @@ -28,52 +30,59 @@ import { AppCircleLabel, PublishQAppChoseFile, PublishQAppInfo, -} from "./Apps-styles"; -import ImageUploader from "../../common/ImageUploader"; -import { isMobile, MyContext } from "../../App"; -import { fileToBase64 } from "../../utils/fileReading"; -import { objectToBase64 } from "../../qdn/encryption/group-encryption"; -import { getFee } from "../../background"; +} from './Apps-styles'; +import ImageUploader from '../../common/ImageUploader'; +import { isMobile, MyContext } from '../../App'; +import { fileToBase64 } from '../../utils/fileReading'; +import { objectToBase64 } from '../../qdn/encryption/group-encryption'; +import { getFee } from '../../background'; const maxFileSize = 50 * 1024 * 1024; // 50MB -export const AppsPrivate = ({myName}) => { +export const AppsPrivate = ({ myName }) => { const { openApp } = useHandlePrivateApps(); const [file, setFile] = useState(null); const [logo, setLogo] = useState(null); - const [qortalUrl, setQortalUrl] = useState(""); + const [qortalUrl, setQortalUrl] = useState(''); const [selectedGroup, setSelectedGroup] = useState(0); - const [groupsProperties] = useRecoilState(groupsPropertiesAtom) + const [groupsProperties] = useRecoilState(groupsPropertiesAtom); const [valueTabPrivateApp, setValueTabPrivateApp] = useState(0); const [myGroupsWhereIAmAdminFromGlobal] = useRecoilState( myGroupsWhereIAmAdminAtom ); - const myGroupsWhereIAmAdmin = useMemo(()=> { - return myGroupsWhereIAmAdminFromGlobal?.filter((group)=> groupsProperties[group?.groupId]?.isOpen === false) - }, [myGroupsWhereIAmAdminFromGlobal, groupsProperties]) - const [isOpenPrivateModal, setIsOpenPrivateModal] = useState(false); - const { show, setInfoSnackCustom, setOpenSnackGlobal, memberGroups } = useContext(MyContext); - + const myGroupsWhereIAmAdmin = useMemo(() => { + return myGroupsWhereIAmAdminFromGlobal?.filter( + (group) => groupsProperties[group?.groupId]?.isOpen === false + ); + }, [myGroupsWhereIAmAdminFromGlobal, groupsProperties]); - const myGroupsPrivate = useMemo(()=> { - return memberGroups?.filter((group)=> groupsProperties[group?.groupId]?.isOpen === false) - }, [memberGroups, groupsProperties]) + const [isOpenPrivateModal, setIsOpenPrivateModal] = useState(false); + const { show, setInfoSnackCustom, setOpenSnackGlobal, memberGroups } = + useContext(MyContext); + const theme = useTheme(); + + const myGroupsPrivate = useMemo(() => { + return memberGroups?.filter( + (group) => groupsProperties[group?.groupId]?.isOpen === false + ); + }, [memberGroups, groupsProperties]); const [privateAppValues, setPrivateAppValues] = useState({ - name: "", - service: "DOCUMENT", - identifier: "", + name: '', + service: 'DOCUMENT', + identifier: '', groupId: 0, }); const [newPrivateAppValues, setNewPrivateAppValues] = useState({ - service: "DOCUMENT", - identifier: "", - name: "", + service: 'DOCUMENT', + identifier: '', + name: '', }); + const { getRootProps, getInputProps } = useDropzone({ accept: { - "application/zip": [".zip"], // Only accept zip files + 'application/zip': ['.zip'], // Only accept zip files }, maxSize: maxFileSize, multiple: false, // Disable multiple file uploads @@ -85,7 +94,7 @@ export const AppsPrivate = ({myName}) => { onDropRejected: (fileRejections) => { fileRejections.forEach(({ file, errors }) => { errors.forEach((error) => { - if (error.code === "file-too-large") { + if (error.code === 'file-too-large') { console.error( `File ${file.name} is too large. Max size allowed is ${ maxFileSize / (1024 * 1024) @@ -100,25 +109,24 @@ export const AppsPrivate = ({myName}) => { const addPrivateApp = async () => { try { if (privateAppValues?.groupId === 0) return; - - await openApp(privateAppValues, true); + + await openApp(privateAppValues, true); } catch (error) { - console.error(error) - + console.error(error); } }; const clearFields = () => { setPrivateAppValues({ - name: "", - service: "DOCUMENT", - identifier: "", + name: '', + service: 'DOCUMENT', + identifier: '', groupId: 0, }); setNewPrivateAppValues({ - service: "DOCUMENT", - identifier: "", - name: "", + service: 'DOCUMENT', + identifier: '', + name: '', }); setFile(null); setValueTabPrivateApp(0); @@ -129,9 +137,9 @@ export const AppsPrivate = ({myName}) => { const publishPrivateApp = async () => { try { if (selectedGroup === 0) return; - if (!logo) throw new Error("Please select an image for a logo"); - if (!myName) throw new Error("You need a Qortal name to publish"); - if (!newPrivateAppValues?.name) throw new Error("Your app needs a name"); + if (!logo) throw new Error('Please select an image for a logo'); + if (!myName) throw new Error('You need a Qortal name to publish'); + if (!newPrivateAppValues?.name) throw new Error('Your app needs a name'); const base64Logo = await fileToBase64(logo); const base64App = await fileToBase64(file); const objectToSave = { @@ -141,27 +149,29 @@ export const AppsPrivate = ({myName}) => { }; const object64 = await objectToBase64(objectToSave); const decryptedData = await window.sendMessage( - "ENCRYPT_QORTAL_GROUP_DATA", + 'ENCRYPT_QORTAL_GROUP_DATA', { base64: object64, groupId: selectedGroup, } ); + if (decryptedData?.error) { throw new Error( - decryptedData?.error || "Unable to encrypt app. App not published" + decryptedData?.error || 'Unable to encrypt app. App not published' ); } - const fee = await getFee("ARBITRARY"); + + const fee = await getFee('ARBITRARY'); await show({ - message: "Would you like to publish this app?", - publishFee: fee.fee + " QORT", + message: 'Would you like to publish this app?', + publishFee: fee.fee + ' QORT', }); await new Promise((res, rej) => { window - .sendMessage("publishOnQDN", { + .sendMessage('publishOnQDN', { data: decryptedData, identifier: newPrivateAppValues?.identifier, service: newPrivateAppValues?.service, @@ -174,9 +184,10 @@ export const AppsPrivate = ({myName}) => { rej(response.error); }) .catch((error) => { - rej(error.message || "An error occurred"); + rej(error.message || 'An error occurred'); }); }); + openApp( { identifier: newPrivateAppValues?.identifier, @@ -188,10 +199,10 @@ export const AppsPrivate = ({myName}) => { ); clearFields(); } catch (error) { - setOpenSnackGlobal(true) + setOpenSnackGlobal(true); setInfoSnackCustom({ - type: "error", - message: error?.message || "Unable to publish app", + type: 'error', + message: error?.message || 'Unable to publish app', }); } }; @@ -203,9 +214,10 @@ export const AppsPrivate = ({myName}) => { function a11yProps(index: number) { return { id: `simple-tab-${index}`, - "aria-controls": `simple-tabpanel-${index}`, + 'aria-controls': `simple-tabpanel-${index}`, }; } + return ( <> { setIsOpenPrivateModal(true); }} sx={{ - width: "80px", + width: '80px', }} > + + Private @@ -233,7 +246,7 @@ export const AppsPrivate = ({myName}) => { aria-labelledby="alert-dialog-title" aria-describedby="alert-dialog-description" onKeyDown={(e) => { - if (e.key === "Enter") { + if (e.key === 'Enter') { if (valueTabPrivateApp === 0) { if ( !privateAppValues.name || @@ -249,23 +262,17 @@ export const AppsPrivate = ({myName}) => { maxWidth="md" fullWidth={true} > - - {valueTabPrivateApp === 0 - ? "Access private app" - : "Publish private app"} - - @@ -273,20 +280,20 @@ export const AppsPrivate = ({myName}) => { label="Access app" {...a11yProps(0)} sx={{ - "&.Mui-selected": { - color: "white", + '&.Mui-selected': { + color: theme.palette.text.primary, }, - fontSize: isMobile ? "0.75rem" : "1rem", // Adjust font size for mobile + fontSize: isMobile ? '0.75rem' : '1rem', // Adjust font size for mobile }} /> @@ -296,9 +303,9 @@ export const AppsPrivate = ({myName}) => { @@ -333,10 +340,10 @@ export const AppsPrivate = ({myName}) => { @@ -355,10 +362,10 @@ export const AppsPrivate = ({myName}) => { @@ -376,6 +383,7 @@ export const AppsPrivate = ({myName}) => { /> + + {logo?.name} + +