From 141298cbec9f515bc8ba0ff7f61eabf90d43a87d Mon Sep 17 00:00:00 2001
From: PhilReact
Date: Fri, 13 Dec 2024 20:11:03 +0200
Subject: [PATCH 001/119] fix css
---
src/components/Group/Group.tsx | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/src/components/Group/Group.tsx b/src/components/Group/Group.tsx
index 9f9966b..f447786 100644
--- a/src/components/Group/Group.tsx
+++ b/src/components/Group/Group.tsx
@@ -157,6 +157,7 @@ export const getPublishesFromAdmins = async (admins: string[], groupId) => {
return dateB.getTime() - dateA.getTime();
});
+
return sortedData[0];
};
interface GroupProps {
@@ -242,6 +243,7 @@ export const getGroupMembers = async (groupNumber: number) => {
return groupData;
};
+
export const decryptResource = async (data: string) => {
try {
return new Promise((res, rej) => {
@@ -519,6 +521,8 @@ export const Group = ({
selectedDirectRef.current = selectedDirect;
}, [selectedDirect]);
+
+
const getUserSettings = async () => {
try {
return new Promise((res, rej) => {
@@ -753,8 +757,9 @@ export const Group = ({
if (
secretKeyToPublish &&
secretKey &&
- lastFetchedSecretKey.current &&
- Date.now() - lastFetchedSecretKey.current < 1800000
+ lastFetchedSecretKey.current
+ &&
+ Date.now() - lastFetchedSecretKey.current < 600000
)
return secretKey;
if (loadingGroupParam) {
@@ -2505,7 +2510,7 @@ export const Group = ({
style={{
display: "flex",
width: "100%",
- height: "100$",
+ height: "100%",
flexDirection: "column",
alignItems: "flex-start",
padding: "20px",
From 64ffe028690c9aff50c03e12305aa0724f82a191 Mon Sep 17 00:00:00 2001
From: PhilReact
Date: Sat, 14 Dec 2024 01:55:37 +0200
Subject: [PATCH 002/119] fix encryption single extra data
---
src/components/Chat/ChatDirect.tsx | 7 ++--
src/components/Chat/ChatGroup.tsx | 20 +++++++----
src/qdn/encryption/group-encryption.ts | 48 +++++++++++++++++++++++---
3 files changed, 60 insertions(+), 15 deletions(-)
diff --git a/src/components/Chat/ChatDirect.tsx b/src/components/Chat/ChatDirect.tsx
index cb40066..9b3dcbb 100644
--- a/src/components/Chat/ChatDirect.tsx
+++ b/src/components/Chat/ChatDirect.tsx
@@ -363,7 +363,7 @@ useEffect(() => {
const htmlContent = editorRef?.current.getHTML();
const stringified = JSON.stringify(htmlContent);
const size = new Blob([stringified]).size;
- setMessageSize(size + 100);
+ setMessageSize(size + 200);
};
// Add a listener for the editorRef?.current's content updates
@@ -646,12 +646,11 @@ useEffect(() => {
)}
-
{messageSize > 750 && (
{
)}
+
+
{
useEffect(() => {
if (!editorRef?.current) return;
- handleUpdateRef.current = throttle(() => {
+ handleUpdateRef.current = throttle(async () => {
+ try {
const htmlContent = editorRef.current.getHTML();
- const size = new TextEncoder().encode(htmlContent).length;
- setMessageSize(size + 100);
+ const message64 = await objectToBase64(JSON.stringify(htmlContent))
+ const secretKeyObject = await getSecretKey(false, true)
+ const encryptSingle = await encryptChatMessage(message64, secretKeyObject)
+ setMessageSize((encryptSingle?.length || 0) + 200);
+ } catch (error) {
+ // calc size error
+ }
}, 1200);
const currentEditor = editorRef.current;
@@ -822,13 +828,11 @@ const clearEditorContent = () => {
-
-
- {messageSize > 750 && (
+ {messageSize > 750 && (
{
)}
+
+
{
+export const encryptSingle = async ({ data64, secretKeyObject, typeNumber = 2 }: any) => {
// Find the highest key in the secretKeyObject
const highestKey = Math.max(...Object.keys(secretKeyObject).filter(item => !isNaN(+item)).map(Number));
const highestKeyObject = secretKeyObject[highestKey];
@@ -188,7 +188,22 @@ export const encryptSingle = async ({ data64, secretKeyObject, typeNumber = 1 }:
// Concatenate the highest key, type number, nonce, and encrypted data (new format)
const highestKeyStr = highestKey.toString().padStart(10, '0'); // Fixed length of 10 digits
- finalEncryptedData = btoa(highestKeyStr + typeNumberStr + nonceBase64 + encryptedDataBase64);
+
+ const highestKeyBytes = new TextEncoder().encode(highestKeyStr.padStart(10, '0'));
+const typeNumberBytes = new TextEncoder().encode(typeNumberStr.padStart(3, '0'));
+
+// Step 3: Concatenate all binary
+const combinedBinary = new Uint8Array(
+ highestKeyBytes.length + typeNumberBytes.length + nonce.length + encryptedData.length
+);
+ // finalEncryptedData = btoa(highestKeyStr) + btoa(typeNumberStr) + nonceBase64 + encryptedDataBase64;
+ combinedBinary.set(highestKeyBytes, 0);
+combinedBinary.set(typeNumberBytes, highestKeyBytes.length);
+combinedBinary.set(nonce, highestKeyBytes.length + typeNumberBytes.length);
+combinedBinary.set(encryptedData, highestKeyBytes.length + typeNumberBytes.length + nonce.length);
+
+// Step 4: Base64 encode once
+ finalEncryptedData = uint8ArrayToBase64(combinedBinary);
}
return finalEncryptedData;
@@ -214,10 +229,8 @@ export const decodeBase64ForUIChatMessages = (messages)=> {
}
return msgs
}
-
-
- export const decryptSingle = async ({ data64, secretKeyObject, skipDecodeBase64 }: any) => {
+export const decryptSingle = async ({ data64, secretKeyObject, skipDecodeBase64 }: any) => {
// First, decode the base64-encoded input (if skipDecodeBase64 is not set)
const decodedData = skipDecodeBase64 ? data64 : atob(data64);
@@ -249,6 +262,28 @@ export const decodeBase64ForUIChatMessages = (messages)=> {
encryptedDataBase64 = decodeForNumber.slice(10); // The remaining part is the encrypted data
} else {
if (hasTypeNumber) {
+ // const typeNumberStr = new TextDecoder().decode(typeNumberBytes);
+ if(decodeForNumber.slice(10, 13) === '002'){
+ const decodedBinary = base64ToUint8Array(decodedData);
+ const highestKeyBytes = decodedBinary.slice(0, 10); // if ASCII digits only
+ const highestKeyStr = new TextDecoder().decode(highestKeyBytes);
+
+const nonce = decodedBinary.slice(13, 13 + 24);
+const encryptedData = decodedBinary.slice(13 + 24);
+const highestKey = parseInt(highestKeyStr, 10);
+
+const messageKey = base64ToUint8Array(secretKeyObject[+highestKey].messageKey);
+const decryptedBytes = nacl.secretbox.open(encryptedData, nonce, messageKey);
+
+ // Check if decryption was successful
+ if (!decryptedBytes) {
+ throw new Error("Decryption failed");
+ }
+
+ // Convert the decrypted Uint8Array back to a Base64 string
+ return uint8ArrayToBase64(decryptedBytes);
+
+ }
// New format: Extract type number and nonce
typeNumberStr = possibleTypeNumberStr; // Extract type number
nonceBase64 = decodeForNumber.slice(13, 45); // Extract nonce (next 32 characters after type number)
@@ -280,6 +315,9 @@ export const decodeBase64ForUIChatMessages = (messages)=> {
// Convert the decrypted Uint8Array back to a Base64 string
return uint8ArrayToBase64(decryptedData);
};
+
+
+
export const decryptGroupEncryptionWithSharingKey = async ({ data64EncryptedData, key }: any) => {
From 1da9fb161e6ac8ebcb72a255b407deed636b4bac Mon Sep 17 00:00:00 2001
From: PhilReact
Date: Sat, 14 Dec 2024 14:13:36 +0200
Subject: [PATCH 003/119] accept decline colors
---
src/App-styles.ts | 41 +++++++++++++++++++++++++++++++++++++++++
src/App.tsx | 42 +++++++++++++++++++++++++++++++++---------
src/index.css | 3 ++-
3 files changed, 76 insertions(+), 10 deletions(-)
diff --git a/src/App-styles.ts b/src/App-styles.ts
index bf3a146..08773ea 100644
--- a/src/App-styles.ts
+++ b/src/App-styles.ts
@@ -136,6 +136,47 @@ border-radius: 5px;
}
}
`;
+interface CustomButtonProps {
+ bgColor?: string;
+ color?: string;
+}
+export const CustomButtonAccept = styled(Box)(
+ ({ bgColor, color }) => ({
+ boxSizing: "border-box",
+ padding: "15px 20px",
+ gap: "10px",
+ border: "0.5px solid rgba(255, 255, 255, 0.5)",
+ filter: "drop-shadow(1px 4px 10.5px rgba(0,0,0,0.3))",
+ borderRadius: 5,
+ display: "inline-flex",
+ justifyContent: "center",
+ alignItems: "center",
+ width: "fit-content",
+ transition: "all 0.2s",
+ minWidth: 160,
+ cursor: "pointer",
+ fontWeight: 600,
+ fontFamily: "Inter",
+ textAlign: "center",
+ opacity: 0.7,
+ // Use the passed-in props or fallback defaults
+ backgroundColor: bgColor || "transparent",
+ color: color || "white",
+
+ "&:hover": {
+ opacity: 1,
+ backgroundColor: bgColor
+ ? bgColor
+ : "rgba(41, 41, 43, 1)", // fallback hover bg
+ color: color || "white",
+ svg: {
+ path: {
+ fill: color || "white",
+ },
+ },
+ },
+ })
+);
export const CustomInput = styled(TextField)({
diff --git a/src/App.tsx b/src/App.tsx
index 77d2585..3a7339c 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -62,6 +62,7 @@ import {
AuthenticatedContainerInnerLeft,
AuthenticatedContainerInnerRight,
CustomButton,
+ CustomButtonAccept,
CustomInput,
CustomLabel,
TextItalic,
@@ -318,7 +319,7 @@ function App() {
useState("");
const [isMain, setIsMain] = useState(true);
const isMainRef = useRef(false);
- const [authenticatePassword, setAuthenticatePassword] = useState("");
+ const [authenticatePassword, setAuthenticatePassword] = useState("1234567890");
const [sendqortState, setSendqortState] = useState(null);
const [isLoading, setIsLoading] = useState(false);
const [
@@ -2683,11 +2684,30 @@ function App() {
-
@@ -2966,22 +2986,26 @@ function App() {
gap: "14px",
}}
>
- onOkQortalRequestExtension("accepted")}
>
accept
-
-
+ onCancelQortalRequestExtension()}
>
decline
-
+
{sendPaymentError}
diff --git a/src/index.css b/src/index.css
index 7db06e7..a9946c7 100644
--- a/src/index.css
+++ b/src/index.css
@@ -35,7 +35,8 @@
--bg-2: #27282c;
--bg-3: rgba(0, 0, 0, 0.1);
--unread: #B14646;
- --apps-circle: #1F2023
+ --apps-circle: #1F2023;
+ --green: #5EB049;
}
body {
From dc7e0db0d8bebf6694c7e5a77d6b8132b77c7fc7 Mon Sep 17 00:00:00 2001
From: PhilReact
Date: Sat, 14 Dec 2024 18:06:40 +0200
Subject: [PATCH 004/119] fix new message send stay bottom
---
src/MessageQueueContext.tsx | 50 ++++++++++++++++++------------
src/components/Chat/ChatDirect.tsx | 6 ++--
src/components/Chat/ChatGroup.tsx | 6 ++--
src/components/Chat/ChatList.tsx | 3 +-
4 files changed, 37 insertions(+), 28 deletions(-)
diff --git a/src/MessageQueueContext.tsx b/src/MessageQueueContext.tsx
index 3727b03..7104520 100644
--- a/src/MessageQueueContext.tsx
+++ b/src/MessageQueueContext.tsx
@@ -92,21 +92,6 @@ export const MessageQueueProvider = ({ children }) => {
// Remove the message from the queue after successful sending
messageQueueRef.current.shift();
- // Remove the message from queueChats
- setQueueChats((prev) => {
- const updatedChats = { ...prev };
- if (updatedChats[groupDirectId]) {
- updatedChats[groupDirectId] = updatedChats[groupDirectId].filter(
- (item) => item.identifier !== identifier
- );
-
- // If no more chats for this group, delete the groupDirectId entry
- if (updatedChats[groupDirectId].length === 0) {
- delete updatedChats[groupDirectId];
- }
- }
- return updatedChats;
- });
} catch (error) {
console.error('Message sending failed', error);
@@ -142,15 +127,25 @@ export const MessageQueueProvider = ({ children }) => {
// Method to process with new messages and groupDirectId
const processWithNewMessages = (newMessages, groupDirectId) => {
+ let updatedNewMessages = newMessages
if (newMessages.length > 0) {
- messageQueueRef.current = messageQueueRef.current.filter((msg) => {
- return !newMessages.some(newMsg => newMsg?.specialId === msg?.specialId);
- });
-
// Remove corresponding entries in queueChats for the provided groupDirectId
setQueueChats((prev) => {
const updatedChats = { ...prev };
if (updatedChats[groupDirectId]) {
+
+ updatedNewMessages = newMessages?.map((msg)=> {
+ const findTempMsg = updatedChats[groupDirectId]?.find((msg2)=> msg2?.message?.specialId === msg?.specialId)
+ if(findTempMsg){
+ return {
+ ...msg,
+ tempSignature: findTempMsg?.signature
+ }
+ }
+ return msg
+ })
+
+
updatedChats[groupDirectId] = updatedChats[groupDirectId].filter((chat) => {
return !newMessages.some(newMsg => newMsg?.specialId === chat?.message?.specialId);
});
@@ -167,8 +162,23 @@ export const MessageQueueProvider = ({ children }) => {
}
return updatedChats;
});
+
}
-
+ setTimeout(() => {
+ if(!messageQueueRef.current.find((msg) => msg?.groupDirectId === groupDirectId)){
+ setQueueChats((prev) => {
+ const updatedChats = { ...prev };
+ if (updatedChats[groupDirectId]) {
+ delete updatedChats[groupDirectId]
+ }
+
+ return updatedChats
+ }
+ )
+ }
+ }, 300);
+
+ return updatedNewMessages
};
return (
diff --git a/src/components/Chat/ChatDirect.tsx b/src/components/Chat/ChatDirect.tsx
index 9b3dcbb..5e2014e 100644
--- a/src/components/Chat/ChatDirect.tsx
+++ b/src/components/Chat/ChatDirect.tsx
@@ -118,9 +118,9 @@ export const ChatDirect = ({ myAddress, isNewChat, selectedDirect, setSelectedDi
data: encryptedMessages,
involvingAddress: selectedDirect?.address,
})
- .then((response) => {
- if (!response?.error) {
- processWithNewMessages(response, selectedDirect?.address);
+ .then((decryptResponse) => {
+ if (!decryptResponse?.error) {
+ const response = processWithNewMessages(decryptResponse, selectedDirect?.address);
res(response);
if (isInitiated) {
diff --git a/src/components/Chat/ChatGroup.tsx b/src/components/Chat/ChatGroup.tsx
index 4aed230..02523a9 100644
--- a/src/components/Chat/ChatGroup.tsx
+++ b/src/components/Chat/ChatGroup.tsx
@@ -193,9 +193,9 @@ const [messageSize, setMessageSize] = useState(0)
const filterUIMessages = encryptedMessages.filter((item) => !isExtMsg(item.data));
const decodedUIMessages = decodeBase64ForUIChatMessages(filterUIMessages);
- const combineUIAndExtensionMsgs = [...decodedUIMessages, ...response];
- processWithNewMessages(
- combineUIAndExtensionMsgs.map((item) => ({
+ const combineUIAndExtensionMsgsBefore = [...decodedUIMessages, ...response];
+ const combineUIAndExtensionMsgs = processWithNewMessages(
+ combineUIAndExtensionMsgsBefore.map((item) => ({
...item,
...(item?.decryptedData || {}),
})),
diff --git a/src/components/Chat/ChatList.tsx b/src/components/Chat/ChatList.tsx
index 3cae591..67a05f7 100644
--- a/src/components/Chat/ChatList.tsx
+++ b/src/components/Chat/ChatList.tsx
@@ -39,11 +39,10 @@ export const ChatList = ({
const scrollingIntervalRef = useRef(null);
const lastSeenUnreadMessageTimestamp = useRef(null);
-
// Initialize the virtualizer
const rowVirtualizer = useVirtualizer({
count: messages.length,
- getItemKey: (index) => messages[index].signature,
+ getItemKey: (index) => messages[index]?.tempSignature || messages[index].signature,
getScrollElement: () => parentRef?.current,
estimateSize: useCallback(() => 80, []), // Provide an estimated height of items, adjust this as needed
overscan: 10, // Number of items to render outside the visible area to improve smoothness
From b7ca08b00867fccf1c9abb94966532170fc0a1a4 Mon Sep 17 00:00:00 2001
From: PhilReact
Date: Sat, 14 Dec 2024 18:28:00 +0200
Subject: [PATCH 005/119] added 'all' category for qapps
---
src/components/Apps/AppInfoSnippet.tsx | 6 ++-
src/components/Apps/AppsCategoryDesktop.tsx | 12 ++++--
src/components/Apps/AppsLibraryDesktop.tsx | 43 ++++++++++++++++++---
3 files changed, 50 insertions(+), 11 deletions(-)
diff --git a/src/components/Apps/AppInfoSnippet.tsx b/src/components/Apps/AppInfoSnippet.tsx
index 01a7083..f141222 100644
--- a/src/components/Apps/AppInfoSnippet.tsx
+++ b/src/components/Apps/AppInfoSnippet.tsx
@@ -22,7 +22,7 @@ import { useRecoilState, useSetRecoilState } from "recoil";
import { settingsLocalLastUpdatedAtom, sortablePinnedAppsAtom } from "../../atoms/global";
import { saveToLocalStorage } from "./AppsNavBar";
-export const AppInfoSnippet = ({ app, myName, isFromCategory }) => {
+export const AppInfoSnippet = ({ app, myName, isFromCategory, parentStyles = {} }) => {
const isInstalled = app?.status?.status === 'READY'
const [sortablePinnedApps, setSortablePinnedApps] = useRecoilState(sortablePinnedAppsAtom);
@@ -30,7 +30,9 @@ export const AppInfoSnippet = ({ app, myName, isFromCategory }) => {
const isSelectedAppPinned = !!sortablePinnedApps?.find((item)=> item?.name === app?.name && item?.service === app?.service)
const setSettingsLocalLastUpdated = useSetRecoilState(settingsLocalLastUpdatedAtom);
return (
-
+
{
+ if(category?.id === 'all') return availableQapps
return availableQapps.filter(
(app) => app?.metadata?.category === category?.id
);
@@ -133,6 +134,9 @@ export const AppsCategoryDesktop = ({
app={app}
myName={myName}
isFromCategory={true}
+ parentStyles={{
+ padding: '0px 10px'
+ }}
/>
);
};
@@ -206,7 +210,7 @@ export const AppsCategoryDesktop = ({
diff --git a/src/components/Apps/AppsLibraryDesktop.tsx b/src/components/Apps/AppsLibraryDesktop.tsx
index 9756d1b..aae46a5 100644
--- a/src/components/Apps/AppsLibraryDesktop.tsx
+++ b/src/components/Apps/AppsLibraryDesktop.tsx
@@ -24,7 +24,7 @@ import {
PublishQAppCTARight,
PublishQAppDotsBG,
} from "./Apps-styles";
-import { Avatar, Box, ButtonBase, InputBase, styled } from "@mui/material";
+import { Avatar, Box, ButtonBase, InputBase, Typography, styled } from "@mui/material";
import { Add } from "@mui/icons-material";
import { MyContext, getBaseApiReact } from "../../App";
import LogoSelected from "../../assets/svgs/LogoSelected.svg";
@@ -145,6 +145,9 @@ export const AppsLibraryDesktop = ({
key={`${app?.service}-${app?.name}`}
app={app}
myName={myName}
+ parentStyles={{
+ padding: '0px 10px'
+ }}
/>
);
};
@@ -261,7 +264,7 @@ export const AppsLibraryDesktop = ({
+ ) : searchedList?.length === 0 && debouncedValue ? (
+
+ No results
+
) : (
<>
+ {
+ executeEvent("selectedCategory", {
+ data: {
+ id: 'all',
+ name: 'All'
+ },
+ });
+ }}
+ >
+
+ All
+
+
{categories?.map((category) => {
return (
Date: Sat, 14 Dec 2024 19:26:35 +0200
Subject: [PATCH 006/119] re-arrange acct creation
---
src/App.tsx | 119 ++++++++++++++++++--
src/components/Apps/AppsCategoryDesktop.tsx | 9 +-
src/components/Apps/AppsLibraryDesktop.tsx | 8 +-
3 files changed, 120 insertions(+), 16 deletions(-)
diff --git a/src/App.tsx b/src/App.tsx
index 3a7339c..353289d 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -354,7 +354,7 @@ function App() {
show: showInfo,
message: messageInfo,
} = useModal();
-
+
const {
onCancel: onCancelQortalRequest,
onOk: onOkQortalRequest,
@@ -383,6 +383,9 @@ function App() {
const [isOpenSendQortSuccess, setIsOpenSendQortSuccess] = useState(false);
const [rootHeight, setRootHeight] = useState("100%");
const [isSettingsOpen, setIsSettingsOpen] = useState(false);
+ const [showSeed, setShowSeed] = useState(false)
+ const [creationStep, setCreationStep] = useState(1)
+
const qortalRequestCheckbox1Ref = useRef(null);
useRetrieveDataLocalStorage();
useQortalGetSaveSettings(userInfo?.name);
@@ -998,6 +1001,8 @@ function App() {
setCountdown(null);
setWalletToBeDownloaded(null);
setWalletToBeDownloadedPassword("");
+ setShowSeed(false)
+ setCreationStep(1)
setExtstate("authenticated");
setIsOpenSendQort(false);
setIsOpenSendQortSuccess(false);
@@ -1023,6 +1028,9 @@ function App() {
setCountdown(null);
setWalletToBeDownloaded(null);
setWalletToBeDownloadedPassword("");
+ setShowSeed(false)
+ setCreationStep(1)
+
setWalletToBeDownloadedPasswordConfirm("");
setWalletToBeDownloadedError("");
setSendqortState(null);
@@ -2397,6 +2405,7 @@ function App() {
value={walletToBeDownloadedPassword}
onChange={(e) =>
setWalletToBeDownloadedPassword(e.target.value)
+
}
/>
@@ -2442,7 +2451,15 @@ function App() {
cursor: "pointer",
}}
onClick={() => {
+ if(creationStep === 2){
+ setCreationStep(1)
+ return
+ }
setExtstate("not-authenticated");
+ setShowSeed(false)
+ setCreationStep(1)
+ setWalletToBeDownloadedPasswordConfirm('')
+ setWalletToBeDownloadedPassword('')
}}
src={Return}
/>
@@ -2474,33 +2491,110 @@ function App() {
justifyContent: 'center',
padding: '10px'
}}>
-
Your seedphrase
- Only shown once! Please copy and keep safe!
+ }}>
+ A ‘ {
+ setShowSeed(true)
+ }} style={{
+ fontSize: '14px',
+ color: 'steelblue',
+ cursor: 'pointer'
+ }}>SEEDPHRASE ’ has been randomly generated in the background.
-
+
+ If you wish to VIEW THE SEEDPHRASE, click the word 'SEEDPHRASE' in this text. Seedphrases are used to generate the private key for your Qortal account. For security by default, seedphrases are NOT displayed unless specifically chosen.
+
+
+ Create your Qortal account by clicking NEXT below.
+
+
+
+ {
+ setCreationStep(2)
+ }}>
+ Next
+
+
+
+
+
+
+
+
+
Wallet Password
@@ -2530,6 +2624,7 @@ function App() {
Create Account
+
{walletToBeDownloadedError}
>
)}
diff --git a/src/components/Apps/AppsCategoryDesktop.tsx b/src/components/Apps/AppsCategoryDesktop.tsx
index 4c4e334..ab4fef1 100644
--- a/src/components/Apps/AppsCategoryDesktop.tsx
+++ b/src/components/Apps/AppsCategoryDesktop.tsx
@@ -109,8 +109,13 @@ export const AppsCategoryDesktop = ({
useEffect(() => {
const handler = setTimeout(() => {
setDebouncedValue(searchValue);
+
}, 350);
-
+ setTimeout(() => {
+ virtuosoRef.current.scrollToIndex({
+ index: 0
+ });
+ }, 500);
// Cleanup timeout if searchValue changes before the timeout completes
return () => {
clearTimeout(handler);
@@ -122,7 +127,7 @@ export const AppsCategoryDesktop = ({
const searchedList = useMemo(() => {
if (!debouncedValue) return categoryList;
return categoryList.filter((app) =>
- app.name.toLowerCase().includes(debouncedValue.toLowerCase())
+ app.name.toLowerCase().includes(debouncedValue.toLowerCase()) || (app?.metadata?.title && app?.metadata?.title?.toLowerCase().includes(debouncedValue.toLowerCase()))
);
}, [debouncedValue, categoryList]);
diff --git a/src/components/Apps/AppsLibraryDesktop.tsx b/src/components/Apps/AppsLibraryDesktop.tsx
index aae46a5..08bf50b 100644
--- a/src/components/Apps/AppsLibraryDesktop.tsx
+++ b/src/components/Apps/AppsLibraryDesktop.tsx
@@ -122,7 +122,11 @@ export const AppsLibraryDesktop = ({
const handler = setTimeout(() => {
setDebouncedValue(searchValue);
}, 350);
-
+ setTimeout(() => {
+ virtuosoRef.current.scrollToIndex({
+ index: 0
+ });
+ }, 500);
// Cleanup timeout if searchValue changes before the timeout completes
return () => {
clearTimeout(handler);
@@ -134,7 +138,7 @@ export const AppsLibraryDesktop = ({
const searchedList = useMemo(() => {
if (!debouncedValue) return [];
return availableQapps.filter((app) =>
- app.name.toLowerCase().includes(debouncedValue.toLowerCase())
+ app.name.toLowerCase().includes(debouncedValue.toLowerCase()) || (app?.metadata?.title && app?.metadata?.title?.toLowerCase().includes(debouncedValue.toLowerCase()))
);
}, [debouncedValue]);
From 46e3d9bcaca1d0c28f36d732a9fc86167b6ddaec Mon Sep 17 00:00:00 2001
From: PhilReact
Date: Sat, 14 Dec 2024 20:31:16 +0200
Subject: [PATCH 007/119] remove unused code group
---
src/components/Group/Group.tsx | 498 ++-------------------------------
1 file changed, 22 insertions(+), 476 deletions(-)
diff --git a/src/components/Group/Group.tsx b/src/components/Group/Group.tsx
index f447786..d3d5b02 100644
--- a/src/components/Group/Group.tsx
+++ b/src/components/Group/Group.tsx
@@ -1,10 +1,7 @@
import {
Avatar,
Box,
- Button,
ButtonBase,
- Grid,
- IconButton,
List,
ListItem,
ListItemAvatar,
@@ -12,36 +9,27 @@ import {
Typography,
} from "@mui/material";
import React, {
- useCallback,
useContext,
useEffect,
useMemo,
useRef,
useState,
} from "react";
-import SettingsIcon from "@mui/icons-material/Settings";
import { ChatGroup } from "../Chat/ChatGroup";
import { CreateCommonSecret } from "../Chat/CreateCommonSecret";
import { base64ToUint8Array } from "../../qdn/encryption/group-encryption";
import { uint8ArrayToObject } from "../../backgroundFunctions/encryption";
-import ChatIcon from "@mui/icons-material/Chat";
import CampaignIcon from "@mui/icons-material/Campaign";
import { AddGroup } from "./AddGroup";
-import MarkUnreadChatAltIcon from "@mui/icons-material/MarkUnreadChatAlt";
import AddCircleOutlineIcon from "@mui/icons-material/AddCircleOutline";
import CreateIcon from "@mui/icons-material/Create";
-import RefreshIcon from "@mui/icons-material/Refresh";
-import AnnouncementsIcon from "@mui/icons-material/Notifications";
-import GroupIcon from "@mui/icons-material/Group";
-import PersonIcon from "@mui/icons-material/Person";
+
import {
AuthenticatedContainerInnerRight,
CustomButton,
} from "../../App-styles";
-import ForumIcon from "@mui/icons-material/Forum";
import { Spacer } from "../../common/Spacer";
-import PeopleIcon from "@mui/icons-material/People";
import { ManageMembers } from "./ManageMembers";
import MarkChatUnreadIcon from "@mui/icons-material/MarkChatUnread";
import {
@@ -58,38 +46,26 @@ import { CustomizedSnackbars } from "../Snackbar/Snackbar";
import { LoadingButton } from "@mui/lab";
import { LoadingSnackbar } from "../Snackbar/LoadingSnackbar";
import { GroupAnnouncements } from "../Chat/GroupAnnouncements";
-import HomeIcon from "@mui/icons-material/Home";
-import CloseIcon from "@mui/icons-material/Close";
-import { ThingsToDoInitial } from "./ThingsToDoInitial";
-import { GroupJoinRequests } from "./GroupJoinRequests";
+
+
import { GroupForum } from "../Chat/GroupForum";
-import { GroupInvites } from "./GroupInvites";
import {
executeEvent,
subscribeToEvent,
unsubscribeFromEvent,
} from "../../utils/events";
-import { ListOfThreadPostsWatched } from "./ListOfThreadPostsWatched";
import { RequestQueueWithPromise } from "../../utils/queue/queue";
import { WebSocketActive } from "./WebsocketActive";
-import { flushSync } from "react-dom";
import { useMessageQueue } from "../../MessageQueueContext";
-import { DrawerComponent } from "../Drawer/Drawer";
import { isExtMsg, isUpdateMsg } from "../../background";
import { ContextMenu } from "../ContextMenu";
-import { MobileFooter } from "../Mobile/MobileFooter";
-import Header from "../Mobile/MobileHeader";
-import { Home } from "./Home";
-import { GroupMenu } from "./GroupMenu";
-import { getRootHeight } from "../../utils/mobile/mobileUtils";
+
import { ReturnIcon } from "../../assets/Icons/ReturnIcon";
import { ExitIcon } from "../../assets/Icons/ExitIcon";
import { HomeDesktop } from "./HomeDesktop";
-import { DesktopFooter, IconWrapper } from "../Desktop/DesktopFooter";
+import { IconWrapper } from "../Desktop/DesktopFooter";
import { DesktopHeader } from "../Desktop/DesktopHeader";
-import { Apps } from "../Apps/Apps";
-import { AppsNavBar } from "../Apps/AppsNavBar";
import { AppsDesktop } from "../Apps/AppsDesktop";
import { AppsDevMode } from "../Apps/AppsDevMode";
import { DesktopSideBar } from "../DesktopSideBar";
@@ -101,36 +77,11 @@ import { useSetRecoilState } from "recoil";
import { selectedGroupIdAtom } from "../../atoms/global";
import { sortArrayByTimestampAndGroupName } from "../../utils/time";
-// let touchStartY = 0;
-// let disablePullToRefresh = false;
-// // Detect when the user touches the screen
-// window.addEventListener('touchstart', function(event) {
-// if (event.touches.length !== 1) return; // Ignore multi-touch events
-// touchStartY = event.touches[0].clientY;
-// disablePullToRefresh = window.scrollY === 0; // Only disable if at the top
-// });
-// // Detect when the user moves their finger on the screen
-// window.addEventListener('touchmove', function(event) {
-// let touchY = event.touches[0].clientY;
-
-// // If pulling down from the top of the page, prevent the default behavior
-// if (disablePullToRefresh && touchY > touchStartY) {
-// event.preventDefault();
-// }
-// });
-
-const isWithinLast15Minutes = (timestamp) => {
- const now = Date.now(); // Current timestamp in milliseconds
- const fifteenMinutes = 15 * 60 * 1000; // 15 minutes in milliseconds
-
- return now - timestamp < fifteenMinutes;
-};
export const getPublishesFromAdmins = async (admins: string[], groupId) => {
- // const validApi = await findUsableApi();
const queryString = admins.map((name) => `name=${name}`).join("&");
const url = `${getBaseApiReact()}${getArbitraryEndpointReact()}?mode=ALL&service=DOCUMENT_PRIVATE&identifier=symmetric-qchat-group-${
groupId
@@ -163,7 +114,6 @@ export const getPublishesFromAdmins = async (admins: string[], groupId) => {
interface GroupProps {
myAddress: string;
isFocused: boolean;
- isMain: boolean;
userInfo: any;
balance: number;
}
@@ -331,16 +281,7 @@ export const getGroupAdmins = async (groupNumber: number) => {
let members: any = [];
let membersAddresses = [];
let both = [];
- // if (groupData && Array.isArray(groupData?.members)) {
- // for (const member of groupData.members) {
- // if (member.member) {
- // const name = await getNameInfo(member.member);
- // if (name) {
- // members.push(name);
- // }
- // }
- // }
- // }
+
const getMemNames = groupData?.members?.map(async (member) => {
if (member?.member) {
@@ -386,17 +327,9 @@ export const getNames = async (listOfMembers) => {
return members;
};
export const getNamesForAdmins = async (admins) => {
- // const validApi = await findUsableApi();
let members: any = [];
- // if (admins && Array.isArray(admins)) {
- // for (const admin of admins) {
- // const name = await getNameInfo(admin);
- // if (name) {
- // members.push({ address: admin, name });
- // }
- // }
- // }
+
const getMemNames = admins?.map(async (admin) => {
if (admin) {
const name = await requestQueueAdminMemberNames.enqueue(() => {
@@ -417,12 +350,9 @@ export const getNamesForAdmins = async (admins) => {
export const Group = ({
myAddress,
isFocused,
- isMain,
userInfo,
balance,
- isOpenDrawerProfile,
setIsOpenDrawerProfile,
- logoutFunc,
setDesktopViewMode,
desktopViewMode
}: GroupProps) => {
@@ -450,7 +380,7 @@ export const Group = ({
const [openAddGroup, setOpenAddGroup] = useState(false);
const [isInitialGroups, setIsInitialGroups] = useState(false);
const [openManageMembers, setOpenManageMembers] = useState(false);
- const { setMemberGroups, memberGroups, rootHeight } = useContext(MyContext);
+ const { setMemberGroups, rootHeight } = useContext(MyContext);
const lastGroupNotification = useRef(null);
const [timestampEnterData, setTimestampEnterData] = useState({});
const [chatMode, setChatMode] = useState("groups");
@@ -570,28 +500,7 @@ export const Group = ({
});
} catch (error) {}
};
- const getGroupDataSingle = async (groupId) => {
- try {
- return new Promise((res, rej) => {
- window.sendMessage("getGroupDataSingle", {
- groupId,
- })
- .then((response) => {
- if (!response?.error) {
- res(response);
- return;
- }
- rej(response.error);
- })
- .catch((error) => {
- rej(error.message || "An error occurred");
- });
-
- });
- } catch (error) {
- return {};
- }
- };
+
const refreshHomeDataFunc = () => {
setGroupSection("default");
setTimeout(() => {
@@ -633,43 +542,8 @@ export const Group = ({
} catch (error) {}
};
- const checkGroupList = React.useCallback(async (address) => {
- try {
- const url = `${getBaseApiReact()}/chat/active/${address}`;
- const response = await fetch(url, {
- method: "GET",
- headers: {
- "Content-Type": "application/json",
- },
- });
- const responseData = await response.json();
- if (!Array.isArray(responseData?.groups)) return;
- const filterOutGeneral = responseData.groups?.filter(
- (item) => item?.groupId !== 0
- );
- const sortedGroups = filterOutGeneral.sort((a, b) => {
- // If a has no timestamp, move it down
- if (!a.timestamp) return 1;
- // If b has no timestamp, move it up
- if (!b.timestamp) return -1;
- // Otherwise, sort by timestamp in descending order (most recent first)
- return b.timestamp - a.timestamp;
- });
- setGroups(sortedGroups);
- setMemberGroups(sortedGroups);
- } catch (error) {
- } finally {
- }
- }, []);
- // const checkGroupListFunc = useCallback((myAddress) => {
- // let isCalling = false;
- // checkGroupInterval.current = setInterval(async () => {
- // if (isCalling) return;
- // isCalling = true;
- // const res = await checkGroupList(myAddress);
- // isCalling = false;
- // }, 120000);
- // }, []);
+
+
const directChatHasUnread = useMemo(() => {
let hasUnread = false;
@@ -721,15 +595,7 @@ export const Group = ({
return hasUnread;
}, [groupAnnouncements, groups]);
- // useEffect(() => {
- // if (!myAddress) return;
- // checkGroupListFunc(myAddress);
- // return () => {
- // if (checkGroupInterval?.current) {
- // clearInterval(checkGroupInterval.current);
- // }
- // };
- // }, [checkGroupListFunc, myAddress]);
+
const getSecretKey = async (
@@ -738,22 +604,10 @@ export const Group = ({
) => {
try {
setIsLoadingGroupMessage("Locating encryption keys");
- // setGroupDataLastSet(null)
pauseAllQueues();
let dataFromStorage;
let publishFromStorage;
let adminsFromStorage;
- // const groupData = await getGroupDataSingle(selectedGroup?.groupId);
- // if (
- // groupData?.secretKeyData &&
- // Date.now() - groupData?.timestampLastSet < 3600000
- // ) {
- // dataFromStorage = groupData.secretKeyData;
- // publishFromStorage = groupData.secretKeyResource;
- // adminsFromStorage = groupData.admins;
- // // setGroupDataLastSet(groupData.timestampLastSet)
- // }
-
if (
secretKeyToPublish &&
secretKey &&
@@ -844,9 +698,6 @@ export const Group = ({
} finally {
setIsLoadingGroup(false);
setIsLoadingGroupMessage("");
- if (!secretKeyToPublish) {
- // await getAdmins(selectedGroup?.groupId);
- }
resumeAllQueues();
}
};
@@ -864,14 +715,7 @@ export const Group = ({
- const getAdmins = async (groupId) => {
- try {
- const res = await getGroupAdminsAddress(groupId);
- setAdmins(res);
- const adminsWithNames = await getNamesForAdmins(res);
- setAdminsWithNames(adminsWithNames);
- } catch (error) {}
- };
+
const getCountNewMesg = async (groupId, after)=> {
try {
@@ -1133,9 +977,7 @@ export const Group = ({
} else {
setMobileViewModeKeepOpen("messaging");
}
- // setChatMode("directs");
setSelectedDirect(null);
- // setSelectedGroup(null);
setNewChat(false);
@@ -1171,7 +1013,6 @@ export const Group = ({
setMobileViewModeKeepOpen("messaging");
}
setSelectedDirect(null);
- // setSelectedGroup(null);
setNewChat(false);
@@ -1485,11 +1326,7 @@ export const Group = ({
if (findGroup?.groupId === selectedGroup?.groupId) {
setGroupSection("forum");
setDefaultThread(data);
- // setTimeout(() => {
- // executeEvent("setThreadByEvent", {
- // data: data
- // });
- // }, 400);
+
return;
}
if (findGroup) {
@@ -1541,31 +1378,13 @@ export const Group = ({
}
setDesktopViewMode('home')
- // setGroupSection("default");
- // clearAllQueues();
+
await new Promise((res) => {
setTimeout(() => {
res(null);
}, 200);
});
- // setGroupSection("home");
- // setSelectedGroup(null);
- // setNewChat(false);
- // setSelectedDirect(null);
- // setSecretKey(null);
- // setGroupOwner(null)
- // lastFetchedSecretKey.current = null;
- // initiatedGetMembers.current = false;
- // setSecretKeyPublishDate(null);
- // setAdmins([]);
- // setSecretKeyDetails(null);
- // setAdminsWithNames([]);
- // setMembers([]);
- // setMemberCountFromSecretKeyData(null);
- // setTriedToFetchSecretKey(false);
- // setFirstSecretKeyInCreation(false);
- // setIsOpenSideViewDirects(false)
- // setIsOpenSideViewGroups(false)
+
};
const goToAnnouncements = async () => {
@@ -1701,54 +1520,6 @@ export const Group = ({
)}
- {isMobile && (
-
-
-
-
-
-
-
- {
- setMobileViewModeKeepOpen('')
- }}
- >
-
-
-
-
-
- )}
{directs.map((direct: any) => (
@@ -1771,15 +1539,9 @@ export const Group = ({
dense={true}
>
- //
- //
- // }
onClick={() => {
setSelectedDirect(null);
setNewChat(false);
- // setSelectedGroup(null);
setIsOpenDrawer(false);
window.sendMessage("addTimestampEnterChat", {
timestamp: Date.now(),
@@ -1820,7 +1582,6 @@ export const Group = ({
color: "white",
}}
alt={direct?.name || direct?.address}
- // src={`${getBaseApiReact()}/arbitrary/THUMBNAIL/${groupOwner?.name}/qortal_group_avatar_${group.groupId}?async=true`}
>
{(direct?.name || direct?.address)?.charAt(0)}
@@ -1881,7 +1642,6 @@ export const Group = ({
onClick={() => {
setNewChat(true);
setSelectedDirect(null);
- // setSelectedGroup(null);
setIsOpenDrawer(false);
}}
>
@@ -1993,11 +1753,6 @@ export const Group = ({
dense={true}
>
- //
- //
- // }
onClick={() => {
setMobileViewMode("group");
setDesktopSideView('groups')
@@ -2018,28 +1773,12 @@ export const Group = ({
setMemberCountFromSecretKeyData(null);
setHideCommonKeyPopup(false);
setFirstSecretKeyInCreation(false);
- // setGroupSection("announcement");
setGroupSection("chat");
setIsOpenDrawer(false);
setTimeout(() => {
setSelectedGroup(group);
- // getTimestampEnterChat();
}, 200);
-
- // window.sendMessage("addTimestampEnterChat", {
- // timestamp: Date.now(),
- // groupId: group.groupId,
- // }).catch((error) => {
- // console.error("Failed to add timestamp:", error.message || "An error occurred");
- // });
-
-
- // setTimeout(() => {
- // getTimestampEnterChat();
- // }, 200);
-
-
}}
sx={{
display: "flex",
@@ -2072,7 +1811,6 @@ export const Group = ({
color: "white",
}}
alt={group?.groupName}
- // src={`${getBaseApiReact()}/arbitrary/THUMBNAIL/${groupOwner?.name}/qortal_group_avatar_${group.groupId}?async=true`}
>
{group.groupName?.charAt(0)}
@@ -2158,7 +1896,6 @@ export const Group = ({
onClick={() => {
setNewChat(true);
setSelectedDirect(null);
- // setSelectedGroup(null);
setIsOpenDrawer(false);
}}
>
@@ -2188,26 +1925,7 @@ export const Group = ({
setInfo={setInfoSnack}
/>
- {isMobile && (
-
- )}
+
- {mobileViewMode === "groups" && !mobileViewModeKeepOpen && renderGroups()}
- {mobileViewModeKeepOpen === "messaging" && renderDirects()}
{newChat && (
<>
{isMobile && (
@@ -2358,7 +2074,7 @@ export const Group = ({
)}
- {mobileViewMode !== 'groups' && (
+
)}
- {isMobile && (
-
-
-
- {
- setMobileViewMode("groups");
- }}
- >
-
-
-
-
- {selectedGroup?.groupName}
-
-
- {/* */}
-
-
-
- )}
+
- {isMobile && mobileViewMode === "group" && (
- <>
-
- >
- )}
+
)}
- )}
+
{selectedDirect && !newChat && (
<>
@@ -2701,62 +2351,7 @@ export const Group = ({
>
)}
- {/* {!isMobile && groupSection === "home" && (
-
- )} */}
- {isMobile && mobileViewMode === "home" && (
-
- )}
- {isMobile && (
-
- )}
+
{!isMobile && (
-
- {(isMobile && mobileViewMode === "home" || (isMobile && mobileViewMode === "apps" && appsMode === 'home')) && !mobileViewModeKeepOpen && (
- <>
-
- {/*
- {renderGroups()}
- */}
- {isMobile && (
-
- )}
- >
- )}
- {(isMobile && mobileViewMode === "apps" && appsMode !== 'home') && !mobileViewModeKeepOpen && (
- <>
-
- >
- )}
>
);
};
From 50955941e42844b64d61d3248d6e2de9f079c8fb Mon Sep 17 00:00:00 2001
From: PhilReact
Date: Sat, 14 Dec 2024 23:24:34 +0200
Subject: [PATCH 008/119] fix reaction- decryption
---
src/qdn/encryption/group-encryption.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/qdn/encryption/group-encryption.ts b/src/qdn/encryption/group-encryption.ts
index eb83e1e..632252b 100644
--- a/src/qdn/encryption/group-encryption.ts
+++ b/src/qdn/encryption/group-encryption.ts
@@ -263,7 +263,7 @@ export const decryptSingle = async ({ data64, secretKeyObject, skipDecodeBase64
} else {
if (hasTypeNumber) {
// const typeNumberStr = new TextDecoder().decode(typeNumberBytes);
- if(decodeForNumber.slice(10, 13) === '002'){
+ if(decodeForNumber.slice(10, 13) !== '001'){
const decodedBinary = base64ToUint8Array(decodedData);
const highestKeyBytes = decodedBinary.slice(0, 10); // if ASCII digits only
const highestKeyStr = new TextDecoder().decode(highestKeyBytes);
From 4cafd57abeab63c12a27be0d0dcef30d7dffce97 Mon Sep 17 00:00:00 2001
From: PhilReact
Date: Sun, 15 Dec 2024 08:05:11 +0200
Subject: [PATCH 009/119] chat portion of unencrypted open groups
---
src/background.ts | 6 +-
src/components/Chat/ChatGroup.tsx | 55 ++++--
src/components/Chat/ChatList.tsx | 14 +-
src/components/Chat/ChatOptions.tsx | 224 ++++++++++++++---------
src/components/Chat/MessageDisplay.tsx | 2 +-
src/components/Chat/MessageItem.tsx | 12 +-
src/components/Chat/styles.css | 2 +-
src/components/Desktop/DesktopHeader.tsx | 20 +-
src/components/Group/Group.tsx | 139 +++++++++++---
src/qdn/encryption/group-encryption.ts | 4 +-
10 files changed, 335 insertions(+), 143 deletions(-)
diff --git a/src/background.ts b/src/background.ts
index 27ad8cc..fa786b9 100644
--- a/src/background.ts
+++ b/src/background.ts
@@ -664,8 +664,7 @@ const handleNotification = async (groups) => {
const data = groups.filter(
(group) =>
group?.sender !== address &&
- !mutedGroups.includes(group.groupId) &&
- !isUpdateMsg(group?.data)
+ !mutedGroups.includes(group.groupId)
);
const dataWithUpdates = groups.filter(
(group) => group?.sender !== address && !mutedGroups.includes(group.groupId)
@@ -716,8 +715,7 @@ const handleNotification = async (groups) => {
Date.now() - lastGroupNotification >= 120000
) {
if (
- !newestLatestTimestamp?.data ||
- !isExtMsg(newestLatestTimestamp?.data)
+ !newestLatestTimestamp?.data
)
return;
diff --git a/src/components/Chat/ChatGroup.tsx b/src/components/Chat/ChatGroup.tsx
index 02523a9..4324913 100644
--- a/src/components/Chat/ChatGroup.tsx
+++ b/src/components/Chat/ChatGroup.tsx
@@ -27,7 +27,7 @@ import { throttle } from 'lodash'
const uid = new ShortUniqueId({ length: 5 });
-export const ChatGroup = ({selectedGroup, secretKey, setSecretKey, getSecretKey, myAddress, handleNewEncryptionNotification, hide, handleSecretKeyCreationInProgress, triedToFetchSecretKey, myName, balance, getTimestampEnterChatParent, hideView}) => {
+export const ChatGroup = ({selectedGroup, secretKey, setSecretKey, getSecretKey, myAddress, handleNewEncryptionNotification, hide, handleSecretKeyCreationInProgress, triedToFetchSecretKey, myName, balance, getTimestampEnterChatParent, hideView, isPrivate}) => {
const [messages, setMessages] = useState([])
const [chatReferences, setChatReferences] = useState({})
const [isSending, setIsSending] = useState(false)
@@ -223,7 +223,7 @@ const [messageSize, setMessageSize] = useState(0)
setChatReferences((prev) => {
const organizedChatReferences = { ...prev };
combineUIAndExtensionMsgs
- .filter((rawItem) => rawItem && rawItem.chatReference && (rawItem.decryptedData?.type === "reaction" || rawItem.decryptedData?.type === "edit"))
+ .filter((rawItem) => rawItem && rawItem.chatReference && (rawItem.decryptedData?.type === "reaction" || rawItem.decryptedData?.type === "edit" || rawItem?.type === "edit" || rawItem?.type === "reaction"))
.forEach((item) => {
try {
if(item.decryptedData?.type === "edit"){
@@ -231,11 +231,16 @@ const [messageSize, setMessageSize] = useState(0)
...(organizedChatReferences[item.chatReference] || {}),
edit: item.decryptedData,
};
+ } else if(item?.type === "edit"){
+ organizedChatReferences[item.chatReference] = {
+ ...(organizedChatReferences[item.chatReference] || {}),
+ edit: item,
+ };
} else {
- const content = item.decryptedData?.content;
+ const content = item?.content || item.decryptedData?.content;
const sender = item.sender;
const newTimestamp = item.timestamp;
- const contentState = item.decryptedData?.contentState;
+ const contentState = item?.contentState || item.decryptedData?.contentState;
if (!content || typeof content !== "string" || !sender || typeof sender !== "string" || !newTimestamp) {
console.warn("Invalid content, sender, or timestamp in reaction data", item);
@@ -306,7 +311,7 @@ const [messageSize, setMessageSize] = useState(0)
const organizedChatReferences = { ...prev };
combineUIAndExtensionMsgs
- .filter((rawItem) => rawItem && rawItem.chatReference && (rawItem.decryptedData?.type === "reaction" || rawItem.decryptedData?.type === "edit"))
+ .filter((rawItem) => rawItem && rawItem.chatReference && (rawItem.decryptedData?.type === "reaction" || rawItem.decryptedData?.type === "edit" || rawItem?.type === "edit" || rawItem?.type === "reaction"))
.forEach((item) => {
try {
if(item.decryptedData?.type === "edit"){
@@ -314,11 +319,16 @@ const [messageSize, setMessageSize] = useState(0)
...(organizedChatReferences[item.chatReference] || {}),
edit: item.decryptedData,
};
+ } else if(item?.type === "edit"){
+ organizedChatReferences[item.chatReference] = {
+ ...(organizedChatReferences[item.chatReference] || {}),
+ edit: item,
+ };
} else {
- const content = item.decryptedData?.content;
+ const content = item?.content || item.decryptedData?.content;
const sender = item.sender;
const newTimestamp = item.timestamp;
- const contentState = item.decryptedData?.contentState;
+ const contentState = item?.contentState || item.decryptedData?.contentState;
if (!content || typeof content !== "string" || !sender || typeof sender !== "string" || !newTimestamp) {
console.warn("Invalid content, sender, or timestamp in reaction data", item);
@@ -453,10 +463,11 @@ const [messageSize, setMessageSize] = useState(0)
setIsLoading(true)
initWebsocketMessageGroup()
}
- }, [triedToFetchSecretKey, secretKey])
+ }, [triedToFetchSecretKey, secretKey, isPrivate])
useEffect(()=> {
- if(!secretKey || hasInitializedWebsocket.current) return
+ if(isPrivate === null) return
+ if(isPrivate === false || !secretKey || hasInitializedWebsocket.current) return
forceCloseWebSocket()
setMessages([])
setIsLoading(true)
@@ -466,7 +477,7 @@ const [messageSize, setMessageSize] = useState(0)
}, 6000);
initWebsocketMessageGroup()
hasInitializedWebsocket.current = true
- }, [secretKey])
+ }, [secretKey, isPrivate])
useEffect(()=> {
@@ -551,6 +562,7 @@ const clearEditorContent = () => {
const sendMessage = async ()=> {
try {
+ if(isPrivate === null) throw new Error('Unable to determine if group is private')
if(isSending) return
if(+balance < 4) throw new Error('You need at least 4 QORT to send a message')
pauseAllQueues()
@@ -558,8 +570,10 @@ const clearEditorContent = () => {
const htmlContent = editorRef.current.getHTML();
if(!htmlContent?.trim() || htmlContent?.trim() === '') return
+
+
setIsSending(true)
- const message = htmlContent
+ const message = isPrivate === false ? editorRef.current.getJSON() : htmlContent
const secretKeyObject = await getSecretKey(false, true)
let repliedTo = replyMessage?.signature
@@ -569,19 +583,24 @@ const clearEditorContent = () => {
}
let chatReference = onEditMessage?.signature
+ const publicData = isPrivate ? {} : {
+ isEdited : chatReference ? true : false,
+ }
const otherData = {
repliedTo,
...(onEditMessage?.decryptedData || {}),
type: chatReference ? 'edit' : '',
specialId: uid.rnd(),
+ ...publicData
}
const objectMessage = {
...(otherData || {}),
- message
+ [isPrivate ? 'message' : 'messageText']: message,
+ version: 3
}
const message64: any = await objectToBase64(objectMessage)
- const encryptSingle = await encryptChatMessage(message64, secretKeyObject)
+ const encryptSingle = isPrivate === false ? JSON.stringify(objectMessage) : await encryptChatMessage(message64, secretKeyObject)
// const res = await sendChatGroup({groupId: selectedGroup,messageText: encryptSingle})
const sendMessageFunc = async () => {
@@ -591,7 +610,7 @@ const clearEditorContent = () => {
// Add the function to the queue
const messageObj = {
message: {
- text: message,
+ text: htmlContent,
timestamp: Date.now(),
senderName: myName,
sender: myAddress,
@@ -668,7 +687,7 @@ const clearEditorContent = () => {
const onEdit = useCallback((message)=> {
setOnEditMessage(message)
setReplyMessage(null)
- editorRef.current.chain().focus().setContent(message?.text).run();
+ editorRef.current.chain().focus().setContent(message?.messageText || message?.text).run();
}, [])
const handleReaction = useCallback(async (reaction, chatMessage, reactionState = true)=> {
@@ -696,7 +715,7 @@ const clearEditorContent = () => {
}
const message64: any = await objectToBase64(objectMessage)
const reactiontypeNumber = RESOURCE_TYPE_NUMBER_GROUP_CHAT_REACTIONS
- const encryptSingle = await encryptChatMessage(message64, secretKeyObject, reactiontypeNumber)
+ const encryptSingle = isPrivate === false ? JSON.stringify(objectMessage) : await encryptChatMessage(message64, secretKeyObject, reactiontypeNumber)
// const res = await sendChatGroup({groupId: selectedGroup,messageText: encryptSingle})
const sendMessageFunc = async () => {
@@ -752,9 +771,9 @@ const clearEditorContent = () => {
left: hide && '-100000px',
}}>
-
+
- {!!secretKey && (
+ {(!!secretKey || isPrivate === false) && (
{
const parentRef = useRef();
const [messages, setMessages] = useState(initialMessages);
const [showScrollButton, setShowScrollButton] = useState(false);
const [showScrollDownButton, setShowScrollDownButton] = useState(false);
-
const hasLoadedInitialRef = useRef(false);
const scrollingIntervalRef = useRef(null);
const lastSeenUnreadMessageTimestamp = useRef(null);
@@ -272,7 +272,10 @@ export const ChatList = ({
message.text = chatReferences[message.signature]?.edit?.message;
message.isEdit = true
}
-
+ if (chatReferences[message.signature]?.edit?.messageText && message?.messageText) {
+ message.messageText = chatReferences[message.signature]?.edit?.messageText;
+ message.isEdit = true
+ }
}
@@ -315,7 +318,6 @@ export const ChatList = ({
);
}
-
return (
@@ -408,7 +411,7 @@ export const ChatList = ({
)}
- {enableMentions && hasSecretKey && (
+ {enableMentions && (hasSecretKey || isPrivate === false) && (
)}
diff --git a/src/components/Chat/ChatOptions.tsx b/src/components/Chat/ChatOptions.tsx
index 6791d68..87f3329 100644
--- a/src/components/Chat/ChatOptions.tsx
+++ b/src/components/Chat/ChatOptions.tsx
@@ -13,6 +13,10 @@ import { Spacer } from "../../common/Spacer";
import AlternateEmailIcon from "@mui/icons-material/AlternateEmail";
import CloseIcon from "@mui/icons-material/Close";
import InsertLinkIcon from '@mui/icons-material/InsertLink';
+import Highlight from "@tiptap/extension-highlight";
+import Mention from "@tiptap/extension-mention";
+import StarterKit from "@tiptap/starter-kit";
+import Underline from "@tiptap/extension-underline";
import {
AppsSearchContainer,
AppsSearchLeft,
@@ -32,6 +36,8 @@ import { useVirtualizer } from "@tanstack/react-virtual";
import { formatTimestamp } from "../../utils/time";
import { ContextMenuMentions } from "../ContextMenuMentions";
import { convert } from 'html-to-text';
+import { generateHTML } from "@tiptap/react";
+import ErrorBoundary from "../../common/ErrorBoundary";
const extractTextFromHTML = (htmlString = '') => {
return convert(htmlString, {
@@ -43,7 +49,7 @@ const cache = new CellMeasurerCache({
defaultHeight: 50,
});
-export const ChatOptions = ({ messages, goToMessage, members, myName, selectedGroup, openQManager }) => {
+export const ChatOptions = ({ messages : untransformedMessages, goToMessage, members, myName, selectedGroup, openQManager, isPrivate }) => {
const [mode, setMode] = useState("default");
const [searchValue, setSearchValue] = useState("");
const [selectedMember, setSelectedMember] = useState(0);
@@ -52,7 +58,27 @@ export const ChatOptions = ({ messages, goToMessage, members, myName, selectedGr
const parentRefMentions = useRef();
const [lastMentionTimestamp, setLastMentionTimestamp] = useState(null)
const [debouncedValue, setDebouncedValue] = useState(""); // Debounced value
-
+ const messages = useMemo(()=> {
+ return untransformedMessages?.map((item)=> {
+ if(item?.messageText){
+ let transformedMessage = item?.messageText
+ try {
+ transformedMessage = generateHTML(item?.messageText, [
+ StarterKit,
+ Underline,
+ Highlight,
+ Mention
+ ])
+ return {
+ ...item,
+ messageText: transformedMessage
+ }
+ } catch (error) {
+ // error
+ }
+ } else return item
+ })
+ }, [untransformedMessages])
const getTimestampMention = async () => {
try {
return new Promise((res, rej) => {
@@ -124,7 +150,7 @@ export const ChatOptions = ({ messages, goToMessage, members, myName, selectedGr
.filter(
(message) =>
message?.senderName === selectedMember &&
- extractTextFromHTML(message?.decryptedData?.message)?.includes(
+ extractTextFromHTML(isPrivate ? message?.messageText : message?.decryptedData?.message)?.includes(
debouncedValue.toLowerCase()
)
)
@@ -132,20 +158,27 @@ export const ChatOptions = ({ messages, goToMessage, members, myName, selectedGr
}
return messages
.filter((message) =>
- extractTextFromHTML(message?.decryptedData?.message)?.includes(debouncedValue.toLowerCase())
+ extractTextFromHTML(isPrivate === false ? message?.messageText : message?.decryptedData?.message)?.includes(debouncedValue.toLowerCase())
)
?.sort((a, b) => b?.timestamp - a?.timestamp);
- }, [debouncedValue, messages, selectedMember]);
+ }, [debouncedValue, messages, selectedMember, isPrivate]);
const mentionList = useMemo(() => {
if(!messages || messages.length === 0 || !myName) return []
-
+ if(isPrivate === false){
+ return messages
+ .filter((message) =>
+ extractTextFromHTML(message?.messageText)?.includes(`@${myName}`)
+ )
+ ?.sort((a, b) => b?.timestamp - a?.timestamp);
+
+ }
return messages
.filter((message) =>
extractTextFromHTML(message?.decryptedData?.message)?.includes(`@${myName}`)
)
?.sort((a, b) => b?.timestamp - a?.timestamp);
- }, [messages, myName]);
+ }, [messages, myName, isPrivate]);
const rowVirtualizer = useVirtualizer({
count: searchedList.length,
@@ -291,7 +324,8 @@ export const ChatOptions = ({ messages, goToMessage, members, myName, selectedGr
gap: "5px",
}}
>
-
+ {/*
-
+ */}
);
})}
@@ -544,6 +578,7 @@ export const ChatOptions = ({ messages, goToMessage, members, myName, selectedGr
const index = virtualRow.index;
let message = searchedList[index];
return (
+
-
-
-
-
- {message?.senderName?.charAt(0)}
-
-
- {message?.senderName}
-
-
-
-
- {formatTimestamp(message.timestamp)}
- {
- const findMsgIndex = messages.findIndex(
- (item) =>
- item?.signature === message?.signature
- );
- if (findMsgIndex !== -1) {
- goToMessage(findMsgIndex);
- }
- }}
- >
- "
- }
- />
-
-
+
+ Error loading content: Invalid Data
+
+ }
+ >
+
+
+
);
})}
@@ -705,3 +677,91 @@ export const ChatOptions = ({ messages, goToMessage, members, myName, selectedGr
);
};
+
+
+const ShowMessage = ({message, goToMessage, messages})=> {
+
+ return (
+
+
+
+
+ {message?.senderName?.charAt(0)}
+
+
+ {message?.senderName}
+
+
+
+
+ {formatTimestamp(message.timestamp)}
+ {
+ const findMsgIndex = messages.findIndex(
+ (item) =>
+ item?.signature === message?.signature
+ );
+ if (findMsgIndex !== -1) {
+ goToMessage(findMsgIndex);
+ }
+ }}
+ >
+ {message?.messageText && (
+
+ )}
+ {message?.decryptedData?.message && (
+
"
+ }
+ />
+ )}
+
+
+
+ )
+}
\ No newline at end of file
diff --git a/src/components/Chat/MessageDisplay.tsx b/src/components/Chat/MessageDisplay.tsx
index edda7d8..916c7d4 100644
--- a/src/components/Chat/MessageDisplay.tsx
+++ b/src/components/Chat/MessageDisplay.tsx
@@ -106,7 +106,7 @@ export const MessageDisplay = ({ htmlContent, isReply }) => {
}
};
- const embedLink = htmlContent.match(/qortal:\/\/use-embed\/[^\s<>]+/);
+ const embedLink = htmlContent?.match(/qortal:\/\/use-embed\/[^\s<>]+/);
let embedData = null;
diff --git a/src/components/Chat/MessageItem.tsx b/src/components/Chat/MessageItem.tsx
index bd2d86c..a088c0a 100644
--- a/src/components/Chat/MessageItem.tsx
+++ b/src/components/Chat/MessageItem.tsx
@@ -8,6 +8,7 @@ import { getBaseApi } from "../../background";
import { getBaseApiReact } from "../../App";
import { generateHTML } from "@tiptap/react";
import Highlight from "@tiptap/extension-highlight";
+import Mention from "@tiptap/extension-mention";
import StarterKit from "@tiptap/starter-kit";
import Underline from "@tiptap/extension-underline";
import { executeEvent } from "../../utils/events";
@@ -33,13 +34,15 @@ export const MessageItem = ({
reactions,
isUpdating,
lastSignature,
- onEdit
+ onEdit,
+ isPrivate
}) => {
const { ref, inView } = useInView({
threshold: 0.7, // Fully visible
triggerOnce: false, // Only trigger once when it becomes visible
});
+
const [anchorEl, setAnchorEl] = useState(null);
const [selectedReaction, setSelectedReaction] = useState(null);
@@ -136,7 +139,7 @@ export const MessageItem = ({
gap: '10px',
alignItems: 'center'
}}>
- {message?.sender === myAddress && !message?.isNotEncrypted && (
+ {message?.sender === myAddress && (!message?.isNotEncrypted || isPrivate === false) && (
{
onEdit(message);
@@ -205,6 +208,7 @@ export const MessageItem = ({
StarterKit,
Underline,
Highlight,
+ Mention
])}
/>
)}
@@ -223,6 +227,7 @@ export const MessageItem = ({
StarterKit,
Underline,
Highlight,
+ Mention
])}
/>
)}
@@ -341,7 +346,7 @@ export const MessageItem = ({
alignItems: 'center',
gap: '15px'
}}>
- {message?.isNotEncrypted && (
+ {message?.isNotEncrypted && isPrivate && (
{
StarterKit,
Underline,
Highlight,
+ Mention
])}
/>
)}
diff --git a/src/components/Chat/styles.css b/src/components/Chat/styles.css
index 7f3f66e..21680c8 100644
--- a/src/components/Chat/styles.css
+++ b/src/components/Chat/styles.css
@@ -125,7 +125,7 @@
font-size: 12px !important;
}
-.tiptap .mention {
+.tiptap [data-type="mention"] {
box-decoration-break: clone;
color: lightblue;
padding: 0.1rem 0.3rem;
diff --git a/src/components/Desktop/DesktopHeader.tsx b/src/components/Desktop/DesktopHeader.tsx
index 7067153..9be4d2f 100644
--- a/src/components/Desktop/DesktopHeader.tsx
+++ b/src/components/Desktop/DesktopHeader.tsx
@@ -19,6 +19,8 @@ import { ChatIcon } from "../../assets/Icons/ChatIcon";
import { ThreadsIcon } from "../../assets/Icons/ThreadsIcon";
import { MembersIcon } from "../../assets/Icons/MembersIcon";
import { AdminsIcon } from "../../assets/Icons/AdminsIcon";
+import LockIcon from '@mui/icons-material/Lock';
+import NoEncryptionGmailerrorredIcon from '@mui/icons-material/NoEncryptionGmailerrorred';
const IconWrapper = ({ children, label, color, selected, selectColor, customHeight }) => {
return (
@@ -80,7 +82,8 @@ export const DesktopHeader = ({
hasUnreadChat,
isChat,
isForum,
- setGroupSection
+ setGroupSection,
+ isPrivate
}) => {
const [value, setValue] = React.useState(0);
return (
@@ -95,7 +98,20 @@ export const DesktopHeader = ({
padding: "10px",
}}
>
-
+
+ {isPrivate && (
+
+ )}
+ {isPrivate === false && (
+
+ )}
{
@@ -347,6 +348,19 @@ export const getNamesForAdmins = async (admins) => {
return members;
};
+function areKeysEqual(array1, array2) {
+ // If lengths differ, the arrays cannot be equal
+ if (array1?.length !== array2?.length) {
+ return false;
+ }
+
+ // Sort both arrays and compare their elements
+ const sortedArray1 = [...array1].sort();
+ const sortedArray2 = [...array2].sort();
+
+ return sortedArray1.every((key, index) => key === sortedArray2[index]);
+}
+
export const Group = ({
myAddress,
isFocused,
@@ -418,6 +432,17 @@ export const Group = ({
const [appsModeDev, setAppsModeDev] = useState('home')
const [isOpenSideViewDirects, setIsOpenSideViewDirects] = useState(false)
const [isOpenSideViewGroups, setIsOpenSideViewGroups] = useState(false)
+
+
+ const [groupsProperties, setGroupsProperties] = useState({})
+
+ const isPrivate = useMemo(()=> {
+ if(!selectedGroup?.groupId || !groupsProperties[selectedGroup?.groupId]) return null
+ if(groupsProperties[selectedGroup?.groupId]?.isOpen === true) return false
+ if(groupsProperties[selectedGroup?.groupId]?.isOpen === false) return true
+ return null
+ }, [selectedGroup])
+
const setSelectedGroupId = useSetRecoilState(selectedGroupIdAtom)
const toggleSideViewDirects = ()=> {
if(isOpenSideViewGroups){
@@ -569,9 +594,8 @@ export const Group = ({
if (
group?.data &&
- isExtMsg(group?.data) &&
group?.sender !== myAddress &&
- group?.timestamp && (!isUpdateMsg(group?.data) || groupChatTimestamps[group?.groupId]) &&
+ group?.timestamp && groupChatTimestamps[group?.groupId] &&
((!timestampEnterData[group?.groupId] &&
Date.now() - group?.timestamp < timeDifferenceForNotificationChats) ||
timestampEnterData[group?.groupId] < group?.timestamp)
@@ -706,12 +730,19 @@ export const Group = ({
useEffect(() => {
- if (selectedGroup) {
- setTriedToFetchSecretKey(false);
- getSecretKey(true);
+ if (selectedGroup && isPrivate !== null) {
+ if(isPrivate){
+ setTriedToFetchSecretKey(false);
+ getSecretKey(true);
+ }
+
getGroupOwner(selectedGroup?.groupId);
}
- }, [selectedGroup]);
+ if(isPrivate === false){
+ setTriedToFetchSecretKey(true);
+
+ }
+ }, [selectedGroup, isPrivate]);
@@ -735,9 +766,8 @@ export const Group = ({
const groupData = {}
const getGroupData = groups.map(async(group)=> {
- const isUpdate = isUpdateMsg(group?.data)
if(!group.groupId || !group?.timestamp) return null
- if(isUpdate && (!groupData[group.groupId] || groupData[group.groupId] < group.timestamp)){
+ if((!groupData[group.groupId] || groupData[group.groupId] < group.timestamp)){
const hasMoreRecentMsg = await getCountNewMesg(group.groupId, timestampEnterDataRef.current[group?.groupId] || Date.now() - 24 * 60 * 60 * 1000)
if(hasMoreRecentMsg){
groupData[group.groupId] = hasMoreRecentMsg
@@ -754,6 +784,32 @@ export const Group = ({
}
}
+ const getGroupsProperties = useCallback(async(address)=> {
+ try {
+ const url = `${getBaseApiReact()}/groups/member/${address}`;
+ const response = await fetch(url);
+ if(!response.ok) throw new Error('Cannot get group properties')
+ let data = await response.json();
+ const transformToObject = data.reduce((result, item) => {
+
+ result[item.groupId] = item
+ return result;
+ }, {});
+ setGroupsProperties(transformToObject)
+ } catch (error) {
+ // error
+ }
+ }, [])
+
+
+ useEffect(()=> {
+ if(!myAddress) return
+ if(areKeysEqual(groups?.map((grp)=> grp?.groupId), Object.keys(groupsProperties))){
+ } else {
+ getGroupsProperties(myAddress)
+ }
+ }, [groups, myAddress])
+
useEffect(() => {
@@ -941,9 +997,9 @@ export const Group = ({
.filter((group) => group?.sender !== myAddress)
.find((gr) => gr?.groupId === selectedGroup?.groupId);
if (!findGroup) return false;
- if (!findGroup?.data || !isExtMsg(findGroup?.data)) return false;
+ if (!findGroup?.data) return false;
return (
- findGroup?.timestamp && (!isUpdateMsg(findGroup?.data) || groupChatTimestamps[findGroup?.groupId]) &&
+ findGroup?.timestamp && groupChatTimestamps[findGroup?.groupId] &&
((!timestampEnterData[selectedGroup?.groupId] &&
Date.now() - findGroup?.timestamp <
timeDifferenceForNotificationChats) ||
@@ -1657,6 +1713,7 @@ export const Group = ({
);
};
+
const renderGroups = () => {
return (
-
- {group.groupName?.charAt(0)}
-
+ display: 'flex',
+ alignItems: 'center',
+ justifyContent: 'center'
+ }}>
+
+
+ ): (
+
+
+
+ //
+ // {group.groupName?.charAt(0)}
+ //
+ )}
+
)}
{group?.data &&
- isExtMsg(group?.data) && (!isUpdateMsg(group?.data) || groupChatTimestamps[group?.groupId]) &&
+ groupChatTimestamps[group?.groupId] &&
group?.sender !== myAddress &&
group?.timestamp &&
((!timestampEnterData[group?.groupId] &&
@@ -2085,6 +2172,7 @@ export const Group = ({
{!isMobile && (
)}
- {firstSecretKeyInCreation &&
+ {isPrivate &&firstSecretKeyInCreation &&
triedToFetchSecretKey &&
!secretKeyPublishDate && (
)}
- {!admins.includes(myAddress) &&
+ {isPrivate && !admins.includes(myAddress) &&
!secretKey &&
triedToFetchSecretKey ? (
<>
@@ -2231,7 +2320,7 @@ export const Group = ({
) : null}
>
) : admins.includes(myAddress) &&
- !secretKey &&
+ (!secretKey && isPrivate) &&
triedToFetchSecretKey ? null : !triedToFetchSecretKey ? null : (
<>
- {admins.includes(myAddress) &&
+ {isPrivate && admins.includes(myAddress) &&
shouldReEncrypt &&
triedToFetchSecretKey &&
!firstSecretKeyInCreation &&
diff --git a/src/qdn/encryption/group-encryption.ts b/src/qdn/encryption/group-encryption.ts
index 632252b..82734ee 100644
--- a/src/qdn/encryption/group-encryption.ts
+++ b/src/qdn/encryption/group-encryption.ts
@@ -217,12 +217,12 @@ export const decodeBase64ForUIChatMessages = (messages)=> {
try {
const decoded = atob(msg?.data);
const parseDecoded =JSON.parse(decodeURIComponent(escape(decoded)))
- if(parseDecoded?.messageText){
+
msgs.push({
...msg,
...parseDecoded
})
- }
+
} catch (error) {
}
From fe9a7acdaa61f6dc94cdffd8ca05d0940f599ab3 Mon Sep 17 00:00:00 2001
From: PhilReact
Date: Sun, 15 Dec 2024 08:49:56 +0200
Subject: [PATCH 010/119] fix message size
---
src/App.tsx | 2 +-
src/components/Chat/ChatDirect.tsx | 4 ++--
src/components/Chat/ChatGroup.tsx | 23 ++++++++++++++++-------
3 files changed, 19 insertions(+), 10 deletions(-)
diff --git a/src/App.tsx b/src/App.tsx
index 353289d..a442e97 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -319,7 +319,7 @@ function App() {
useState("");
const [isMain, setIsMain] = useState(true);
const isMainRef = useRef(false);
- const [authenticatePassword, setAuthenticatePassword] = useState("1234567890");
+ const [authenticatePassword, setAuthenticatePassword] = useState("");
const [sendqortState, setSendqortState] = useState(null);
const [isLoading, setIsLoading] = useState(false);
const [
diff --git a/src/components/Chat/ChatDirect.tsx b/src/components/Chat/ChatDirect.tsx
index 5e2014e..ace54ce 100644
--- a/src/components/Chat/ChatDirect.tsx
+++ b/src/components/Chat/ChatDirect.tsx
@@ -377,7 +377,8 @@ useEffect(() => {
const sendMessage = async ()=> {
try {
-
+ if(messageSize > 4000) return
+
if(+balance < 4) throw new Error('You need at least 4 QORT to send a message')
if(isSending) return
@@ -674,7 +675,6 @@ useEffect(() => {
{
- if(messageSize > 4000) return
if(isSending) return
sendMessage()
diff --git a/src/components/Chat/ChatGroup.tsx b/src/components/Chat/ChatGroup.tsx
index 4324913..25be721 100644
--- a/src/components/Chat/ChatGroup.tsx
+++ b/src/components/Chat/ChatGroup.tsx
@@ -562,6 +562,7 @@ const clearEditorContent = () => {
const sendMessage = async ()=> {
try {
+ if(messageSize > 4000) return
if(isPrivate === null) throw new Error('Unable to determine if group is private')
if(isSending) return
if(+balance < 4) throw new Error('You need at least 4 QORT to send a message')
@@ -647,11 +648,19 @@ const clearEditorContent = () => {
handleUpdateRef.current = throttle(async () => {
try {
- const htmlContent = editorRef.current.getHTML();
- const message64 = await objectToBase64(JSON.stringify(htmlContent))
- const secretKeyObject = await getSecretKey(false, true)
- const encryptSingle = await encryptChatMessage(message64, secretKeyObject)
- setMessageSize((encryptSingle?.length || 0) + 200);
+ if(isPrivate){
+ const htmlContent = editorRef.current.getHTML();
+ const message64 = await objectToBase64(JSON.stringify(htmlContent))
+ const secretKeyObject = await getSecretKey(false, true)
+ const encryptSingle = await encryptChatMessage(message64, secretKeyObject)
+ setMessageSize((encryptSingle?.length || 0) + 200);
+ } else {
+ const htmlContent = editorRef.current.getJSON();
+ const message = JSON.stringify(htmlContent)
+ const size = new Blob([message]).size
+ setMessageSize(size + 300);
+ }
+
} catch (error) {
// calc size error
}
@@ -664,7 +673,7 @@ const clearEditorContent = () => {
return () => {
currentEditor.off("update", handleUpdateRef.current);
};
- }, [editorRef, setMessageSize]);
+ }, [editorRef, setMessageSize, isPrivate]);
useEffect(() => {
if (hide) {
@@ -874,7 +883,7 @@ const clearEditorContent = () => {
{
- if(messageSize > 4000) return
+
if(isSending) return
sendMessage()
}}
From 0cb3c80c2572c4e4a43e99c64254e59b6a7c9437 Mon Sep 17 00:00:00 2001
From: PhilReact
Date: Sun, 15 Dec 2024 20:14:25 +0200
Subject: [PATCH 011/119] announcements public group non-encrypted
---
.../Chat/AnnouncementDiscussion.tsx | 28 +++----
src/components/Chat/GroupAnnouncements.tsx | 74 ++++++++++---------
src/components/Group/Group.tsx | 13 +++-
3 files changed, 67 insertions(+), 48 deletions(-)
diff --git a/src/components/Chat/AnnouncementDiscussion.tsx b/src/components/Chat/AnnouncementDiscussion.tsx
index cc6af24..5603de0 100644
--- a/src/components/Chat/AnnouncementDiscussion.tsx
+++ b/src/components/Chat/AnnouncementDiscussion.tsx
@@ -6,7 +6,7 @@ import { objectToBase64 } from "../../qdn/encryption/group-encryption";
import ShortUniqueId from "short-unique-id";
import { LoadingSnackbar } from "../Snackbar/LoadingSnackbar";
import { getBaseApi, getFee } from "../../background";
-import { decryptPublishes, getTempPublish, saveTempPublish } from "./GroupAnnouncements";
+import { decryptPublishes, getTempPublish, handleUnencryptedPublishes, saveTempPublish } from "./GroupAnnouncements";
import { AnnouncementList } from "./AnnouncementList";
import { Spacer } from "../../common/Spacer";
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
@@ -22,7 +22,8 @@ export const AnnouncementDiscussion = ({
secretKey,
setSelectedAnnouncement,
show,
- myName
+ myName,
+ isPrivate
}) => {
const [isSending, setIsSending] = useState(false);
const [isLoading, setIsLoading] = useState(false);
@@ -49,7 +50,7 @@ export const AnnouncementDiscussion = ({
}
};
- const getData = async ({ identifier, name }) => {
+ const getData = async ({ identifier, name }, isPrivate) => {
try {
const res = await fetch(
@@ -57,7 +58,7 @@ export const AnnouncementDiscussion = ({
);
if(!res?.ok) return
const data = await res.text();
- const response = await decryptPublishes([{ data }], secretKey);
+ const response = isPrivate === false ? handleUnencryptedPublishes([data]) : await decryptPublishes([{ data }], secretKey);
const messageData = response[0];
setData((prev) => {
@@ -132,10 +133,10 @@ export const AnnouncementDiscussion = ({
extra: {},
message: htmlContent,
};
- const secretKeyObject = await getSecretKey(false, true);
- const message64: any = await objectToBase64(message);
+ const secretKeyObject = isPrivate === false ? null : await getSecretKey(false, true);
+ const message64: any = await objectToBase64(message);
- const encryptSingle = await encryptChatMessage(
+ const encryptSingle = isPrivate === false ? message64 : await encryptChatMessage(
message64,
secretKeyObject
);
@@ -169,7 +170,7 @@ export const AnnouncementDiscussion = ({
};
const getComments = React.useCallback(
- async (selectedAnnouncement) => {
+ async (selectedAnnouncement, isPrivate) => {
try {
setIsLoading(true);
@@ -190,7 +191,7 @@ export const AnnouncementDiscussion = ({
setComments(responseData);
setIsLoading(false);
for (const data of responseData) {
- getData({ name: data.name, identifier: data.identifier });
+ getData({ name: data.name, identifier: data.identifier }, isPrivate);
}
} catch (error) {
} finally {
@@ -220,7 +221,7 @@ export const AnnouncementDiscussion = ({
setComments((prev)=> [...prev, ...responseData]);
setIsLoading(false);
for (const data of responseData) {
- getData({ name: data.name, identifier: data.identifier });
+ getData({ name: data.name, identifier: data.identifier }, isPrivate);
}
} catch (error) {
@@ -245,11 +246,12 @@ export const AnnouncementDiscussion = ({
}, [tempPublishedList, comments]);
React.useEffect(() => {
- if (selectedAnnouncement && secretKey && !firstMountRef.current) {
- getComments(selectedAnnouncement);
+ if(!secretKey && isPrivate) return
+ if (selectedAnnouncement && !firstMountRef.current && isPrivate !== null) {
+ getComments(selectedAnnouncement, isPrivate);
firstMountRef.current = true
}
- }, [selectedAnnouncement, secretKey]);
+ }, [selectedAnnouncement, secretKey, isPrivate]);
return (
{
.then((response) => {
if (!response?.error) {
res(response);
- // if(hasInitialized.current){
- // setMessages((prev) => [...prev, ...formatted]);
- // } else {
- // const formatted = response.map((item) => ({
- // ...item,
- // id: item.signature,
- // text: item.text,
- // unread: false
- // }));
- // setMessages(formatted);
- // hasInitialized.current = true;
- // }
return;
}
rej(response.error);
@@ -117,6 +105,20 @@ export const decryptPublishes = async (encryptedMessages: any[], secretKey) => {
});
} catch (error) {}
};
+export const handleUnencryptedPublishes = (publishes) => {
+ let publishesData = []
+ publishes.forEach((pub)=> {
+ try {
+ const decodedData = JSON.parse(atob(pub))
+ if(decodedData){
+ publishesData.push({decryptedData: decodedData})
+ }
+ } catch (error) {
+
+ }
+ })
+ return publishesData
+};
export const GroupAnnouncements = ({
selectedGroup,
secretKey,
@@ -127,6 +129,7 @@ export const GroupAnnouncements = ({
isAdmin,
hide,
myName,
+ isPrivate
}) => {
const [messages, setMessages] = useState([]);
const [isSending, setIsSending] = useState(false);
@@ -160,7 +163,7 @@ export const GroupAnnouncements = ({
})();
}, [selectedGroup]);
- const getAnnouncementData = async ({ identifier, name, resource }) => {
+ const getAnnouncementData = async ({ identifier, name, resource }, isPrivate) => {
try {
let data = dataPublishes.current[`${name}-${identifier}`];
if (
@@ -180,9 +183,9 @@ export const GroupAnnouncements = ({
data = data.data;
}
- const response = await decryptPublishes([{ data }], secretKey);
-
+ const response = isPrivate === false ? handleUnencryptedPublishes([data]) : await decryptPublishes([{ data }], secretKey);
const messageData = response[0];
+ if(!messageData) return
setAnnouncementData((prev) => {
return {
...prev,
@@ -195,11 +198,11 @@ export const GroupAnnouncements = ({
};
useEffect(() => {
- if (!secretKey || hasInitializedWebsocket.current) return;
+ if ((!secretKey && isPrivate) || hasInitializedWebsocket.current || isPrivate === null) return;
setIsLoading(true);
// initWebsocketMessageGroup()
hasInitializedWebsocket.current = true;
- }, [secretKey]);
+ }, [secretKey, isPrivate]);
const encryptChatMessage = async (data: string, secretKeyObject: any) => {
try {
@@ -257,12 +260,12 @@ export const GroupAnnouncements = ({
}
};
- const setTempData = async () => {
+ const setTempData = async (selectedGroup) => {
try {
const getTempAnnouncements = await getTempPublish();
if (getTempAnnouncements?.announcement) {
let tempData = [];
- Object.keys(getTempAnnouncements?.announcement || {}).map((key) => {
+ Object.keys(getTempAnnouncements?.announcement || {}).filter((annKey)=> annKey?.startsWith(`grp-${selectedGroup}-anc`)).map((key) => {
const value = getTempAnnouncements?.announcement[key];
tempData.push(value.data);
});
@@ -289,9 +292,9 @@ export const GroupAnnouncements = ({
extra: {},
message: htmlContent,
};
- const secretKeyObject = await getSecretKey(false, true);
- const message64: any = await objectToBase64(message);
- const encryptSingle = await encryptChatMessage(
+ const secretKeyObject = isPrivate === false ? null : await getSecretKey(false, true);
+ const message64: any = await objectToBase64(message);
+ const encryptSingle = isPrivate === false ? message64 : await encryptChatMessage(
message64,
secretKeyObject
);
@@ -313,7 +316,7 @@ export const GroupAnnouncements = ({
data: dataToSaveToStorage,
key: "announcement",
});
- setTempData();
+ setTempData(selectedGroup);
clearEditorContent();
}
// send chat message
@@ -331,7 +334,7 @@ export const GroupAnnouncements = ({
};
const getAnnouncements = React.useCallback(
- async (selectedGroup) => {
+ async (selectedGroup, isPrivate) => {
try {
const offset = 0;
@@ -346,7 +349,7 @@ export const GroupAnnouncements = ({
});
const responseData = await response.json();
- setTempData();
+ setTempData(selectedGroup);
setAnnouncements(responseData);
setIsLoading(false);
for (const data of responseData) {
@@ -354,7 +357,7 @@ export const GroupAnnouncements = ({
name: data.name,
identifier: data.identifier,
resource: data,
- });
+ }, isPrivate);
}
} catch (error) {
} finally {
@@ -365,11 +368,12 @@ export const GroupAnnouncements = ({
);
React.useEffect(() => {
- if (selectedGroup && secretKey && !hasInitialized.current && !hide) {
- getAnnouncements(selectedGroup);
+ if(!secretKey && isPrivate) return
+ if (selectedGroup && !hasInitialized.current && !hide && isPrivate !== null) {
+ getAnnouncements(selectedGroup, isPrivate);
hasInitialized.current = true;
}
- }, [selectedGroup, secretKey, hide]);
+ }, [selectedGroup, secretKey, hide, isPrivate]);
const loadMore = async () => {
try {
@@ -389,7 +393,7 @@ export const GroupAnnouncements = ({
setAnnouncements((prev) => [...prev, ...responseData]);
setIsLoading(false);
for (const data of responseData) {
- getAnnouncementData({ name: data.name, identifier: data.identifier });
+ getAnnouncementData({ name: data.name, identifier: data.identifier }, isPrivate);
}
} catch (error) {}
};
@@ -414,7 +418,7 @@ export const GroupAnnouncements = ({
getAnnouncementData({
name: data.name,
identifier: data.identifier,
- });
+ }, isPrivate);
} catch (error) {}
}
setAnnouncements(responseData);
@@ -429,7 +433,7 @@ export const GroupAnnouncements = ({
for (const data of newArray) {
try {
- getAnnouncementData({ name: data.name, identifier: data.identifier });
+ getAnnouncementData({ name: data.name, identifier: data.identifier }, isPrivate);
} catch (error) {}
}
setAnnouncements((prev) => [...newArray, ...prev]);
@@ -449,14 +453,14 @@ export const GroupAnnouncements = ({
}, [checkNewMessages]);
useEffect(() => {
- if (!secretKey || hide) return;
+ if ((!secretKey && isPrivate) || hide || isPrivate === null) return;
checkNewMessagesFunc();
return () => {
if (interval?.current) {
clearInterval(interval.current);
}
};
- }, [checkNewMessagesFunc, hide]);
+ }, [checkNewMessagesFunc, hide, isPrivate]);
const combinedListTempAndReal = useMemo(() => {
// Combine the two lists
@@ -498,11 +502,13 @@ export const GroupAnnouncements = ({
setSelectedAnnouncement={setSelectedAnnouncement}
encryptChatMessage={encryptChatMessage}
getSecretKey={getSecretKey}
+ isPrivate={isPrivate}
/>
);
}
+
return (
{
+ try {
+ const { names, addresses, both } =
+ await getGroupAdmins(selectedGroup?.groupId)
+ setAdmins(addresses);
+ setAdminsWithNames(both);
+ } catch (error) {
+ //error
+ }
+ }
useEffect(() => {
if (selectedGroup && isPrivate !== null) {
@@ -740,6 +749,7 @@ export const Group = ({
}
if(isPrivate === false){
setTriedToFetchSecretKey(true);
+ getAdminsForPublic(selectedGroup)
}
}, [selectedGroup, isPrivate]);
@@ -2335,6 +2345,7 @@ export const Group = ({
}
myName={userInfo?.name}
hide={groupSection !== "announcement"}
+ isPrivate={isPrivate}
/>
Date: Sun, 15 Dec 2024 21:09:16 +0200
Subject: [PATCH 012/119] threads unencrypted for public grps
---
src/components/Chat/GroupForum.tsx | 5 ++--
src/components/Group/Forum/GroupMail.tsx | 29 +++++++++++++-----------
src/components/Group/Forum/NewThread.tsx | 13 ++++++-----
src/components/Group/Forum/Thread.tsx | 18 +++++++++------
src/components/Group/Group.tsx | 1 +
5 files changed, 38 insertions(+), 28 deletions(-)
diff --git a/src/components/Chat/GroupForum.tsx b/src/components/Chat/GroupForum.tsx
index bfc1f05..d8dd7e5 100644
--- a/src/components/Chat/GroupForum.tsx
+++ b/src/components/Chat/GroupForum.tsx
@@ -24,7 +24,8 @@ export const GroupForum = ({
myAddress,
hide,
defaultThread,
- setDefaultThread
+ setDefaultThread,
+ isPrivate
}) => {
const { rootHeight } = useContext(MyContext);
const [isMoved, setIsMoved] = useState(false);
@@ -50,7 +51,7 @@ export const GroupForum = ({
left: hide && '-1000px'
}}
>
-
+
);
diff --git a/src/components/Group/Forum/GroupMail.tsx b/src/components/Group/Forum/GroupMail.tsx
index d569b27..38d93e9 100644
--- a/src/components/Group/Forum/GroupMail.tsx
+++ b/src/components/Group/Forum/GroupMail.tsx
@@ -46,7 +46,7 @@ import LazyLoad from "../../../common/LazyLoad";
import { delay } from "../../../utils/helpers";
import { NewThread } from "./NewThread";
import { getBaseApi } from "../../../background";
-import { decryptPublishes, getTempPublish } from "../../Chat/GroupAnnouncements";
+import { decryptPublishes, getTempPublish, handleUnencryptedPublishes } from "../../Chat/GroupAnnouncements";
import CheckSVG from "../../../assets/svgs/Check.svg";
import SortSVG from "../../../assets/svgs/Sort.svg";
import ArrowDownSVG from "../../../assets/svgs/ArrowDown.svg";
@@ -66,7 +66,8 @@ export const GroupMail = ({
secretKey,
defaultThread,
setDefaultThread,
- hide
+ hide,
+ isPrivate
}) => {
const [viewedThreads, setViewedThreads] = React.useState({});
const [filterMode, setFilterMode] = useState("Recently active");
@@ -123,7 +124,7 @@ export const GroupMail = ({
}
- const getEncryptedResource = async ({ name, identifier, resource }) => {
+ const getEncryptedResource = async ({ name, identifier, resource }, isPrivate) => {
let data = dataPublishes.current[`${name}-${identifier}`]
if(!data || (data?.update || data?.created !== (resource?.updated || resource?.created))){
const res = await fetch(
@@ -136,7 +137,7 @@ export const GroupMail = ({
} else {
data = data.data
}
- const response = await decryptPublishes([{ data }], secretKey);
+ const response = isPrivate === false ? handleUnencryptedPublishes([data]) : await decryptPublishes([{ data }], secretKey);
const messageData = response[0];
return messageData.decryptedData;
@@ -212,7 +213,7 @@ export const GroupMail = ({
name: message.name,
identifier: message.identifier,
resource: message
- }),
+ }, isPrivate),
delay(5000),
]);
} catch (error) {}
@@ -255,7 +256,7 @@ export const GroupMail = ({
}
}
},
- [allThreads]
+ [allThreads, isPrivate]
);
const getMailMessages = React.useCallback(
async (groupId: string, members: any) => {
@@ -327,7 +328,7 @@ export const GroupMail = ({
name: thread.name,
identifier: message.threadId,
resource: thread
- }),
+ }, isPrivate),
delay(10000),
]);
if (threadRes?.title) {
@@ -356,16 +357,16 @@ export const GroupMail = ({
// dispatch(setIsLoadingCustom(null));
}
},
- [secretKey]
+ [secretKey, isPrivate]
);
const getMessages = React.useCallback(async () => {
// if ( !groupId || members?.length === 0) return;
- if (!groupId) return;
+ if (!groupId || isPrivate === null) return;
await getMailMessages(groupId, members);
- }, [getMailMessages, groupId, members, secretKey]);
+ }, [getMailMessages, groupId, members, secretKey, isPrivate]);
const interval = useRef(null);
@@ -378,7 +379,7 @@ export const GroupMail = ({
firstMount.current = false;
}
// if (groupId && !firstMount.current && members.length > 0) {
- if (groupId && !firstMount.current) {
+ if (groupId && !firstMount.current && isPrivate !== null) {
if (filterMode === "Recently active") {
getMessages();
} else if (filterMode === "Newest") {
@@ -389,7 +390,7 @@ export const GroupMail = ({
setTempData()
firstMount.current = true;
}
- }, [groupId, members, filterMode, hide]);
+ }, [groupId, members, filterMode, hide, isPrivate]);
const closeThread = useCallback(() => {
setCurrentThread(null);
@@ -468,7 +469,7 @@ export const GroupMail = ({
} else if (filterMode === "Oldest") {
getAllThreads(groupId, "Oldest", true);
}
- }, [filterMode])
+ }, [filterMode, isPrivate])
const updateThreadActivityCurrentThread = ()=> {
if(!currentThread) return
@@ -540,6 +541,7 @@ export const GroupMail = ({
secretKey={secretKey}
getSecretKey={getSecretKey}
updateThreadActivityCurrentThread={updateThreadActivityCurrentThread}
+ isPrivate={isPrivate}
/>
);
@@ -620,6 +622,7 @@ export const GroupMail = ({
userInfo={userInfo}
getSecretKey={getSecretKey}
myName={userInfo?.name}
+ isPrivate={isPrivate}
/>
{
const { show } = React.useContext(MyContext);
@@ -245,8 +246,8 @@ export const NewThread = ({
reply,
};
- const secretKey = await getSecretKey(false, true);
- if (!secretKey) {
+ const secretKey = isPrivate === false ? null : await getSecretKey(false, true);
+ if (!secretKey && isPrivate) {
throw new Error("Cannot get group secret key");
}
@@ -254,7 +255,7 @@ export const NewThread = ({
const idThread = uid.rnd();
const idMsg = uid.rnd();
const messageToBase64 = await objectToBase64(mailObject);
- const encryptSingleFirstPost = await encryptSingleFunc(
+ const encryptSingleFirstPost = isPrivate === false ? messageToBase64 : await encryptSingleFunc(
messageToBase64,
secretKey
);
@@ -266,7 +267,7 @@ export const NewThread = ({
};
const threadToBase64 = await objectToBase64(threadObject);
- const encryptSingleThread = await encryptSingleFunc(
+ const encryptSingleThread = isPrivate === false ? threadToBase64 : await encryptSingleFunc(
threadToBase64,
secretKey
);
@@ -321,7 +322,7 @@ export const NewThread = ({
if (!currentThread) throw new Error("unable to locate thread Id");
const idThread = currentThread.threadId;
const messageToBase64 = await objectToBase64(mailObject);
- const encryptSinglePost = await encryptSingleFunc(
+ const encryptSinglePost = isPrivate === false ? messageToBase64 : await encryptSingleFunc(
messageToBase64,
secretKey
);
diff --git a/src/components/Group/Forum/Thread.tsx b/src/components/Group/Forum/Thread.tsx
index f393d5d..22b2ba3 100644
--- a/src/components/Group/Forum/Thread.tsx
+++ b/src/components/Group/Forum/Thread.tsx
@@ -37,6 +37,7 @@ import { NewThread } from "./NewThread";
import {
decryptPublishes,
getTempPublish,
+ handleUnencryptedPublishes,
} from "../../Chat/GroupAnnouncements";
import { LoadingSnackbar } from "../../Snackbar/LoadingSnackbar";
import { subscribeToEvent, unsubscribeFromEvent } from "../../../utils/events";
@@ -71,7 +72,7 @@ const getEncryptedResource = async ({
resource,
groupId,
dataPublishes,
-}) => {
+}, isPrivate) => {
let data = dataPublishes[`${name}-${identifier}`];
if (
!data ||
@@ -99,7 +100,7 @@ const getEncryptedResource = async ({
} else {
data = data.data;
}
- const response = await decryptPublishes([{ data }], secretKey);
+ const response = isPrivate === false ? handleUnencryptedPublishes([data]) : await decryptPublishes([{ data }], secretKey);
const messageData = response[0];
return messageData.decryptedData;
@@ -114,6 +115,7 @@ export const Thread = ({
secretKey,
getSecretKey,
updateThreadActivityCurrentThread,
+ isPrivate
}: ThreadProps) => {
const [tempPublishedList, setTempPublishedList] = useState([]);
const [messages, setMessages] = useState([]);
@@ -164,7 +166,7 @@ export const Thread = ({
resource: message,
groupId: groupInfo?.groupId,
dataPublishes: dataPublishes.current,
- });
+ }, isPrivate);
if (responseDataMessage?.error) {
const fullObject = {
@@ -323,9 +325,9 @@ export const Thread = ({
[messages, secretKey]
);
const getMessages = React.useCallback(async () => {
- if (!currentThread || !secretKey || !groupInfo?.groupId) return;
+ if (!currentThread || (!secretKey && isPrivate) || !groupInfo?.groupId || isPrivate === null) return;
await getMailMessages(currentThread, null, null, false, groupInfo?.groupId);
- }, [getMailMessages, currentThread, secretKey, groupInfo?.groupId]);
+ }, [getMailMessages, currentThread, secretKey, groupInfo?.groupId, isPrivate]);
const firstMount = useRef(false);
const saveTimestamp = useCallback((currentThread: any, username?: string) => {
@@ -380,10 +382,11 @@ export const Thread = ({
if (currentThreadRef.current?.threadId !== currentThread?.threadId) {
firstMount.current = false;
}
- if (currentThread && secretKey && !firstMount.current) {
+ if(!secretKey && isPrivate) return
+ if (currentThread && !firstMount.current && isPrivate !== null) {
getMessagesMiddleware();
}
- }, [currentThread, secretKey]);
+ }, [currentThread, secretKey, isPrivate]);
const messageCallback = useCallback((msg: any) => {
// dispatch(addToHashMapMail(msg))
// setMessages((prev) => [msg, ...prev])
@@ -576,6 +579,7 @@ export const Thread = ({
myName={userInfo?.name}
publishCallback={setTempData}
setPostReply={setPostReply}
+ isPrivate={isPrivate}
/>
From e2d12880d147d67158d734a1f7aa9a693599bc2e Mon Sep 17 00:00:00 2001
From: PhilReact
Date: Sun, 15 Dec 2024 21:55:20 +0200
Subject: [PATCH 013/119] added lock icon to list of groups
---
src/components/Group/AddGroup.tsx | 13 +++++--
src/components/Group/AddGroupList.tsx | 27 +++++++++++----
.../Group/ListOfGroupPromotions.tsx | 27 +++++++++++++++
src/components/Group/UserListOfInvites.tsx | 34 ++++++++++++++++---
4 files changed, 88 insertions(+), 13 deletions(-)
diff --git a/src/components/Group/AddGroup.tsx b/src/components/Group/AddGroup.tsx
index ed90c8c..af23fd9 100644
--- a/src/components/Group/AddGroup.tsx
+++ b/src/components/Group/AddGroup.tsx
@@ -217,6 +217,9 @@ export const AddGroup = ({ address, open, setOpen }) => {
flexGrow: 1,
overflowY: "auto",
color: "white",
+ flexDirection: 'column',
+ flexGrow: 1,
+ display: 'flex'
}}
>
@@ -454,7 +457,10 @@ export const AddGroup = ({ address, open, setOpen }) => {
{value === 1 && (
@@ -465,7 +471,10 @@ export const AddGroup = ({ address, open, setOpen }) => {
{value === 2 && (
diff --git a/src/components/Group/AddGroupList.tsx b/src/components/Group/AddGroupList.tsx
index 17eb3a8..977430d 100644
--- a/src/components/Group/AddGroupList.tsx
+++ b/src/components/Group/AddGroupList.tsx
@@ -26,7 +26,9 @@ import _ from "lodash";
import { MyContext, getBaseApiReact } from "../../App";
import { LoadingButton } from "@mui/lab";
import { getBaseApi, getFee } from "../../background";
-
+import LockIcon from '@mui/icons-material/Lock';
+import NoEncryptionGmailerrorredIcon from '@mui/icons-material/NoEncryptionGmailerrorred';
+import { Spacer } from "../../common/Spacer";
const cache = new CellMeasurerCache({
fixedWidth: true,
defaultHeight: 50,
@@ -231,7 +233,17 @@ export const AddGroupList = ({ setInfoSnack, setOpenSnack }) => {
handlePopoverOpen(event, index)}
>
-
+ {group?.isOpen === false && (
+
+ )}
+ {group?.isOpen === true && (
+
+ )}
+
{
};
return (
-
+
Groups list
{
@@ -278,6 +293,6 @@ export const AddGroupList = ({ setInfoSnack, setOpenSnack }) => {
)}
-
+
);
};
diff --git a/src/components/Group/ListOfGroupPromotions.tsx b/src/components/Group/ListOfGroupPromotions.tsx
index fdc13f2..a9ed3de 100644
--- a/src/components/Group/ListOfGroupPromotions.tsx
+++ b/src/components/Group/ListOfGroupPromotions.tsx
@@ -33,6 +33,8 @@ import {
import { getNameInfo } from "./Group";
import { getBaseApi, getFee } from "../../background";
import { LoadingButton } from "@mui/lab";
+import LockIcon from '@mui/icons-material/Lock';
+import NoEncryptionGmailerrorredIcon from '@mui/icons-material/NoEncryptionGmailerrorred';
import {
MyContext,
getArbitraryEndpointReact,
@@ -540,6 +542,31 @@ export const ListOfGroupPromotions = () => {
{promotion?.groupName}
+
+
+ {promotion?.isOpen === false && (
+
+ )}
+ {promotion?.isOpen === true && (
+
+ )}
+
+ {promotion?.isOpen ? 'Public group' : 'Private group' }
+
+
{
handlePopoverOpen(event, index)}>
-
+ {invite?.isOpen === false && (
+
+ )}
+ {invite?.isOpen === true && (
+
+ )}
+
@@ -194,9 +206,21 @@ export const UserListOfInvites = ({myAddress, setInfoSnack, setOpenSnack}) => {
};
return (
-
+
Invite list
-
+
{({ height, width }) => (
{
)}
-
+
);
}
From c17b67106cabd98d85ff8f6363e56cc61239f862 Mon Sep 17 00:00:00 2001
From: PhilReact
Date: Mon, 16 Dec 2024 03:39:16 +0200
Subject: [PATCH 014/119] fixes
---
src/components/Chat/ChatOptions.tsx | 74 +----------------------------
src/components/Group/AddGroup.tsx | 1 -
src/components/Group/Group.tsx | 2 +-
3 files changed, 2 insertions(+), 75 deletions(-)
diff --git a/src/components/Chat/ChatOptions.tsx b/src/components/Chat/ChatOptions.tsx
index 87f3329..42f009c 100644
--- a/src/components/Chat/ChatOptions.tsx
+++ b/src/components/Chat/ChatOptions.tsx
@@ -325,79 +325,7 @@ export const ChatOptions = ({ messages : untransformedMessages, goToMessage, mem
}}
>
- {/*
-
-
-
- {message?.senderName?.charAt(0)}
-
-
- {message?.senderName}
-
-
-
-
- {formatTimestamp(message.timestamp)}
- {
- const findMsgIndex = messages.findIndex(
- (item) =>
- item?.signature === message?.signature
- );
- if (findMsgIndex !== -1) {
- goToMessage(findMsgIndex);
- }
- }}
- >
- "
- }
- />
-
- */}
+
);
})}
diff --git a/src/components/Group/AddGroup.tsx b/src/components/Group/AddGroup.tsx
index af23fd9..1cf86fe 100644
--- a/src/components/Group/AddGroup.tsx
+++ b/src/components/Group/AddGroup.tsx
@@ -218,7 +218,6 @@ export const AddGroup = ({ address, open, setOpen }) => {
overflowY: "auto",
color: "white",
flexDirection: 'column',
- flexGrow: 1,
display: 'flex'
}}
>
diff --git a/src/components/Group/Group.tsx b/src/components/Group/Group.tsx
index 7d77cc2..c699f48 100644
--- a/src/components/Group/Group.tsx
+++ b/src/components/Group/Group.tsx
@@ -2252,7 +2252,7 @@ export const Group = ({
getTimestampEnterChatParent={getTimestampEnterChat}
/>
)}
- {isPrivate &&firstSecretKeyInCreation &&
+ {isPrivate && firstSecretKeyInCreation &&
triedToFetchSecretKey &&
!secretKeyPublishDate && (
Date: Mon, 16 Dec 2024 05:14:44 +0200
Subject: [PATCH 015/119] bug fixes
---
src/components/Chat/ChatGroup.tsx | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/src/components/Chat/ChatGroup.tsx b/src/components/Chat/ChatGroup.tsx
index 25be721..b7f7d4f 100644
--- a/src/components/Chat/ChatGroup.tsx
+++ b/src/components/Chat/ChatGroup.tsx
@@ -223,15 +223,15 @@ const [messageSize, setMessageSize] = useState(0)
setChatReferences((prev) => {
const organizedChatReferences = { ...prev };
combineUIAndExtensionMsgs
- .filter((rawItem) => rawItem && rawItem.chatReference && (rawItem.decryptedData?.type === "reaction" || rawItem.decryptedData?.type === "edit" || rawItem?.type === "edit" || rawItem?.type === "reaction"))
+ .filter((rawItem) => rawItem && rawItem.chatReference && (rawItem?.decryptedData?.type === "reaction" || rawItem?.decryptedData?.type === "edit" || rawItem?.type === "edit" || rawItem?.isEdited || rawItem?.type === "reaction"))
.forEach((item) => {
try {
- if(item.decryptedData?.type === "edit"){
+ if(item?.decryptedData?.type === "edit"){
organizedChatReferences[item.chatReference] = {
...(organizedChatReferences[item.chatReference] || {}),
edit: item.decryptedData,
};
- } else if(item?.type === "edit"){
+ } else if(item?.type === "edit" || item?.isEdited){
organizedChatReferences[item.chatReference] = {
...(organizedChatReferences[item.chatReference] || {}),
edit: item,
@@ -287,6 +287,7 @@ const [messageSize, setMessageSize] = useState(0)
});
} else {
let firstUnreadFound = false;
+ console.log('combineUIAndExtensionMsgs', combineUIAndExtensionMsgs)
const formatted = combineUIAndExtensionMsgs
.filter((rawItem) => !rawItem?.chatReference)
.map((item) => {
@@ -311,15 +312,15 @@ const [messageSize, setMessageSize] = useState(0)
const organizedChatReferences = { ...prev };
combineUIAndExtensionMsgs
- .filter((rawItem) => rawItem && rawItem.chatReference && (rawItem.decryptedData?.type === "reaction" || rawItem.decryptedData?.type === "edit" || rawItem?.type === "edit" || rawItem?.type === "reaction"))
+ .filter((rawItem) => rawItem && rawItem.chatReference && (rawItem?.decryptedData?.type === "reaction" || rawItem?.decryptedData?.type === "edit" || rawItem?.type === "edit" || rawItem?.isEdited || rawItem?.type === "reaction"))
.forEach((item) => {
try {
- if(item.decryptedData?.type === "edit"){
+ if(item?.decryptedData?.type === "edit"){
organizedChatReferences[item.chatReference] = {
...(organizedChatReferences[item.chatReference] || {}),
edit: item.decryptedData,
};
- } else if(item?.type === "edit"){
+ } else if(item?.type === "edit" || item?.isEdited){
organizedChatReferences[item.chatReference] = {
...(organizedChatReferences[item.chatReference] || {}),
edit: item,
From 900fe2a2fbebb8a2d955174408430eda4f50c0ba Mon Sep 17 00:00:00 2001
From: PhilReact
Date: Mon, 16 Dec 2024 11:20:53 +0200
Subject: [PATCH 016/119] changes to saved pinned apps
---
src/App.tsx | 2 +-
src/atoms/global.ts | 4 +
src/components/Apps/AppsDesktop.tsx | 2 +-
src/components/Apps/AppsDevMode.tsx | 2 +-
src/components/DesktopSideBar.tsx | 4 +-
src/components/Save/Save.tsx | 235 ++++++++++++++++++++++++++--
src/useQortalGetSaveSettings.tsx | 10 +-
src/useRetrieveDataLocalStorage.tsx | 5 +-
8 files changed, 241 insertions(+), 23 deletions(-)
diff --git a/src/App.tsx b/src/App.tsx
index a442e97..01d00e1 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -388,7 +388,7 @@ function App() {
const qortalRequestCheckbox1Ref = useRef(null);
useRetrieveDataLocalStorage();
- useQortalGetSaveSettings(userInfo?.name);
+ useQortalGetSaveSettings(userInfo?.name, extState === "authenticated");
const [fullScreen, setFullScreen] = useRecoilState(fullScreenAtom);
const [isEnabledDevMode, setIsEnabledDevMode] =
useRecoilState(enabledDevModeAtom);
diff --git a/src/atoms/global.ts b/src/atoms/global.ts
index 846753b..dfb9f82 100644
--- a/src/atoms/global.ts
+++ b/src/atoms/global.ts
@@ -40,6 +40,10 @@ export const sortablePinnedAppsAtom = atom({
{
name: 'Q-Manager',
service: 'APP'
+ },
+ {
+ name: 'Q-Blog',
+ service: 'APP'
}
],
});
diff --git a/src/components/Apps/AppsDesktop.tsx b/src/components/Apps/AppsDesktop.tsx
index 121dd6e..8797a52 100644
--- a/src/components/Apps/AppsDesktop.tsx
+++ b/src/components/Apps/AppsDesktop.tsx
@@ -407,7 +407,7 @@ export const AppsDesktop = ({ mode, setMode, show , myName, goToHome, setDesktop
/>
*/}
-
+
{isEnabledDevMode && (
{
diff --git a/src/components/Apps/AppsDevMode.tsx b/src/components/Apps/AppsDevMode.tsx
index 297db33..0514ce3 100644
--- a/src/components/Apps/AppsDevMode.tsx
+++ b/src/components/Apps/AppsDevMode.tsx
@@ -282,7 +282,7 @@ export const AppsDevMode = ({ mode, setMode, show , myName, goToHome, setDesktop
/>
-
+
{
setDesktopViewMode('dev')
diff --git a/src/components/DesktopSideBar.tsx b/src/components/DesktopSideBar.tsx
index ae55a50..9ee123d 100644
--- a/src/components/DesktopSideBar.tsx
+++ b/src/components/DesktopSideBar.tsx
@@ -11,7 +11,7 @@ import { useRecoilState } from 'recoil';
import { enabledDevModeAtom } from '../atoms/global';
import { AppsIcon } from '../assets/Icons/AppsIcon';
-export const DesktopSideBar = ({goToHome, setDesktopSideView, toggleSideViewDirects, hasUnreadDirects, isDirects, toggleSideViewGroups,hasUnreadGroups, isGroups, isApps, setDesktopViewMode, desktopViewMode }) => {
+export const DesktopSideBar = ({goToHome, setDesktopSideView, toggleSideViewDirects, hasUnreadDirects, isDirects, toggleSideViewGroups,hasUnreadGroups, isGroups, isApps, setDesktopViewMode, desktopViewMode, myName }) => {
const [isEnabledDevMode, setIsEnabledDevMode] = useRecoilState(enabledDevModeAtom)
return (
@@ -98,7 +98,7 @@ export const DesktopSideBar = ({goToHome, setDesktopSideView, toggleSideViewDire
/>
*/}
-
+
{/* */}
{isEnabledDevMode && (
{
+import { Spacer } from "../../common/Spacer";
+import { LoadingButton } from "@mui/lab";
+import { saveToLocalStorage } from "../Apps/AppsNavBar";
+export const Save = ({ isDesktop, disableWidth, myName }) => {
const [pinnedApps, setPinnedApps] = useRecoilState(sortablePinnedAppsAtom);
const [settingsQdnLastUpdated, setSettingsQdnLastUpdated] = useRecoilState(
settingsQDNLastUpdatedAtom
@@ -31,7 +34,7 @@ export const Save = ({ isDesktop, disableWidth }) => {
const [isLoading, setIsLoading] = useState(false);
const [infoSnack, setInfoSnack] = useState(null);
const [oldPinnedApps, setOldPinnedApps] = useRecoilState(oldPinnedAppsAtom);
-
+ const [anchorEl, setAnchorEl] = useState(null);
const { show } = useContext(MyContext);
const hasChanged = useMemo(() => {
@@ -83,9 +86,7 @@ export const Save = ({ isDesktop, disableWidth }) => {
.sendMessage(
"ENCRYPT_DATA",
{
-
- data64,
-
+ data64,
},
60000
)
@@ -135,6 +136,7 @@ export const Save = ({ isDesktop, disableWidth }) => {
message: "Sucessfully published to QDN",
});
setOpenSnack(true);
+ setAnchorEl(null)
}
}
} catch (error) {
@@ -147,20 +149,31 @@ export const Save = ({ isDesktop, disableWidth }) => {
setIsLoading(false);
}
};
+ const handlePopupClick = (event) => {
+ event.stopPropagation(); // Prevent parent onClick from firing
+ setAnchorEl(event.currentTarget);
+ };
+
+ const revertChanges = () => {
+ setPinnedApps(oldPinnedApps);
+ saveToLocalStorage("ext_saved_settings", "sortablePinnedApps", null);
+ setAnchorEl(null)
+ };
+
return (
<>
{isDesktop ? (
{
/>
)}
+ setAnchorEl(null)} // Close popover on click outside
+ anchorOrigin={{
+ vertical: "bottom",
+ horizontal: "center",
+ }}
+ transformOrigin={{
+ vertical: "top",
+ horizontal: "center",
+ }}
+ sx={{
+ width: "300px",
+ maxWidth: "90%",
+ maxHeight: "80%",
+ overflow: "auto",
+ }}
+ >
+
+ {!myName ? (
+
+
+ You need a registered Qortal name to save your pinned apps to QDN.
+
+
+ ) : (
+ <>
+ {hasChanged && (
+
+
+ You have unsaved changes to your pinned apps. Save them to QDN.
+
+
+
+ Save to QDN
+
+
+ {!isNaN(settingsQdnLastUpdated) && settingsQdnLastUpdated > 0 && (
+ <>
+
+ Don't like your current local changes? Would you like to
+ reset to your saved QDN pinned apps?
+
+
+
+ Revert to QDN
+
+ >
+ )}
+ {!isNaN(settingsQdnLastUpdated) && settingsQdnLastUpdated === 0 && (
+ <>
+
+ Don't like your current local changes? Would you like to
+ reset to the default pinned apps?
+
+
+
+ Revert to default
+
+ >
+ )}
+
+ )}
+ {!isNaN(settingsQdnLastUpdated) && settingsQdnLastUpdated === -100 && (
+
+
+ The app was unable to download your existing QDN-saved pinned
+ apps. Would you like to overwrite those changes?
+
+
+
+ Overwrite to QDN
+
+
+ )}
+ {!hasChanged && (
+
+
+ You currently do not have any changes to your pinned apps
+
+
+
+ )}
+ >
+ )}
+
+
+
{
);
data = await res.text();
-
if(!data) throw new Error('Unable to fetch publish')
const decryptedKey: any = await decryptResource(data);
@@ -53,7 +52,8 @@ const getPublishRecord = async (myName) => {
}
};
-export const useQortalGetSaveSettings = (myName) => {
+
+export const useQortalGetSaveSettings = (myName, isAuthenticated) => {
const setSortablePinnedApps = useSetRecoilState(sortablePinnedAppsAtom);
const setCanSave = useSetRecoilState(canSaveSettingToQdnAtom);
const setSettingsQDNLastUpdated = useSetRecoilState(settingsQDNLastUpdatedAtom);
@@ -67,7 +67,7 @@ export const useQortalGetSaveSettings = (myName) => {
const settings = await getPublish(myName)
if(settings?.sortablePinnedApps && timestamp > settingsLocalLastUpdated){
setSortablePinnedApps(settings.sortablePinnedApps)
-
+
setSettingsQDNLastUpdated(timestamp || 0)
} else if(settings?.sortablePinnedApps){
setSettingsQDNLastUpdated(timestamp || 0)
@@ -87,8 +87,8 @@ export const useQortalGetSaveSettings = (myName) => {
}
}, [])
useEffect(()=> {
- if(!myName || !settingsLocalLastUpdated) return
+ if(!myName || !settingsLocalLastUpdated || !isAuthenticated) return
getSavedSettings(myName, settingsLocalLastUpdated)
- }, [getSavedSettings, myName, settingsLocalLastUpdated])
+ }, [getSavedSettings, myName, settingsLocalLastUpdated, isAuthenticated])
}
diff --git a/src/useRetrieveDataLocalStorage.tsx b/src/useRetrieveDataLocalStorage.tsx
index 88e93f4..8f808ab 100644
--- a/src/useRetrieveDataLocalStorage.tsx
+++ b/src/useRetrieveDataLocalStorage.tsx
@@ -23,8 +23,11 @@ export const useRetrieveDataLocalStorage = () => {
const pinnedAppsLocal = fetchFromLocalStorage('ext_saved_settings')
if(pinnedAppsLocal?.sortablePinnedApps){
setSortablePinnedApps(pinnedAppsLocal?.sortablePinnedApps)
+ setSettingsLocalLastUpdated(pinnedAppsLocal?.timestamp || -1)
+ } else {
+ setSettingsLocalLastUpdated(-1)
}
- setSettingsLocalLastUpdated(pinnedAppsLocal?.timestamp || -1)
+
}, [])
useEffect(()=> {
From c8a08c9fa365f8da8ebe8bc5dcd6db665ecae362 Mon Sep 17 00:00:00 2001
From: PhilReact
Date: Mon, 16 Dec 2024 11:38:06 +0200
Subject: [PATCH 017/119] fix mute
---
src/background.ts | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/background.ts b/src/background.ts
index fa786b9..845df71 100644
--- a/src/background.ts
+++ b/src/background.ts
@@ -2964,6 +2964,9 @@ function setupMessageListener() {
case "publishOnQDN":
publishOnQDNCase(request, event);
break;
+ case "getUserSettings":
+ getUserSettingsCase(request, event);
+ break;
case "handleActiveGroupDataFromSocket":
handleActiveGroupDataFromSocketCase(request, event);
break;
From d77b6caed4fe1c053b0561f3c1d970cfd7834b2e Mon Sep 17 00:00:00 2001
From: PhilReact
Date: Mon, 16 Dec 2024 11:48:42 +0200
Subject: [PATCH 018/119] fixes
---
src/background.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/background.ts b/src/background.ts
index 845df71..c6fdb62 100644
--- a/src/background.ts
+++ b/src/background.ts
@@ -2220,7 +2220,7 @@ export async function createGroup({
const res = await processTransactionVersion2(signedBytes);
if (!res?.signature)
- throw new Error("Transaction was not able to be processed");
+ throw new Error(res?.message || "Transaction was not able to be processed");
return res;
}
export async function inviteToGroup({ groupId, qortalAddress, inviteTime }) {
From 4c4ee5b1d7686a32ebd6020f29c1746c581fbde7 Mon Sep 17 00:00:00 2001
From: PhilReact
Date: Mon, 16 Dec 2024 14:00:43 +0200
Subject: [PATCH 019/119] added force publish option for admins
---
src/components/Chat/AdminSpace.tsx | 5 +-
src/components/Chat/AdminSpaceInner.tsx | 376 +++++++++++++--------
src/components/Chat/ChatGroup.tsx | 23 +-
src/components/Chat/CreateCommonSecret.tsx | 6 +-
src/components/Group/Group.tsx | 14 +-
5 files changed, 269 insertions(+), 155 deletions(-)
diff --git a/src/components/Chat/AdminSpace.tsx b/src/components/Chat/AdminSpace.tsx
index f340e45..6eaf541 100644
--- a/src/components/Chat/AdminSpace.tsx
+++ b/src/components/Chat/AdminSpace.tsx
@@ -27,7 +27,8 @@ export const AdminSpace = ({
myAddress,
hide,
defaultThread,
- setDefaultThread
+ setDefaultThread,
+ setIsForceShowCreationKeyPopup
}) => {
const { rootHeight } = useContext(MyContext);
const [isMoved, setIsMoved] = useState(false);
@@ -59,7 +60,7 @@ export const AdminSpace = ({
justifyContent: 'center',
paddingTop: '25px'
}}>Sorry, this space is only for Admins.}
- {isAdmin && }
+ {isAdmin && }
);
diff --git a/src/components/Chat/AdminSpaceInner.tsx b/src/components/Chat/AdminSpaceInner.tsx
index 1307ad1..65852b6 100644
--- a/src/components/Chat/AdminSpaceInner.tsx
+++ b/src/components/Chat/AdminSpaceInner.tsx
@@ -1,150 +1,248 @@
-import React, { useCallback, useContext, useEffect, useState } from 'react'
-import { MyContext, getArbitraryEndpointReact, getBaseApiReact } from '../../App';
-import { Box, Button, Typography } from '@mui/material';
-import { decryptResource, validateSecretKey } from '../Group/Group';
-import { getFee } from '../../background';
-import { base64ToUint8Array } from '../../qdn/encryption/group-encryption';
-import { uint8ArrayToObject } from '../../backgroundFunctions/encryption';
-import { formatTimestampForum } from '../../utils/time';
-import { Spacer } from '../../common/Spacer';
+import React, { useCallback, useContext, useEffect, useState } from "react";
+import {
+ MyContext,
+ getArbitraryEndpointReact,
+ getBaseApiReact,
+} from "../../App";
+import { Box, Button, Typography } from "@mui/material";
+import {
+ decryptResource,
+ getPublishesFromAdmins,
+ validateSecretKey,
+} from "../Group/Group";
+import { getFee } from "../../background";
+import { base64ToUint8Array } from "../../qdn/encryption/group-encryption";
+import { uint8ArrayToObject } from "../../backgroundFunctions/encryption";
+import { formatTimestampForum } from "../../utils/time";
+import { Spacer } from "../../common/Spacer";
+export const getPublishesFromAdminsAdminSpace = async (
+ admins: string[],
+ groupId
+) => {
+ const queryString = admins.map((name) => `name=${name}`).join("&");
+ const url = `${getBaseApiReact()}${getArbitraryEndpointReact()}?mode=ALL&service=DOCUMENT_PRIVATE&identifier=admins-symmetric-qchat-group-${groupId}&exactmatchnames=true&limit=0&reverse=true&${queryString}&prefix=true`;
+ const response = await fetch(url);
+ if (!response.ok) {
+ throw new Error("network error");
+ }
+ const adminData = await response.json();
-export const getPublishesFromAdminsAdminSpace = async (admins: string[], groupId) => {
- const queryString = admins.map((name) => `name=${name}`).join("&");
- const url = `${getBaseApiReact()}${getArbitraryEndpointReact()}?mode=ALL&service=DOCUMENT_PRIVATE&identifier=admins-symmetric-qchat-group-${
- groupId
- }&exactmatchnames=true&limit=0&reverse=true&${queryString}&prefix=true`;
- const response = await fetch(url);
- if (!response.ok) {
- throw new Error("network error");
+ const filterId = adminData.filter(
+ (data: any) => data.identifier === `admins-symmetric-qchat-group-${groupId}`
+ );
+ if (filterId?.length === 0) {
+ return false;
+ }
+ const sortedData = filterId.sort((a: any, b: any) => {
+ // Get the most recent date for both a and b
+ const dateA = a.updated ? new Date(a.updated) : new Date(a.created);
+ const dateB = b.updated ? new Date(b.updated) : new Date(b.created);
+
+ // Sort by most recent
+ return dateB.getTime() - dateA.getTime();
+ });
+
+ return sortedData[0];
+};
+
+export const AdminSpaceInner = ({
+ selectedGroup,
+ adminsWithNames,
+ setIsForceShowCreationKeyPopup,
+}) => {
+ const [adminGroupSecretKey, setAdminGroupSecretKey] = useState(null);
+ const [isFetchingAdminGroupSecretKey, setIsFetchingAdminGroupSecretKey] =
+ useState(true);
+ const [isFetchingGroupSecretKey, setIsFetchingGroupSecretKey] =
+ useState(true);
+ const [
+ adminGroupSecretKeyPublishDetails,
+ setAdminGroupSecretKeyPublishDetails,
+ ] = useState(null);
+ const [groupSecretKeyPublishDetails, setGroupSecretKeyPublishDetails] =
+ useState(null);
+ const [isLoadingPublishKey, setIsLoadingPublishKey] = useState(false);
+ const { show, setTxList, setInfoSnackCustom, setOpenSnackGlobal } =
+ useContext(MyContext);
+
+ const getAdminGroupSecretKey = useCallback(async () => {
+ try {
+ if (!selectedGroup) return;
+ const getLatestPublish = await getPublishesFromAdminsAdminSpace(
+ adminsWithNames.map((admin) => admin?.name),
+ selectedGroup
+ );
+ if (getLatestPublish === false) return;
+ let data;
+
+ const res = await fetch(
+ `${getBaseApiReact()}/arbitrary/DOCUMENT_PRIVATE/${
+ getLatestPublish.name
+ }/${getLatestPublish.identifier}?encoding=base64`
+ );
+ data = await res.text();
+
+ const decryptedKey: any = await decryptResource(data);
+ const dataint8Array = base64ToUint8Array(decryptedKey.data);
+ const decryptedKeyToObject = uint8ArrayToObject(dataint8Array);
+ if (!validateSecretKey(decryptedKeyToObject))
+ throw new Error("SecretKey is not valid");
+ setAdminGroupSecretKey(decryptedKeyToObject);
+ setAdminGroupSecretKeyPublishDetails(getLatestPublish);
+ } catch (error) {
+ } finally {
+ setIsFetchingAdminGroupSecretKey(false);
}
- const adminData = await response.json();
-
- const filterId = adminData.filter(
- (data: any) =>
- data.identifier === `admins-symmetric-qchat-group-${groupId}`
- );
- if (filterId?.length === 0) {
- return false;
+ }, [adminsWithNames, selectedGroup]);
+
+ const getGroupSecretKey = useCallback(async () => {
+ try {
+ if (!selectedGroup) return;
+ const getLatestPublish = await getPublishesFromAdmins(
+ adminsWithNames.map((admin) => admin?.name),
+ selectedGroup
+ );
+ if (getLatestPublish === false) setGroupSecretKeyPublishDetails(false);
+ setGroupSecretKeyPublishDetails(getLatestPublish);
+ } catch (error) {
+ } finally {
+ setIsFetchingGroupSecretKey(false);
}
- const sortedData = filterId.sort((a: any, b: any) => {
- // Get the most recent date for both a and b
- const dateA = a.updated ? new Date(a.updated) : new Date(a.created);
- const dateB = b.updated ? new Date(b.updated) : new Date(b.created);
-
- // Sort by most recent
- return dateB.getTime() - dateA.getTime();
- });
-
- return sortedData[0];
+ }, [adminsWithNames, selectedGroup]);
+
+ const createCommonSecretForAdmins = async () => {
+ try {
+ const fee = await getFee("ARBITRARY");
+ await show({
+ message: "Would you like to perform an ARBITRARY transaction?",
+ publishFee: fee.fee + " QORT",
+ });
+ setIsLoadingPublishKey(true);
+
+ window
+ .sendMessage("encryptAndPublishSymmetricKeyGroupChatForAdmins", {
+ groupId: selectedGroup,
+ previousData: null,
+ admins: adminsWithNames,
+ })
+ .then((response) => {
+ if (!response?.error) {
+ setInfoSnackCustom({
+ type: "success",
+ message:
+ "Successfully re-encrypted secret key. It may take a couple of minutes for the changes to propagate. Refresh the group in 5 mins.",
+ });
+ setOpenSnackGlobal(true);
+ return;
+ }
+ setInfoSnackCustom({
+ type: "error",
+ message: response?.error || "unable to re-encrypt secret key",
+ });
+ setOpenSnackGlobal(true);
+ })
+ .catch((error) => {
+ setInfoSnackCustom({
+ type: "error",
+ message: error?.message || "unable to re-encrypt secret key",
+ });
+ setOpenSnackGlobal(true);
+ });
+ } catch (error) {}
};
-export const AdminSpaceInner = ({selectedGroup, adminsWithNames}) => {
- const [adminGroupSecretKey, setAdminGroupSecretKey] = useState(null)
- const [isFetchingAdminGroupSecretKey, setIsFetchingAdminGroupSecretKey] = useState(true)
- const [adminGroupSecretKeyPublishDetails, setAdminGroupSecretKeyPublishDetails] = useState(null)
-
- const [isLoadingPublishKey, setIsLoadingPublishKey] = useState(false)
- const { show, setTxList, setInfoSnackCustom,
- setOpenSnackGlobal } = useContext(MyContext);
-
-
- const getAdminGroupSecretKey = useCallback(async ()=> {
- try {
- if(!selectedGroup) return
- const getLatestPublish = await getPublishesFromAdminsAdminSpace(adminsWithNames.map((admin)=> admin?.name), selectedGroup)
- if(getLatestPublish === false) return
- let data;
-
- const res = await fetch(
- `${getBaseApiReact()}/arbitrary/DOCUMENT_PRIVATE/${getLatestPublish.name}/${
- getLatestPublish.identifier
- }?encoding=base64`
- );
- data = await res.text();
-
- const decryptedKey: any = await decryptResource(data);
- const dataint8Array = base64ToUint8Array(decryptedKey.data);
- const decryptedKeyToObject = uint8ArrayToObject(dataint8Array);
- if (!validateSecretKey(decryptedKeyToObject))
- throw new Error("SecretKey is not valid");
- setAdminGroupSecretKey(decryptedKeyToObject)
- setAdminGroupSecretKeyPublishDetails(getLatestPublish)
- } catch (error) {
-
- } finally {
- setIsFetchingAdminGroupSecretKey(false)
- }
- }, [adminsWithNames, selectedGroup])
-
- const createCommonSecretForAdmins = async ()=> {
- try {
- const fee = await getFee('ARBITRARY')
- await show({
- message: "Would you like to perform an ARBITRARY transaction?" ,
- publishFee: fee.fee + ' QORT'
- })
- setIsLoadingPublishKey(true)
-
-
- window.sendMessage("encryptAndPublishSymmetricKeyGroupChatForAdmins", {
- groupId: selectedGroup,
- previousData: null,
- admins: adminsWithNames
- })
- .then((response) => {
-
- if (!response?.error) {
- setInfoSnackCustom({
- type: "success",
- message: "Successfully re-encrypted secret key. It may take a couple of minutes for the changes to propagate. Refresh the group in 5 mins.",
- });
- setOpenSnackGlobal(true);
- return
- }
- setInfoSnackCustom({
- type: "error",
- message: response?.error || "unable to re-encrypt secret key",
- });
- setOpenSnackGlobal(true);
- })
- .catch((error) => {
- setInfoSnackCustom({
- type: "error",
- message: error?.message || "unable to re-encrypt secret key",
- });
- setOpenSnackGlobal(true);
- });
-
- } catch (error) {
-
- }
- }
- useEffect(() => {
- getAdminGroupSecretKey()
- }, [getAdminGroupSecretKey]);
+ useEffect(() => {
+ getAdminGroupSecretKey();
+ getGroupSecretKey();
+ }, [getAdminGroupSecretKey, getGroupSecretKey]);
return (
-
+
+ Reminder: After publishing the key, it will take a couple of minutes for it to appear. Please just wait.
-
- {isFetchingAdminGroupSecretKey && Fetching Admins secret keys}
- {!isFetchingAdminGroupSecretKey && !adminGroupSecretKey && No secret key published yet}
- {adminGroupSecretKeyPublishDetails && (
- Last encryption date: {formatTimestampForum(adminGroupSecretKeyPublishDetails?.updated || adminGroupSecretKeyPublishDetails?.created)}
+
+ {isFetchingGroupSecretKey && (
+ Fetching Group secret key publishes
)}
- Publish admin secret key
+ {!isFetchingGroupSecretKey &&
+ groupSecretKeyPublishDetails === false && (
+ No secret key published yet
+ )}
+ {groupSecretKeyPublishDetails && (
+
+ Last encryption date:{" "}
+ {formatTimestampForum(
+ groupSecretKeyPublishDetails?.updated ||
+ groupSecretKeyPublishDetails?.created
+ )}{" "}
+ {` by ${groupSecretKeyPublishDetails?.name}`}
+
+ )}
+
+ Publish group secret key
+
+
+ This key is to encrypt GROUP related content. This is the only one used in this UI as of now. All group members will be able to see content encrypted with this key.
+
+
+
+ {isFetchingAdminGroupSecretKey && (
+ Fetching Admins secret key
+ )}
+ {!isFetchingAdminGroupSecretKey && !adminGroupSecretKey && (
+ No secret key published yet
+ )}
+ {adminGroupSecretKeyPublishDetails && (
+
+ Last encryption date:{" "}
+ {formatTimestampForum(
+ adminGroupSecretKeyPublishDetails?.updated ||
+ adminGroupSecretKeyPublishDetails?.created
+ )}
+
+ )}
+
+ Publish admin secret key
+
+
+ This key is to encrypt ADMIN related content. Only admins would see content encrypted with it.
- )
-}
+ );
+};
diff --git a/src/components/Chat/ChatGroup.tsx b/src/components/Chat/ChatGroup.tsx
index b7f7d4f..f4ae843 100644
--- a/src/components/Chat/ChatGroup.tsx
+++ b/src/components/Chat/ChatGroup.tsx
@@ -54,14 +54,14 @@ const [messageSize, setMessageSize] = useState(0)
const handleUpdateRef = useRef(null);
- const getTimestampEnterChat = async () => {
+ const getTimestampEnterChat = async (selectedGroup) => {
try {
return new Promise((res, rej) => {
window.sendMessage("getTimestampEnterChat")
.then((response) => {
if (!response?.error) {
- if(response && selectedGroup && response[selectedGroup]){
- lastReadTimestamp.current = response[selectedGroup]
+ if(response && selectedGroup){
+ lastReadTimestamp.current = response[selectedGroup] || undefined
window.sendMessage("addTimestampEnterChat", {
timestamp: Date.now(),
groupId: selectedGroup
@@ -89,8 +89,9 @@ const [messageSize, setMessageSize] = useState(0)
};
useEffect(()=> {
- getTimestampEnterChat()
- }, [])
+ if(!selectedGroup) return
+ getTimestampEnterChat(selectedGroup)
+ }, [selectedGroup])
@@ -208,7 +209,9 @@ const [messageSize, setMessageSize] = useState(0)
const formatted = combineUIAndExtensionMsgs
.filter((rawItem) => !rawItem?.chatReference)
.map((item) => {
-
+ const additionalFields = item?.data === 'NDAwMQ==' ? {
+ text: "First group key created.
"
+ } : {}
return {
...item,
id: item.signature,
@@ -216,6 +219,7 @@ const [messageSize, setMessageSize] = useState(0)
repliedTo: item?.repliedTo || item?.decryptedData?.repliedTo,
unread: item?.sender === myAddress ? false : !!item?.chatReference ? false : true,
isNotEncrypted: !!item?.messageText,
+ ...additionalFields
}
});
setMessages((prev) => [...prev, ...formatted]);
@@ -287,10 +291,12 @@ const [messageSize, setMessageSize] = useState(0)
});
} else {
let firstUnreadFound = false;
- console.log('combineUIAndExtensionMsgs', combineUIAndExtensionMsgs)
const formatted = combineUIAndExtensionMsgs
.filter((rawItem) => !rawItem?.chatReference)
.map((item) => {
+ const additionalFields = item?.data === 'NDAwMQ==' ? {
+ text: "First group key created.
"
+ } : {}
const divide = lastReadTimestamp.current && !firstUnreadFound && item.timestamp > lastReadTimestamp.current && myAddress !== item?.sender;
if(divide){
@@ -303,7 +309,8 @@ const [messageSize, setMessageSize] = useState(0)
repliedTo: item?.repliedTo || item?.decryptedData?.repliedTo,
isNotEncrypted: !!item?.messageText,
unread: false,
- divide
+ divide,
+ ...additionalFields
}
});
setMessages(formatted);
diff --git a/src/components/Chat/CreateCommonSecret.tsx b/src/components/Chat/CreateCommonSecret.tsx
index c371c55..468b35f 100644
--- a/src/components/Chat/CreateCommonSecret.tsx
+++ b/src/components/Chat/CreateCommonSecret.tsx
@@ -8,7 +8,7 @@ import { decryptResource, getGroupAdmins, validateSecretKey } from '../Group/Gro
import { base64ToUint8Array } from '../../qdn/encryption/group-encryption';
import { uint8ArrayToObject } from '../../backgroundFunctions/encryption';
-export const CreateCommonSecret = ({groupId, secretKey, isOwner, myAddress, secretKeyDetails, userInfo, noSecretKey, setHideCommonKeyPopup}) => {
+export const CreateCommonSecret = ({groupId, secretKey, isOwner, myAddress, secretKeyDetails, userInfo, noSecretKey, setHideCommonKeyPopup, setIsForceShowCreationKeyPopup}) => {
const { show, setTxList } = useContext(MyContext);
const [openSnack, setOpenSnack] = React.useState(false);
@@ -131,6 +131,9 @@ export const CreateCommonSecret = ({groupId, secretKey, isOwner, myAddress, sec
]);
}
setIsLoading(false);
+ setTimeout(() => {
+ setIsForceShowCreationKeyPopup(false)
+ }, 1000);
})
.catch((error) => {
console.error("Failed to encrypt and publish symmetric key for group chat:", error.message || "An error occurred");
@@ -173,6 +176,7 @@ export const CreateCommonSecret = ({groupId, secretKey, isOwner, myAddress, sec
}}>
{
setHideCommonKeyPopup(true)
+ setIsForceShowCreationKeyPopup(false)
}} size='small'>Hide
diff --git a/src/components/Group/Group.tsx b/src/components/Group/Group.tsx
index c699f48..ebfa5e2 100644
--- a/src/components/Group/Group.tsx
+++ b/src/components/Group/Group.tsx
@@ -432,7 +432,7 @@ export const Group = ({
const [appsModeDev, setAppsModeDev] = useState('home')
const [isOpenSideViewDirects, setIsOpenSideViewDirects] = useState(false)
const [isOpenSideViewGroups, setIsOpenSideViewGroups] = useState(false)
-
+ const [isForceShowCreationKeyPopup, setIsForceShowCreationKeyPopup] = useState(false)
const [groupsProperties, setGroupsProperties] = useState({})
@@ -2360,8 +2360,11 @@ export const Group = ({
setDefaultThread={setDefaultThread}
isPrivate={isPrivate}
/>
-
+ {groupSection === "adminSpace" && (
+
+ )}
+
>
)}
@@ -2374,11 +2377,11 @@ export const Group = ({
zIndex: 100,
}}
>
- {isPrivate && admins.includes(myAddress) &&
+ {(isPrivate && admins.includes(myAddress) &&
shouldReEncrypt &&
triedToFetchSecretKey &&
!firstSecretKeyInCreation &&
- !hideCommonKeyPopup && (
+ !hideCommonKeyPopup) || isForceShowCreationKeyPopup && (
Date: Mon, 16 Dec 2024 14:11:02 +0200
Subject: [PATCH 020/119] update version
---
electron/package.json | 2 +-
src/ExtStates/NotAuthenticated.tsx | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/electron/package.json b/electron/package.json
index 78de618..ec3a789 100644
--- a/electron/package.json
+++ b/electron/package.json
@@ -1,6 +1,6 @@
{
"name": "qortal-hub",
- "version": "0.3.7",
+ "version": "0.3.8",
"description": "A desktop app that gives you access to the Qortal network",
"author": {
"name": ""
diff --git a/src/ExtStates/NotAuthenticated.tsx b/src/ExtStates/NotAuthenticated.tsx
index d560e7f..548ef0b 100644
--- a/src/ExtStates/NotAuthenticated.tsx
+++ b/src/ExtStates/NotAuthenticated.tsx
@@ -23,7 +23,7 @@ import { set } from "lodash";
import { cleanUrl, isUsingLocal } from "../background";
const manifestData = {
- version: "0.3.7",
+ version: "0.3.8",
};
export const NotAuthenticated = ({
From ac7b00662ff261d1a06666a2d89747432d9b74a5 Mon Sep 17 00:00:00 2001
From: PhilReact
Date: Mon, 16 Dec 2024 16:18:25 +0200
Subject: [PATCH 021/119] fix local node auth
---
src/ExtStates/NotAuthenticated.tsx | 31 ++++++++++++++++++++++++++++--
1 file changed, 29 insertions(+), 2 deletions(-)
diff --git a/src/ExtStates/NotAuthenticated.tsx b/src/ExtStates/NotAuthenticated.tsx
index 548ef0b..a386186 100644
--- a/src/ExtStates/NotAuthenticated.tsx
+++ b/src/ExtStates/NotAuthenticated.tsx
@@ -82,8 +82,14 @@ export const NotAuthenticated = ({
const data = await response.json();
if (data?.height) {
setHasLocalNode(true);
+ return true
}
- } catch (error) {}
+ return false
+
+ } catch (error) {
+ return false
+
+ }
}, []);
useEffect(() => {
@@ -122,8 +128,9 @@ export const NotAuthenticated = ({
const validateApiKey = useCallback(async (key, fromStartUp) => {
try {
if (!currentNodeRef.current) return;
+ const stillHasLocal = await checkIfUserHasLocalNode()
const isLocalKey = cleanUrl(key?.url) === "127.0.0.1:12391";
- if (isLocalKey && !hasLocalNodeRef.current && !fromStartUp) {
+ if (isLocalKey && !stillHasLocal && !fromStartUp) {
throw new Error("Please turn on your local node");
}
const isCurrentNodeLocal =
@@ -185,6 +192,26 @@ export const NotAuthenticated = ({
} catch (error) {
setIsValidApiKey(false);
setUseLocalNode(false);
+ if(fromStartUp){
+ setCurrentNode({
+ url: "http://127.0.0.1:12391",
+ });
+ window
+ .sendMessage("setApiKey", null)
+ .then((response) => {
+ if (response) {
+ setApiKey(null);
+ handleSetGlobalApikey(null);
+ }
+ })
+ .catch((error) => {
+ console.error(
+ "Failed to set API key:",
+ error.message || "An error occurred"
+ );
+ });
+ return
+ }
setInfoSnack({
type: "error",
message: error?.message || "Select a valid apikey",
From 0f95f947eccd2a988a5996ad4fc3bc88cdb35517 Mon Sep 17 00:00:00 2001
From: PhilReact
Date: Tue, 17 Dec 2024 04:03:37 +0200
Subject: [PATCH 022/119] change unread color
---
src/App.tsx | 6 ++---
src/Wallets.tsx | 6 ++---
src/components/Apps/AppsDesktop.tsx | 4 ++--
src/components/Apps/AppsNavBarDesktop.tsx | 4 ++--
src/components/Chat/ChatDirect.tsx | 2 +-
src/components/Chat/ChatGroup.tsx | 2 +-
src/components/Chat/ChatList.tsx | 2 +-
src/components/Chat/GroupAnnouncements.tsx | 2 +-
src/components/Desktop/DesktopFooter.tsx | 4 ++--
src/components/Desktop/DesktopHeader.tsx | 6 ++---
src/components/DesktopSideBar.tsx | 2 +-
src/components/Embeds/AttachmentEmbed.tsx | 2 +-
src/components/Embeds/ImageEmbed.tsx | 2 +-
src/components/Embeds/PollEmbed.tsx | 2 +-
src/components/Group/AddGroupList.tsx | 2 +-
src/components/Group/Forum/NewThread.tsx | 2 --
src/components/Group/Group.tsx | 8 +++----
src/components/Group/GroupMenu.tsx | 14 ++++++------
.../Group/ListOfGroupPromotions.tsx | 2 +-
src/components/Group/UserListOfInvites.tsx | 2 +-
src/components/Mobile/MobileFooter.tsx | 4 ++--
src/components/Mobile/MobileHeader.tsx | 22 +++++++++----------
src/components/Save/Save.tsx | 8 +++----
src/index.css | 3 ++-
24 files changed, 56 insertions(+), 57 deletions(-)
diff --git a/src/App.tsx b/src/App.tsx
index 01d00e1..f6bffc6 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -2793,11 +2793,11 @@ function App() {
accept
{
{
@@ -330,7 +330,7 @@ export const AppsNavBarDesktop = ({disableBack}) => {
"& .MuiTypography-root": {
fontSize: "12px",
fontWeight: 600,
- color: isSelectedAppPinned ? "red" : "rgba(250, 250, 250, 0.5)",
+ color: isSelectedAppPinned ? "var(--danger)" : "rgba(250, 250, 250, 0.5)",
},
}}
primary={`${isSelectedAppPinned ? "Unpin app" : "Pin app"}`}
diff --git a/src/components/Chat/ChatDirect.tsx b/src/components/Chat/ChatDirect.tsx
index ace54ce..d23f026 100644
--- a/src/components/Chat/ChatDirect.tsx
+++ b/src/components/Chat/ChatDirect.tsx
@@ -656,7 +656,7 @@ useEffect(() => {
}}>
4000 ? 'var(--unread)' : 'unset'
+ color: messageSize > 4000 ? 'var(--danger)' : 'unset'
}}>{`Your message size is of ${messageSize} bytes out of a maximum of 4000`}
diff --git a/src/components/Chat/ChatGroup.tsx b/src/components/Chat/ChatGroup.tsx
index f4ae843..afcb055 100644
--- a/src/components/Chat/ChatGroup.tsx
+++ b/src/components/Chat/ChatGroup.tsx
@@ -873,7 +873,7 @@ const clearEditorContent = () => {
}}>
4000 ? 'var(--unread)' : 'unset'
+ color: messageSize > 4000 ? 'var(--danger)' : 'unset'
}}>{`Your message size is of ${messageSize} bytes out of a maximum of 4000`}
diff --git a/src/components/Chat/ChatList.tsx b/src/components/Chat/ChatList.tsx
index 7504301..9d5e42b 100644
--- a/src/components/Chat/ChatList.tsx
+++ b/src/components/Chat/ChatList.tsx
@@ -377,7 +377,7 @@ export const ChatList = ({
position: "absolute",
right: 20,
backgroundColor: "var(--unread)",
- color: "white",
+ color: "black",
padding: "10px 20px",
borderRadius: "20px",
cursor: "pointer",
diff --git a/src/components/Chat/GroupAnnouncements.tsx b/src/components/Chat/GroupAnnouncements.tsx
index fe5bf34..192114b 100644
--- a/src/components/Chat/GroupAnnouncements.tsx
+++ b/src/components/Chat/GroupAnnouncements.tsx
@@ -647,7 +647,7 @@ export const GroupAnnouncements = ({
marginTop: "auto",
alignSelf: "center",
cursor: isSending ? "default" : "pointer",
- background: "red",
+ background: "var(--danger)",
flexShrink: 0,
padding: isMobile && "5px",
fontSize: isMobile && "14px",
diff --git a/src/components/Desktop/DesktopFooter.tsx b/src/components/Desktop/DesktopFooter.tsx
index faac91b..6da8f4e 100644
--- a/src/components/Desktop/DesktopFooter.tsx
+++ b/src/components/Desktop/DesktopFooter.tsx
@@ -150,7 +150,7 @@ export const DesktopFooter = ({
height={30}
color={
hasUnreadGroups
- ? "var(--unread)"
+ ? "var(--danger)"
: isGroups
? "white"
: "rgba(250, 250, 250, 0.5)"
@@ -172,7 +172,7 @@ export const DesktopFooter = ({
height={30}
color={
hasUnreadDirects
- ? "var(--unread)"
+ ? "var(--danger)"
: isDirects
? "white"
: "rgba(250, 250, 250, 0.5)"
diff --git a/src/components/Desktop/DesktopHeader.tsx b/src/components/Desktop/DesktopHeader.tsx
index 9be4d2f..6c256e8 100644
--- a/src/components/Desktop/DesktopHeader.tsx
+++ b/src/components/Desktop/DesktopHeader.tsx
@@ -109,7 +109,7 @@ export const DesktopHeader = ({
)}
{isPrivate === false && (
)}
{errorMsg}
diff --git a/src/components/Embeds/ImageEmbed.tsx b/src/components/Embeds/ImageEmbed.tsx
index 0ac1a7c..f1cc859 100644
--- a/src/components/Embeds/ImageEmbed.tsx
+++ b/src/components/Embeds/ImageEmbed.tsx
@@ -159,7 +159,7 @@ export const ImageCard = ({
{errorMsg}
diff --git a/src/components/Embeds/PollEmbed.tsx b/src/components/Embeds/PollEmbed.tsx
index 69d1369..3da02c3 100644
--- a/src/components/Embeds/PollEmbed.tsx
+++ b/src/components/Embeds/PollEmbed.tsx
@@ -221,7 +221,7 @@ export const PollCard = ({
{errorMsg}
diff --git a/src/components/Group/AddGroupList.tsx b/src/components/Group/AddGroupList.tsx
index 977430d..ccd4850 100644
--- a/src/components/Group/AddGroupList.tsx
+++ b/src/components/Group/AddGroupList.tsx
@@ -240,7 +240,7 @@ export const AddGroupList = ({ setInfoSnack, setOpenSnack }) => {
)}
{group?.isOpen === true && (
)}
diff --git a/src/components/Group/Forum/NewThread.tsx b/src/components/Group/Forum/NewThread.tsx
index 165b760..4c237ec 100644
--- a/src/components/Group/Forum/NewThread.tsx
+++ b/src/components/Group/Forum/NewThread.tsx
@@ -534,14 +534,12 @@ export const NewThread = ({
{isMessage ? (
) : (
)}
@@ -1897,7 +1897,7 @@ export const Group = ({
justifyContent: 'center'
}}>
//
@@ -1956,7 +1956,7 @@ export const Group = ({
group?.timestamp) && (
)}
diff --git a/src/components/Group/GroupMenu.tsx b/src/components/Group/GroupMenu.tsx
index a02dbff..a44c480 100644
--- a/src/components/Group/GroupMenu.tsx
+++ b/src/components/Group/GroupMenu.tsx
@@ -73,13 +73,13 @@ export const GroupMenu = ({ setGroupSection, groupSection, setOpenManageMembers,
}}
>
{groupSection === "announcement" &&(
- <> {" Announcements"}>
+ <> {" Announcements"}>
)}
{groupSection === "chat" &&(
- <> {" Group Chats"}>
+ <> {" Group Chats"}>
)}
{groupSection === "forum" &&(
- <> {" Threads"}>
+ <> {" Threads"}>
)}
@@ -128,13 +128,13 @@ export const GroupMenu = ({ setGroupSection, groupSection, setOpenManageMembers,
minWidth: '24px !important'
}}>
-
+
@@ -148,13 +148,13 @@ export const GroupMenu = ({ setGroupSection, groupSection, setOpenManageMembers,
minWidth: '24px !important'
}}>
-
+
diff --git a/src/components/Group/ListOfGroupPromotions.tsx b/src/components/Group/ListOfGroupPromotions.tsx
index a9ed3de..6ed444a 100644
--- a/src/components/Group/ListOfGroupPromotions.tsx
+++ b/src/components/Group/ListOfGroupPromotions.tsx
@@ -555,7 +555,7 @@ export const ListOfGroupPromotions = () => {
)}
{promotion?.isOpen === true && (
)}
{
)}
{invite?.isOpen === true && (
)}
diff --git a/src/components/Mobile/MobileFooter.tsx b/src/components/Mobile/MobileFooter.tsx
index 7179f6e..52e5c7c 100644
--- a/src/components/Mobile/MobileFooter.tsx
+++ b/src/components/Mobile/MobileFooter.tsx
@@ -108,7 +108,7 @@ export const MobileFooter = ({
}}
icon={
-
+
}
sx={{
@@ -175,7 +175,7 @@ export const MobileFooter = ({
}}
icon={
-
+
}
sx={{
diff --git a/src/components/Mobile/MobileHeader.tsx b/src/components/Mobile/MobileHeader.tsx
index 9902a28..cd98ba9 100644
--- a/src/components/Mobile/MobileHeader.tsx
+++ b/src/components/Mobile/MobileHeader.tsx
@@ -92,7 +92,7 @@ const Header = ({
onClick={handleClick}
>
-
+
{fullScreen && (
{
@@ -135,7 +135,7 @@ const Header = ({
setMobileViewModeKeepOpen("messaging");
}}
>
-
@@ -197,13 +197,13 @@ const Header = ({
minWidth: '24px !important'
}}>
-
+
@@ -218,13 +218,13 @@ const Header = ({
minWidth: '24px !important'
}}>
-
+
@@ -358,7 +358,7 @@ const Header = ({
}}
>
-
+
@@ -433,13 +433,13 @@ const Header = ({
minWidth: '24px !important'
}}>
-
+
@@ -454,13 +454,13 @@ const Header = ({
minWidth: '24px !important'
}}>
-
+
diff --git a/src/components/Save/Save.tsx b/src/components/Save/Save.tsx
index 378f198..4f2a293 100644
--- a/src/components/Save/Save.tsx
+++ b/src/components/Save/Save.tsx
@@ -300,11 +300,11 @@ export const Save = ({ isDesktop, disableWidth, myName }) => {
onClick={revertChanges}
variant="contained"
sx={{
- backgroundColor: "var(--unread)",
+ backgroundColor: "var(--danger)",
color: "black",
opacity: 0.7,
"&:hover": {
- backgroundColor: "var(--unread)",
+ backgroundColor: "var(--danger)",
color: "black",
opacity: 1,
},
@@ -360,11 +360,11 @@ export const Save = ({ isDesktop, disableWidth, myName }) => {
onClick={saveToQdn}
variant="contained"
sx={{
- backgroundColor: "var(--unread)",
+ backgroundColor: "var(--danger)",
color: "black",
opacity: 0.7,
"&:hover": {
- backgroundColor: "var(--unread)",
+ backgroundColor: "var(--danger)",
color: "black",
opacity: 1,
},
diff --git a/src/index.css b/src/index.css
index a9946c7..147eae9 100644
--- a/src/index.css
+++ b/src/index.css
@@ -34,7 +34,8 @@
--bg-primary : rgba(31, 32, 35, 1);
--bg-2: #27282c;
--bg-3: rgba(0, 0, 0, 0.1);
- --unread: #B14646;
+ --unread: #4297e2;
+ --danger: #B14646;
--apps-circle: #1F2023;
--green: #5EB049;
}
From 0bc3e69560de87af5d14c9db243ca96474658685 Mon Sep 17 00:00:00 2001
From: PhilReact
Date: Tue, 17 Dec 2024 06:37:43 +0200
Subject: [PATCH 023/119] added bold
---
src/App.tsx | 2 ++
src/components/Group/Group.tsx | 2 +-
src/components/Save/Save.tsx | 3 +++
3 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/src/App.tsx b/src/App.tsx
index f6bffc6..008e25e 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -2783,6 +2783,7 @@ function App() {
{
let hasUnread = false;
diff --git a/src/components/Save/Save.tsx b/src/components/Save/Save.tsx
index 4f2a293..ffb23dd 100644
--- a/src/components/Save/Save.tsx
+++ b/src/components/Save/Save.tsx
@@ -269,6 +269,7 @@ export const Save = ({ isDesktop, disableWidth, myName }) => {
backgroundColor: "var(--green)",
color: "black",
opacity: 0.7,
+ fontWeight: 'bold',
"&:hover": {
backgroundColor: "var(--green)",
color: "black",
@@ -302,6 +303,7 @@ export const Save = ({ isDesktop, disableWidth, myName }) => {
sx={{
backgroundColor: "var(--danger)",
color: "black",
+ fontWeight: 'bold',
opacity: 0.7,
"&:hover": {
backgroundColor: "var(--danger)",
@@ -362,6 +364,7 @@ export const Save = ({ isDesktop, disableWidth, myName }) => {
sx={{
backgroundColor: "var(--danger)",
color: "black",
+ fontWeight: 'bold',
opacity: 0.7,
"&:hover": {
backgroundColor: "var(--danger)",
From d8de4dc87944d435244f1f6929d477e17558a303 Mon Sep 17 00:00:00 2001
From: PhilReact
Date: Tue, 17 Dec 2024 19:18:54 +0200
Subject: [PATCH 024/119] fix popup key
---
src/components/Chat/AdminSpaceInner.tsx | 2 +-
src/components/Chat/CreateCommonSecret.tsx | 4 ++--
src/components/Group/Group.tsx | 11 +++++++++--
3 files changed, 12 insertions(+), 5 deletions(-)
diff --git a/src/components/Chat/AdminSpaceInner.tsx b/src/components/Chat/AdminSpaceInner.tsx
index 65852b6..381302d 100644
--- a/src/components/Chat/AdminSpaceInner.tsx
+++ b/src/components/Chat/AdminSpaceInner.tsx
@@ -199,7 +199,7 @@ export const AdminSpaceInner = ({
{` by ${groupSecretKeyPublishDetails?.name}`}
)}
-
+ setIsForceShowCreationKeyPopup(true)} variant="contained">
Publish group secret key
diff --git a/src/components/Chat/CreateCommonSecret.tsx b/src/components/Chat/CreateCommonSecret.tsx
index 468b35f..e729386 100644
--- a/src/components/Chat/CreateCommonSecret.tsx
+++ b/src/components/Chat/CreateCommonSecret.tsx
@@ -8,7 +8,7 @@ import { decryptResource, getGroupAdmins, validateSecretKey } from '../Group/Gro
import { base64ToUint8Array } from '../../qdn/encryption/group-encryption';
import { uint8ArrayToObject } from '../../backgroundFunctions/encryption';
-export const CreateCommonSecret = ({groupId, secretKey, isOwner, myAddress, secretKeyDetails, userInfo, noSecretKey, setHideCommonKeyPopup, setIsForceShowCreationKeyPopup}) => {
+export const CreateCommonSecret = ({groupId, secretKey, isOwner, myAddress, secretKeyDetails, userInfo, noSecretKey, setHideCommonKeyPopup, setIsForceShowCreationKeyPopup, isForceShowCreationKeyPopup}) => {
const { show, setTxList } = useContext(MyContext);
const [openSnack, setOpenSnack] = React.useState(false);
@@ -164,7 +164,7 @@ export const CreateCommonSecret = ({groupId, secretKey, isOwner, myAddress, sec
The latest group secret key was published by a non-owner. As the owner of the group please re-encrypt the key as a safeguard
- ): (
+ ): isForceShowCreationKeyPopup ? null : (
The group member list has changed. Please re-encrypt the secret key.
diff --git a/src/components/Group/Group.tsx b/src/components/Group/Group.tsx
index dab3254..f97292b 100644
--- a/src/components/Group/Group.tsx
+++ b/src/components/Group/Group.tsx
@@ -1167,6 +1167,7 @@ export const Group = ({
setSecretKeyDetails(null);
setNewEncryptionNotification(null);
setMemberCountFromSecretKeyData(null);
+ setIsForceShowCreationKeyPopup(false)
setSelectedGroup(null);
setSelectedDirect(null);
setGroups([]);
@@ -1296,6 +1297,7 @@ export const Group = ({
setAdminsWithNames([]);
setMembers([]);
setMemberCountFromSecretKeyData(null);
+ setIsForceShowCreationKeyPopup(false)
setTriedToFetchSecretKey(false);
setFirstSecretKeyInCreation(false);
setGroupSection("chat");
@@ -1349,6 +1351,7 @@ export const Group = ({
setAdminsWithNames([]);
setMembers([]);
setMemberCountFromSecretKeyData(null);
+ setIsForceShowCreationKeyPopup(false)
setTriedToFetchSecretKey(false);
setFirstSecretKeyInCreation(false);
setGroupSection("announcement");
@@ -1408,6 +1411,7 @@ export const Group = ({
setAdminsWithNames([]);
setMembers([]);
setMemberCountFromSecretKeyData(null);
+ setIsForceShowCreationKeyPopup(false)
setTriedToFetchSecretKey(false);
setFirstSecretKeyInCreation(false);
setGroupSection("forum");
@@ -1512,6 +1516,7 @@ export const Group = ({
};
+
const renderDirects = () => {
return (