From 0f0f65533a10bb18feb777ce450f4a45991d2e12 Mon Sep 17 00:00:00 2001 From: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com> Date: Fri, 26 Jan 2024 13:57:04 +0400 Subject: [PATCH] android: group welcome message byte limit (#3756) * android: group welcome message byte limit * text * change footer --- .../src/commonMain/cpp/android/simplex-api.c | 9 ++++ .../src/commonMain/cpp/desktop/simplex-api.c | 9 ++++ .../chat/simplex/common/platform/Core.kt | 1 + .../views/chat/group/WelcomeMessageView.kt | 48 +++++++++++++++++-- .../simplex/common/views/helpers/Section.kt | 8 ++-- .../commonMain/resources/MR/base/strings.xml | 2 + 6 files changed, 69 insertions(+), 8 deletions(-) diff --git a/apps/multiplatform/common/src/commonMain/cpp/android/simplex-api.c b/apps/multiplatform/common/src/commonMain/cpp/android/simplex-api.c index 5936bd5ff2..d0581b4336 100644 --- a/apps/multiplatform/common/src/commonMain/cpp/android/simplex-api.c +++ b/apps/multiplatform/common/src/commonMain/cpp/android/simplex-api.c @@ -66,6 +66,7 @@ extern char *chat_parse_markdown(const char *str); extern char *chat_parse_server(const char *str); extern char *chat_password_hash(const char *pwd, const char *salt); extern char *chat_valid_name(const char *name); +extern int chat_json_length(const char *str); extern char *chat_write_file(chat_ctrl ctrl, const char *path, char *ptr, int length); extern char *chat_read_file(const char *path, const char *key, const char *nonce); extern char *chat_encrypt_file(chat_ctrl ctrl, const char *from_path, const char *to_path); @@ -163,6 +164,14 @@ Java_chat_simplex_common_platform_CoreKt_chatValidName(JNIEnv *env, jclass clazz return res; } +JNIEXPORT int JNICALL +Java_chat_simplex_common_platform_CoreKt_chatJsonLength(JNIEnv *env, jclass clazz, jstring str) { + const char *_str = (*env)->GetStringUTFChars(env, str, JNI_FALSE); + int res = chat_json_length(_str); + (*env)->ReleaseStringUTFChars(env, str, _str); + return res; +} + JNIEXPORT jstring JNICALL Java_chat_simplex_common_platform_CoreKt_chatWriteFile(JNIEnv *env, jclass clazz, jlong controller, jstring path, jobject buffer) { const char *_path = (*env)->GetStringUTFChars(env, path, JNI_FALSE); diff --git a/apps/multiplatform/common/src/commonMain/cpp/desktop/simplex-api.c b/apps/multiplatform/common/src/commonMain/cpp/desktop/simplex-api.c index f15689285a..90504e25c1 100644 --- a/apps/multiplatform/common/src/commonMain/cpp/desktop/simplex-api.c +++ b/apps/multiplatform/common/src/commonMain/cpp/desktop/simplex-api.c @@ -39,6 +39,7 @@ extern char *chat_parse_markdown(const char *str); extern char *chat_parse_server(const char *str); extern char *chat_password_hash(const char *pwd, const char *salt); extern char *chat_valid_name(const char *name); +extern int chat_json_length(const char *str); extern char *chat_write_file(chat_ctrl ctrl, const char *path, char *ptr, int length); extern char *chat_read_file(const char *path, const char *key, const char *nonce); extern char *chat_encrypt_file(chat_ctrl ctrl, const char *from_path, const char *to_path); @@ -173,6 +174,14 @@ Java_chat_simplex_common_platform_CoreKt_chatValidName(JNIEnv *env, jclass clazz return res; } +JNIEXPORT int JNICALL +Java_chat_simplex_common_platform_CoreKt_chatJsonLength(JNIEnv *env, jclass clazz, jstring str) { + const char *_str = encode_to_utf8_chars(env, str); + int res = chat_json_length(_str); + (*env)->ReleaseStringUTFChars(env, str, _str); + return res; +} + JNIEXPORT jstring JNICALL Java_chat_simplex_common_platform_CoreKt_chatWriteFile(JNIEnv *env, jclass clazz, jlong controller, jstring path, jobject buffer) { const char *_path = encode_to_utf8_chars(env, path); diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/platform/Core.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/platform/Core.kt index ec81e54418..0b5ce25044 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/platform/Core.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/platform/Core.kt @@ -28,6 +28,7 @@ external fun chatParseMarkdown(str: String): String external fun chatParseServer(str: String): String external fun chatPasswordHash(pwd: String, salt: String): String external fun chatValidName(name: String): String +external fun chatJsonLength(str: String): Int external fun chatWriteFile(ctrl: ChatCtrl, path: String, buffer: ByteBuffer): String external fun chatReadFile(path: String, key: String, nonce: String): Array external fun chatEncryptFile(ctrl: ChatCtrl, fromPath: String, toPath: String): String diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/WelcomeMessageView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/WelcomeMessageView.kt index 9124eed4c3..6c2c37503c 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/WelcomeMessageView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/WelcomeMessageView.kt @@ -3,6 +3,7 @@ package chat.simplex.common.views.chat.group import SectionBottomSpacer import SectionDividerSpaced import SectionItemView +import SectionTextFooter import SectionView import TextIconSpaced import androidx.compose.foundation.layout.* @@ -14,6 +15,7 @@ import androidx.compose.runtime.* import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Modifier import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalClipboardManager import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.text.AnnotatedString @@ -27,9 +29,13 @@ import chat.simplex.common.views.chat.item.MarkdownText import chat.simplex.common.views.helpers.* import chat.simplex.common.model.ChatModel import chat.simplex.common.model.GroupInfo +import chat.simplex.common.platform.chatJsonLength +import chat.simplex.common.ui.theme.DEFAULT_PADDING_HALF import chat.simplex.res.MR import kotlinx.coroutines.delay +private const val maxByteCount = 1200 + @Composable fun GroupWelcomeView(m: ChatModel, rhId: Long?, groupInfo: GroupInfo, close: () -> Unit) { var gInfo by remember { mutableStateOf(groupInfo) } @@ -54,8 +60,11 @@ fun GroupWelcomeView(m: ChatModel, rhId: Long?, groupInfo: GroupInfo, close: () ModalView( close = { - if (welcomeText.value == gInfo.groupProfile.description || (welcomeText.value == "" && gInfo.groupProfile.description == null)) close() - else showUnsavedChangesAlert({ save(close) }, close) + when { + welcomeTextUnchanged(welcomeText, gInfo) -> close() + !welcomeTextFitsLimit(welcomeText) -> showUnsavedChangesTooLongAlert(close) + else -> showUnsavedChangesAlert({ save(close) }, close) + } }, ) { GroupWelcomeLayout( @@ -67,6 +76,14 @@ fun GroupWelcomeView(m: ChatModel, rhId: Long?, groupInfo: GroupInfo, close: () } } +private fun welcomeTextUnchanged(welcomeText: MutableState, groupInfo: GroupInfo): Boolean { + return welcomeText.value == groupInfo.groupProfile.description || (welcomeText.value == "" && groupInfo.groupProfile.description == null) +} + +private fun welcomeTextFitsLimit(welcomeText: MutableState): Boolean { + return chatJsonLength(welcomeText.value) <= maxByteCount +} + @Composable private fun GroupWelcomeLayout( welcomeText: MutableState, @@ -95,6 +112,13 @@ private fun GroupWelcomeLayout( } else { TextPreview(wt.value, linkMode) } + SectionTextFooter( + if (!welcomeTextFitsLimit(wt)) { generalGetString(MR.strings.message_too_large) } else "", + color = if (welcomeTextFitsLimit(wt)) MaterialTheme.colors.secondary else Color.Red + ) + + Spacer(Modifier.size(8.dp)) + ChangeModeButton( editMode.value, click = { @@ -104,10 +128,18 @@ private fun GroupWelcomeLayout( ) val clipboard = LocalClipboardManager.current CopyTextButton { clipboard.setText(AnnotatedString(wt.value)) } - SectionDividerSpaced(maxBottomPadding = false) + + Divider( + Modifier.padding( + start = DEFAULT_PADDING_HALF, + top = 8.dp, + end = DEFAULT_PADDING_HALF, + bottom = 8.dp) + ) + SaveButton( save = save, - disabled = wt.value == groupInfo.groupProfile.description || (wt.value == "" && groupInfo.groupProfile.description == null) + disabled = welcomeTextUnchanged(wt, groupInfo) || !welcomeTextFitsLimit(wt) ) } else { val clipboard = LocalClipboardManager.current @@ -182,3 +214,11 @@ private fun showUnsavedChangesAlert(save: () -> Unit, revert: () -> Unit) { onDismiss = revert, ) } + +private fun showUnsavedChangesTooLongAlert(revert: () -> Unit) { + AlertManager.shared.showAlertDialogStacked( + title = generalGetString(MR.strings.welcome_message_is_too_long), + confirmText = generalGetString(MR.strings.exit_without_saving), + onConfirm = revert, + ) +} diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/Section.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/Section.kt index ba0edb98d1..1c3540d7f2 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/Section.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/Section.kt @@ -198,16 +198,16 @@ fun SectionItemWithValue( } @Composable -fun SectionTextFooter(text: String) { - SectionTextFooter(AnnotatedString(text)) +fun SectionTextFooter(text: String, color: Color = MaterialTheme.colors.secondary) { + SectionTextFooter(AnnotatedString(text), color = color) } @Composable -fun SectionTextFooter(text: AnnotatedString, textAlign: TextAlign = TextAlign.Start) { +fun SectionTextFooter(text: AnnotatedString, textAlign: TextAlign = TextAlign.Start, color: Color = MaterialTheme.colors.secondary) { Text( text, Modifier.padding(start = DEFAULT_PADDING, end = DEFAULT_PADDING, top = DEFAULT_PADDING_HALF).fillMaxWidth(0.9F), - color = MaterialTheme.colors.secondary, + color = color, lineHeight = 18.sp, fontSize = 14.sp, textAlign = textAlign 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 d36eca273e..6fa106120c 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml @@ -1377,9 +1377,11 @@ Welcome message Save welcome message? + Welcome message is too long Save and update group profile Preview Enter welcome message… + Message too large SERVERS