diff --git a/app/src/main/java/com/nextcloud/talk/chat/MessageInputFragment.kt b/app/src/main/java/com/nextcloud/talk/chat/MessageInputFragment.kt index c6041ccd4..c30746c78 100644 --- a/app/src/main/java/com/nextcloud/talk/chat/MessageInputFragment.kt +++ b/app/src/main/java/com/nextcloud/talk/chat/MessageInputFragment.kt @@ -79,7 +79,6 @@ import com.nextcloud.talk.utils.SpreedFeatures import com.nextcloud.talk.utils.database.user.CurrentUserProviderNew import com.nextcloud.talk.utils.text.Spans import com.otaliastudios.autocomplete.Autocomplete -import com.stfalcon.chatkit.commons.models.IMessage import com.vanniktech.emoji.EmojiPopup import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.onEach @@ -87,7 +86,7 @@ import kotlinx.coroutines.launch import java.util.Objects import javax.inject.Inject -@Suppress("LongParameterList", "TooManyFunctions") +@Suppress("LongParameterList", "TooManyFunctions", "LargeClass", "LongMethod") @AutoInjector(NextcloudTalkApplication::class) class MessageInputFragment : Fragment() { @@ -110,6 +109,10 @@ class MessageInputFragment : Fragment() { private const val CONNECTION_ESTABLISHED_ANIM_DURATION: Long = 3000 private const val FULLY_OPAQUE: Float = 1.0f private const val FULLY_TRANSPARENT: Float = 0.0f + private const val QUOTED_MESSAGE_TEXT = "QUOTED_MESSAGE_TEXT" + private const val QUOTED_MESSAGE_ID = "QUOTED_MESSAGE_ID" + private const val QUOTED_MESSAGE_URL = "QUOTED_MESSAGE_URL" + private const val QUOTED_MESSAGE_NAME = "QUOTED_MESSAGE_NAME" } @Inject @@ -134,6 +137,10 @@ class MessageInputFragment : Fragment() { private var xcounter = 0f private var ycounter = 0f private var collapsed = false + private var quotedMessageText: String? = "" + private var quotedActorDisplayName: String? = null + private var quotedImageUrl: String? = null + private var quotedJsonId: Int = -1 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -157,8 +164,8 @@ class MessageInputFragment : Fragment() { } override fun onPause() { - super.onPause() saveState() + super.onPause() } override fun onDestroyView() { @@ -167,7 +174,10 @@ class MessageInputFragment : Fragment() { mentionAutocomplete?.dismissPopup() } clearEditUI() - cancelReply() + val isInReplyState = (quotedJsonId != -1 && quotedActorDisplayName != null && quotedMessageText != "") + if (!isInReplyState) { + cancelReply() + } } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { @@ -178,7 +188,13 @@ class MessageInputFragment : Fragment() { private fun initObservers() { Log.d(TAG, "LifeCyclerOwner is: ${viewLifecycleOwner.lifecycle}") chatActivity.messageInputViewModel.getReplyChatMessage.observe(viewLifecycleOwner) { message -> - message?.let { replyToMessage(message) } + (message as ChatMessage?)?.let { + quotedMessageText = message.text + quotedActorDisplayName = message.actorDisplayName + quotedImageUrl = message.imageUrl + quotedJsonId = message.jsonMessageId + replyToMessage(message.text, message.actorDisplayName, message.imageUrl, message.jsonMessageId) + } } chatActivity.messageInputViewModel.getEditChatMessage.observe(viewLifecycleOwner) { message -> @@ -300,6 +316,14 @@ class MessageInputFragment : Fragment() { val cursor = getInt(chatActivity.roomToken + CURSOR_KEY, 0) binding.fragmentMessageInputView.messageInput.setText(text) binding.fragmentMessageInputView.messageInput.setSelection(cursor) + quotedJsonId = getInt(QUOTED_MESSAGE_ID, -1) + quotedImageUrl = getString(QUOTED_MESSAGE_URL, null) + quotedMessageText = getString(QUOTED_MESSAGE_TEXT, "") + quotedActorDisplayName = getString(QUOTED_MESSAGE_NAME, null) + val isInReplyState = (quotedJsonId != -1 && quotedActorDisplayName != null && quotedMessageText != "") + if (isInReplyState) { + replyToMessage(quotedMessageText, quotedActorDisplayName, quotedImageUrl, quotedJsonId) + } } } } @@ -313,15 +337,23 @@ class MessageInputFragment : Fragment() { .MODE_PRIVATE ).getString(chatActivity.roomToken, "null") - if (text != previous) { - requireContext().getSharedPreferences( - chatActivity.localClassName, - AppCompatActivity.MODE_PRIVATE - ).edit().apply { + val isInReplyState = (quotedJsonId != -1 && quotedActorDisplayName != null && quotedMessageText != "") + requireContext().getSharedPreferences( + chatActivity.localClassName, + AppCompatActivity.MODE_PRIVATE + ).edit().apply { + if (text != previous) { putString(chatActivity.roomToken, text) putInt(chatActivity.roomToken + CURSOR_KEY, cursor) - apply() } + + if (isInReplyState) { + putInt(QUOTED_MESSAGE_ID, quotedJsonId) + putString(QUOTED_MESSAGE_NAME, quotedActorDisplayName) + putString(QUOTED_MESSAGE_TEXT, quotedMessageText) + putString(QUOTED_MESSAGE_URL, quotedImageUrl) // may be null + } + apply() } } @@ -598,7 +630,7 @@ class MessageInputFragment : Fragment() { } } } - v?.onTouchEvent(event) ?: true + v?.onTouchEvent(event) != false } } @@ -700,52 +732,54 @@ class MessageInputFragment : Fragment() { } } - private fun replyToMessage(message: IMessage?) { + private fun replyToMessage( + quotedMessageText: String?, + quotedActorDisplayName: String?, + quotedImageUrl: String?, + quotedJsonId: Int + ) { Log.d(TAG, "Reply") - val chatMessage = message as ChatMessage? - chatMessage?.let { - val view = binding.fragmentMessageInputView - view.findViewById(R.id.attachmentButton)?.visibility = - View.GONE - view.findViewById(R.id.cancelReplyButton)?.visibility = - View.VISIBLE + val view = binding.fragmentMessageInputView + view.findViewById(R.id.attachmentButton)?.visibility = + View.GONE + view.findViewById(R.id.cancelReplyButton)?.visibility = + View.VISIBLE - val quotedMessage = view.findViewById(R.id.quotedMessage) + val quotedMessage = view.findViewById(R.id.quotedMessage) - quotedMessage?.maxLines = 2 - quotedMessage?.ellipsize = TextUtils.TruncateAt.END - quotedMessage?.text = it.text - view.findViewById(R.id.quotedMessageAuthor)?.text = - it.actorDisplayName ?: requireContext().getText(R.string.nc_nick_guest) + quotedMessage?.maxLines = 2 + quotedMessage?.ellipsize = TextUtils.TruncateAt.END + quotedMessage?.text = quotedMessageText + view.findViewById(R.id.quotedMessageAuthor)?.text = + quotedActorDisplayName ?: requireContext().getText(R.string.nc_nick_guest) - chatActivity.conversationUser?.let { - val quotedMessageImage = view.findViewById(R.id.quotedMessageImage) - chatMessage.imageUrl?.let { previewImageUrl -> - quotedMessageImage?.visibility = View.VISIBLE + chatActivity.conversationUser?.let { + val quotedMessageImage = view.findViewById(R.id.quotedMessageImage) + quotedImageUrl.let { previewImageUrl -> + quotedMessageImage?.visibility = View.VISIBLE - val px = TypedValue.applyDimension( - TypedValue.COMPLEX_UNIT_DIP, - QUOTED_MESSAGE_IMAGE_MAX_HEIGHT, - resources.displayMetrics - ) + val px = TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_DIP, + QUOTED_MESSAGE_IMAGE_MAX_HEIGHT, + resources.displayMetrics + ) - quotedMessageImage?.maxHeight = px.toInt() - val layoutParams = quotedMessageImage?.layoutParams as FlexboxLayout.LayoutParams - layoutParams.flexGrow = 0f - quotedMessageImage.layoutParams = layoutParams - quotedMessageImage.load(previewImageUrl) { - addHeader("Authorization", chatActivity.credentials!!) - } - } ?: run { - view.findViewById(R.id.quotedMessageImage)?.visibility = View.GONE + quotedMessageImage?.maxHeight = px.toInt() + val layoutParams = quotedMessageImage?.layoutParams as FlexboxLayout.LayoutParams + layoutParams.flexGrow = 0f + quotedMessageImage.layoutParams = layoutParams + quotedMessageImage.load(previewImageUrl) { + addHeader("Authorization", chatActivity.credentials!!) } + } ?: run { + view.findViewById(R.id.quotedMessageImage)?.visibility = View.GONE } - - val quotedChatMessageView = - view.findViewById(R.id.quotedChatMessageView) - quotedChatMessageView?.tag = message?.jsonMessageId - quotedChatMessageView?.visibility = View.VISIBLE } + + val quotedChatMessageView = + view.findViewById(R.id.quotedChatMessageView) + quotedChatMessageView?.tag = quotedJsonId + quotedChatMessageView?.visibility = View.VISIBLE } fun updateOwnTypingStatus(typedText: CharSequence) { @@ -1020,5 +1054,21 @@ class MessageInputFragment : Fragment() { quote.tag = null binding.fragmentMessageInputView.findViewById(R.id.attachmentButton)?.visibility = View.VISIBLE chatActivity.messageInputViewModel.reply(null) + + quotedMessageText = "" + quotedActorDisplayName = null + quotedImageUrl = null + quotedJsonId = -1 + + requireContext().getSharedPreferences( + chatActivity.localClassName, + AppCompatActivity.MODE_PRIVATE + ).edit().apply { + putInt(QUOTED_MESSAGE_ID, quotedJsonId) + putString(QUOTED_MESSAGE_NAME, quotedActorDisplayName) + putString(QUOTED_MESSAGE_TEXT, quotedMessageText) + putString(QUOTED_MESSAGE_URL, quotedImageUrl) // may be null + apply() + } } }