diff --git a/apps/ios/SimpleX.xcodeproj/project.pbxproj b/apps/ios/SimpleX.xcodeproj/project.pbxproj
index ef98ddc678..d342b277ce 100644
--- a/apps/ios/SimpleX.xcodeproj/project.pbxproj
+++ b/apps/ios/SimpleX.xcodeproj/project.pbxproj
@@ -1935,7 +1935,7 @@
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 255;
+ CURRENT_PROJECT_VERSION = 256;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
@@ -1960,7 +1960,7 @@
"@executable_path/Frameworks",
);
LLVM_LTO = YES_THIN;
- MARKETING_VERSION = 6.2.1;
+ MARKETING_VERSION = 6.2.2;
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app;
PRODUCT_NAME = SimpleX;
SDKROOT = iphoneos;
@@ -1984,7 +1984,7 @@
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 255;
+ CURRENT_PROJECT_VERSION = 256;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
@@ -2009,7 +2009,7 @@
"@executable_path/Frameworks",
);
LLVM_LTO = YES;
- MARKETING_VERSION = 6.2.1;
+ MARKETING_VERSION = 6.2.2;
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app;
PRODUCT_NAME = SimpleX;
SDKROOT = iphoneos;
@@ -2025,11 +2025,11 @@
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 255;
+ CURRENT_PROJECT_VERSION = 256;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
- MARKETING_VERSION = 6.2.1;
+ MARKETING_VERSION = 6.2.2;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.Tests-iOS";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
@@ -2045,11 +2045,11 @@
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 255;
+ CURRENT_PROJECT_VERSION = 256;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
- MARKETING_VERSION = 6.2.1;
+ MARKETING_VERSION = 6.2.2;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.Tests-iOS";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
@@ -2070,7 +2070,7 @@
CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 255;
+ CURRENT_PROJECT_VERSION = 256;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
GCC_OPTIMIZATION_LEVEL = s;
@@ -2085,7 +2085,7 @@
"@executable_path/../../Frameworks",
);
LLVM_LTO = YES;
- MARKETING_VERSION = 6.2.1;
+ MARKETING_VERSION = 6.2.2;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-NSE";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -2107,7 +2107,7 @@
CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 255;
+ CURRENT_PROJECT_VERSION = 256;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
ENABLE_CODE_COVERAGE = NO;
@@ -2122,7 +2122,7 @@
"@executable_path/../../Frameworks",
);
LLVM_LTO = YES;
- MARKETING_VERSION = 6.2.1;
+ MARKETING_VERSION = 6.2.2;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-NSE";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -2144,7 +2144,7 @@
CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YES;
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 255;
+ CURRENT_PROJECT_VERSION = 256;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
DYLIB_COMPATIBILITY_VERSION = 1;
@@ -2170,7 +2170,7 @@
"$(PROJECT_DIR)/Libraries/sim",
);
LLVM_LTO = YES;
- MARKETING_VERSION = 6.2.1;
+ MARKETING_VERSION = 6.2.2;
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.SimpleXChat;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SDKROOT = iphoneos;
@@ -2195,7 +2195,7 @@
CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YES;
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 255;
+ CURRENT_PROJECT_VERSION = 256;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
DYLIB_COMPATIBILITY_VERSION = 1;
@@ -2221,7 +2221,7 @@
"$(PROJECT_DIR)/Libraries/sim",
);
LLVM_LTO = YES;
- MARKETING_VERSION = 6.2.1;
+ MARKETING_VERSION = 6.2.2;
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.SimpleXChat;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SDKROOT = iphoneos;
@@ -2246,7 +2246,7 @@
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CODE_SIGN_ENTITLEMENTS = "SimpleX SE/SimpleX SE.entitlements";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 255;
+ CURRENT_PROJECT_VERSION = 256;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
@@ -2261,7 +2261,7 @@
"@executable_path/../../Frameworks",
);
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
- MARKETING_VERSION = 6.2.1;
+ MARKETING_VERSION = 6.2.2;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-SE";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
@@ -2280,7 +2280,7 @@
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CODE_SIGN_ENTITLEMENTS = "SimpleX SE/SimpleX SE.entitlements";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 255;
+ CURRENT_PROJECT_VERSION = 256;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
@@ -2295,7 +2295,7 @@
"@executable_path/../../Frameworks",
);
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
- MARKETING_VERSION = 6.2.1;
+ MARKETING_VERSION = 6.2.2;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-SE";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
diff --git a/apps/multiplatform/android/src/main/AndroidManifest.xml b/apps/multiplatform/android/src/main/AndroidManifest.xml
index 67bc0d70c8..bb6a6f8f8a 100644
--- a/apps/multiplatform/android/src/main/AndroidManifest.xml
+++ b/apps/multiplatform/android/src/main/AndroidManifest.xml
@@ -27,6 +27,14 @@
+
+
+
+
+
+
+
+
= if (Build.VERSION.SDK_INT >= 33) {
+// pm.queryIntentActivities(openIntent, PackageManager.ResolveInfoFlags.of((PackageManager.MATCH_DEFAULT_ONLY).toLong()))
+// } else {
+// pm.queryIntentActivities(openIntent, PackageManager.MATCH_DEFAULT_ONLY)
+// }.sortedBy { it.priority }
+// val first = resInfoList.firstOrNull { it.isDefault } ?: resInfoList.firstOrNull() ?: return null
+ val act = pm.resolveActivity(openIntent, PackageManager.MATCH_DEFAULT_ONLY) ?: return null
+// Log.d(TAG, "Default launch action ${act} ${act.loadLabel(pm)} ${act.activityInfo?.name}")
+ val label = act.loadLabel(pm).toString()
+ val icon = act.loadIcon(pm).toBitmap().asImageBitmap()
+ val chooser = act.activityInfo?.name?.endsWith("ResolverActivity") == true
+ return OpenDefaultApp(label, icon, chooser)
}
actual fun shareFile(text: String, fileSource: CryptoFile) {
diff --git a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/chat/item/CIFileView.android.kt b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/chat/item/CIFileView.android.kt
new file mode 100644
index 0000000000..b24150ed24
--- /dev/null
+++ b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/chat/item/CIFileView.android.kt
@@ -0,0 +1,57 @@
+package chat.simplex.common.views.chat.item
+
+import androidx.compose.material.MaterialTheme
+import androidx.compose.runtime.*
+import chat.simplex.common.model.CryptoFile
+import chat.simplex.common.platform.*
+import chat.simplex.common.views.helpers.DefaultDropdownMenu
+import chat.simplex.res.MR
+import dev.icerock.moko.resources.compose.painterResource
+import dev.icerock.moko.resources.compose.stringResource
+import java.net.URI
+
+@Composable
+actual fun SaveOrOpenFileMenu(
+ showMenu: MutableState,
+ encrypted: Boolean,
+ ext: String?,
+ encryptedUri: URI,
+ fileSource: CryptoFile,
+ saveFile: () -> Unit
+) {
+ val defaultApp = remember(encryptedUri.toString()) { if (ext != null) queryDefaultAppForExtension(ext, encryptedUri) else null }
+ DefaultDropdownMenu(showMenu) {
+ if (defaultApp != null) {
+ if (!defaultApp.isSystemChooser) {
+ ItemAction(
+ stringResource(MR.strings.open_with_app).format(defaultApp.name),
+ defaultApp.icon,
+ textColor = MaterialTheme.colors.primary,
+ onClick = {
+ openOrShareFile("", fileSource, justOpen = true, useChooser = false)
+ showMenu.value = false
+ }
+ )
+ } else {
+ ItemAction(
+ stringResource(MR.strings.open_with_app).format("…"),
+ painterResource(MR.images.ic_open_in_new),
+ color = MaterialTheme.colors.primary,
+ onClick = {
+ openOrShareFile("", fileSource, justOpen = true, useChooser = false)
+ showMenu.value = false
+ }
+ )
+ }
+ }
+ ItemAction(
+ stringResource(MR.strings.save_verb),
+ painterResource(if (encrypted) MR.images.ic_lock_open_right else MR.images.ic_download),
+ color = MaterialTheme.colors.primary,
+ onClick = {
+ saveFile()
+ showMenu.value = false
+ }
+ )
+ }
+}
diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatInfoView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatInfoView.kt
index ed661245a3..9b580edb62 100644
--- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatInfoView.kt
+++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatInfoView.kt
@@ -697,13 +697,19 @@ fun ChatInfoHeader(cInfo: ChatInfo, contact: Contact) {
Icon(painterResource(MR.images.ic_verified_user), null, tint = MaterialTheme.colors.secondary)
}
)
+ val clipboard = LocalClipboardManager.current
+ val copyNameToClipboard = {
+ clipboard.setText(AnnotatedString(contact.profile.displayName))
+ showToast(generalGetString(MR.strings.copied))
+ }
Text(
text,
inlineContent = inlineContent,
style = MaterialTheme.typography.h1.copy(fontWeight = FontWeight.Normal),
textAlign = TextAlign.Center,
maxLines = 3,
- overflow = TextOverflow.Ellipsis
+ overflow = TextOverflow.Ellipsis,
+ modifier = Modifier.combinedClickable(onClick = copyNameToClipboard, onLongClick = copyNameToClipboard).onRightClick(copyNameToClipboard)
)
if (cInfo.fullName != "" && cInfo.fullName != cInfo.displayName && cInfo.fullName != contact.profile.displayName) {
Text(
@@ -711,7 +717,8 @@ fun ChatInfoHeader(cInfo: ChatInfo, contact: Contact) {
color = MaterialTheme.colors.onBackground,
textAlign = TextAlign.Center,
maxLines = 4,
- overflow = TextOverflow.Ellipsis
+ overflow = TextOverflow.Ellipsis,
+ modifier = Modifier.combinedClickable(onClick = copyNameToClipboard, onLongClick = copyNameToClipboard).onRightClick(copyNameToClipboard)
)
}
}
diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupChatInfoView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupChatInfoView.kt
index 5ee6e40e6e..c92ac2ddc3 100644
--- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupChatInfoView.kt
+++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupChatInfoView.kt
@@ -9,6 +9,7 @@ import SectionSpacer
import SectionTextFooter
import SectionView
import androidx.compose.desktop.ui.tooling.preview.Preview
+import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.*
import androidx.compose.material.*
@@ -17,6 +18,8 @@ import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.platform.LocalClipboardManager
+import androidx.compose.ui.text.AnnotatedString
import dev.icerock.moko.resources.compose.painterResource
import dev.icerock.moko.resources.compose.stringResource
import androidx.compose.ui.text.font.FontWeight
@@ -446,12 +449,18 @@ private fun GroupChatInfoHeader(cInfo: ChatInfo) {
horizontalAlignment = Alignment.CenterHorizontally
) {
ChatInfoImage(cInfo, size = 192.dp, iconColor = if (isInDarkTheme()) GroupDark else SettingsSecondaryLight)
+ val clipboard = LocalClipboardManager.current
+ val copyNameToClipboard = {
+ clipboard.setText(AnnotatedString(cInfo.displayName))
+ showToast(generalGetString(MR.strings.copied))
+ }
Text(
cInfo.displayName, style = MaterialTheme.typography.h1.copy(fontWeight = FontWeight.Normal),
color = MaterialTheme.colors.onBackground,
textAlign = TextAlign.Center,
maxLines = 4,
- overflow = TextOverflow.Ellipsis
+ overflow = TextOverflow.Ellipsis,
+ modifier = Modifier.combinedClickable(onClick = copyNameToClipboard, onLongClick = copyNameToClipboard).onRightClick(copyNameToClipboard)
)
if (cInfo.fullName != "" && cInfo.fullName != cInfo.displayName) {
Text(
@@ -459,7 +468,8 @@ private fun GroupChatInfoHeader(cInfo: ChatInfo) {
color = MaterialTheme.colors.onBackground,
textAlign = TextAlign.Center,
maxLines = 8,
- overflow = TextOverflow.Ellipsis
+ overflow = TextOverflow.Ellipsis,
+ modifier = Modifier.combinedClickable(onClick = copyNameToClipboard, onLongClick = copyNameToClipboard).onRightClick(copyNameToClipboard)
)
}
}
diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupMemberInfoView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupMemberInfoView.kt
index e4e5494364..e607efeddc 100644
--- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupMemberInfoView.kt
+++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupMemberInfoView.kt
@@ -8,6 +8,7 @@ import SectionSpacer
import SectionTextFooter
import SectionView
import androidx.compose.desktop.ui.tooling.preview.Preview
+import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.text.InlineTextContent
import androidx.compose.foundation.text.appendInlineContent
@@ -537,13 +538,19 @@ fun GroupMemberInfoHeader(member: GroupMember) {
Icon(painterResource(MR.images.ic_verified_user), null, tint = MaterialTheme.colors.secondary)
}
)
+ val clipboard = LocalClipboardManager.current
+ val copyNameToClipboard = {
+ clipboard.setText(AnnotatedString(member.displayName))
+ showToast(generalGetString(MR.strings.copied))
+ }
Text(
text,
inlineContent = inlineContent,
style = MaterialTheme.typography.h1.copy(fontWeight = FontWeight.Normal),
textAlign = TextAlign.Center,
maxLines = 3,
- overflow = TextOverflow.Ellipsis
+ overflow = TextOverflow.Ellipsis,
+ modifier = Modifier.combinedClickable(onClick = copyNameToClipboard, onLongClick = copyNameToClipboard).onRightClick(copyNameToClipboard)
)
if (member.fullName != "" && member.fullName != member.displayName) {
Text(
@@ -551,7 +558,8 @@ fun GroupMemberInfoHeader(member: GroupMember) {
color = MaterialTheme.colors.onBackground,
textAlign = TextAlign.Center,
maxLines = 4,
- overflow = TextOverflow.Ellipsis
+ overflow = TextOverflow.Ellipsis,
+ modifier = Modifier.combinedClickable(onClick = copyNameToClipboard, onLongClick = copyNameToClipboard).onRightClick(copyNameToClipboard)
)
}
}
diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIFileView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIFileView.kt
index 59643afdf4..2c16de40e9 100644
--- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIFileView.kt
+++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIFileView.kt
@@ -1,12 +1,12 @@
package chat.simplex.common.views.chat.item
-import androidx.compose.foundation.background
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CornerSize
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
import androidx.compose.runtime.*
+import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
@@ -184,14 +184,26 @@ fun CIFileView(
}
}
+ val showOpenSaveMenu = rememberSaveable(file?.fileId) { mutableStateOf(false) }
+ val ext = file?.fileSource?.filePath?.substringAfterLast(".")?.takeIf { it.isNotBlank() }
+ val loadedFilePath = if (appPlatform.isAndroid && file?.fileSource != null) getLoadedFilePath(file) else null
+ if (loadedFilePath != null && file?.fileSource != null) {
+ val encrypted = file.fileSource.cryptoArgs != null
+ SaveOrOpenFileMenu(showOpenSaveMenu, encrypted, ext, File(loadedFilePath).toURI(), file.fileSource, saveFile = { fileAction() })
+ }
Row(
Modifier
.combinedClickable(
- onClick = { fileAction() },
+ onClick = {
+ if (appPlatform.isAndroid && loadedFilePath != null) {
+ showOpenSaveMenu.value = true
+ } else {
+ fileAction()
+ }
+ },
onLongClick = { showMenu.value = true }
)
.padding(if (smallView) PaddingValues() else PaddingValues(top = 4.sp.toDp(), bottom = 6.sp.toDp(), start = 6.sp.toDp(), end = 12.sp.toDp())),
- //Modifier.clickable(enabled = file?.fileSource != null) { if (file?.fileSource != null && getLoadedFilePath(file) != null) openFile(file.fileSource) }.padding(top = 4.dp, bottom = 6.dp, start = 6.dp, end = 12.dp),
verticalAlignment = Alignment.Bottom,
horizontalArrangement = Arrangement.spacedBy(2.sp.toDp())
) {
@@ -223,6 +235,16 @@ fun CIFileView(
fun fileSizeValid(file: CIFile): Boolean = file.fileSize <= getMaxFileSize(file.fileProtocol)
+@Composable
+expect fun SaveOrOpenFileMenu(
+ showMenu: MutableState,
+ encrypted: Boolean,
+ ext: String?,
+ encryptedUri: URI,
+ fileSource: CryptoFile,
+ saveFile: () -> Unit
+)
+
@Composable
fun rememberSaveFileLauncher(ciFile: CIFile?): FileChooserLauncher =
rememberFileChooserLauncher(false, ciFile) { to: URI? ->
diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/ChatItemView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/ChatItemView.kt
index 22842eb350..647c74da06 100644
--- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/ChatItemView.kt
+++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/ChatItemView.kt
@@ -867,6 +867,32 @@ fun ItemAction(text: String, icon: Painter, color: Color = Color.Unspecified, on
}
}
+@Composable
+fun ItemAction(text: String, icon: ImageBitmap, textColor: Color = Color.Unspecified, iconColor: Color = Color.Unspecified, onClick: () -> Unit) {
+ val finalColor = if (textColor == Color.Unspecified) {
+ MenuTextColor
+ } else textColor
+ DropdownMenuItem(onClick, contentPadding = PaddingValues(horizontal = DEFAULT_PADDING * 1.5f)) {
+ Row(verticalAlignment = Alignment.CenterVertically) {
+ Text(
+ text,
+ modifier = Modifier
+ .fillMaxWidth()
+ .weight(1F)
+ .padding(end = 15.dp),
+ color = finalColor,
+ maxLines = 1,
+ overflow = TextOverflow.Ellipsis
+ )
+ if (iconColor == Color.Unspecified) {
+ Image(icon, text, Modifier.size(22.dp))
+ } else {
+ Icon(icon, text, Modifier.size(22.dp), tint = iconColor)
+ }
+ }
+ }
+}
+
@Composable
fun ItemAction(
text: String,
diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml
index a209126a89..a45d1a5458 100644
--- a/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml
+++ b/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml
@@ -482,6 +482,7 @@
Please, wait while the file is being loaded from the linked mobile
File error
Temporary file error
+ Open with %s
Voice message
diff --git a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/chat/item/CIFileView.desktop.kt b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/chat/item/CIFileView.desktop.kt
new file mode 100644
index 0000000000..eceb7de9be
--- /dev/null
+++ b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/chat/item/CIFileView.desktop.kt
@@ -0,0 +1,18 @@
+package chat.simplex.common.views.chat.item
+
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.MutableState
+import chat.simplex.common.model.CryptoFile
+import java.net.URI
+
+@Composable
+actual fun SaveOrOpenFileMenu(
+ showMenu: MutableState,
+ encrypted: Boolean,
+ ext: String?,
+ encryptedUri: URI,
+ fileSource: CryptoFile,
+ saveFile: () -> Unit
+) {
+
+}
diff --git a/apps/multiplatform/gradle.properties b/apps/multiplatform/gradle.properties
index cde173f24c..00c7578a8e 100644
--- a/apps/multiplatform/gradle.properties
+++ b/apps/multiplatform/gradle.properties
@@ -24,11 +24,11 @@ android.nonTransitiveRClass=true
kotlin.mpp.androidSourceSetLayoutVersion=2
kotlin.jvm.target=11
-android.version_name=6.2.1
-android.version_code=261
+android.version_name=6.2.2
+android.version_code=263
-desktop.version_name=6.2.1
-desktop.version_code=83
+desktop.version_name=6.2.2
+desktop.version_code=84
kotlin.version=1.9.23
gradle.plugin.version=8.2.0
diff --git a/blog/20241210-simplex-network-v6-2-servers-by-flux-business-chats.md b/blog/20241210-simplex-network-v6-2-servers-by-flux-business-chats.md
index 502a42c559..339fab4d16 100644
--- a/blog/20241210-simplex-network-v6-2-servers-by-flux-business-chats.md
+++ b/blog/20241210-simplex-network-v6-2-servers-by-flux-business-chats.md
@@ -72,7 +72,7 @@ This is a small but important change - you can now see who reacted to your messa
### Improving notifications in iOS app
-iOS notifications in a decentralized network is a complex problems. We [support iOS notifications](./20220404-simplex-chat-instant-notifications.md#ios-notifications-require-a-server) from early versions of the app, focussing on preserving privacy as much as possible. But the reliability of notifications was not good enough.
+iOS notifications in a decentralized network is a complex problem. We [support iOS notifications](./20220404-simplex-chat-instant-notifications.md#ios-notifications-require-a-server) from early versions of the app, focussing on preserving privacy as much as possible. But the reliability of notifications was not good enough.
We solved several problems of notification delivery in this release:
- messaging servers no longer lose notifications while notification servers are restarted.
diff --git a/cabal.project b/cabal.project
index c8ab5b4c28..327342f8a7 100644
--- a/cabal.project
+++ b/cabal.project
@@ -12,7 +12,7 @@ constraints: zip +disable-bzip2 +disable-zstd
source-repository-package
type: git
location: https://github.com/simplex-chat/simplexmq.git
- tag: f5cef2556b05cf384db284644c112f822407b361
+ tag: 426bf68763c4461e218f6775e4cec8143393640f
source-repository-package
type: git
diff --git a/package.yaml b/package.yaml
index 2eec40d9d1..57e67c3329 100644
--- a/package.yaml
+++ b/package.yaml
@@ -1,5 +1,5 @@
name: simplex-chat
-version: 6.2.0.7
+version: 6.2.2.0
#synopsis:
#description:
homepage: https://github.com/simplex-chat/simplex-chat#readme
diff --git a/scripts/nix/sha256map.nix b/scripts/nix/sha256map.nix
index 7887987f12..353310605f 100644
--- a/scripts/nix/sha256map.nix
+++ b/scripts/nix/sha256map.nix
@@ -1,5 +1,5 @@
{
- "https://github.com/simplex-chat/simplexmq.git"."f5cef2556b05cf384db284644c112f822407b361" = "14w0fji1fdr63w4pjkhlrdiz93p2axghzkb1ykvnrw111by87g8l";
+ "https://github.com/simplex-chat/simplexmq.git"."426bf68763c4461e218f6775e4cec8143393640f" = "1h2hxn1qv33frpdaspbqz7ivysrnk5lcrgxsv88mk6mbm6bf7cwy";
"https://github.com/simplex-chat/hs-socks.git"."a30cc7a79a08d8108316094f8f2f82a0c5e1ac51" = "0yasvnr7g91k76mjkamvzab2kvlb1g5pspjyjn2fr6v83swjhj38";
"https://github.com/simplex-chat/direct-sqlcipher.git"."f814ee68b16a9447fbb467ccc8f29bdd3546bfd9" = "1ql13f4kfwkbaq7nygkxgw84213i0zm7c1a8hwvramayxl38dq5d";
"https://github.com/simplex-chat/sqlcipher-simple.git"."a46bd361a19376c5211f1058908fc0ae6bf42446" = "1z0r78d8f0812kxbgsm735qf6xx8lvaz27k1a0b4a2m0sshpd5gl";
diff --git a/simplex-chat.cabal b/simplex-chat.cabal
index 4e917e885b..feabf61bc8 100644
--- a/simplex-chat.cabal
+++ b/simplex-chat.cabal
@@ -5,7 +5,7 @@ cabal-version: 1.12
-- see: https://github.com/sol/hpack
name: simplex-chat
-version: 6.2.0.7
+version: 6.2.2.0
category: Web, System, Services, Cryptography
homepage: https://github.com/simplex-chat/simplex-chat#readme
author: simplex.chat
diff --git a/src/Simplex/Chat.hs b/src/Simplex/Chat.hs
index 7a23792a6a..69bdddd220 100644
--- a/src/Simplex/Chat.hs
+++ b/src/Simplex/Chat.hs
@@ -36,7 +36,11 @@ import Simplex.Chat.Protocol
import Simplex.Chat.Store
import Simplex.Chat.Store.Profiles
import Simplex.Chat.Types
-import Simplex.Chat.Util (shuffle)
+import Simplex.Chat.Types.Preferences
+import Simplex.Chat.Types.Shared
+import Simplex.Chat.Util (encryptFile, liftIOEither, shuffle)
+import qualified Simplex.Chat.Util as U
+import Simplex.FileTransfer.Description (maxFileSize, maxFileSizeHard)
import Simplex.FileTransfer.Client.Presets (defaultXFTPServers)
import Simplex.Messaging.Agent as Agent
import Simplex.Messaging.Agent.Env.SQLite (AgentConfig (..), InitialAgentServers (..), ServerCfg (..), ServerRoles (..), allRoles, createAgentStore, defaultAgentConfig, presetServerCfg)