diff --git a/src/common/useModal.tsx b/src/common/useModal.tsx
index b9ab713..e1d0272 100644
--- a/src/common/useModal.tsx
+++ b/src/common/useModal.tsx
@@ -48,7 +48,7 @@ export const useModal = () => {
const onCancel = () => {
const { reject } = promiseConfig.current;
hide();
- reject();
+ reject('Declined');
setMessage({
publishFee: "",
message: ""
diff --git a/src/components/Chat/ChatGroup.tsx b/src/components/Chat/ChatGroup.tsx
index 3248587..2de131e 100644
--- a/src/components/Chat/ChatGroup.tsx
+++ b/src/components/Chat/ChatGroup.tsx
@@ -15,12 +15,12 @@ import { CustomizedSnackbars } from '../Snackbar/Snackbar'
import { PUBLIC_NOTIFICATION_CODE_FIRST_SECRET_KEY } from '../../constants/codes'
import { useMessageQueue } from '../../MessageQueueContext'
import { executeEvent, subscribeToEvent, unsubscribeFromEvent } from '../../utils/events'
-import { Box, ButtonBase, Divider, Typography } from '@mui/material'
+import { Box, ButtonBase, Divider, IconButton, Tooltip, Typography } from '@mui/material'
import ShortUniqueId from "short-unique-id";
import { ReplyPreview } from './MessageItem'
import { ExitIcon } from '../../assets/Icons/ExitIcon'
import { RESOURCE_TYPE_NUMBER_GROUP_CHAT_REACTIONS } from '../../constants/resourceTypes'
-import { isExtMsg } from '../../background'
+import { getFee, isExtMsg } from '../../background'
import MentionList from './MentionList'
import { ChatOptions } from './ChatOptions'
import { isFocusedParentGroupAtom } from '../../atoms/global'
@@ -28,6 +28,10 @@ import { useRecoilState } from 'recoil'
import AppViewerContainer from '../Apps/AppViewerContainer'
import CloseIcon from "@mui/icons-material/Close";
import { throttle } from 'lodash'
+import ImageIcon from '@mui/icons-material/Image';
+import { messageHasImage } from '../../utils/chat'
+
+const uidImages = new ShortUniqueId({ length: 12 });
const uid = new ShortUniqueId({ length: 5 });
@@ -55,8 +59,9 @@ export const ChatGroup = ({selectedGroup, secretKey, setSecretKey, getSecretKey,
const editorRef = useRef(null);
const { queueChats, addToQueue, processWithNewMessages } = useMessageQueue();
const handleUpdateRef = useRef(null);
- const {isUserBlocked} = useContext(MyContext)
-
+ const {isUserBlocked, show} = useContext(MyContext)
+ const [chatImagesToSave, setChatImagesToSave] = useState([]);
+ const [isDeleteImage, setIsDeleteImage] = useState(false);
const lastReadTimestamp = useRef(null)
@@ -624,6 +629,8 @@ if(isFocusedParent === false){
setReplyMessage(null)
setOnEditMessage(null)
clearEditorContent()
+ setIsDeleteImage(false);
+ setChatImagesToSave([]);
}
}, [isFocusedParent])
const clearEditorContent = () => {
@@ -644,88 +651,193 @@ const clearEditorContent = () => {
-const sendMessage = async ()=> {
+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')
- pauseAllQueues()
+ if (messageSize > 4000) return; // TODO magic number
+ if (isPrivate === null)
+ throw new Error(
+ "Onable to determine if group is private"
+ );
+ if (isSending) return;
+ if (+balance < 4)
+ // TODO magic number
+ throw new Error(
+ "You need at least 4 QORT to send a message"
+ );
+ pauseAllQueues();
if (editorRef.current) {
- const htmlContent = editorRef.current.getHTML();
-
- if(!htmlContent?.trim() || htmlContent?.trim() === '
') return
-
+ let htmlContent = editorRef.current.getHTML();
+ const deleteImage =
+ onEditMessage && isDeleteImage && messageHasImage(onEditMessage);
- setIsSending(true)
- const message = isPrivate === false ? editorRef.current.getJSON() : htmlContent
- const secretKeyObject = await getSecretKey(false, true)
+ const hasImage =
+ chatImagesToSave?.length > 0 || onEditMessage?.images?.length > 0;
+ if (
+ (!htmlContent?.trim() || htmlContent?.trim() === '') &&
+ !hasImage &&
+ !deleteImage
+ )
+ return;
+ if (htmlContent?.trim() === '') {
+ htmlContent = null;
+ }
+ setIsSending(true);
+ const message =
+ isPrivate === false
+ ? !htmlContent
+ ? ''
+ : editorRef.current.getJSON()
+ : htmlContent;
+ const secretKeyObject = await getSecretKey(false, true);
- let repliedTo = replyMessage?.signature
+ let repliedTo = replyMessage?.signature;
- if (replyMessage?.chatReference) {
- repliedTo = replyMessage?.chatReference
- }
- let chatReference = onEditMessage?.signature
+ if (replyMessage?.chatReference) {
+ repliedTo = replyMessage?.chatReference;
+ }
- const publicData = isPrivate ? {} : {
- isEdited : chatReference ? true : false,
- }
- const otherData = {
- repliedTo,
- ...(onEditMessage?.decryptedData || {}),
- type: chatReference ? 'edit' : '',
- specialId: uid.rnd(),
- ...publicData
- }
- const objectMessage = {
- ...(otherData || {}),
- [isPrivate ? 'message' : 'messageText']: message,
- version: 3
- }
- const message64: any = await objectToBase64(objectMessage)
-
- const encryptSingle = isPrivate === false ? JSON.stringify(objectMessage) : await encryptChatMessage(message64, secretKeyObject)
- // const res = await sendChatGroup({groupId: selectedGroup,messageText: encryptSingle})
-
- const sendMessageFunc = async () => {
- return await sendChatGroup({groupId: selectedGroup,messageText: encryptSingle, chatReference})
- };
+ const chatReference = onEditMessage?.signature;
- // Add the function to the queue
- const messageObj = {
- message: {
- text: htmlContent,
- timestamp: Date.now(),
- senderName: myName,
- sender: myAddress,
- ...(otherData || {})
- },
- chatReference
- }
- addToQueue(sendMessageFunc, messageObj, 'chat',
- selectedGroup );
- setTimeout(() => {
- executeEvent("sent-new-message-group", {})
- }, 150);
- clearEditorContent()
- setReplyMessage(null)
- setOnEditMessage(null)
+ const publicData = isPrivate
+ ? {}
+ : {
+ isEdited: chatReference ? true : false,
+ };
+
+ interface ImageToPublish {
+ service: string;
+ identifier: string;
+ name: string;
+ base64: string;
+ }
+
+ const imagesToPublish: ImageToPublish[] = [];
+
+ if (deleteImage) {
+ const fee = await getFee('ARBITRARY');
+ await show({
+ publishFee: fee.fee + ' QORT',
+ message: "Would you like to delete your previous chat image?",
+ });
+
+ // TODO magic string
+ await window.sendMessage('publishOnQDN', {
+ data: 'RA==',
+ identifier: onEditMessage?.images[0]?.identifier,
+ service: onEditMessage?.images[0]?.service,
+ uploadType: 'base64',
+ });
+ }
+
+ if (chatImagesToSave?.length > 0) {
+ const imageToSave = chatImagesToSave[0];
+
+ const base64ToSave = isPrivate
+ ? await encryptChatMessage(imageToSave, secretKeyObject)
+ : imageToSave;
+
+ // 1 represents public group, 0 is private
+ const identifier = `grp-q-manager_${isPrivate ? 0 : 1}_group_${selectedGroup}_${uidImages.rnd()}`;
+ imagesToPublish.push({
+ service: 'IMAGE',
+ identifier,
+ name: myName,
+ base64: base64ToSave,
+ });
+
+ const res = await window.sendMessage(
+ 'PUBLISH_MULTIPLE_QDN_RESOURCES',
+ {
+ resources: imagesToPublish,
+ },
+ 240000,
+ true
+ );
+ if (res !== true)
+ throw new Error(
+ "Unable to publish image"
+ );
+ }
+
+ const images =
+ imagesToPublish?.length > 0
+ ? imagesToPublish.map((item) => {
+ return {
+ name: item.name,
+ identifier: item.identifier,
+ service: item.service,
+ timestamp: Date.now(),
+ };
+ })
+ : chatReference
+ ? isDeleteImage
+ ? []
+ : onEditMessage?.images || []
+ : [];
+
+ const otherData = {
+ repliedTo,
+ ...(onEditMessage?.decryptedData || {}),
+ type: chatReference ? 'edit' : '',
+ specialId: uid.rnd(),
+ images: images,
+ ...publicData,
+ };
+ const objectMessage = {
+ ...(otherData || {}),
+ [isPrivate ? 'message' : 'messageText']: message,
+ version: 3,
+ };
+ const message64: any = await objectToBase64(objectMessage);
+
+ const encryptSingle =
+ isPrivate === false
+ ? JSON.stringify(objectMessage)
+ : await encryptChatMessage(message64, secretKeyObject);
+
+ const sendMessageFunc = async () => {
+ return await sendChatGroup({
+ groupId: selectedGroup,
+ messageText: encryptSingle,
+ chatReference,
+ });
+ };
+
+ // Add the function to the queue
+ const messageObj = {
+ message: {
+ text: htmlContent,
+ timestamp: Date.now(),
+ senderName: myName,
+ sender: myAddress,
+ ...(otherData || {}),
+ },
+ chatReference,
+ };
+ addToQueue(sendMessageFunc, messageObj, 'chat', selectedGroup);
+ setTimeout(() => {
+ executeEvent('sent-new-message-group', {});
+ }, 150);
+ clearEditorContent();
+ setReplyMessage(null);
+ setOnEditMessage(null);
+ setIsDeleteImage(false);
+ setChatImagesToSave([]);
}
// send chat message
} catch (error) {
- const errorMsg = error?.message || error
+ const errorMsg = error?.message || error;
setInfoSnack({
- type: "error",
+ type: 'error',
message: errorMsg,
});
setOpenSnack(true);
- console.error(error)
+ console.error(error);
} finally {
- setIsSending(false)
- resumeAllQueues()
+ setIsSending(false);
+ resumeAllQueues();
}
-}
+};
useEffect(() => {
if (hide) {
@@ -742,7 +854,8 @@ const sendMessage = async ()=> {
setReplyMessage(message)
setOnEditMessage(null)
setIsFocusedParent(true);
-
+ setIsDeleteImage(false);
+ setChatImagesToSave([]);
setTimeout(() => {
editorRef?.current?.chain().focus()
@@ -755,7 +868,7 @@ const sendMessage = async ()=> {
setReplyMessage(null)
setIsFocusedParent(true);
setTimeout(() => {
- editorRef.current.chain().focus().setContent(message?.messageText || message?.text).run();
+ editorRef?.current?.chain().focus().setContent(message?.messageText || message?.text || '').run();
}, 250);
}, [])
@@ -824,6 +937,24 @@ const sendMessage = async ()=> {
resumeAllQueues()
}
}, [isPrivate])
+
+ const insertImage = useCallback(
+ (img) => {
+ if (
+ chatImagesToSave?.length > 0 ||
+ (messageHasImage(onEditMessage) && !isDeleteImage)
+ ) {
+ setInfoSnack({
+ type: 'error',
+ message: 'This message already has an image',
+ });
+ setOpenSnack(true);
+ return;
+ }
+ setChatImagesToSave((prev) => [...prev, img]);
+ },
+ [chatImagesToSave, onEditMessage?.images, isDeleteImage]
+ );
return (
{
overflow: !isMobile && "auto",
flexShrink: 0
}}>
+
+ {!isDeleteImage &&
+ onEditMessage &&
+ messageHasImage(onEditMessage) &&
+ onEditMessage?.images?.map((_, index) => (
+
+
+
+ setIsDeleteImage(true)}
+ size="small"
+ sx={{
+ position: 'absolute',
+ top: '50%',
+ left: '50%',
+ transform: 'translate(-50%, -50%)',
+ backgroundColor: (theme) =>
+ theme.palette.background.paper,
+ color: (theme) => theme.palette.text.primary,
+ borderRadius: '50%',
+ opacity: 0,
+ transition: 'opacity 0.2s',
+ boxShadow: (theme) => theme.shadows[2],
+ '&:hover': {
+ backgroundColor: (theme) =>
+ theme.palette.background.default,
+ opacity: 1,
+ },
+ pointerEvents: 'auto',
+ }}
+ >
+
+
+
+
+ ))}
+ {chatImagesToSave.map((imgBase64, index) => (
+
+

+
+
+ setChatImagesToSave((prev) =>
+ prev.filter((_, i) => i !== index)
+ )
+ }
+ size="small"
+ sx={{
+ position: 'absolute',
+ top: '50%',
+ left: '50%',
+ transform: 'translate(-50%, -50%)',
+ backgroundColor: (theme) =>
+ theme.palette.background.paper,
+ color: (theme) => theme.palette.text.primary,
+ borderRadius: '50%',
+ opacity: 0,
+ transition: 'opacity 0.2s',
+ boxShadow: (theme) => theme.shadows[2],
+ '&:hover': {
+ backgroundColor: (theme) =>
+ theme.palette.background.default,
+ opacity: 1,
+ },
+ pointerEvents: 'auto',
+ }}
+ >
+
+
+
+
+ ))}
+
{replyMessage && (
{
}}>
-
+
diff --git a/src/components/Chat/ChatList.tsx b/src/components/Chat/ChatList.tsx
index 82dc915..cd1aa51 100644
--- a/src/components/Chat/ChatList.tsx
+++ b/src/components/Chat/ChatList.tsx
@@ -261,20 +261,17 @@ export const ChatList = ({ initialMessages, myAddress, tempMessages, chatId, onR
if (chatReferences?.[message.signature]) {
reactions = chatReferences[message.signature]?.reactions || null;
- if (chatReferences[message.signature]?.edit?.message && message?.text) {
- message.text = chatReferences[message.signature]?.edit?.message;
- message.isEdit = true
- message.editTimestamp = chatReferences[message.signature]?.edit?.timestamp
- }
- if (chatReferences[message.signature]?.edit?.messageText && message?.messageText) {
- message.messageText = chatReferences[message.signature]?.edit?.messageText;
- message.isEdit = true
- message.editTimestamp = chatReferences[message.signature]?.edit?.timestamp
- }
- if (chatReferences[message.signature]?.edit?.images) {
+ if (chatReferences[message.signature]?.edit) {
+ message.text =
+ chatReferences[message.signature]?.edit?.message;
+ message.messageText =
+ chatReferences[message.signature]?.edit?.messageText;
message.images =
chatReferences[message.signature]?.edit?.images;
+
message.isEdit = true;
+ message.editTimestamp =
+ chatReferences[message.signature]?.edit?.timestamp;
}
}
diff --git a/src/components/Chat/MessageItem.tsx b/src/components/Chat/MessageItem.tsx
index c134d1d..18d7d0e 100644
--- a/src/components/Chat/MessageItem.tsx
+++ b/src/components/Chat/MessageItem.tsx
@@ -35,6 +35,7 @@ import level9Img from "../../assets/badges/level-9.png"
import level10Img from "../../assets/badges/level-10.png"
import { Embed } from "../Embeds/Embed";
import { buildImageEmbedLink, isHtmlString, messageHasImage } from "../../utils/chat";
+import CommentsDisabledIcon from '@mui/icons-material/CommentsDisabled';
const getBadgeImg = (level)=> {
switch(level?.toString()){
@@ -142,6 +143,13 @@ const onSeenFunc = useCallback(()=> {
onSeen(message.id);
}, [message?.id])
+const hasNoMessage =
+(!message.decryptedData?.data?.message ||
+ message.decryptedData?.data?.message === '') &&
+(message?.images || [])?.length === 0 &&
+(!message?.messageText || message?.messageText === '') &&
+(!message?.text || message?.text === '');
+
return (
{message?.divide && (
@@ -335,7 +343,7 @@ const onSeenFunc = useCallback(()=> {
>
)}
- {message?.messageText && (
+ {htmlText && !hasNoMessage && (
{
)}
{message?.decryptedData?.type === "notification" ? (
- ) : (
+ ) : hasNoMessage ? null : (
)}
+ {hasNoMessage && (
+
+
+
+ No Message
+
+
+ )}
{message?.images && messageHasImage(message) && (
)}
@@ -523,6 +549,7 @@ const onSeenFunc = useCallback(()=> {
export const ReplyPreview = ({message, isEdit})=> {
const replyMessageText = useMemo(() => {
+ if (!message?.messageText) return null;
const isHtml = isHtmlString(message?.messageText);
if (isHtml) return message?.messageText;
return generateHTML(message?.messageText, [
@@ -568,7 +595,7 @@ export const ReplyPreview = ({message, isEdit})=> {
}}>Replied to {message?.senderName || message?.senderAddress}
)}
- {message?.messageText && (
+ {replyMessageText && (
diff --git a/src/components/Chat/TipTap.tsx b/src/components/Chat/TipTap.tsx
index 38b2126..e644a64 100644
--- a/src/components/Chat/TipTap.tsx
+++ b/src/components/Chat/TipTap.tsx
@@ -1,4 +1,4 @@
-import React, { useEffect, useMemo, useRef, useState } from "react";
+import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { EditorProvider, useCurrentEditor, useEditor } from "@tiptap/react";
import StarterKit from "@tiptap/starter-kit";
import { Color } from "@tiptap/extension-color";
@@ -34,6 +34,7 @@ import ListItemButton from '@mui/material/ListItemButton';
import ListItemText from '@mui/material/ListItemText';
import { ReactRenderer } from '@tiptap/react'
import MentionList from './MentionList.jsx'
+import { fileToBase64 } from "../../utils/fileReading/index.js";
function textMatcher(doc, from) {
const textBeforeCursor = doc.textBetween(0, from, ' ', ' ');
@@ -110,13 +111,13 @@ const MenuBar = ({ setEditorRef, isChat }) => {
};
useEffect(() => {
- if (editor) {
+ if (editor && !isChat) {
editor.view.dom.addEventListener("paste", handlePaste);
return () => {
editor.view.dom.removeEventListener("paste", handlePaste);
};
}
- }, [editor]);
+ }, [editor, isChat]);
return (
@@ -299,7 +300,8 @@ export default ({
customEditorHeight,
membersWithNames,
enableMentions,
- isReply
+ isReply,
+ insertImage,
}) => {
const extensionsFiltered = isChat
@@ -329,7 +331,35 @@ export default ({
}, [membersWithNames])
+ const handleImageUpload = useCallback(async (file) => {
+ try {
+ if (!file.type.includes('image')) return;
+ let compressedFile = file;
+ if (file.type !== 'image/gif') {
+ await new Promise((resolve) => {
+ new Compressor(file, {
+ quality: 0.6,
+ maxWidth: 1200,
+ mimeType: 'image/webp',
+ success(result) {
+ compressedFile = result;
+ resolve();
+ },
+ error(err) {
+ console.error('Image compression error:', err);
+ },
+ });
+ });
+ }
+ if (compressedFile) {
+ const toBase64 = await fileToBase64(compressedFile);
+ insertImage(toBase64);
+ }
+ } catch (error) {
+ console.error(error);
+ }
+ }, [insertImage]);
const usersRef = useRef([]);
@@ -470,6 +500,25 @@ export default ({
}
return false;
},
+ handlePaste(view, event) {
+ if(!handleImageUpload) return
+ if (!isChat) return;
+ const items = event.clipboardData?.items;
+ if (!items) return false;
+
+ for (const item of items) {
+ if (item.type.startsWith('image/')) {
+ const file = item.getAsFile();
+ if (file) {
+ event.preventDefault(); // Block the default paste
+ handleImageUpload(file); // Custom handler
+ return true; // Let ProseMirror know we handled it
+ }
+ }
+ }
+
+ return false; // fallback to default behavior otherwise
+ },
}}
/>
diff --git a/src/components/Embeds/ImageEmbed.tsx b/src/components/Embeds/ImageEmbed.tsx
index 8e02e63..e401737 100644
--- a/src/components/Embeds/ImageEmbed.tsx
+++ b/src/components/Embeds/ImageEmbed.tsx
@@ -52,6 +52,8 @@ export const ImageCard = ({
backgroundColor: "#1F2023",
height: height,
transition: "height 0.6s ease-in-out",
+ display: 'flex',
+ flexDirection: 'column',
}}
>
-
-
+
+
@@ -203,6 +215,7 @@ export const ImageCard = ({
display: "flex",
justifyContent: "center",
cursor: "pointer",
+ height: '100%',
}}
onClick={handleOpenFullscreen}
>
diff --git a/src/components/Home/NewUsersCTA.tsx b/src/components/Home/NewUsersCTA.tsx
index 486c4da..12a9bfb 100644
--- a/src/components/Home/NewUsersCTA.tsx
+++ b/src/components/Home/NewUsersCTA.tsx
@@ -54,35 +54,19 @@ export const NewUsersCTA = ({ balance }) => {
textDecoration: "underline",
}}
onClick={() => {
- if (chrome && chrome.tabs) {
- chrome.tabs.create({ url: "https://link.qortal.dev/telegram-invite" }, (tab) => {
- if (chrome.runtime.lastError) {
- console.error("Error opening tab:", chrome.runtime.lastError);
- } else {
- console.log("Tab opened successfully:", tab);
- }
- });
- }
-
+ window.open("https://link.qortal.dev/support", '_system')
}}
>
- Telegram
+ Nextcloud
{
- if (chrome && chrome.tabs) {
- chrome.tabs.create({ url: "https://link.qortal.dev/discord-invite" }, (tab) => {
- if (chrome.runtime.lastError) {
- console.error("Error opening tab:", chrome.runtime.lastError);
- } else {
- console.log("Tab opened successfully:", tab);
- }
- });
- }
+ window.open("https://link.qortal.dev/discord-invite", '_system')
}}
+
>
Discord
diff --git a/src/constants/constants.ts b/src/constants/constants.ts
index 5b5e427..72b7632 100644
--- a/src/constants/constants.ts
+++ b/src/constants/constants.ts
@@ -173,3 +173,6 @@ const STATIC_BCRYPT_SALT = `$${BCRYPT_VERSION}$${BCRYPT_ROUNDS}$IxVE941tXVUD4cW0
const KDF_THREADS = 16
export { TX_TYPES, ERROR_CODES, QORT_DECIMALS, PROXY_URL, STATIC_SALT, ADDRESS_VERSION, KDF_THREADS, STATIC_BCRYPT_SALT, CHAT_REFERENCE_FEATURE_TRIGGER_TIMESTAMP, DYNAMIC_FEE_TIMESTAMP }
+
+export const MAX_SIZE_PUBLIC_NODE = 500 * 1024 * 1024; // 500mb
+export const MAX_SIZE_PUBLISH = 2000 * 1024 * 1024; // 2GB
\ No newline at end of file
diff --git a/src/qortalRequests/get.ts b/src/qortalRequests/get.ts
index 220c292..55c4ce9 100644
--- a/src/qortalRequests/get.ts
+++ b/src/qortalRequests/get.ts
@@ -42,7 +42,7 @@ import {
} from "../background";
import { getNameInfo, uint8ArrayToObject,getAllUserNames } from "../backgroundFunctions/encryption";
import { saveFileInChunksFromUrl, showSaveFilePicker } from "../components/Apps/useQortalMessageListener";
-import { QORT_DECIMALS } from "../constants/constants";
+import { MAX_SIZE_PUBLIC_NODE, MAX_SIZE_PUBLISH, QORT_DECIMALS } from "../constants/constants";
import Base58 from "../deps/Base58";
import {
base64ToUint8Array,
@@ -955,6 +955,22 @@ export const publishQDNResource = async (
const tags = data?.tags || [];
const result = {};
+
+ if (file && file.size > MAX_SIZE_PUBLISH) {
+ throw new Error(
+ "Maximum file size allowed is 2 GB per file"
+ );
+ }
+
+ if (file && file.size > MAX_SIZE_PUBLIC_NODE) {
+ const isPublicNode = await isRunningGateway();
+ if (isPublicNode) {
+ throw new Error(
+ "Maximum file size allowed on the public node is 500 MB. Please use your local node for larger files."
+ );
+ }
+ }
+
// Fill tags dynamically while maintaining backward compatibility
for (let i = 0; i < 5; i++) {
result[`tag${i + 1}`] = tags[i] || data[`tag${i + 1}`] || undefined;
@@ -1125,6 +1141,31 @@ export const publishMultipleQDNResources = async (
throw new Error('No resources to publish');
}
+ const isPublicNode = await isRunningGateway();
+ if (isPublicNode) {
+ const hasOversizedFilePublicNode = resources.some((resource) => {
+ const file = resource?.file;
+ return file instanceof File && file.size > MAX_SIZE_PUBLIC_NODE;
+ });
+
+ if (hasOversizedFilePublicNode) {
+ throw new Error(
+ "Maximum file size allowed on the public node is 500 MB. Please use your local node for larger files."
+ );
+ }
+ }
+
+ const hasOversizedFile = resources.some((resource) => {
+ const file = resource?.file;
+ return file instanceof File && file.size > MAX_SIZE_PUBLISH;
+ });
+
+ if (hasOversizedFile) {
+ throw new Error(
+ "Maximum file size allowed is 2 GB per file"
+ );
+ }
+
const encrypt = data?.encrypt;
for (const resource of resources) {