This commit is contained in:
PhilReact 2025-05-01 01:05:28 +03:00
parent 09c5625a07
commit 5d1ef926c8
4 changed files with 121 additions and 3 deletions

View File

@ -3219,7 +3219,7 @@ function App() {
onClick={onOkUnsavedChanges}
autoFocus
>
{t('core:action.decline', {
{t('core:action.continue_logout', {
postProcess: 'capitalize',
})}
</Button>

View File

@ -42,7 +42,7 @@ import CloseIcon from '@mui/icons-material/Close';
import { throttle } from 'lodash';
const uid = new ShortUniqueId({ length: 5 });
const uidImages = new ShortUniqueId({ length: 12 });
export const ChatGroup = ({
selectedGroup,
secretKey,
@ -74,6 +74,7 @@ export const ChatGroup = ({
const [isOpenQManager, setIsOpenQManager] = useState(null);
const [messageSize, setMessageSize] = useState(0);
const [chatImagesToSave, setChatImagesToSave] = useState([]);
const hasInitializedWebsocket = useRef(false);
const socketRef = useRef(null); // WebSocket reference
const timeoutIdRef = useRef(null); // Timeout ID reference
@ -778,11 +779,45 @@ export const ChatGroup = ({
: {
isEdited: chatReference ? true : false,
};
const imagesToPublish = [];
if (!chatReference && chatImagesToSave?.length > 0) {
chatImagesToSave.forEach((base64Img) => {
const identifier = `qchat_1_group_${selectedGroup}_${uidImages.rnd()}`;
imagesToPublish.push({
service: 'IMAGE',
identifier,
name: myName,
base64: base64Img,
});
});
const res = await window.sendMessage(
'PUBLISH_MULTIPLE_QDN_RESOURCES',
{
resources: imagesToPublish,
},
240000,
true
);
console.log('res', res);
if (res !== true) throw new Error('Unable to publish images');
}
const otherData = {
repliedTo,
...(onEditMessage?.decryptedData || {}),
type: chatReference ? 'edit' : '',
specialId: uid.rnd(),
images:
onEditMessage?.images ||
imagesToPublish.map((item) => {
return {
name: item.name,
identifier: item.identifier,
service: item.service,
};
}),
...publicData,
};
const objectMessage = {
@ -824,6 +859,7 @@ export const ChatGroup = ({
clearEditorContent();
setReplyMessage(null);
setOnEditMessage(null);
setChatImagesToSave([]);
}
// send chat message
} catch (error) {
@ -986,6 +1022,10 @@ export const ChatGroup = ({
const theme = useTheme();
const insertImage = useCallback((img) => {
setChatImagesToSave((prev) => [...prev, img]);
}, []);
return (
<div
style={{
@ -1049,6 +1089,29 @@ export const ChatGroup = ({
width: 'calc(100% - 100px)',
}}
>
<Box
sx={{
alignItems: 'flex-start',
display: 'flex',
width: '100%',
gap: '10px',
flexWrap: 'wrap',
}}
>
{chatImagesToSave?.map((imgBase64) => {
return (
<img
style={{
height: '50px',
width: '50px',
objectFit: 'contain',
borderRadius: '3px',
}}
src={`data:image/webp;base64,${imgBase64}`}
/>
);
})}
</Box>
{replyMessage && (
<Box
sx={{
@ -1104,6 +1167,7 @@ export const ChatGroup = ({
isFocusedParent={isFocusedParent}
setIsFocusedParent={setIsFocusedParent}
membersWithNames={members}
insertImage={insertImage}
/>
{messageSize > 750 && (
<Box

View File

@ -30,6 +30,7 @@ import MentionList from './MentionList.jsx';
import { isDisabledEditorEnterAtom } from '../../atoms/global.js';
import { Box, Checkbox, Typography, useTheme } from '@mui/material';
import { useAtom } from 'jotai';
import { fileToBase64 } from '../../utils/fileReading/index.js';
function textMatcher(doc, from) {
const textBeforeCursor = doc.textBetween(0, from, ' ', ' ');
@ -114,7 +115,7 @@ const MenuBar = React.memo(
};
useEffect(() => {
if (editor) {
if (editor && !isChat) {
editor.view.dom.addEventListener('paste', handlePaste);
return () => {
editor.view.dom.removeEventListener('paste', handlePaste);
@ -366,12 +367,46 @@ export default ({
customEditorHeight,
membersWithNames,
enableMentions,
insertImage,
}) => {
const theme = useTheme();
const [isDisabledEditorEnter, setIsDisabledEditorEnter] = useAtom(
isDisabledEditorEnterAtom
);
const handleImageUpload = async (file) => {
try {
if (!file.type.includes('image')) return;
let compressedFile = file;
if (file.type !== 'image/gif') {
await new Promise<void>((resolve) => {
new Compressor(file, {
quality: 0.6,
maxWidth: 1200,
mimeType: 'image/webp',
success(result) {
compressedFile = new File([result], 'image.webp', {
type: 'image/webp',
});
resolve();
},
error(err) {
console.error('Image compression error:', err);
},
});
});
}
if (compressedFile) {
const toBase64 = await fileToBase64(compressedFile);
insertImage(toBase64);
console.log('toBase64', toBase64);
}
} catch (error) {
console.error(error);
}
};
const extensionsFiltered = isChat
? extensions.filter((item) => item?.name !== 'image')
: extensions;
@ -543,6 +578,24 @@ export default ({
}
return false;
},
handlePaste(view, event) {
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
},
}}
/>
</Box>

View File

@ -1218,6 +1218,7 @@ export const publishMultipleQDNResources = async (
sender,
isFromExtension
) => {
console.log('data', data);
const requiredFields = ['resources'];
const missingFields: string[] = [];
let feeAmount = null;