mirror of
https://github.com/nextcloud/talk-android
synced 2025-06-19 03:29:28 +01:00
Merge 4b44a939f5
into 2a7359c1e9
This commit is contained in:
commit
be8c4ecb0f
@ -79,7 +79,6 @@ import com.nextcloud.talk.utils.SpreedFeatures
|
|||||||
import com.nextcloud.talk.utils.database.user.CurrentUserProviderNew
|
import com.nextcloud.talk.utils.database.user.CurrentUserProviderNew
|
||||||
import com.nextcloud.talk.utils.text.Spans
|
import com.nextcloud.talk.utils.text.Spans
|
||||||
import com.otaliastudios.autocomplete.Autocomplete
|
import com.otaliastudios.autocomplete.Autocomplete
|
||||||
import com.stfalcon.chatkit.commons.models.IMessage
|
|
||||||
import com.vanniktech.emoji.EmojiPopup
|
import com.vanniktech.emoji.EmojiPopup
|
||||||
import kotlinx.coroutines.flow.collect
|
import kotlinx.coroutines.flow.collect
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
@ -87,7 +86,7 @@ import kotlinx.coroutines.launch
|
|||||||
import java.util.Objects
|
import java.util.Objects
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@Suppress("LongParameterList", "TooManyFunctions")
|
@Suppress("LongParameterList", "TooManyFunctions", "LargeClass", "LongMethod")
|
||||||
@AutoInjector(NextcloudTalkApplication::class)
|
@AutoInjector(NextcloudTalkApplication::class)
|
||||||
class MessageInputFragment : Fragment() {
|
class MessageInputFragment : Fragment() {
|
||||||
|
|
||||||
@ -110,6 +109,10 @@ class MessageInputFragment : Fragment() {
|
|||||||
private const val CONNECTION_ESTABLISHED_ANIM_DURATION: Long = 3000
|
private const val CONNECTION_ESTABLISHED_ANIM_DURATION: Long = 3000
|
||||||
private const val FULLY_OPAQUE: Float = 1.0f
|
private const val FULLY_OPAQUE: Float = 1.0f
|
||||||
private const val FULLY_TRANSPARENT: Float = 0.0f
|
private const val FULLY_TRANSPARENT: Float = 0.0f
|
||||||
|
const val QUOTED_MESSAGE_TEXT = "QUOTED_MESSAGE_TEXT"
|
||||||
|
const val QUOTED_MESSAGE_ID = "QUOTED_MESSAGE_ID"
|
||||||
|
const val QUOTED_MESSAGE_URL = "QUOTED_MESSAGE_URL"
|
||||||
|
const val QUOTED_MESSAGE_NAME = "QUOTED_MESSAGE_NAME"
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@ -134,6 +137,10 @@ class MessageInputFragment : Fragment() {
|
|||||||
private var xcounter = 0f
|
private var xcounter = 0f
|
||||||
private var ycounter = 0f
|
private var ycounter = 0f
|
||||||
private var collapsed = false
|
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?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
@ -157,8 +164,8 @@ class MessageInputFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
super.onPause()
|
|
||||||
saveState()
|
saveState()
|
||||||
|
super.onPause()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
@ -167,8 +174,11 @@ class MessageInputFragment : Fragment() {
|
|||||||
mentionAutocomplete?.dismissPopup()
|
mentionAutocomplete?.dismissPopup()
|
||||||
}
|
}
|
||||||
clearEditUI()
|
clearEditUI()
|
||||||
|
val isInReplyState = (quotedJsonId != -1 && quotedActorDisplayName != null && quotedMessageText != "")
|
||||||
|
if (!isInReplyState) {
|
||||||
cancelReply()
|
cancelReply()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
@ -178,7 +188,13 @@ class MessageInputFragment : Fragment() {
|
|||||||
private fun initObservers() {
|
private fun initObservers() {
|
||||||
Log.d(TAG, "LifeCyclerOwner is: ${viewLifecycleOwner.lifecycle}")
|
Log.d(TAG, "LifeCyclerOwner is: ${viewLifecycleOwner.lifecycle}")
|
||||||
chatActivity.messageInputViewModel.getReplyChatMessage.observe(viewLifecycleOwner) { message ->
|
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 ->
|
chatActivity.messageInputViewModel.getEditChatMessage.observe(viewLifecycleOwner) { message ->
|
||||||
@ -295,11 +311,20 @@ class MessageInputFragment : Fragment() {
|
|||||||
|
|
||||||
private fun restoreState() {
|
private fun restoreState() {
|
||||||
if (binding.fragmentMessageInputView.inputEditText.text.isEmpty()) {
|
if (binding.fragmentMessageInputView.inputEditText.text.isEmpty()) {
|
||||||
|
Log.d("Julius", "State restored from: ${chatActivity.localClassName}")
|
||||||
requireContext().getSharedPreferences(chatActivity.localClassName, AppCompatActivity.MODE_PRIVATE).apply {
|
requireContext().getSharedPreferences(chatActivity.localClassName, AppCompatActivity.MODE_PRIVATE).apply {
|
||||||
val text = getString(chatActivity.roomToken, "")
|
val text = getString(chatActivity.roomToken, "")
|
||||||
val cursor = getInt(chatActivity.roomToken + CURSOR_KEY, 0)
|
val cursor = getInt(chatActivity.roomToken + CURSOR_KEY, 0)
|
||||||
binding.fragmentMessageInputView.messageInput.setText(text)
|
binding.fragmentMessageInputView.messageInput.setText(text)
|
||||||
binding.fragmentMessageInputView.messageInput.setSelection(cursor)
|
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 +338,23 @@ class MessageInputFragment : Fragment() {
|
|||||||
.MODE_PRIVATE
|
.MODE_PRIVATE
|
||||||
).getString(chatActivity.roomToken, "null")
|
).getString(chatActivity.roomToken, "null")
|
||||||
|
|
||||||
if (text != previous) {
|
val isInReplyState = (quotedJsonId != -1 && quotedActorDisplayName != null && quotedMessageText != "")
|
||||||
requireContext().getSharedPreferences(
|
requireContext().getSharedPreferences(
|
||||||
chatActivity.localClassName,
|
chatActivity.localClassName,
|
||||||
AppCompatActivity.MODE_PRIVATE
|
AppCompatActivity.MODE_PRIVATE
|
||||||
).edit().apply {
|
).edit().apply {
|
||||||
|
if (text != previous) {
|
||||||
putString(chatActivity.roomToken, text)
|
putString(chatActivity.roomToken, text)
|
||||||
putInt(chatActivity.roomToken + CURSOR_KEY, cursor)
|
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 +631,7 @@ class MessageInputFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
v?.onTouchEvent(event) ?: true
|
v?.onTouchEvent(event) != false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -700,10 +733,13 @@ class MessageInputFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun replyToMessage(message: IMessage?) {
|
private fun replyToMessage(
|
||||||
|
quotedMessageText: String?,
|
||||||
|
quotedActorDisplayName: String?,
|
||||||
|
quotedImageUrl: String?,
|
||||||
|
quotedJsonId: Int
|
||||||
|
) {
|
||||||
Log.d(TAG, "Reply")
|
Log.d(TAG, "Reply")
|
||||||
val chatMessage = message as ChatMessage?
|
|
||||||
chatMessage?.let {
|
|
||||||
val view = binding.fragmentMessageInputView
|
val view = binding.fragmentMessageInputView
|
||||||
view.findViewById<ImageButton>(R.id.attachmentButton)?.visibility =
|
view.findViewById<ImageButton>(R.id.attachmentButton)?.visibility =
|
||||||
View.GONE
|
View.GONE
|
||||||
@ -714,13 +750,13 @@ class MessageInputFragment : Fragment() {
|
|||||||
|
|
||||||
quotedMessage?.maxLines = 2
|
quotedMessage?.maxLines = 2
|
||||||
quotedMessage?.ellipsize = TextUtils.TruncateAt.END
|
quotedMessage?.ellipsize = TextUtils.TruncateAt.END
|
||||||
quotedMessage?.text = it.text
|
quotedMessage?.text = quotedMessageText
|
||||||
view.findViewById<EmojiTextView>(R.id.quotedMessageAuthor)?.text =
|
view.findViewById<EmojiTextView>(R.id.quotedMessageAuthor)?.text =
|
||||||
it.actorDisplayName ?: requireContext().getText(R.string.nc_nick_guest)
|
quotedActorDisplayName ?: requireContext().getText(R.string.nc_nick_guest)
|
||||||
|
|
||||||
chatActivity.conversationUser?.let {
|
chatActivity.conversationUser?.let {
|
||||||
val quotedMessageImage = view.findViewById<ImageView>(R.id.quotedMessageImage)
|
val quotedMessageImage = view.findViewById<ImageView>(R.id.quotedMessageImage)
|
||||||
chatMessage.imageUrl?.let { previewImageUrl ->
|
quotedImageUrl.let { previewImageUrl ->
|
||||||
quotedMessageImage?.visibility = View.VISIBLE
|
quotedMessageImage?.visibility = View.VISIBLE
|
||||||
|
|
||||||
val px = TypedValue.applyDimension(
|
val px = TypedValue.applyDimension(
|
||||||
@ -743,10 +779,9 @@ class MessageInputFragment : Fragment() {
|
|||||||
|
|
||||||
val quotedChatMessageView =
|
val quotedChatMessageView =
|
||||||
view.findViewById<RelativeLayout>(R.id.quotedChatMessageView)
|
view.findViewById<RelativeLayout>(R.id.quotedChatMessageView)
|
||||||
quotedChatMessageView?.tag = message?.jsonMessageId
|
quotedChatMessageView?.tag = quotedJsonId
|
||||||
quotedChatMessageView?.visibility = View.VISIBLE
|
quotedChatMessageView?.visibility = View.VISIBLE
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fun updateOwnTypingStatus(typedText: CharSequence) {
|
fun updateOwnTypingStatus(typedText: CharSequence) {
|
||||||
fun sendStartTypingSignalingMessage() {
|
fun sendStartTypingSignalingMessage() {
|
||||||
@ -1020,5 +1055,21 @@ class MessageInputFragment : Fragment() {
|
|||||||
quote.tag = null
|
quote.tag = null
|
||||||
binding.fragmentMessageInputView.findViewById<ImageButton>(R.id.attachmentButton)?.visibility = View.VISIBLE
|
binding.fragmentMessageInputView.findViewById<ImageButton>(R.id.attachmentButton)?.visibility = View.VISIBLE
|
||||||
chatActivity.messageInputViewModel.reply(null)
|
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()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -85,6 +85,10 @@ import com.nextcloud.talk.api.NcApi
|
|||||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||||
import com.nextcloud.talk.arbitrarystorage.ArbitraryStorageManager
|
import com.nextcloud.talk.arbitrarystorage.ArbitraryStorageManager
|
||||||
import com.nextcloud.talk.chat.ChatActivity
|
import com.nextcloud.talk.chat.ChatActivity
|
||||||
|
import com.nextcloud.talk.chat.MessageInputFragment.Companion.QUOTED_MESSAGE_ID
|
||||||
|
import com.nextcloud.talk.chat.MessageInputFragment.Companion.QUOTED_MESSAGE_NAME
|
||||||
|
import com.nextcloud.talk.chat.MessageInputFragment.Companion.QUOTED_MESSAGE_TEXT
|
||||||
|
import com.nextcloud.talk.chat.MessageInputFragment.Companion.QUOTED_MESSAGE_URL
|
||||||
import com.nextcloud.talk.chat.viewmodels.ChatViewModel
|
import com.nextcloud.talk.chat.viewmodels.ChatViewModel
|
||||||
import com.nextcloud.talk.contacts.ContactsActivity
|
import com.nextcloud.talk.contacts.ContactsActivity
|
||||||
import com.nextcloud.talk.contacts.ContactsUiState
|
import com.nextcloud.talk.contacts.ContactsUiState
|
||||||
@ -306,6 +310,16 @@ class ConversationsListActivity :
|
|||||||
showNotificationWarning()
|
showNotificationWarning()
|
||||||
|
|
||||||
showShareToScreen = hasActivityActionSendIntent()
|
showShareToScreen = hasActivityActionSendIntent()
|
||||||
|
context.getSharedPreferences(
|
||||||
|
CHAT_ACTIVITY_LOCAL_NAME,
|
||||||
|
MODE_PRIVATE
|
||||||
|
).edit().apply {
|
||||||
|
putInt(QUOTED_MESSAGE_ID, -1)
|
||||||
|
putString(QUOTED_MESSAGE_NAME, null)
|
||||||
|
putString(QUOTED_MESSAGE_TEXT, "")
|
||||||
|
putString(QUOTED_MESSAGE_URL, null)
|
||||||
|
apply()
|
||||||
|
}
|
||||||
|
|
||||||
if (!eventBus.isRegistered(this)) {
|
if (!eventBus.isRegistered(this)) {
|
||||||
eventBus.register(this)
|
eventBus.register(this)
|
||||||
@ -2196,6 +2210,7 @@ class ConversationsListActivity :
|
|||||||
const val UNREAD_BUBBLE_DELAY = 2500
|
const val UNREAD_BUBBLE_DELAY = 2500
|
||||||
const val BOTTOM_SHEET_DELAY: Long = 2500
|
const val BOTTOM_SHEET_DELAY: Long = 2500
|
||||||
private const val KEY_SEARCH_QUERY = "ConversationsListActivity.searchQuery"
|
private const val KEY_SEARCH_QUERY = "ConversationsListActivity.searchQuery"
|
||||||
|
private const val CHAT_ACTIVITY_LOCAL_NAME = "com.nextcloud.talk.chat.ChatActivity"
|
||||||
const val SEARCH_DEBOUNCE_INTERVAL_MS = 300
|
const val SEARCH_DEBOUNCE_INTERVAL_MS = 300
|
||||||
const val SEARCH_MIN_CHARS = 1
|
const val SEARCH_MIN_CHARS = 1
|
||||||
const val HTTP_UNAUTHORIZED = 401
|
const val HTTP_UNAUTHORIZED = 401
|
||||||
|
Loading…
Reference in New Issue
Block a user