mirror of
https://github.com/Qortal/Qortal-Hub.git
synced 2025-07-23 04:36:52 +00:00
temp replace storage
This commit is contained in:
@@ -118,32 +118,32 @@ export const AppRating = ({ app, myName, ratingCountPosition = "right" }) => {
|
||||
const pollName = `app-library-${app.service}-rating-${app.name}`;
|
||||
const pollOptions = [`1, 2, 3, 4, 5, initialValue-${newValue}`];
|
||||
await new Promise((res, rej) => {
|
||||
chrome?.runtime?.sendMessage(
|
||||
{
|
||||
action: "CREATE_POLL",
|
||||
type: "qortalRequest",
|
||||
payload: {
|
||||
pollName: pollName,
|
||||
pollDescription: `Rating for ${app.service} ${app.name}`,
|
||||
pollOptions: pollOptions,
|
||||
pollOwnerAddress: myName,
|
||||
},
|
||||
window.sendMessage("CREATE_POLL", {
|
||||
payload: {
|
||||
pollName: pollName,
|
||||
pollDescription: `Rating for ${app.service} ${app.name}`,
|
||||
pollOptions: pollOptions,
|
||||
pollOwnerAddress: myName,
|
||||
},
|
||||
(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);
|
||||
}
|
||||
}, 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}`;
|
||||
@@ -153,30 +153,30 @@ export const AppRating = ({ app, myName, ratingCountPosition = "right" }) => {
|
||||
if (isNaN(optionIndex) || optionIndex === -1)
|
||||
throw new Error("Cannot find rating option");
|
||||
await new Promise((res, rej) => {
|
||||
chrome?.runtime?.sendMessage(
|
||||
{
|
||||
action: "VOTE_ON_POLL",
|
||||
type: "qortalRequest",
|
||||
payload: {
|
||||
pollName: pollName,
|
||||
optionIndex,
|
||||
},
|
||||
window.sendMessage("VOTE_ON_POLL", {
|
||||
payload: {
|
||||
pollName: pollName,
|
||||
optionIndex,
|
||||
},
|
||||
(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);
|
||||
}
|
||||
}, 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) {
|
||||
|
@@ -368,7 +368,8 @@ isDOMContentLoaded: false
|
||||
if (event?.data?.requestedHandler !== 'UI') return;
|
||||
|
||||
const sendMessageToRuntime = (message, eventPort) => {
|
||||
chrome?.runtime?.sendMessage(message, (response) => {
|
||||
window.sendMessage(message.action, message, 60000, message.isFromExtension)
|
||||
.then((response) => {
|
||||
if (response.error) {
|
||||
eventPort.postMessage({
|
||||
result: null,
|
||||
@@ -380,7 +381,11 @@ isDOMContentLoaded: false
|
||||
error: null,
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Failed qortalRequest", error);
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
// Check if action is included in the predefined list of UI requests
|
||||
|
@@ -126,7 +126,7 @@ const timeDifferenceForNotificationChats = 900000;
|
||||
export const requestQueueMemberNames = new RequestQueueWithPromise(5);
|
||||
export const requestQueueAdminMemberNames = new RequestQueueWithPromise(5);
|
||||
|
||||
const audio = new Audio(chrome.runtime?.getURL("msg-not1.wav"));
|
||||
// const audio = new Audio(chrome.runtime?.getURL("msg-not1.wav"));
|
||||
|
||||
export const getGroupAdminsAddress = async (groupNumber: number) => {
|
||||
// const validApi = await findUsableApi();
|
||||
@@ -203,6 +203,7 @@ export const decryptResource = async (data: string) => {
|
||||
data,
|
||||
})
|
||||
.then((response) => {
|
||||
console.log('decryptseroucs', response)
|
||||
if (!response?.error) {
|
||||
res(response);
|
||||
return;
|
||||
@@ -892,78 +893,89 @@ export const Group = ({
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
// Listen for messages from the background script
|
||||
chrome?.runtime?.onMessage.addListener((message, sender, sendResponse) => {
|
||||
if (message.action === "SET_GROUPS") {
|
||||
// Handler function for incoming messages
|
||||
const messageHandler = (event) => {
|
||||
const message = event.data;
|
||||
|
||||
if (message?.action === "SET_GROUPS") {
|
||||
// Update the component state with the received 'sendqort' state
|
||||
setGroups(message.payload);
|
||||
getLatestRegularChat(message.payload)
|
||||
getLatestRegularChat(message.payload);
|
||||
setMemberGroups(message.payload);
|
||||
|
||||
|
||||
if (selectedGroupRef.current && groupSectionRef.current === "chat") {
|
||||
window.sendMessage("addTimestampEnterChat", {
|
||||
timestamp: Date.now(),
|
||||
groupId: selectedGroupRef.current.groupId,
|
||||
}).catch((error) => {
|
||||
console.error("Failed to add timestamp:", error.message || "An error occurred");
|
||||
});
|
||||
|
||||
console.error("Failed to add timestamp:", error.message || "An error occurred");
|
||||
});
|
||||
}
|
||||
|
||||
if (selectedDirectRef.current) {
|
||||
window.sendMessage("addTimestampEnterChat", {
|
||||
timestamp: Date.now(),
|
||||
groupId: selectedDirectRef.current.address,
|
||||
}).catch((error) => {
|
||||
console.error("Failed to add timestamp:", error.message || "An error occurred");
|
||||
});
|
||||
|
||||
console.error("Failed to add timestamp:", error.message || "An error occurred");
|
||||
});
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
getTimestampEnterChat();
|
||||
}, 200);
|
||||
}
|
||||
if (message.action === "SET_GROUP_ANNOUNCEMENTS") {
|
||||
|
||||
if (message?.action === "SET_GROUP_ANNOUNCEMENTS") {
|
||||
// Update the component state with the received 'sendqort' state
|
||||
setGroupAnnouncements(message.payload);
|
||||
|
||||
if (
|
||||
selectedGroupRef.current &&
|
||||
groupSectionRef.current === "announcement"
|
||||
) {
|
||||
|
||||
if (selectedGroupRef.current && groupSectionRef.current === "announcement") {
|
||||
window.sendMessage("addGroupNotificationTimestamp", {
|
||||
timestamp: Date.now(),
|
||||
groupId: selectedGroupRef.current.groupId,
|
||||
}).catch((error) => {
|
||||
console.error("Failed to add group notification timestamp:", error.message || "An error occurred");
|
||||
});
|
||||
|
||||
console.error("Failed to add group notification timestamp:", error.message || "An error occurred");
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
getGroupAnnouncements();
|
||||
}, 200);
|
||||
}
|
||||
}
|
||||
if (message.action === "SET_DIRECTS") {
|
||||
|
||||
if (message?.action === "SET_DIRECTS") {
|
||||
// Update the component state with the received 'sendqort' state
|
||||
setDirects(message.payload);
|
||||
|
||||
|
||||
} else if (message.action === "PLAY_NOTIFICATION_SOUND") {
|
||||
audio.play();
|
||||
} else if (message?.action === "PLAY_NOTIFICATION_SOUND") {
|
||||
// audio.play();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Attach the event listener
|
||||
window.addEventListener("message", messageHandler);
|
||||
|
||||
// Clean up the event listener on component unmount
|
||||
return () => {
|
||||
window.removeEventListener("message", messageHandler);
|
||||
};
|
||||
}, []);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
!myAddress ||
|
||||
hasInitializedWebsocket.current ||
|
||||
!window?.location?.href?.includes("?main=true") ||
|
||||
!groups ||
|
||||
groups?.length === 0
|
||||
)
|
||||
return;
|
||||
|
||||
chrome?.runtime?.sendMessage({ action: "setupGroupWebsocket" });
|
||||
window.sendMessage("setupGroupWebsocket", {})
|
||||
.catch((error) => {
|
||||
console.error("Failed to setup group websocket:", error.message || "An error occurred");
|
||||
});
|
||||
|
||||
|
||||
hasInitializedWebsocket.current = true;
|
||||
}, [myAddress, groups]);
|
||||
|
@@ -18,7 +18,7 @@ export const WebSocketActive = ({ myAddress, setIsLoadingGroups }) => {
|
||||
|
||||
useEffect(() => {
|
||||
if (!myAddress) return; // Only proceed if myAddress is set
|
||||
if (!window?.location?.href?.includes("?main=true")) return;
|
||||
|
||||
|
||||
const pingHeads = () => {
|
||||
try {
|
||||
|
@@ -1,97 +1,121 @@
|
||||
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, oldPinnedAppsAtom, settingsLocalLastUpdatedAtom, settingsQDNLastUpdatedAtom, sortablePinnedAppsAtom } from '../../atoms/global';
|
||||
import { ButtonBase } 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';
|
||||
export const Save = ({isDesktop}) => {
|
||||
const [pinnedApps, setPinnedApps] = useRecoilState(sortablePinnedAppsAtom);
|
||||
const [settingsQdnLastUpdated, setSettingsQdnLastUpdated] = useRecoilState(settingsQDNLastUpdatedAtom);
|
||||
const [settingsLocalLastUpdated] = useRecoilState(settingsLocalLastUpdatedAtom);
|
||||
const setHasSettingsChangedAtom = useSetRecoilState(hasSettingsChangedAtom);
|
||||
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,
|
||||
oldPinnedAppsAtom,
|
||||
settingsLocalLastUpdatedAtom,
|
||||
settingsQDNLastUpdatedAtom,
|
||||
sortablePinnedAppsAtom,
|
||||
} from "../../atoms/global";
|
||||
import { ButtonBase } 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";
|
||||
export const Save = ({ isDesktop }) => {
|
||||
const [pinnedApps, setPinnedApps] = useRecoilState(sortablePinnedAppsAtom);
|
||||
const [settingsQdnLastUpdated, setSettingsQdnLastUpdated] = useRecoilState(
|
||||
settingsQDNLastUpdatedAtom
|
||||
);
|
||||
const [settingsLocalLastUpdated] = useRecoilState(
|
||||
settingsLocalLastUpdatedAtom
|
||||
);
|
||||
const setHasSettingsChangedAtom = useSetRecoilState(hasSettingsChangedAtom);
|
||||
|
||||
const [canSave] = useRecoilState(canSaveSettingToQdnAtom);
|
||||
const [openSnack, setOpenSnack] = useState(false);
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
const [canSave] = useRecoilState(canSaveSettingToQdnAtom);
|
||||
const [openSnack, setOpenSnack] = useState(false);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [infoSnack, setInfoSnack] = useState(null);
|
||||
const [oldPinnedApps, setOldPinnedApps] = useRecoilState(oldPinnedAppsAtom)
|
||||
const [oldPinnedApps, setOldPinnedApps] = useRecoilState(oldPinnedAppsAtom);
|
||||
|
||||
const { show } = useContext(MyContext);
|
||||
const { show } = useContext(MyContext);
|
||||
|
||||
const hasChanged = useMemo(()=> {
|
||||
const newChanges = {
|
||||
sortablePinnedApps: pinnedApps.map((item)=> {
|
||||
const hasChanged = useMemo(() => {
|
||||
const newChanges = {
|
||||
sortablePinnedApps: pinnedApps.map((item) => {
|
||||
return {
|
||||
name: item?.name,
|
||||
service: item?.service,
|
||||
};
|
||||
}),
|
||||
};
|
||||
const oldChanges = {
|
||||
sortablePinnedApps: oldPinnedApps.map((item) => {
|
||||
return {
|
||||
name: item?.name,
|
||||
service: item?.service,
|
||||
};
|
||||
}),
|
||||
};
|
||||
if (settingsQdnLastUpdated === -100) return false;
|
||||
return (
|
||||
!isEqual(oldChanges, newChanges) &&
|
||||
settingsQdnLastUpdated < settingsLocalLastUpdated
|
||||
);
|
||||
}, [
|
||||
oldPinnedApps,
|
||||
pinnedApps,
|
||||
settingsQdnLastUpdated,
|
||||
settingsLocalLastUpdated,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
setHasSettingsChangedAtom(hasChanged);
|
||||
}, [hasChanged]);
|
||||
|
||||
const saveToQdn = async () => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
const data64 = await objectToBase64({
|
||||
sortablePinnedApps: pinnedApps.map((item) => {
|
||||
return {
|
||||
name: item?.name,
|
||||
service: item?.service
|
||||
}
|
||||
})
|
||||
}
|
||||
const oldChanges = {
|
||||
sortablePinnedApps: oldPinnedApps.map((item)=> {
|
||||
return {
|
||||
name: item?.name,
|
||||
service: item?.service
|
||||
}
|
||||
})
|
||||
}
|
||||
if(settingsQdnLastUpdated === -100) return false
|
||||
return !isEqual(oldChanges, newChanges) && settingsQdnLastUpdated < settingsLocalLastUpdated
|
||||
}, [oldPinnedApps, pinnedApps, settingsQdnLastUpdated, settingsLocalLastUpdated])
|
||||
|
||||
useEffect(()=> {
|
||||
setHasSettingsChangedAtom(hasChanged)
|
||||
}, [hasChanged])
|
||||
|
||||
const saveToQdn = async ()=> {
|
||||
try {
|
||||
setIsLoading(true)
|
||||
const data64 = await objectToBase64({
|
||||
sortablePinnedApps: pinnedApps.map((item)=> {
|
||||
return {
|
||||
name: item?.name,
|
||||
service: item?.service
|
||||
}
|
||||
})
|
||||
})
|
||||
const encryptData = await new Promise((res, rej) => {
|
||||
chrome?.runtime?.sendMessage(
|
||||
service: item?.service,
|
||||
};
|
||||
}),
|
||||
});
|
||||
const encryptData = await new Promise((res, rej) => {
|
||||
window
|
||||
.sendMessage(
|
||||
"ENCRYPT_DATA",
|
||||
{
|
||||
action: "ENCRYPT_DATA",
|
||||
type: "qortalRequest",
|
||||
payload: {
|
||||
data64
|
||||
data64,
|
||||
},
|
||||
},
|
||||
(response) => {
|
||||
if (response.error) {
|
||||
rej(response?.message);
|
||||
return;
|
||||
} else {
|
||||
res(response);
|
||||
|
||||
}
|
||||
60000
|
||||
)
|
||||
.then((response) => {
|
||||
if (response.error) {
|
||||
rej(response?.message);
|
||||
return;
|
||||
} else {
|
||||
res(response);
|
||||
}
|
||||
);
|
||||
});
|
||||
if(encryptData && !encryptData?.error){
|
||||
const fee = await getFee('ARBITRARY')
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Failed qortalRequest", error);
|
||||
});
|
||||
});
|
||||
if (encryptData && !encryptData?.error) {
|
||||
const fee = await getFee("ARBITRARY");
|
||||
|
||||
await show({
|
||||
message: "Would you like to publish your settings to QDN (encrypted) ?" ,
|
||||
publishFee: fee.fee + ' QORT'
|
||||
})
|
||||
const response = await new Promise((res, rej) => {
|
||||
window.sendMessage("publishOnQDN", {
|
||||
data: encryptData,
|
||||
identifier: "ext_saved_settings",
|
||||
service: "DOCUMENT_PRIVATE",
|
||||
})
|
||||
await show({
|
||||
message:
|
||||
"Would you like to publish your settings to QDN (encrypted) ?",
|
||||
publishFee: fee.fee + " QORT",
|
||||
});
|
||||
const response = await new Promise((res, rej) => {
|
||||
window
|
||||
.sendMessage("publishOnQDN", {
|
||||
data: encryptData,
|
||||
identifier: "ext_saved_settings",
|
||||
service: "DOCUMENT_PRIVATE",
|
||||
})
|
||||
.then((response) => {
|
||||
if (!response?.error) {
|
||||
res(response);
|
||||
@@ -102,51 +126,67 @@ export const Save = ({isDesktop}) => {
|
||||
.catch((error) => {
|
||||
rej(error.message || "An error occurred");
|
||||
});
|
||||
|
||||
});
|
||||
if(response?.identifier){
|
||||
setOldPinnedApps(pinnedApps)
|
||||
setSettingsQdnLastUpdated(Date.now())
|
||||
setInfoSnack({
|
||||
type: "success",
|
||||
message:
|
||||
"Sucessfully published to QDN",
|
||||
});
|
||||
setOpenSnack(true);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
setInfoSnack({
|
||||
type: "error",
|
||||
message:
|
||||
error?.message || "Unable to save to QDN",
|
||||
});
|
||||
setOpenSnack(true);
|
||||
} finally {
|
||||
setIsLoading(false)
|
||||
if (response?.identifier) {
|
||||
setOldPinnedApps(pinnedApps);
|
||||
setSettingsQdnLastUpdated(Date.now());
|
||||
setInfoSnack({
|
||||
type: "success",
|
||||
message: "Sucessfully published to QDN",
|
||||
});
|
||||
setOpenSnack(true);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
setInfoSnack({
|
||||
type: "error",
|
||||
message: error?.message || "Unable to save to QDN",
|
||||
});
|
||||
setOpenSnack(true);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<ButtonBase onClick={saveToQdn} disabled={!hasChanged || !canSave || isLoading || settingsQdnLastUpdated === -100}>
|
||||
{isDesktop ? (
|
||||
<ButtonBase
|
||||
onClick={saveToQdn}
|
||||
disabled={
|
||||
!hasChanged ||
|
||||
!canSave ||
|
||||
isLoading ||
|
||||
settingsQdnLastUpdated === -100
|
||||
}
|
||||
>
|
||||
{isDesktop ? (
|
||||
<IconWrapper
|
||||
color="rgba(250, 250, 250, 0.5)"
|
||||
label="Save"
|
||||
selected={false}
|
||||
>
|
||||
<SaveIcon
|
||||
color={settingsQdnLastUpdated === -100 ? '#8F8F91' : (hasChanged && !isLoading) ? '#5EB049' : '#8F8F91'}
|
||||
/>
|
||||
color="rgba(250, 250, 250, 0.5)"
|
||||
label="Save"
|
||||
selected={false}
|
||||
>
|
||||
<SaveIcon
|
||||
color={
|
||||
settingsQdnLastUpdated === -100
|
||||
? "#8F8F91"
|
||||
: hasChanged && !isLoading
|
||||
? "#5EB049"
|
||||
: "#8F8F91"
|
||||
}
|
||||
/>
|
||||
</IconWrapper>
|
||||
) : (
|
||||
<SaveIcon
|
||||
color={settingsQdnLastUpdated === -100 ? '#8F8F91' : (hasChanged && !isLoading) ? '#5EB049' : '#8F8F91'}
|
||||
/>
|
||||
)}
|
||||
|
||||
) : (
|
||||
<SaveIcon
|
||||
color={
|
||||
settingsQdnLastUpdated === -100
|
||||
? "#8F8F91"
|
||||
: hasChanged && !isLoading
|
||||
? "#5EB049"
|
||||
: "#8F8F91"
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</ButtonBase>
|
||||
<CustomizedSnackbars
|
||||
<CustomizedSnackbars
|
||||
duration={3500}
|
||||
open={openSnack}
|
||||
setOpen={setOpenSnack}
|
||||
@@ -154,6 +194,5 @@ export const Save = ({isDesktop}) => {
|
||||
setInfo={setInfoSnack}
|
||||
/>
|
||||
</>
|
||||
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
Reference in New Issue
Block a user