desktop: add image pasting from clipboard (#3378)

* first pass at desktop image pasting for multiplatform

* removed debug println

* fixed bug with pasting text

* temp files are deleted now following simplex conventions

* optimizations

---------

Co-authored-by: Avently <7953703+avently@users.noreply.github.com>
This commit is contained in:
Jesse Horne 2023-11-21 14:37:15 -05:00 committed by GitHub
parent a8576c2340
commit 097242e7a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -22,12 +22,21 @@ import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import chat.simplex.common.views.chat.* import chat.simplex.common.views.chat.*
import chat.simplex.common.views.helpers.generalGetString import chat.simplex.common.views.helpers.*
import chat.simplex.res.MR import chat.simplex.res.MR
import dev.icerock.moko.resources.StringResource import dev.icerock.moko.resources.StringResource
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import java.awt.Image
import java.awt.Toolkit
import java.awt.datatransfer.DataFlavor
import java.awt.datatransfer.UnsupportedFlavorException
import java.awt.image.BufferedImage
import java.io.ByteArrayOutputStream
import java.io.File import java.io.File
import java.net.URI import java.net.URI
import java.util.*
import javax.imageio.ImageIO
import kotlin.collections.ArrayList
import kotlin.io.path.* import kotlin.io.path.*
import kotlin.math.min import kotlin.math.min
import kotlin.text.substring import kotlin.text.substring
@ -112,12 +121,45 @@ actual fun PlatformTextField(
onUpArrow() onUpArrow()
true true
} else if (it.key == Key.V && } else if (it.key == Key.V &&
it.type == KeyEventType.KeyDown && it.type == KeyEventType.KeyDown &&
((it.isCtrlPressed && !desktopPlatform.isMac()) || (it.isMetaPressed && desktopPlatform.isMac())) && ((it.isCtrlPressed && !desktopPlatform.isMac()) || (it.isMetaPressed && desktopPlatform.isMac()))) {
parseToFiles(clipboard.getText()).isNotEmpty()) { if (parseToFiles(clipboard.getText()).isNotEmpty()) {
onFilesPasted(parseToFiles(clipboard.getText())) onFilesPasted(parseToFiles(clipboard.getText()))
true true
} } else {
// It's much faster to getData instead of getting transferable first
val image = try {
Toolkit.getDefaultToolkit().systemClipboard.getData(DataFlavor.imageFlavor) as Image
} catch (e: UnsupportedFlavorException) {
null
}
if (image != null) {
try {
// create BufferedImage from Image
val bi = BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_ARGB)
val bgr = bi.createGraphics()
bgr.drawImage(image, 0, 0, null)
bgr.dispose()
// create byte array from BufferedImage
val baos = ByteArrayOutputStream()
ImageIO.write(bi, "png", baos)
val bytes = baos.toByteArray()
withBGApi {
val tempFile = File(tmpDir, "${UUID.randomUUID()}.png")
chatModel.filesToDelete.add(tempFile)
tempFile.writeBytes(bytes)
composeState.processPickedMedia(listOf(tempFile.toURI()), composeState.value.message)
}
} catch (e: Exception) {
Log.e(TAG, "Pasting image exception: ${e.stackTraceToString()}")
}
true
} else {
false
}
}
}
else false else false
}, },
cursorBrush = SolidColor(MaterialTheme.colors.secondary), cursorBrush = SolidColor(MaterialTheme.colors.secondary),