fix(images): fix second pasted image replaces the first one

Fixes #9966

Uses the validate function to paste images so that it concatenates the previous images.
FIxes the validate function to also accept data images.
Moves the size validation function to Utils to reuse the data path prefix constant and fix the possible crash when we try to get the size of a data image.
This commit is contained in:
Jonathan Rainville 2023-03-27 13:53:17 -04:00
parent b580f0a810
commit e5ff0b4a6a
6 changed files with 34 additions and 20 deletions

View File

@ -32,7 +32,7 @@ DropArea {
}
// needed because drag.urls is not a normal js array
rptDraggedPreviews.model = drag.urls.filter(img => Utils.hasDragNDropImageExtension(img))
rptDraggedPreviews.model = drag.urls.filter(img => Utils.isValidDragNDropImage(img))
}
onPositionChanged: {
rptDraggedPreviews.x = drag.x

View File

@ -15,7 +15,7 @@ StatusChatImageValidator {
onImagesChanged: {
let isValid = true
root.validImages = images.filter(img => {
const isImage = Utils.hasDragNDropImageExtension(img)
const isImage = Utils.isValidDragNDropImage(img)
isValid = isValid && isImage
return isImage
})

View File

@ -4,13 +4,11 @@ import utils 1.0
StatusChatImageValidator {
id: root
readonly property int maxImgSizeBytes: Constants.maxUploadFilesizeMB * 1048576 /* 1 MB in bytes */
onImagesChanged: {
let isValid = true
root.validImages = images.filter(img => {
let size = parseInt(globalUtils.getFileSize(img))
const isSmallEnough = size <= maxImgSizeBytes
const isSmallEnough = Utils.isFilesizeValid(img)
isValid = isValid && isSmallEnough
return isSmallEnough
})

View File

@ -436,7 +436,7 @@ Rectangle {
if (event.matches(StandardKey.Paste)) {
if (QClipboardProxy.hasImage) {
const clipboardImage = QClipboardProxy.imageBase64
showImageArea([clipboardImage])
validateImagesAndShowImageArea([clipboardImage])
event.accepted = true
} else if (QClipboardProxy.hasText) {
messageInputField.remove(messageInputField.selectionStart, messageInputField.selectionEnd)
@ -883,11 +883,22 @@ Rectangle {
function showImageArea(imagePathsOrData) {
isImage = true;
imageArea.imageSource = imagePathsOrData
control.fileUrlsAndSources = imageArea.imageSource
}
// Use this to validate and show the images. The concatanation of previous selected images is done automatically
// Returns true if the images were valid and added
function validateImagesAndShowImageArea(imagePaths) {
const validImages = validateImages(imagePaths)
if (validImages.length > 0) {
showImageArea(validImages)
return true
}
return false
}
function showReplyArea(messageId, userName, message, contentType, image, sticker) {
isReply = true
replyArea.userName = userName
@ -908,9 +919,7 @@ Rectangle {
target: Global.dragArea
ignoreUnknownSignals: true
function onDroppedOnValidScreen(drop) {
let validImages = validateImages(drop.urls)
if (validImages.length > 0) {
showImageArea(validImages)
if (validateImagesAndShowImageArea(drop.urls)) {
drop.acceptProposedAction()
}
}
@ -918,10 +927,7 @@ Rectangle {
// This is used by Squish tests to not have to access the file dialog
function selectImageString(filePath) {
let validImages = validateImages([filePath])
if (validImages.length > 0) {
control.showImageArea(validImages)
}
validateImagesAndShowImageArea([filePath])
messageInputField.forceActiveFocus();
}
@ -935,10 +941,7 @@ Rectangle {
]
onAccepted: {
imageBtn.highlighted = false
let validImages = validateImages(imageDialog.fileUrls)
if (validImages.length > 0) {
control.showImageArea(validImages)
}
validateImagesAndShowImageArea(imageDialog.fileUrls)
messageInputField.forceActiveFocus();
}
onRejected: {

View File

@ -797,6 +797,7 @@ QtObject {
readonly property int maxNumberOfPins: 3
readonly property string dataImagePrefix: "data:image"
readonly property var acceptedImageExtensions: [".png", ".jpg", ".jpeg", ".svg", ".gif"]
readonly property var acceptedDragNDropImageExtensions: [".png", ".jpg", ".jpeg", ".heif", ".tif", ".tiff"]

View File

@ -10,6 +10,8 @@ QtObject {
property var mainModuleInst: typeof mainModule !== "undefined" ? mainModule : null
property var globalUtilsInst: typeof globalUtils !== "undefined" ? globalUtils : null
readonly property int maxImgSizeBytes: Constants.maxUploadFilesizeMB * 1048576 /* 1 MB in bytes */
function isDigit(value) {
return /^\d$/.test(value);
}
@ -320,8 +322,18 @@ QtObject {
return message.replace(/(?:https?|ftp):\/\/[\n\S]*(\.gif)+/gm, '');
}
function hasDragNDropImageExtension(url) {
return Constants.acceptedDragNDropImageExtensions.some(ext => url.toLowerCase().includes(ext))
function isValidDragNDropImage(url) {
let lowerCaseUrl = url.toLowerCase()
return Constants.acceptedDragNDropImageExtensions.some(ext => lowerCaseUrl.endsWith(ext)) ||
lowerCaseUrl.startsWith(Constants.dataImagePrefix);
}
function isFilesizeValid(img) {
if (img.startsWith(Constants.dataImagePrefix)) {
return img.length < maxImgSizeBytes
}
let size = parseInt(globalUtils.getFileSize(img))
return size <= maxImgSizeBytes
}
function deduplicate(array) {