mirror of
https://github.com/Qortal/chrome-extension.git
synced 2025-02-11 17:55:49 +00:00
batch of updates 3
This commit is contained in:
parent
97a0dd7557
commit
d1be494420
12
package-lock.json
generated
12
package-lock.json
generated
@ -53,6 +53,7 @@
|
|||||||
"react-frame-component": "^5.2.7",
|
"react-frame-component": "^5.2.7",
|
||||||
"react-infinite-scroller": "^1.2.6",
|
"react-infinite-scroller": "^1.2.6",
|
||||||
"react-intersection-observer": "^9.13.0",
|
"react-intersection-observer": "^9.13.0",
|
||||||
|
"react-json-view-lite": "^2.0.1",
|
||||||
"react-qr-code": "^2.0.15",
|
"react-qr-code": "^2.0.15",
|
||||||
"react-quill": "^2.0.0",
|
"react-quill": "^2.0.0",
|
||||||
"react-redux": "^9.1.2",
|
"react-redux": "^9.1.2",
|
||||||
@ -9573,6 +9574,17 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
||||||
},
|
},
|
||||||
|
"node_modules/react-json-view-lite": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-json-view-lite/-/react-json-view-lite-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-yElNMSzL7UJ9rMDQIbTiBemXbvfAoqpxM/0IQd3nr52CLLBC0HxOSKcta/bayct2QCq7ZVzLzI8CGfuf387hHw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^18.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-lifecycles-compat": {
|
"node_modules/react-lifecycles-compat": {
|
||||||
"version": "3.0.4",
|
"version": "3.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
|
||||||
|
@ -57,6 +57,7 @@
|
|||||||
"react-frame-component": "^5.2.7",
|
"react-frame-component": "^5.2.7",
|
||||||
"react-infinite-scroller": "^1.2.6",
|
"react-infinite-scroller": "^1.2.6",
|
||||||
"react-intersection-observer": "^9.13.0",
|
"react-intersection-observer": "^9.13.0",
|
||||||
|
"react-json-view-lite": "^2.0.1",
|
||||||
"react-qr-code": "^2.0.15",
|
"react-qr-code": "^2.0.15",
|
||||||
"react-quill": "^2.0.0",
|
"react-quill": "^2.0.0",
|
||||||
"react-redux": "^9.1.2",
|
"react-redux": "^9.1.2",
|
||||||
|
12
src/App.tsx
12
src/App.tsx
@ -43,7 +43,8 @@ import Return from "./assets/svgs/Return.svg";
|
|||||||
import Success from "./assets/svgs/Success.svg";
|
import Success from "./assets/svgs/Success.svg";
|
||||||
import Info from "./assets/svgs/Info.svg";
|
import Info from "./assets/svgs/Info.svg";
|
||||||
import CloseIcon from "@mui/icons-material/Close";
|
import CloseIcon from "@mui/icons-material/Close";
|
||||||
|
import { JsonView, allExpanded, darkStyles } from 'react-json-view-lite';
|
||||||
|
import 'react-json-view-lite/dist/index.css';
|
||||||
import {
|
import {
|
||||||
createAccount,
|
createAccount,
|
||||||
generateRandomSentence,
|
generateRandomSentence,
|
||||||
@ -2797,6 +2798,15 @@ function App() {
|
|||||||
{messageQortalRequestExtension?.highlightedText}
|
{messageQortalRequestExtension?.highlightedText}
|
||||||
</TextP>
|
</TextP>
|
||||||
|
|
||||||
|
{messageQortalRequestExtension?.json && (
|
||||||
|
<>
|
||||||
|
<Spacer height="15px" />
|
||||||
|
|
||||||
|
<JsonView data={messageQortalRequestExtension?.json} shouldExpandNode={allExpanded} style={darkStyles} />
|
||||||
|
<Spacer height="15px" />
|
||||||
|
|
||||||
|
</>
|
||||||
|
)}
|
||||||
{messageQortalRequestExtension?.fee && (
|
{messageQortalRequestExtension?.fee && (
|
||||||
<>
|
<>
|
||||||
<Spacer height="15px" />
|
<Spacer height="15px" />
|
||||||
|
@ -103,14 +103,15 @@ export const AppRating = ({ app, myName, ratingCountPosition = "right" }) => {
|
|||||||
getRating(app?.name, app?.service);
|
getRating(app?.name, app?.service);
|
||||||
}, [getRating, app?.name]);
|
}, [getRating, app?.name]);
|
||||||
|
|
||||||
const rateFunc = async (event, newValue) => {
|
const rateFunc = async (event, chosenValue, currentValue) => {
|
||||||
try {
|
try {
|
||||||
|
const newValue = chosenValue || currentValue
|
||||||
if (!myName) throw new Error("You need a name to rate.");
|
if (!myName) throw new Error("You need a name to rate.");
|
||||||
if (!app?.name) return;
|
if (!app?.name) return;
|
||||||
const fee = await getFee("ARBITRARY");
|
const fee = await getFee("CREATE_POLL");
|
||||||
|
|
||||||
await show({
|
await show({
|
||||||
message: `Would you like to rate this app a rating of ${newValue}?`,
|
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",
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -212,7 +213,7 @@ export const AppRating = ({ app, myName, ratingCountPosition = "right" }) => {
|
|||||||
|
|
||||||
<Rating
|
<Rating
|
||||||
value={value}
|
value={value}
|
||||||
onChange={rateFunc}
|
onChange={(event, rating)=> rateFunc(event, rating, value)}
|
||||||
precision={1}
|
precision={1}
|
||||||
readOnly={hasPublishedRating === null}
|
readOnly={hasPublishedRating === null}
|
||||||
size="small"
|
size="small"
|
||||||
|
@ -368,7 +368,7 @@ export const AppsDesktop = ({ mode, setMode, show , myName, goToHome, setDesktop
|
|||||||
</ButtonBase>
|
</ButtonBase>
|
||||||
<Save isDesktop myName={myName} />
|
<Save isDesktop myName={myName} />
|
||||||
{mode !== 'home' && (
|
{mode !== 'home' && (
|
||||||
<AppsNavBarDesktop />
|
<AppsNavBarDesktop disableBack={isNewTabWindow && mode === 'viewer'} />
|
||||||
|
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ export function saveToLocalStorage(key, subKey, newValue) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const AppsNavBarDesktop = () => {
|
export const AppsNavBarDesktop = ({disableBack}) => {
|
||||||
const [tabs, setTabs] = useState([]);
|
const [tabs, setTabs] = useState([]);
|
||||||
const [selectedTab, setSelectedTab] = useState(null);
|
const [selectedTab, setSelectedTab] = useState(null);
|
||||||
const [navigationController, setNavigationController] = useRecoilState(navigationControllerAtom)
|
const [navigationController, setNavigationController] = useRecoilState(navigationControllerAtom)
|
||||||
@ -108,10 +108,11 @@ export const AppsNavBarDesktop = () => {
|
|||||||
|
|
||||||
|
|
||||||
const isDisableBackButton = useMemo(()=> {
|
const isDisableBackButton = useMemo(()=> {
|
||||||
|
if(disableBack) return true
|
||||||
if(selectedTab && navigationController[selectedTab?.tabId]?.hasBack) return false
|
if(selectedTab && navigationController[selectedTab?.tabId]?.hasBack) return false
|
||||||
if(selectedTab && !navigationController[selectedTab?.tabId]?.hasBack) return true
|
if(selectedTab && !navigationController[selectedTab?.tabId]?.hasBack) return true
|
||||||
return false
|
return false
|
||||||
}, [navigationController, selectedTab])
|
}, [navigationController, selectedTab, disableBack])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -252,7 +252,7 @@ export const ChatGroup = ({selectedGroup, secretKey, setSecretKey, getSecretKey,
|
|||||||
const content = item?.content || item.decryptedData?.content;
|
const content = item?.content || item.decryptedData?.content;
|
||||||
const sender = item.sender;
|
const sender = item.sender;
|
||||||
const newTimestamp = item.timestamp;
|
const newTimestamp = item.timestamp;
|
||||||
const contentState = item?.contentState || item.decryptedData?.contentState;
|
const contentState = item?.contentState !== undefined ? item?.contentState : item.decryptedData?.contentState;
|
||||||
|
|
||||||
if (!content || typeof content !== "string" || !sender || typeof sender !== "string" || !newTimestamp) {
|
if (!content || typeof content !== "string" || !sender || typeof sender !== "string" || !newTimestamp) {
|
||||||
console.warn("Invalid content, sender, or timestamp in reaction data", item);
|
console.warn("Invalid content, sender, or timestamp in reaction data", item);
|
||||||
@ -344,7 +344,7 @@ export const ChatGroup = ({selectedGroup, secretKey, setSecretKey, getSecretKey,
|
|||||||
const content = item?.content || item.decryptedData?.content;
|
const content = item?.content || item.decryptedData?.content;
|
||||||
const sender = item.sender;
|
const sender = item.sender;
|
||||||
const newTimestamp = item.timestamp;
|
const newTimestamp = item.timestamp;
|
||||||
const contentState = item?.contentState || item.decryptedData?.contentState;
|
const contentState = item?.contentState !== undefined ? item?.contentState : item.decryptedData?.contentState;
|
||||||
|
|
||||||
if (!content || typeof content !== "string" || !sender || typeof sender !== "string" || !newTimestamp) {
|
if (!content || typeof content !== "string" || !sender || typeof sender !== "string" || !newTimestamp) {
|
||||||
console.warn("Invalid content, sender, or timestamp in reaction data", item);
|
console.warn("Invalid content, sender, or timestamp in reaction data", item);
|
||||||
@ -755,7 +755,7 @@ useEffect(() => {
|
|||||||
setIsSending(false)
|
setIsSending(false)
|
||||||
resumeAllQueues()
|
resumeAllQueues()
|
||||||
}
|
}
|
||||||
}, [])
|
}, [isPrivate])
|
||||||
|
|
||||||
console.log('isPrivate', isPrivate)
|
console.log('isPrivate', isPrivate)
|
||||||
|
|
||||||
|
@ -48,16 +48,17 @@ export const PollCard = ({
|
|||||||
});
|
});
|
||||||
setIsLoadingSubmit(true);
|
setIsLoadingSubmit(true);
|
||||||
|
|
||||||
window
|
chrome?.runtime?.sendMessage(
|
||||||
.sendMessage(
|
|
||||||
"voteOnPoll",
|
|
||||||
{
|
{
|
||||||
pollName: poll?.info?.pollName,
|
action: "VOTE_ON_POLL",
|
||||||
|
type: "qortalRequest",
|
||||||
|
payload: {
|
||||||
|
pollName: poll?.info?.pollName,
|
||||||
optionIndex: +selectedOption,
|
optionIndex: +selectedOption,
|
||||||
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
60000
|
(response) => {
|
||||||
)
|
|
||||||
.then((response) => {
|
|
||||||
setIsLoadingSubmit(false);
|
setIsLoadingSubmit(false);
|
||||||
if (response.error) {
|
if (response.error) {
|
||||||
setInfoSnack({
|
setInfoSnack({
|
||||||
@ -75,14 +76,6 @@ export const PollCard = ({
|
|||||||
setOpenSnack(true);
|
setOpenSnack(true);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
|
||||||
setIsLoadingSubmit(false);
|
|
||||||
setInfoSnack({
|
|
||||||
type: "error",
|
|
||||||
message: error?.message || "Unable to vote.",
|
|
||||||
});
|
|
||||||
setOpenSnack(true);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const getName = async (owner) => {
|
const getName = async (owner) => {
|
||||||
|
@ -96,6 +96,7 @@ import LockIcon from '@mui/icons-material/Lock';
|
|||||||
import NoEncryptionGmailerrorredIcon from '@mui/icons-material/NoEncryptionGmailerrorred';
|
import NoEncryptionGmailerrorredIcon from '@mui/icons-material/NoEncryptionGmailerrorred';
|
||||||
import { useSetRecoilState } from "recoil";
|
import { useSetRecoilState } from "recoil";
|
||||||
import { selectedGroupIdAtom } from "../../atoms/global";
|
import { selectedGroupIdAtom } from "../../atoms/global";
|
||||||
|
import { sortArrayByTimestampAndGroupName } from "../../utils/time";
|
||||||
|
|
||||||
// let touchStartY = 0;
|
// let touchStartY = 0;
|
||||||
// let disablePullToRefresh = false;
|
// let disablePullToRefresh = false;
|
||||||
@ -976,7 +977,7 @@ export const Group = ({
|
|||||||
chrome?.runtime?.onMessage.addListener((message, sender, sendResponse) => {
|
chrome?.runtime?.onMessage.addListener((message, sender, sendResponse) => {
|
||||||
if (message.action === "SET_GROUPS") {
|
if (message.action === "SET_GROUPS") {
|
||||||
// Update the component state with the received 'sendqort' state
|
// Update the component state with the received 'sendqort' state
|
||||||
setGroups(message.payload);
|
setGroups(sortArrayByTimestampAndGroupName(message.payload));
|
||||||
getLatestRegularChat(message.payload)
|
getLatestRegularChat(message.payload)
|
||||||
setMemberGroups(message.payload);
|
setMemberGroups(message.payload);
|
||||||
|
|
||||||
@ -2632,6 +2633,10 @@ export const Group = ({
|
|||||||
Wait until an admin re-encrypts the keys.
|
Wait until an admin re-encrypts the keys.
|
||||||
</Typography>
|
</Typography>
|
||||||
<Spacer height="25px" />
|
<Spacer height="25px" />
|
||||||
|
<Typography>
|
||||||
|
<strong>Only unencrypted messages will be displayed.</strong>
|
||||||
|
</Typography>
|
||||||
|
<Spacer height="25px" />
|
||||||
<Typography>
|
<Typography>
|
||||||
Try notifying an admin from the list of admins below:
|
Try notifying an admin from the list of admins below:
|
||||||
</Typography>
|
</Typography>
|
||||||
|
@ -12,7 +12,7 @@ export const getMemberInvites = async (groupNumber) => {
|
|||||||
return groupData;
|
return groupData;
|
||||||
}
|
}
|
||||||
|
|
||||||
const getNames = async (listOfMembers) => {
|
const getNames = async (listOfMembers, includeNoNames) => {
|
||||||
let members = [];
|
let members = [];
|
||||||
if (listOfMembers && Array.isArray(listOfMembers)) {
|
if (listOfMembers && Array.isArray(listOfMembers)) {
|
||||||
for (const member of listOfMembers) {
|
for (const member of listOfMembers) {
|
||||||
@ -20,6 +20,8 @@ const getNames = async (listOfMembers) => {
|
|||||||
const name = await getNameInfo(member.offender);
|
const name = await getNameInfo(member.offender);
|
||||||
if (name) {
|
if (name) {
|
||||||
members.push({ ...member, name });
|
members.push({ ...member, name });
|
||||||
|
} else if(includeNoNames){
|
||||||
|
members.push({ ...member, name: name || "" });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -42,7 +44,8 @@ export const ListOfBans = ({ groupId, setInfoSnack, setOpenSnack, show }) => {
|
|||||||
const getInvites = async (groupId) => {
|
const getInvites = async (groupId) => {
|
||||||
try {
|
try {
|
||||||
const res = await getMemberInvites(groupId);
|
const res = await getMemberInvites(groupId);
|
||||||
const resWithNames = await getNames(res);
|
const resWithNames = await getNames(res, true);
|
||||||
|
|
||||||
setBans(resWithNames);
|
setBans(resWithNames);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
@ -151,9 +154,9 @@ export const ListOfBans = ({ groupId, setInfoSnack, setOpenSnack, show }) => {
|
|||||||
</Popover>
|
</Popover>
|
||||||
<ListItemButton onClick={(event) => handlePopoverOpen(event, index)}>
|
<ListItemButton onClick={(event) => handlePopoverOpen(event, index)}>
|
||||||
<ListItemAvatar>
|
<ListItemAvatar>
|
||||||
<Avatar
|
<Avatar
|
||||||
alt={member?.name}
|
alt={member?.name}
|
||||||
src={`${getBaseApiReact()}/arbitrary/THUMBNAIL/${member?.name}/qortal_avatar?async=true`}
|
src={member?.name ? `${getBaseApiReact()}/arbitrary/THUMBNAIL/${member?.name}/qortal_avatar?async=true` : ''}
|
||||||
/>
|
/>
|
||||||
</ListItemAvatar>
|
</ListItemAvatar>
|
||||||
<ListItemText primary={member?.name || member?.offender} />
|
<ListItemText primary={member?.name || member?.offender} />
|
||||||
|
@ -12,7 +12,7 @@ export const getMemberInvites = async (groupNumber) => {
|
|||||||
return groupData;
|
return groupData;
|
||||||
}
|
}
|
||||||
|
|
||||||
const getNames = async (listOfMembers) => {
|
const getNames = async (listOfMembers, includeNoNames) => {
|
||||||
let members = [];
|
let members = [];
|
||||||
if (listOfMembers && Array.isArray(listOfMembers)) {
|
if (listOfMembers && Array.isArray(listOfMembers)) {
|
||||||
for (const member of listOfMembers) {
|
for (const member of listOfMembers) {
|
||||||
@ -20,6 +20,8 @@ const getNames = async (listOfMembers) => {
|
|||||||
const name = await getNameInfo(member.invitee);
|
const name = await getNameInfo(member.invitee);
|
||||||
if (name) {
|
if (name) {
|
||||||
members.push({ ...member, name });
|
members.push({ ...member, name });
|
||||||
|
} else if(includeNoNames){
|
||||||
|
members.push({ ...member, name: name || "" });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -43,7 +45,7 @@ export const ListOfInvites = ({ groupId, setInfoSnack, setOpenSnack, show }) =>
|
|||||||
const getInvites = async (groupId) => {
|
const getInvites = async (groupId) => {
|
||||||
try {
|
try {
|
||||||
const res = await getMemberInvites(groupId);
|
const res = await getMemberInvites(groupId);
|
||||||
const resWithNames = await getNames(res);
|
const resWithNames = await getNames(res, true);
|
||||||
setInvites(resWithNames);
|
setInvites(resWithNames);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
@ -152,9 +154,9 @@ export const ListOfInvites = ({ groupId, setInfoSnack, setOpenSnack, show }) =>
|
|||||||
</Popover>
|
</Popover>
|
||||||
<ListItemButton onClick={(event) => handlePopoverOpen(event, index)}>
|
<ListItemButton onClick={(event) => handlePopoverOpen(event, index)}>
|
||||||
<ListItemAvatar>
|
<ListItemAvatar>
|
||||||
<Avatar
|
<Avatar
|
||||||
alt={member?.name}
|
alt={member?.name}
|
||||||
src={`${getBaseApiReact()}/arbitrary/THUMBNAIL/${member?.name}/qortal_avatar?async=true`}
|
src={member?.name ? `${getBaseApiReact()}/arbitrary/THUMBNAIL/${member?.name}/qortal_avatar?async=true` : ''}
|
||||||
/>
|
/>
|
||||||
</ListItemAvatar>
|
</ListItemAvatar>
|
||||||
<ListItemText primary={member?.name || member?.invitee} />
|
<ListItemText primary={member?.name || member?.invitee} />
|
||||||
|
@ -12,14 +12,16 @@ export const getMemberInvites = async (groupNumber) => {
|
|||||||
return groupData;
|
return groupData;
|
||||||
}
|
}
|
||||||
|
|
||||||
const getNames = async (listOfMembers) => {
|
const getNames = async (listOfMembers, includeNoNames) => {
|
||||||
let members = [];
|
let members = [];
|
||||||
if (listOfMembers && Array.isArray(listOfMembers)) {
|
if (listOfMembers && Array.isArray(listOfMembers)) {
|
||||||
for (const member of listOfMembers) {
|
for (const member of listOfMembers) {
|
||||||
if (member.joiner) {
|
if (member.joiner) {
|
||||||
const name = await getNameInfo(member.joiner);
|
const name = await getNameInfo(member.joiner);
|
||||||
if (name) {
|
if (name) {
|
||||||
members.push({ ...member, name });
|
members.push({ ...member, name: name || "" });
|
||||||
|
} else if(includeNoNames){
|
||||||
|
members.push({ ...member, name: name || "" });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -27,6 +29,7 @@ const getNames = async (listOfMembers) => {
|
|||||||
return members;
|
return members;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const cache = new CellMeasurerCache({
|
const cache = new CellMeasurerCache({
|
||||||
fixedWidth: true,
|
fixedWidth: true,
|
||||||
defaultHeight: 50,
|
defaultHeight: 50,
|
||||||
@ -44,7 +47,7 @@ export const ListOfJoinRequests = ({ groupId, setInfoSnack, setOpenSnack, show }
|
|||||||
const getInvites = async (groupId) => {
|
const getInvites = async (groupId) => {
|
||||||
try {
|
try {
|
||||||
const res = await getMemberInvites(groupId);
|
const res = await getMemberInvites(groupId);
|
||||||
const resWithNames = await getNames(res);
|
const resWithNames = await getNames(res, true);
|
||||||
setInvites(resWithNames);
|
setInvites(resWithNames);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
@ -165,9 +168,9 @@ export const ListOfJoinRequests = ({ groupId, setInfoSnack, setOpenSnack, show }
|
|||||||
</Popover>
|
</Popover>
|
||||||
<ListItemButton onClick={(event) => handlePopoverOpen(event, index)}>
|
<ListItemButton onClick={(event) => handlePopoverOpen(event, index)}>
|
||||||
<ListItemAvatar>
|
<ListItemAvatar>
|
||||||
<Avatar
|
<Avatar
|
||||||
alt={member?.name}
|
alt={member?.name}
|
||||||
src={`${getBaseApiReact()}/arbitrary/THUMBNAIL/${member?.name}/qortal_avatar?async=true`}
|
src={member?.name ? `${getBaseApiReact()}/arbitrary/THUMBNAIL/${member?.name}/qortal_avatar?async=true` : ''}
|
||||||
/>
|
/>
|
||||||
</ListItemAvatar>
|
</ListItemAvatar>
|
||||||
<ListItemText primary={member?.name || member?.joiner} />
|
<ListItemText primary={member?.name || member?.joiner} />
|
||||||
|
@ -328,7 +328,7 @@ const ListOfMembers = ({
|
|||||||
<ListItemAvatar>
|
<ListItemAvatar>
|
||||||
<Avatar
|
<Avatar
|
||||||
alt={member?.name || member?.member}
|
alt={member?.name || member?.member}
|
||||||
src={`${getBaseApiReact()}/arbitrary/THUMBNAIL/${member?.name}/qortal_avatar?async=true`}
|
src={member?.name ? `${getBaseApiReact()}/arbitrary/THUMBNAIL/${member?.name}/qortal_avatar?async=true` : ''}
|
||||||
/>
|
/>
|
||||||
</ListItemAvatar>
|
</ListItemAvatar>
|
||||||
<ListItemText
|
<ListItemText
|
||||||
|
@ -25,6 +25,7 @@ import { LoadingSnackbar } from "../Snackbar/LoadingSnackbar";
|
|||||||
import { getFee } from "../../background";
|
import { getFee } from "../../background";
|
||||||
import { LoadingButton } from "@mui/lab";
|
import { LoadingButton } from "@mui/lab";
|
||||||
import { subscribeToEvent, unsubscribeFromEvent } from "../../utils/events";
|
import { subscribeToEvent, unsubscribeFromEvent } from "../../utils/events";
|
||||||
|
import { Spacer } from "../../common/Spacer";
|
||||||
|
|
||||||
function a11yProps(index: number) {
|
function a11yProps(index: number) {
|
||||||
return {
|
return {
|
||||||
@ -113,7 +114,7 @@ export const ManageMembers = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getMembers = async (groupId) => {
|
const getMembersWithNames = React.useCallback(async (groupId) => {
|
||||||
try {
|
try {
|
||||||
setIsLoadingMembers(true)
|
setIsLoadingMembers(true)
|
||||||
const res = await getGroupMembers(groupId);
|
const res = await getGroupMembers(groupId);
|
||||||
@ -121,6 +122,13 @@ export const ManageMembers = ({
|
|||||||
setMembersWithNames(resWithNames);
|
setMembersWithNames(resWithNames);
|
||||||
setIsLoadingMembers(false)
|
setIsLoadingMembers(false)
|
||||||
} catch (error) {}
|
} catch (error) {}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const getMembers = async (groupId) => {
|
||||||
|
try {
|
||||||
|
const res = await getGroupMembers(groupId);
|
||||||
|
setMembersWithNames(res?.members || []);
|
||||||
|
} catch (error) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
React.useEffect(()=> {
|
React.useEffect(()=> {
|
||||||
@ -256,6 +264,8 @@ export const ManageMembers = ({
|
|||||||
maxWidth: '750px'
|
maxWidth: '750px'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
<Button variant="contained" onClick={()=> getMembersWithNames(selectedGroup?.groupId)}>Load members with names</Button>
|
||||||
|
<Spacer height="10px" />
|
||||||
<ListOfMembers
|
<ListOfMembers
|
||||||
members={membersWithNames || []}
|
members={membersWithNames || []}
|
||||||
groupId={selectedGroup?.groupId}
|
groupId={selectedGroup?.groupId}
|
||||||
|
@ -1,77 +1,69 @@
|
|||||||
import { List, ListItemButton, ListItemIcon } from "@mui/material";
|
import {
|
||||||
|
List,
|
||||||
|
ListItemButton,
|
||||||
|
ListItemIcon,
|
||||||
|
ListItemText,
|
||||||
|
Collapse,
|
||||||
|
IconButton,
|
||||||
|
} from "@mui/material";
|
||||||
import React, { useContext, useEffect, useRef } from "react";
|
import React, { useContext, useEffect, useRef } from "react";
|
||||||
|
|
||||||
import ListItemText from "@mui/material/ListItemText";
|
|
||||||
import Collapse from "@mui/material/Collapse";
|
|
||||||
import InboxIcon from "@mui/icons-material/MoveToInbox";
|
|
||||||
|
|
||||||
import ExpandLess from "@mui/icons-material/ExpandLess";
|
|
||||||
import ExpandMore from "@mui/icons-material/ExpandMore";
|
|
||||||
import StarBorder from "@mui/icons-material/StarBorder";
|
|
||||||
import PendingIcon from "@mui/icons-material/Pending";
|
import PendingIcon from "@mui/icons-material/Pending";
|
||||||
import TaskAltIcon from "@mui/icons-material/TaskAlt";
|
import TaskAltIcon from "@mui/icons-material/TaskAlt";
|
||||||
|
import ExpandLess from "@mui/icons-material/ExpandLess";
|
||||||
|
import ExpandMore from "@mui/icons-material/ExpandMore";
|
||||||
import { MyContext, getBaseApiReact, isMobile } from "../../App";
|
import { MyContext, getBaseApiReact, isMobile } from "../../App";
|
||||||
import { getBaseApi } from "../../background";
|
|
||||||
|
|
||||||
|
export const TaskManger = ({ getUserInfo }) => {
|
||||||
|
|
||||||
export const TaskManger = ({getUserInfo}) => {
|
|
||||||
const { txList, setTxList, memberGroups } = useContext(MyContext);
|
const { txList, setTxList, memberGroups } = useContext(MyContext);
|
||||||
const [open, setOpen] = React.useState(true);
|
const [open, setOpen] = React.useState(false);
|
||||||
|
const intervals = useRef({});
|
||||||
|
|
||||||
const handleClick = () => {
|
const handleClick = () => {
|
||||||
setOpen(!open);
|
setOpen((prev) => !prev);
|
||||||
};
|
};
|
||||||
|
|
||||||
const intervals = useRef({})
|
const getStatus = ({ signature }, callback) => {
|
||||||
|
let stop = false;
|
||||||
|
const getAnswer = async () => {
|
||||||
|
const getTx = async () => {
|
||||||
|
const url = `${getBaseApiReact()}/transactions/signature/${signature}`;
|
||||||
|
const res = await fetch(url);
|
||||||
|
return await res.json();
|
||||||
|
};
|
||||||
|
|
||||||
const getStatus = ({signature}, callback?: any) =>{
|
if (!stop) {
|
||||||
|
stop = true;
|
||||||
let stop = false
|
try {
|
||||||
|
const txTransaction = await getTx();
|
||||||
const getAnswer = async () => {
|
if (!txTransaction.error && txTransaction.signature) {
|
||||||
const getTx = async () => {
|
await new Promise((res) =>
|
||||||
const url = `${getBaseApiReact()}/transactions/signature/${signature}`
|
|
||||||
const res = await fetch(url)
|
|
||||||
|
|
||||||
return await res.json()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!stop) {
|
|
||||||
stop = true
|
|
||||||
|
|
||||||
try {
|
|
||||||
const txTransaction = await getTx()
|
|
||||||
|
|
||||||
if (!txTransaction.error && txTransaction.signature) {
|
|
||||||
await new Promise((res)=> {
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
res(null)
|
res(null);
|
||||||
}, 300000);
|
}, 300000)
|
||||||
})
|
);
|
||||||
setTxList((prev)=> {
|
setTxList((prev) => {
|
||||||
let previousData = [...prev];
|
let previousData = [...prev];
|
||||||
const findTxWithSignature = previousData.findIndex((tx)=> tx.signature === signature)
|
const findTxWithSignature = previousData.findIndex(
|
||||||
if(findTxWithSignature !== -1){
|
(tx) => tx.signature === signature
|
||||||
|
);
|
||||||
|
if (findTxWithSignature !== -1) {
|
||||||
previousData[findTxWithSignature].done = true;
|
previousData[findTxWithSignature].done = true;
|
||||||
return previousData
|
return previousData;
|
||||||
}
|
}
|
||||||
return previousData
|
return previousData;
|
||||||
})
|
});
|
||||||
if(callback){
|
if (callback) {
|
||||||
callback(true)
|
callback(true);
|
||||||
}
|
}
|
||||||
clearInterval(intervals.current[signature])
|
clearInterval(intervals.current[signature]);
|
||||||
|
}
|
||||||
|
} catch (error) {}
|
||||||
|
stop = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
}
|
intervals.current[signature] = setInterval(getAnswer, 120000);
|
||||||
} catch (error) { }
|
};
|
||||||
|
|
||||||
stop = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
intervals.current[signature] = setInterval(getAnswer, 120000)
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setTxList((prev) => {
|
setTxList((prev) => {
|
||||||
@ -80,111 +72,117 @@ export const TaskManger = ({getUserInfo}) => {
|
|||||||
const findGroup = txList.findIndex(
|
const findGroup = txList.findIndex(
|
||||||
(tx) => tx?.type === "joined-group" && tx?.groupId === group.groupId
|
(tx) => tx?.type === "joined-group" && tx?.groupId === group.groupId
|
||||||
);
|
);
|
||||||
if (findGroup !== -1 && !previousData[findGroup]?.done ) {
|
if (findGroup !== -1 && !previousData[findGroup]?.done) {
|
||||||
// add notification
|
|
||||||
previousData[findGroup].done = true;
|
previousData[findGroup].done = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
memberGroups.forEach((group) => {
|
memberGroups.forEach((group) => {
|
||||||
const findGroup = txList.findIndex(
|
const findGroup = txList.findIndex(
|
||||||
(tx) => tx?.type === "created-group" && tx?.groupName === group.groupName
|
(tx) =>
|
||||||
|
tx?.type === "created-group" && tx?.groupName === group.groupName
|
||||||
);
|
);
|
||||||
if (findGroup !== -1 && !previousData[findGroup]?.done ) {
|
if (findGroup !== -1 && !previousData[findGroup]?.done) {
|
||||||
// add notification
|
|
||||||
previousData[findGroup].done = true;
|
previousData[findGroup].done = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
prev.forEach((tx, index)=> {
|
|
||||||
if(tx?.type === "leave-group" && memberGroups.findIndex(
|
prev.forEach((tx, index) => {
|
||||||
(group) => tx?.groupId === group.groupId
|
if (
|
||||||
) === -1){
|
tx?.type === "leave-group" &&
|
||||||
|
memberGroups.findIndex((group) => tx?.groupId === group.groupId) === -1
|
||||||
|
) {
|
||||||
previousData[index].done = true;
|
previousData[index].done = true;
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
})
|
prev.forEach((tx) => {
|
||||||
prev.forEach((tx, index)=> {
|
if (
|
||||||
|
["created-common-secret", "joined-group-request", "join-request-accept"].includes(
|
||||||
if(tx?.type === "created-common-secret" && tx?.signature && !tx.done){
|
tx?.type
|
||||||
if(intervals.current[tx.signature]) return
|
) &&
|
||||||
|
tx?.signature &&
|
||||||
getStatus({signature: tx.signature})
|
!tx.done
|
||||||
|
) {
|
||||||
|
if (!intervals.current[tx.signature]) {
|
||||||
|
getStatus({ signature: tx.signature });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (tx?.type === "register-name" && tx?.signature && !tx.done) {
|
||||||
})
|
if (!intervals.current[tx.signature]) {
|
||||||
prev.forEach((tx, index)=> {
|
getStatus({ signature: tx.signature }, getUserInfo);
|
||||||
|
}
|
||||||
if(tx?.type === "joined-group-request" && tx?.signature && !tx.done){
|
|
||||||
if(intervals.current[tx.signature]) return
|
|
||||||
|
|
||||||
getStatus({signature: tx.signature})
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
})
|
|
||||||
prev.forEach((tx, index)=> {
|
|
||||||
|
|
||||||
if(tx?.type === "join-request-accept" && tx?.signature && !tx.done){
|
|
||||||
if(intervals.current[tx.signature]) return
|
|
||||||
|
|
||||||
getStatus({signature: tx.signature})
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
prev.forEach((tx, index)=> {
|
|
||||||
|
|
||||||
if(tx?.type === "register-name" && tx?.signature && !tx.done){
|
|
||||||
if(intervals.current[tx.signature]) return
|
|
||||||
|
|
||||||
getStatus({signature: tx.signature}, getUserInfo)
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
return previousData;
|
return previousData;
|
||||||
});
|
});
|
||||||
}, [memberGroups, getUserInfo]);
|
}, [memberGroups, getUserInfo]);
|
||||||
|
|
||||||
if(isMobile) return null
|
if (isMobile || txList?.length === 0 || txList.every((item) => item?.done))
|
||||||
|
return null;
|
||||||
|
|
||||||
if (txList?.length === 0 || txList.filter((item) => !item?.done).length === 0) return null;
|
|
||||||
return (
|
return (
|
||||||
<List
|
<>
|
||||||
sx={{ width: "100%", maxWidth: 360, bgcolor: "background.paper" }}
|
{!open && (
|
||||||
component="nav"
|
<IconButton
|
||||||
aria-labelledby="nested-list-subheader"
|
onClick={handleClick}
|
||||||
>
|
sx={{
|
||||||
<ListItemButton onClick={handleClick}>
|
position: "fixed",
|
||||||
<ListItemIcon>
|
bottom: 16,
|
||||||
{txList.find((item) => !item.done) ? (
|
right: 16,
|
||||||
<PendingIcon sx={{
|
bgcolor: "primary.main",
|
||||||
color: 'white'
|
color: "white",
|
||||||
}} />
|
":hover": { bgcolor: "primary.dark" },
|
||||||
) : (
|
}}
|
||||||
<TaskAltIcon sx={{
|
>
|
||||||
color: 'white'
|
{txList.some((item) => !item.done) ? <PendingIcon /> : <TaskAltIcon />}
|
||||||
}} />
|
</IconButton>
|
||||||
)}
|
)}
|
||||||
</ListItemIcon>
|
{open && (
|
||||||
<ListItemText primary="Ongoing Transactions" />
|
<List
|
||||||
{open ? <ExpandLess /> : <ExpandMore />}
|
sx={{
|
||||||
</ListItemButton>
|
position: "fixed",
|
||||||
<Collapse in={open} timeout="auto" unmountOnExit>
|
bottom: 16,
|
||||||
<List component="div" disablePadding sx={{
|
right: 16,
|
||||||
maxHeight: '400px',
|
width: "300px",
|
||||||
overflow: 'auto'
|
maxHeight: "400px",
|
||||||
}}>
|
bgcolor: "background.paper",
|
||||||
{txList.map((item) => {
|
boxShadow: 4,
|
||||||
return (
|
overflow: "auto",
|
||||||
<ListItemButton key={item?.signature} sx={{ pl: 4 }}>
|
zIndex: 10,
|
||||||
|
padding: '0px'
|
||||||
<ListItemText primary={item?.done ? item.labelDone : item.label} />
|
}}
|
||||||
</ListItemButton>
|
component="nav"
|
||||||
);
|
>
|
||||||
})}
|
<ListItemButton onClick={handleClick}>
|
||||||
|
<ListItemIcon>
|
||||||
|
{txList.some((item) => !item.done) ? (
|
||||||
|
<PendingIcon sx={{
|
||||||
|
color:'white'
|
||||||
|
}} />
|
||||||
|
) : (
|
||||||
|
<TaskAltIcon sx={{
|
||||||
|
color:'white'
|
||||||
|
}} />
|
||||||
|
)}
|
||||||
|
</ListItemIcon>
|
||||||
|
<ListItemText primary="Ongoing Transactions" />
|
||||||
|
{open ? <ExpandLess /> : <ExpandMore />}
|
||||||
|
</ListItemButton>
|
||||||
|
<Collapse in={open} timeout="auto" unmountOnExit>
|
||||||
|
<List component="div" disablePadding>
|
||||||
|
{txList.map((item) => (
|
||||||
|
<ListItemButton key={item?.signature} sx={{ pl: 4 }}>
|
||||||
|
<ListItemText
|
||||||
|
primary={item?.done ? item.labelDone : item.label}
|
||||||
|
/>
|
||||||
|
</ListItemButton>
|
||||||
|
))}
|
||||||
|
</List>
|
||||||
|
</Collapse>
|
||||||
</List>
|
</List>
|
||||||
</Collapse>
|
)}
|
||||||
</List>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1638,6 +1638,10 @@ export const getWalletBalance = async (data, bypassPermission?: boolean, isFromE
|
|||||||
throw new Error(errorMsg);
|
throw new Error(errorMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isGateway = await isRunningGateway()
|
||||||
|
|
||||||
|
if(data?.coin === 'ARRR' && isGateway) throw new Error('Cannot view ARRR balance through the gateway. Please use your local node.')
|
||||||
|
|
||||||
const value = (await getPermission(`qAPPAutoWalletBalance-${appInfo?.name}-${data.coin}`)) || false;
|
const value = (await getPermission(`qAPPAutoWalletBalance-${appInfo?.name}-${data.coin}`)) || false;
|
||||||
let skip = false;
|
let skip = false;
|
||||||
if (value) {
|
if (value) {
|
||||||
@ -1691,7 +1695,7 @@ export const getWalletBalance = async (data, bypassPermission?: boolean, isFromE
|
|||||||
case "BTC":
|
case "BTC":
|
||||||
_url = await createEndpoint(`/crosschain/btc/walletbalance`);
|
_url = await createEndpoint(`/crosschain/btc/walletbalance`);
|
||||||
|
|
||||||
_body = parsedData.derivedMasterPublicKey;
|
_body = parsedData.btcPublicKey;
|
||||||
break;
|
break;
|
||||||
case "LTC":
|
case "LTC":
|
||||||
_url = await createEndpoint(`/crosschain/ltc/walletbalance`);
|
_url = await createEndpoint(`/crosschain/ltc/walletbalance`);
|
||||||
|
@ -35,4 +35,22 @@ export function formatTimestamp(timestamp: number): string {
|
|||||||
const date = moment(unixTimestamp, 'x').fromNow()
|
const date = moment(unixTimestamp, 'x').fromNow()
|
||||||
|
|
||||||
return date
|
return date
|
||||||
|
}
|
||||||
|
|
||||||
|
export function sortArrayByTimestampAndGroupName(array) {
|
||||||
|
return array.sort((a, b) => {
|
||||||
|
if (a.timestamp && b.timestamp) {
|
||||||
|
// Both have timestamp, sort by timestamp descending
|
||||||
|
return b.timestamp - a.timestamp;
|
||||||
|
} else if (a.timestamp) {
|
||||||
|
// Only `a` has timestamp, it comes first
|
||||||
|
return -1;
|
||||||
|
} else if (b.timestamp) {
|
||||||
|
// Only `b` has timestamp, it comes first
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
// Neither has timestamp, sort alphabetically by groupName
|
||||||
|
return a.groupName.localeCompare(b.groupName);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user