From b7bf3678e583c1cf5eb9e3ff0eed6c2db213fefb Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com> Date: Sat, 12 Mar 2022 16:52:04 +0000 Subject: [PATCH] fix: markdown and links interaction/copy in messages (#432) --- .../main/java/chat/simplex/app/SimplexApp.kt | 4 +-- .../chat/simplex/app/views/chat/ChatView.kt | 32 +++++++---------- .../chat/simplex/app/views/helpers/Util.kt | 34 +++++++++++++++++++ 3 files changed, 47 insertions(+), 23 deletions(-) diff --git a/apps/android/app/src/main/java/chat/simplex/app/SimplexApp.kt b/apps/android/app/src/main/java/chat/simplex/app/SimplexApp.kt index 28e5fb91a4..a8f0ada2be 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/SimplexApp.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/SimplexApp.kt @@ -1,10 +1,8 @@ package chat.simplex.app import android.app.Application -import android.net.* +import android.net.LocalServerSocket import android.util.Log -import androidx.lifecycle.* -import androidx.work.* import chat.simplex.app.model.* import chat.simplex.app.views.helpers.withApi import java.io.BufferedReader diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatView.kt index 6340e8c29c..c53f83d552 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatView.kt @@ -5,7 +5,6 @@ import android.util.Log import androidx.activity.compose.BackHandler import androidx.compose.foundation.background import androidx.compose.foundation.clickable -import androidx.compose.foundation.gestures.scrollBy import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.* import androidx.compose.material.* @@ -25,8 +24,7 @@ import chat.simplex.app.TAG import chat.simplex.app.model.* import chat.simplex.app.ui.theme.SimpleXTheme import chat.simplex.app.views.chat.item.ChatItemView -import chat.simplex.app.views.helpers.ChatInfoImage -import chat.simplex.app.views.helpers.withApi +import chat.simplex.app.views.helpers.* import chat.simplex.app.views.newchat.ModalManager import com.google.accompanist.insets.ProvideWindowInsets import com.google.accompanist.insets.navigationBarsWithImePadding @@ -141,23 +139,24 @@ fun ChatInfoToolbar(chat: Chat, back: () -> Unit, info: () -> Unit) { } } -data class MessageListState(val scrolled: Boolean, val msgCount: Int, val keyboardOffset: Int) +data class CIListState(val scrolled: Boolean, val itemCount: Int, val keyboardState: KeyboardState) -val MessageListStateSaver = run { +val CIListStateSaver = run { val scrolledKey = "scrolled" - val countKey = "msgCount" - val keyboardKey = "keyboardOffset" + val countKey = "itemCount" + val keyboardKey = "keyboardState" mapSaver( - save = { mapOf(scrolledKey to it.scrolled, countKey to it.msgCount, keyboardKey to it.keyboardOffset) }, - restore = { MessageListState(it[scrolledKey] as Boolean, it[countKey] as Int, it[keyboardKey] as Int) } + save = { mapOf(scrolledKey to it.scrolled, countKey to it.itemCount, keyboardKey to it.keyboardState) }, + restore = { CIListState(it[scrolledKey] as Boolean, it[countKey] as Int, it[keyboardKey] as KeyboardState) } ) } @Composable fun ChatItemsList(chatItems: List) { val listState = rememberLazyListState() - var messageListState = rememberSaveable(stateSaver = MessageListStateSaver) { - mutableStateOf(MessageListState(false, chatItems.count(), listState.layoutInfo.viewportEndOffset)) + val keyboardState by getKeyboardState() + val ciListState = rememberSaveable(stateSaver = CIListStateSaver) { + mutableStateOf(CIListState(false, chatItems.count(), keyboardState)) } val scope = rememberCoroutineScope() val uriHandler = LocalUriHandler.current @@ -166,16 +165,9 @@ fun ChatItemsList(chatItems: List) { ChatItemView(cItem, uriHandler) } val len = chatItems.count() - if(listState.layoutInfo.viewportEndOffset != messageListState.value.keyboardOffset) { + if (keyboardState != ciListState.value.keyboardState || !ciListState.value.scrolled || len != ciListState.value.itemCount) { scope.launch { - val scrollBy = maxOf(messageListState.value.keyboardOffset.toFloat() - listState.layoutInfo.viewportEndOffset.toFloat(), 0f) - listState.scrollBy( scrollBy) - messageListState.value = messageListState.value.copy(keyboardOffset = listState.layoutInfo.viewportEndOffset) - } - } - if (len > 1 && (!messageListState.value.scrolled || len != messageListState.value.msgCount)) { - scope.launch { - messageListState.value = MessageListState(true, chatItems.count(), listState.layoutInfo.viewportEndOffset) + ciListState.value = CIListState(true, len, keyboardState) listState.animateScrollToItem(len - 1) } } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/Util.kt b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/Util.kt index 8f148fbd3b..454e880837 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/Util.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/Util.kt @@ -1,6 +1,40 @@ package chat.simplex.app.views.helpers +import android.graphics.Rect +import android.view.ViewTreeObserver +import androidx.compose.runtime.* +import androidx.compose.ui.platform.LocalView import kotlinx.coroutines.* fun withApi(action: suspend CoroutineScope.() -> Unit): Job = GlobalScope.launch { withContext(Dispatchers.Main, action) } + +enum class KeyboardState { + Opened, Closed +} + +@Composable +fun getKeyboardState(): State { + val keyboardState = remember { mutableStateOf(KeyboardState.Closed) } + val view = LocalView.current + DisposableEffect(view) { + val onGlobalListener = ViewTreeObserver.OnGlobalLayoutListener { + val rect = Rect() + view.getWindowVisibleDisplayFrame(rect) + val screenHeight = view.rootView.height + val keypadHeight = screenHeight - rect.bottom + keyboardState.value = if (keypadHeight > screenHeight * 0.15) { + KeyboardState.Opened + } else { + KeyboardState.Closed + } + } + view.viewTreeObserver.addOnGlobalLayoutListener(onGlobalListener) + + onDispose { + view.viewTreeObserver.removeOnGlobalLayoutListener(onGlobalListener) + } + } + + return keyboardState +}