mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2024-12-17 17:20:21 +01:00
desktop: sending and receiving files via connected mobile (#3365)
* desktop: support remote files (WIP) * working with remote files locally * better * working with remote file downloads * sending files * fixes of loading files in some situations * image compression * constant for remote hosts * refactor --------- Co-authored-by: Avently <7953703+avently@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
e95d9d0b49
commit
ca8833c0c1
+1
-1
@@ -113,7 +113,7 @@ object NtfManager {
|
||||
|
||||
private fun prepareIconPath(icon: ImageBitmap?): String? = if (icon != null) {
|
||||
tmpDir.mkdir()
|
||||
val newFile = File(tmpDir.absolutePath + File.separator + generateNewFileName("IMG", "png"))
|
||||
val newFile = File(tmpDir.absolutePath + File.separator + generateNewFileName("IMG", "png", tmpDir))
|
||||
try {
|
||||
ImageIO.write(icon.toAwtImage(), "PNG", newFile.outputStream())
|
||||
newFile.absolutePath
|
||||
|
||||
+2
@@ -21,6 +21,8 @@ actual val agentDatabaseFileName: String = "simplex_v1_agent.db"
|
||||
|
||||
actual val databaseExportDir: File = tmpDir
|
||||
|
||||
actual val remoteHostsDir: File = File(dataDir.absolutePath + File.separator + "remote_hosts")
|
||||
|
||||
actual fun desktopOpenDatabaseDir() {
|
||||
if (Desktop.isDesktopSupported()) {
|
||||
try {
|
||||
|
||||
-2
@@ -2,12 +2,10 @@ package chat.simplex.common.views.chat.item
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.graphics.*
|
||||
import androidx.compose.ui.graphics.painter.BitmapPainter
|
||||
import androidx.compose.ui.graphics.painter.Painter
|
||||
import chat.simplex.common.model.CIFile
|
||||
import chat.simplex.common.platform.*
|
||||
import chat.simplex.common.views.helpers.ModalManager
|
||||
import java.net.URI
|
||||
|
||||
@Composable
|
||||
actual fun SimpleAndAnimatedImageView(
|
||||
|
||||
+26
-10
@@ -34,35 +34,51 @@ actual fun ReactionIcon(text: String, fontSize: TextUnit) {
|
||||
@Composable
|
||||
actual fun SaveContentItemAction(cItem: ChatItem, saveFileLauncher: FileChooserLauncher, showMenu: MutableState<Boolean>) {
|
||||
ItemAction(stringResource(MR.strings.save_verb), painterResource(if (cItem.file?.fileSource?.cryptoArgs == null) MR.images.ic_download else MR.images.ic_lock_open_right), onClick = {
|
||||
when (cItem.content.msgContent) {
|
||||
is MsgContent.MCImage, is MsgContent.MCFile, is MsgContent.MCVoice, is MsgContent.MCVideo -> withApi { saveFileLauncher.launch(cItem.file?.fileName ?: "") }
|
||||
else -> {}
|
||||
val saveIfExists = {
|
||||
when (cItem.content.msgContent) {
|
||||
is MsgContent.MCImage, is MsgContent.MCFile, is MsgContent.MCVoice, is MsgContent.MCVideo -> withApi { saveFileLauncher.launch(cItem.file?.fileName ?: "") }
|
||||
else -> {}
|
||||
}
|
||||
showMenu.value = false
|
||||
}
|
||||
showMenu.value = false
|
||||
var fileSource = getLoadedFileSource(cItem.file)
|
||||
if (chatModel.connectedToRemote() && fileSource == null) {
|
||||
withBGApi {
|
||||
cItem.file?.loadRemoteFile(true)
|
||||
fileSource = getLoadedFileSource(cItem.file)
|
||||
saveIfExists()
|
||||
}
|
||||
} else saveIfExists()
|
||||
})
|
||||
}
|
||||
|
||||
actual fun copyItemToClipboard(cItem: ChatItem, clipboard: ClipboardManager) {
|
||||
val fileSource = getLoadedFileSource(cItem.file)
|
||||
actual fun copyItemToClipboard(cItem: ChatItem, clipboard: ClipboardManager) = withBGApi {
|
||||
var fileSource = getLoadedFileSource(cItem.file)
|
||||
if (chatModel.connectedToRemote() && fileSource == null) {
|
||||
cItem.file?.loadRemoteFile(true)
|
||||
fileSource = getLoadedFileSource(cItem.file)
|
||||
}
|
||||
|
||||
if (fileSource != null) {
|
||||
val filePath: String = if (fileSource.cryptoArgs != null) {
|
||||
val tmpFile = File(tmpDir, fileSource.filePath)
|
||||
tmpFile.deleteOnExit()
|
||||
try {
|
||||
decryptCryptoFile(getAppFilePath(fileSource.filePath), fileSource.cryptoArgs, tmpFile.absolutePath)
|
||||
decryptCryptoFile(getAppFilePath(fileSource.filePath), fileSource.cryptoArgs ?: return@withBGApi, tmpFile.absolutePath)
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Unable to decrypt crypto file: " + e.stackTraceToString())
|
||||
return
|
||||
return@withBGApi
|
||||
}
|
||||
tmpFile.absolutePath
|
||||
} else {
|
||||
getAppFilePath(fileSource.filePath)
|
||||
}
|
||||
when {
|
||||
when {
|
||||
desktopPlatform.isWindows() -> clipboard.setText(AnnotatedString("\"${File(filePath).absolutePath}\""))
|
||||
else -> clipboard.setText(AnnotatedString(filePath))
|
||||
}
|
||||
} else {
|
||||
clipboard.setText(AnnotatedString(cItem.content.text))
|
||||
}
|
||||
}
|
||||
showToast(MR.strings.copied.localized())
|
||||
}.run {}
|
||||
|
||||
+16
-7
@@ -5,8 +5,7 @@ import androidx.compose.ui.text.*
|
||||
import androidx.compose.ui.text.font.FontStyle
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.Density
|
||||
import chat.simplex.common.model.CIFile
|
||||
import chat.simplex.common.model.readCryptoFile
|
||||
import chat.simplex.common.model.*
|
||||
import chat.simplex.common.platform.*
|
||||
import chat.simplex.common.simplexWindowState
|
||||
import chat.simplex.res.MR
|
||||
@@ -88,11 +87,21 @@ actual fun escapedHtmlToAnnotatedString(text: String, density: Density): Annotat
|
||||
AnnotatedString(text)
|
||||
}
|
||||
|
||||
actual fun getAppFileUri(fileName: String): URI =
|
||||
URI(appFilesDir.toURI().toString() + "/" + fileName)
|
||||
actual fun getAppFileUri(fileName: String): URI {
|
||||
val rh = chatModel.currentRemoteHost.value
|
||||
return if (rh == null) {
|
||||
URI(appFilesDir.toURI().toString() + "/" + fileName)
|
||||
} else {
|
||||
URI(dataDir.absolutePath + "/remote_hosts/" + rh.storePath + "/simplex_v1_files/" + fileName)
|
||||
}
|
||||
}
|
||||
|
||||
actual fun getLoadedImage(file: CIFile?): Pair<ImageBitmap, ByteArray>? {
|
||||
val filePath = getLoadedFilePath(file)
|
||||
actual suspend fun getLoadedImage(file: CIFile?): Pair<ImageBitmap, ByteArray>? {
|
||||
var filePath = getLoadedFilePath(file)
|
||||
if (chatModel.connectedToRemote() && filePath == null) {
|
||||
file?.loadRemoteFile(false)
|
||||
filePath = getLoadedFilePath(file)
|
||||
}
|
||||
return if (filePath != null) {
|
||||
try {
|
||||
val data = if (file?.fileSource?.cryptoArgs != null) readCryptoFile(filePath, file.fileSource.cryptoArgs) else File(filePath).readBytes()
|
||||
@@ -141,7 +150,7 @@ actual suspend fun saveTempImageUncompressed(image: ImageBitmap, asPng: Boolean)
|
||||
return if (file != null) {
|
||||
try {
|
||||
val ext = if (asPng) "png" else "jpg"
|
||||
val newFile = File(file.absolutePath + File.separator + generateNewFileName("IMG", ext))
|
||||
val newFile = File(file.absolutePath + File.separator + generateNewFileName("IMG", ext, File(getAppFilePath(""))))
|
||||
// LALAL FILE IS EMPTY
|
||||
ImageIO.write(image.toAwtImage(), ext.uppercase(), newFile.outputStream())
|
||||
newFile
|
||||
|
||||
Reference in New Issue
Block a user