mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-20 16:49:40 +01:00
Make the 'see replies' bottom sheet respond to new/deleted messages.
This commit is contained in:
@@ -257,7 +257,7 @@ public class ConversationDataSource implements PagedDataSource<MessageId, Conver
|
||||
private Collection<MessageId> messageIds = new LinkedList<>();
|
||||
private Map<MessageId, List<ReactionRecord>> messageIdToReactions = new HashMap<>();
|
||||
|
||||
void add(MessageRecord record) {
|
||||
public void add(MessageRecord record) {
|
||||
messageIds.add(new MessageId(record.getId(), record.isMms()));
|
||||
}
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ class MessageQuotesBottomSheet : FixedRoundedCornerBottomSheetDialogFragment() {
|
||||
)
|
||||
|
||||
private val disposables: LifecycleDisposable = LifecycleDisposable()
|
||||
private var firstRender: Boolean = true
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||
val view = inflater.inflate(R.layout.message_quotes_bottom_sheet, container, false)
|
||||
@@ -86,7 +87,12 @@ class MessageQuotesBottomSheet : FixedRoundedCornerBottomSheetDialogFragment() {
|
||||
}
|
||||
|
||||
messageAdapter.submitList(messages) {
|
||||
(list.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(messages.size - 1, 100)
|
||||
if (firstRender) {
|
||||
(list.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(messages.size - 1, 100)
|
||||
firstRender = false
|
||||
} else if (!list.canScrollVertically(1)) {
|
||||
list.layoutManager?.scrollToPosition(0)
|
||||
}
|
||||
}
|
||||
recyclerViewColorizer.setChatColors(conversationRecipient.chatColors)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
package org.thoughtcrime.securesms.conversation.quotes
|
||||
|
||||
import android.app.Application
|
||||
import androidx.annotation.WorkerThread
|
||||
import io.reactivex.rxjava3.core.Observable
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.thoughtcrime.securesms.conversation.ConversationDataSource
|
||||
import org.thoughtcrime.securesms.conversation.ConversationMessage
|
||||
import org.thoughtcrime.securesms.conversation.ConversationMessage.ConversationMessageFactory
|
||||
import org.thoughtcrime.securesms.database.DatabaseObserver
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord
|
||||
import org.thoughtcrime.securesms.database.model.MessageId
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord
|
||||
import org.thoughtcrime.securesms.database.model.Quote
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
||||
import org.thoughtcrime.securesms.util.getQuote
|
||||
|
||||
class MessageQuotesRepository {
|
||||
|
||||
companion object {
|
||||
private val TAG = Log.tag(MessageQuotesRepository::class.java)
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all messages that quote the target message, as well as any messages that quote _those_ messages, recursively.
|
||||
*/
|
||||
fun getMessagesInQuoteChain(application: Application, messageId: MessageId): Observable<List<ConversationMessage>> {
|
||||
return Observable.create { emitter ->
|
||||
val threadId: Long = SignalDatabase.mmsSms.getThreadId(messageId)
|
||||
if (threadId < 0) {
|
||||
Log.w(TAG, "Could not find a threadId for $messageId!")
|
||||
emitter.onNext(emptyList())
|
||||
return@create
|
||||
}
|
||||
|
||||
val databaseObserver: DatabaseObserver = ApplicationDependencies.getDatabaseObserver()
|
||||
val observer = DatabaseObserver.Observer { emitter.onNext(getMessageInQuoteChainSync(application, messageId)) }
|
||||
|
||||
databaseObserver.registerConversationObserver(threadId, observer)
|
||||
|
||||
emitter.setCancellable { databaseObserver.unregisterObserver(observer) }
|
||||
emitter.onNext(getMessageInQuoteChainSync(application, messageId))
|
||||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun getMessageInQuoteChainSync(application: Application, messageId: MessageId): List<ConversationMessage> {
|
||||
val originalRecord: MessageRecord? = if (messageId.mms) {
|
||||
SignalDatabase.mms.getMessageRecordOrNull(messageId.id)
|
||||
} else {
|
||||
SignalDatabase.sms.getMessageRecordOrNull(messageId.id)
|
||||
}
|
||||
|
||||
if (originalRecord == null) {
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
val replyRecords: List<MessageRecord> = SignalDatabase.mmsSms.getAllMessagesThatQuote(messageId)
|
||||
|
||||
val replies: List<ConversationMessage> = ConversationDataSource.ReactionHelper()
|
||||
.apply {
|
||||
addAll(replyRecords)
|
||||
fetchReactions()
|
||||
}
|
||||
.buildUpdatedModels(replyRecords)
|
||||
.map { replyRecord ->
|
||||
val replyQuote: Quote? = replyRecord.getQuote()
|
||||
if (replyQuote != null && replyQuote.id == originalRecord.dateSent) {
|
||||
(replyRecord as MediaMmsMessageRecord).withoutQuote()
|
||||
} else {
|
||||
replyRecord
|
||||
}
|
||||
}
|
||||
.map { ConversationMessageFactory.createWithUnresolvedData(application, it) }
|
||||
|
||||
val originalMessage: List<ConversationMessage> = ConversationDataSource.ReactionHelper()
|
||||
.apply {
|
||||
add(originalRecord)
|
||||
fetchReactions()
|
||||
}
|
||||
.buildUpdatedModels(listOf(originalRecord))
|
||||
.map { ConversationMessageFactory.createWithUnresolvedData(application, it, it.getDisplayBody(application), 0) }
|
||||
|
||||
return replies + originalMessage
|
||||
}
|
||||
}
|
||||
@@ -7,18 +7,12 @@ import androidx.lifecycle.ViewModelProvider
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.rxjava3.core.Observable
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||
import org.thoughtcrime.securesms.conversation.ConversationDataSource
|
||||
import org.thoughtcrime.securesms.conversation.ConversationMessage
|
||||
import org.thoughtcrime.securesms.conversation.colors.GroupAuthorNameColorHelper
|
||||
import org.thoughtcrime.securesms.conversation.colors.NameColor
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord
|
||||
import org.thoughtcrime.securesms.database.model.MessageId
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord
|
||||
import org.thoughtcrime.securesms.database.model.Quote
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.util.getQuote
|
||||
|
||||
class MessageQuotesViewModel(
|
||||
application: Application,
|
||||
@@ -27,40 +21,11 @@ class MessageQuotesViewModel(
|
||||
) : AndroidViewModel(application) {
|
||||
|
||||
private val groupAuthorNameColorHelper = GroupAuthorNameColorHelper()
|
||||
private val repository = MessageQuotesRepository()
|
||||
|
||||
fun getMessages(): Observable<List<ConversationMessage>> {
|
||||
return Observable.create<List<ConversationMessage>> { emitter ->
|
||||
val originalRecord: MessageRecord? = if (messageId.mms) {
|
||||
SignalDatabase.mms.getMessageRecordOrNull(messageId.id)
|
||||
} else {
|
||||
SignalDatabase.sms.getMessageRecordOrNull(messageId.id)
|
||||
}
|
||||
|
||||
if (originalRecord == null) {
|
||||
emitter.onNext(emptyList())
|
||||
return@create
|
||||
}
|
||||
|
||||
val replyRecords: List<MessageRecord> = SignalDatabase.mmsSms.getAllMessagesThatQuote(messageId)
|
||||
|
||||
val reactionHelper = ConversationDataSource.ReactionHelper()
|
||||
reactionHelper.addAll(replyRecords)
|
||||
reactionHelper.fetchReactions()
|
||||
|
||||
val replies = reactionHelper.buildUpdatedModels(replyRecords)
|
||||
.map { replyRecord ->
|
||||
val replyQuote: Quote? = replyRecord.getQuote()
|
||||
if (replyQuote != null && replyQuote.id == originalRecord.dateSent) {
|
||||
(replyRecord as MediaMmsMessageRecord).withoutQuote()
|
||||
} else {
|
||||
replyRecord
|
||||
}
|
||||
}
|
||||
.map { ConversationMessage.ConversationMessageFactory.createWithUnresolvedData(getApplication(), it) }
|
||||
|
||||
val originalMessage: ConversationMessage = ConversationMessage.ConversationMessageFactory.createWithUnresolvedData(getApplication(), originalRecord, originalRecord.getDisplayBody(getApplication()), 0)
|
||||
emitter.onNext(replies + listOf(originalMessage))
|
||||
}
|
||||
return repository
|
||||
.getMessagesInQuoteChain(getApplication(), messageId)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
}
|
||||
|
||||
@@ -426,6 +426,18 @@ public class MmsSmsDatabase extends Database {
|
||||
SignalDatabase.mms().hasMeaningfulMessage(threadId);
|
||||
}
|
||||
|
||||
public long getThreadId(MessageId messageId) {
|
||||
if (messageId.isMms()) {
|
||||
return SignalDatabase.mms().getThreadIdForMessage(messageId.getId());
|
||||
} else {
|
||||
return SignalDatabase.sms().getThreadIdForMessage(messageId.getId());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is currently only used in an old migration and shouldn't be used by anyone else, just because it flat-out isn't correct.
|
||||
*/
|
||||
@Deprecated
|
||||
public long getThreadForMessageId(long messageId) {
|
||||
long id = SignalDatabase.sms().getThreadIdForMessage(messageId);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user