deleting works

Signed-off-by: rapterjet2004 <juliuslinus1@gmail.com>
This commit is contained in:
rapterjet2004 2024-09-27 08:12:03 -05:00 committed by Marcel Hibbe
parent 98e0b7a270
commit 0041fb3b71
No known key found for this signature in database
GPG key ID: C793F8B59F43CE7B
8 changed files with 127 additions and 25 deletions

View file

@ -65,6 +65,8 @@ public class TalkMessagesListAdapter<M extends IMessage> extends MessagesListAda
((SystemMessageViewHolder) holder).assignSystemMessageInterface(chatActivity); ((SystemMessageViewHolder) holder).assignSystemMessageInterface(chatActivity);
} else if (holder instanceof CallStartedViewHolder) { } else if (holder instanceof CallStartedViewHolder) {
((CallStartedViewHolder) holder).assignCallStartedMessageInterface(chatActivity); ((CallStartedViewHolder) holder).assignCallStartedMessageInterface(chatActivity);
} else if (holder instanceof TemporaryMessageViewHolder) {
((TemporaryMessageViewHolder) holder).assignTemporaryMessageInterface(chatActivity);
} }
super.onBindViewHolder(holder, position); super.onBindViewHolder(holder, position);

View file

@ -0,0 +1,13 @@
/*
* Nextcloud Talk - Android Client
*
* SPDX-FileCopyrightText: 2024 Your Name <your@email.com>
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package com.nextcloud.talk.adapters.messages
interface TemporaryMessageInterface {
fun editTemporaryMessage(id: Int, newMessage: String)
fun deleteTemporaryMessage(id: Int)
}

View file

@ -11,6 +11,7 @@ import android.view.View
import androidx.core.content.res.ResourcesCompat import androidx.core.content.res.ResourcesCompat
import androidx.core.view.ViewCompat import androidx.core.view.ViewCompat
import autodagger.AutoInjector import autodagger.AutoInjector
import com.nextcloud.android.common.ui.theme.utils.ColorRole
import com.nextcloud.talk.R import com.nextcloud.talk.R
import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.chat.data.model.ChatMessage import com.nextcloud.talk.chat.data.model.ChatMessage
@ -29,10 +30,23 @@ class TemporaryMessageViewHolder(outgoingView: View, payload: Any) :
@Inject @Inject
lateinit var viewThemeUtils: ViewThemeUtils lateinit var viewThemeUtils: ViewThemeUtils
override fun onBind(message: ChatMessage?) { lateinit var temporaryMessageInterface: TemporaryMessageInterface
override fun onBind(message: ChatMessage) {
super.onBind(message) super.onBind(message)
NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this) NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
viewThemeUtils.platform.colorImageView(binding.tempMsgEdit, ColorRole.PRIMARY)
viewThemeUtils.platform.colorImageView(binding.tempMsgDelete, ColorRole.PRIMARY)
binding.tempMsgEdit.setOnClickListener {
// TODO
}
binding.tempMsgDelete.setOnClickListener {
temporaryMessageInterface.deleteTemporaryMessage(message.tempMessageId)
}
val bgBubbleColor = bubble.resources.getColor(R.color.bg_message_list_incoming_bubble, null) val bgBubbleColor = bubble.resources.getColor(R.color.bg_message_list_incoming_bubble, null)
val layout = R.drawable.shape_outcoming_message val layout = R.drawable.shape_outcoming_message
val bubbleDrawable = DisplayUtils.getMessageSelector( val bubbleDrawable = DisplayUtils.getMessageSelector(
@ -45,6 +59,10 @@ class TemporaryMessageViewHolder(outgoingView: View, payload: Any) :
} }
fun assignTemporaryMessageInterface(temporaryMessageInterface: TemporaryMessageInterface) {
this.temporaryMessageInterface = temporaryMessageInterface
}
override fun viewDetached() { override fun viewDetached() {
// unused atm // unused atm
} }

View file

@ -101,6 +101,7 @@ import com.nextcloud.talk.adapters.messages.PreviewMessageViewHolder
import com.nextcloud.talk.adapters.messages.SystemMessageInterface import com.nextcloud.talk.adapters.messages.SystemMessageInterface
import com.nextcloud.talk.adapters.messages.SystemMessageViewHolder import com.nextcloud.talk.adapters.messages.SystemMessageViewHolder
import com.nextcloud.talk.adapters.messages.TalkMessagesListAdapter import com.nextcloud.talk.adapters.messages.TalkMessagesListAdapter
import com.nextcloud.talk.adapters.messages.TemporaryMessageInterface
import com.nextcloud.talk.adapters.messages.TemporaryMessageViewHolder import com.nextcloud.talk.adapters.messages.TemporaryMessageViewHolder
import com.nextcloud.talk.adapters.messages.UnreadNoticeMessageViewHolder import com.nextcloud.talk.adapters.messages.UnreadNoticeMessageViewHolder
import com.nextcloud.talk.adapters.messages.VoiceMessageInterface import com.nextcloud.talk.adapters.messages.VoiceMessageInterface
@ -214,7 +215,8 @@ class ChatActivity :
CommonMessageInterface, CommonMessageInterface,
PreviewMessageInterface, PreviewMessageInterface,
SystemMessageInterface, SystemMessageInterface,
CallStartedMessageInterface { CallStartedMessageInterface,
TemporaryMessageInterface {
var active = false var active = false
@ -536,13 +538,15 @@ class ChatActivity :
Log.d(TAG, "initObservers Called") Log.d(TAG, "initObservers Called")
messageInputViewModel.messageQueueFlow.observe(this) { list -> messageInputViewModel.messageQueueFlow.observe(this) { list ->
for (message in list) { list.forEachIndexed { _, qMsg ->
Log.d("Julius", "Message recieved: $message") Log.d("Julius", "Message recieved: ${qMsg.message}")
val temporaryChatMessage = ChatMessage() val temporaryChatMessage = ChatMessage()
temporaryChatMessage.jsonMessageId = -3 temporaryChatMessage.jsonMessageId = -3
temporaryChatMessage.actorId = "-3" temporaryChatMessage.actorId = "-3"
temporaryChatMessage.timestamp = System.currentTimeMillis() / 1000 temporaryChatMessage.timestamp = System.currentTimeMillis() / 1000
temporaryChatMessage.message = message temporaryChatMessage.message = qMsg.message.toString()
temporaryChatMessage.tempMessageId = qMsg.id
temporaryChatMessage.isTempMessage = true
adapter?.addToStart(temporaryChatMessage, true) adapter?.addToStart(temporaryChatMessage, true)
} }
} }
@ -3103,7 +3107,10 @@ class ChatActivity :
private fun openMessageActionsDialog(iMessage: IMessage?) { private fun openMessageActionsDialog(iMessage: IMessage?) {
val message = iMessage as ChatMessage val message = iMessage as ChatMessage
if (hasVisibleItems(message) && !isSystemMessage(message)) { if (hasVisibleItems(message) &&
!isSystemMessage(message) &&
message.id != "-3"
) {
MessageActionsDialog( MessageActionsDialog(
this, this,
message, message,
@ -3658,6 +3665,29 @@ class ChatActivity :
startACall(false, false) startACall(false, false)
} }
override fun editTemporaryMessage(id: Int, newMessage: String) {
// TODO("Not yet implemented")
}
override fun deleteTemporaryMessage(id: Int) {
messageInputViewModel.removeFromQueue(roomToken, id)
var i = 0
val max = messageInputViewModel.messageQueueSizeFlow.value?.plus(1)
for (item in adapter?.items!!) { // add limit?
if (i >= max!!) break
if (item.item is ChatMessage &&
(item.item as ChatMessage).isTempMessage &&
(item.item as ChatMessage).tempMessageId == id
) {
val index = adapter?.items!!.indexOf(item)
adapter?.items!!.removeAt(index)
adapter?.notifyItemRemoved(index)
break
}
i++
}
}
private fun logConversationInfos(methodName: String) { private fun logConversationInfos(methodName: String) {
Log.d(TAG, " |-----------------------------------------------") Log.d(TAG, " |-----------------------------------------------")
Log.d(TAG, " | method: $methodName") Log.d(TAG, " | method: $methodName")

View file

@ -111,7 +111,11 @@ data class ChatMessage(
var hiddenByCollapse: Boolean = false, var hiddenByCollapse: Boolean = false,
var openWhenDownloaded: Boolean = true var openWhenDownloaded: Boolean = true,
var isTempMessage: Boolean = false,
var tempMessageId: Int = -1
) : MessageContentType, MessageContentType.Image { ) : MessageContentType, MessageContentType.Image {

View file

@ -48,6 +48,7 @@ class MessageInputViewModel @Inject constructor(
val disposableSet = mutableSetOf<Disposable>() val disposableSet = mutableSetOf<Disposable>()
data class QueuedMessage( data class QueuedMessage(
val id: Int,
val message: CharSequence? = null, val message: CharSequence? = null,
val displayName: String? = null, val displayName: String? = null,
val replyTo: Int? = null, val replyTo: Int? = null,
@ -124,8 +125,8 @@ class MessageInputViewModel @Inject constructor(
val messageQueueSizeFlow: LiveData<Int> val messageQueueSizeFlow: LiveData<Int>
get() = _messageQueueSizeFlow.asLiveData() get() = _messageQueueSizeFlow.asLiveData()
private val _messageQueueFlow: MutableLiveData<List<String>> = MutableLiveData() private val _messageQueueFlow: MutableLiveData<List<QueuedMessage>> = MutableLiveData()
val messageQueueFlow: LiveData<List<String>> val messageQueueFlow: LiveData<List<QueuedMessage>>
get() = _messageQueueFlow get() = _messageQueueFlow
@Suppress("LongParameterList") @Suppress("LongParameterList")
@ -139,10 +140,12 @@ class MessageInputViewModel @Inject constructor(
sendWithoutNotification: Boolean sendWithoutNotification: Boolean
) { ) {
if (isQueueing) { if (isQueueing) {
messageQueue.add(QueuedMessage(message, displayName, replyTo, sendWithoutNotification)) val tempID = System.currentTimeMillis().toInt()
val qMsg = QueuedMessage(tempID, message, displayName, replyTo, sendWithoutNotification)
messageQueue.add(qMsg)
dataStore.saveMessageQueue(roomToken, messageQueue) dataStore.saveMessageQueue(roomToken, messageQueue)
_messageQueueSizeFlow.update { messageQueue.size } _messageQueueSizeFlow.update { messageQueue.size }
_messageQueueFlow.postValue(listOf(message.toString())) _messageQueueFlow.postValue(listOf(qMsg))
return return
} }
@ -271,10 +274,10 @@ class MessageInputViewModel @Inject constructor(
fun getTempMessagesFromMessageQueue(roomToken: String) { fun getTempMessagesFromMessageQueue(roomToken: String) {
val queue = dataStore.getMessageQueue(roomToken) val queue = dataStore.getMessageQueue(roomToken)
val list = mutableListOf<String>() val list = mutableListOf<QueuedMessage>()
for (msg in queue) { for (msg in queue) {
Log.d("Julius", "Msg: ${msg.message}") Log.d("Julius", "Msg: ${msg.message}")
list.add(msg.message.toString()) list.add(msg)
} }
_messageQueueFlow.postValue(list) _messageQueueFlow.postValue(list)
} }
@ -288,6 +291,18 @@ class MessageInputViewModel @Inject constructor(
_messageQueueSizeFlow.tryEmit(messageQueue.size) _messageQueueSizeFlow.tryEmit(messageQueue.size)
} }
fun removeFromQueue(roomToken: String, id: Int) {
val queue = dataStore.getMessageQueue(roomToken)
for (qMsg in queue) {
if (qMsg.id == id) {
queue.remove(qMsg)
break
}
}
dataStore.saveMessageQueue(roomToken, queue)
_messageQueueSizeFlow.tryEmit(queue.size)
}
companion object { companion object {
private val TAG = MessageInputViewModel::class.java.simpleName private val TAG = MessageInputViewModel::class.java.simpleName
private const val DELAY_BETWEEN_QUEUED_MESSAGES: Long = 100 private const val DELAY_BETWEEN_QUEUED_MESSAGES: Long = 100

View file

@ -484,7 +484,10 @@ class AppPreferencesImpl(val context: Context) : AppPreferences {
var queueStr = "" var queueStr = ""
queue?.let { queue?.let {
for (msg in queue) { for (msg in queue) {
val msgStr = "${msg.message},${msg.replyTo},${msg.displayName},${msg.sendWithoutNotification}^" val msgStr = "${msg.id},${msg.message},${msg.replyTo},${msg.displayName},${
msg
.sendWithoutNotification
}^"
queueStr += msgStr queueStr += msgStr
} }
} }
@ -504,12 +507,13 @@ class AppPreferencesImpl(val context: Context) : AppPreferences {
try { try {
if (msgStr.isNotEmpty()) { if (msgStr.isNotEmpty()) {
val msgArray = msgStr.split(",") val msgArray = msgStr.split(",")
val id = msgArray[ID].toInt()
val message = msgArray[MESSAGE_INDEX] val message = msgArray[MESSAGE_INDEX]
val replyTo = msgArray[REPLY_TO_INDEX].toInt() val replyTo = msgArray[REPLY_TO_INDEX].toInt()
val displayName = msgArray[DISPLY_NAME_INDEX] val displayName = msgArray[DISPLAY_NAME_INDEX]
val silent = msgArray[SILENT_INDEX].toBoolean() val silent = msgArray[SILENT_INDEX].toBoolean()
val qMsg = MessageInputViewModel.QueuedMessage(message, displayName, replyTo, silent) val qMsg = MessageInputViewModel.QueuedMessage(id, message, displayName, replyTo, silent)
queue.add(qMsg) queue.add(qMsg)
} }
} catch (e: IndexOutOfBoundsException) { } catch (e: IndexOutOfBoundsException) {
@ -572,10 +576,11 @@ class AppPreferencesImpl(val context: Context) : AppPreferences {
@Suppress("UnusedPrivateProperty") @Suppress("UnusedPrivateProperty")
private val TAG = AppPreferencesImpl::class.simpleName private val TAG = AppPreferencesImpl::class.simpleName
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "settings") private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "settings")
private const val MESSAGE_INDEX: Int = 0 private const val ID: Int = 0
private const val REPLY_TO_INDEX: Int = 1 private const val MESSAGE_INDEX: Int = 1
private const val DISPLY_NAME_INDEX: Int = 2 private const val REPLY_TO_INDEX: Int = 2
private const val SILENT_INDEX: Int = 3 private const val DISPLAY_NAME_INDEX: Int = 3
private const val SILENT_INDEX: Int = 4
const val PROXY_TYPE = "proxy_type" const val PROXY_TYPE = "proxy_type"
const val PROXY_SERVER = "proxy_server" const val PROXY_SERVER = "proxy_server"
const val PROXY_HOST = "proxy_host" const val PROXY_HOST = "proxy_host"

View file

@ -15,13 +15,28 @@
android:layout_marginRight="16dp" android:layout_marginRight="16dp"
android:layout_marginBottom="2dp"> android:layout_marginBottom="2dp">
<ImageView <LinearLayout
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:src="@drawable/ic_signal_wifi_off_white_24dp" android:orientation="horizontal"
android:layout_centerVertical="true" android:layout_centerVertical="true">
android:layout_marginLeft="@dimen/standard_margin"
app:tint="@color/hwSecurityRed" /> <ImageView
android:id="@+id/temp_msg_edit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_edit"
android:paddingHorizontal="@dimen/standard_half_padding"
android:layout_marginEnd="@dimen/standard_quarter_margin" />
<ImageView
android:id="@+id/temp_msg_delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_delete"
android:paddingHorizontal="@dimen/standard_half_padding"
android:layout_marginStart="@dimen/standard_quarter_margin" />
</LinearLayout>
<com.google.android.flexbox.FlexboxLayout <com.google.android.flexbox.FlexboxLayout
android:id="@id/bubble" android:id="@id/bubble"