mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-19 16:19:33 +01:00
Display thread header in CFv2.
This commit is contained in:
committed by
Greyson Parrelli
parent
ffbbdc1576
commit
3ba128793a
@@ -37,7 +37,6 @@ import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
@@ -99,7 +98,7 @@ public class ConversationDataSource implements PagedDataSource<MessageId, Conver
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull List<ConversationMessage> load(int start, int length, @NonNull CancellationSignal cancellationSignal) {
|
||||
public @NonNull List<ConversationMessage> load(int start, int length, int totalSize, @NonNull CancellationSignal cancellationSignal) {
|
||||
Stopwatch stopwatch = new Stopwatch("load(" + start + ", " + length + "), thread " + threadId);
|
||||
List<MessageRecord> records = new ArrayList<>(length);
|
||||
MentionHelper mentionHelper = new MentionHelper();
|
||||
@@ -128,11 +127,11 @@ public class ConversationDataSource implements PagedDataSource<MessageId, Conver
|
||||
}
|
||||
}
|
||||
|
||||
if (messageRequestData.includeWarningUpdateMessage() && (start + length >= size())) {
|
||||
if (messageRequestData.includeWarningUpdateMessage() && (start + length >= totalSize)) {
|
||||
records.add(new InMemoryMessageRecord.NoGroupsInCommon(threadId, messageRequestData.isGroup()));
|
||||
}
|
||||
|
||||
if (messageRequestData.isHidden() && (start + length >= size())) {
|
||||
if (messageRequestData.isHidden() && (start + length >= totalSize)) {
|
||||
records.add(new InMemoryMessageRecord.RemovedContactHidden(threadId));
|
||||
}
|
||||
|
||||
|
||||
@@ -89,7 +89,6 @@ import org.thoughtcrime.securesms.components.TypingStatusRepository;
|
||||
import org.thoughtcrime.securesms.components.menu.ActionItem;
|
||||
import org.thoughtcrime.securesms.components.menu.SignalBottomActionBar;
|
||||
import org.thoughtcrime.securesms.components.recyclerview.SmoothScrollingLinearLayoutManager;
|
||||
import org.thoughtcrime.securesms.components.settings.app.AppSettingsActivity;
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.DonateToSignalFragment;
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.DonateToSignalType;
|
||||
import org.thoughtcrime.securesms.components.voice.VoiceNoteMediaControllerOwner;
|
||||
@@ -194,7 +193,6 @@ import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
import org.thoughtcrime.securesms.util.WindowUtil;
|
||||
import org.thoughtcrime.securesms.util.concurrent.ListenableFuture;
|
||||
import org.thoughtcrime.securesms.util.task.ProgressDialogAsyncTask;
|
||||
import org.thoughtcrime.securesms.verify.VerifyIdentityActivity;
|
||||
import org.thoughtcrime.securesms.wallpaper.ChatWallpaper;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -2065,6 +2063,11 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onShowGroupDescriptionClicked(@NonNull String groupName, @NonNull String description, boolean shouldLinkifyWebLinks) {
|
||||
GroupDescriptionDialog.show(getChildFragmentManager(), groupName, description, shouldLinkifyWebLinks);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivatePaymentsClicked() {
|
||||
Intent intent = new Intent(requireContext(), PaymentsActivity.class);
|
||||
|
||||
@@ -437,7 +437,7 @@ public class ConversationIntents {
|
||||
}
|
||||
|
||||
private static long resolveThreadId(@NonNull RecipientId recipientId, long threadId) {
|
||||
if (threadId >= 0 && SignalStore.internalValues().useConversationFragmentV2()) {
|
||||
if (threadId < 0 && SignalStore.internalValues().useConversationFragmentV2()) {
|
||||
Log.w(TAG, "Getting thread id from database...");
|
||||
// TODO [alex] -- Yes, this hits the database. No, we shouldn't be doing this.
|
||||
return SignalDatabase.threads().getOrCreateThreadIdFor(Recipient.resolved(recipientId));
|
||||
|
||||
@@ -5,8 +5,10 @@
|
||||
|
||||
package org.thoughtcrime.securesms.conversation.v2
|
||||
|
||||
import android.text.TextUtils
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.text.HtmlCompat
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import com.google.android.exoplayer2.MediaItem
|
||||
import org.signal.core.util.logging.Log
|
||||
@@ -15,6 +17,7 @@ import org.thoughtcrime.securesms.BindableConversationItem
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.conversation.ConversationAdapter
|
||||
import org.thoughtcrime.securesms.conversation.ConversationAdapterBridge
|
||||
import org.thoughtcrime.securesms.conversation.ConversationBannerView
|
||||
import org.thoughtcrime.securesms.conversation.ConversationItemDisplayMode
|
||||
import org.thoughtcrime.securesms.conversation.ConversationMessage
|
||||
import org.thoughtcrime.securesms.conversation.colors.Colorizable
|
||||
@@ -27,11 +30,17 @@ import org.thoughtcrime.securesms.conversation.v2.data.IncomingMedia
|
||||
import org.thoughtcrime.securesms.conversation.v2.data.IncomingTextOnly
|
||||
import org.thoughtcrime.securesms.conversation.v2.data.OutgoingMedia
|
||||
import org.thoughtcrime.securesms.conversation.v2.data.OutgoingTextOnly
|
||||
import org.thoughtcrime.securesms.conversation.v2.data.ThreadHeader
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord
|
||||
import org.thoughtcrime.securesms.giph.mp4.GiphyMp4Playable
|
||||
import org.thoughtcrime.securesms.giph.mp4.GiphyMp4PlaybackPolicyEnforcer
|
||||
import org.thoughtcrime.securesms.groups.v2.GroupDescriptionUtil
|
||||
import org.thoughtcrime.securesms.messagerequests.MessageRequestState
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
||||
import org.thoughtcrime.securesms.phonenumbers.PhoneNumberFormatter
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.util.CachedInflater
|
||||
import org.thoughtcrime.securesms.util.HtmlUtil
|
||||
import org.thoughtcrime.securesms.util.Projection
|
||||
import org.thoughtcrime.securesms.util.ProjectionList
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingViewHolder
|
||||
@@ -65,6 +74,8 @@ class ConversationAdapterV2(
|
||||
private val condensedMode: ConversationItemDisplayMode? = null
|
||||
|
||||
init {
|
||||
registerFactory(ThreadHeader::class.java, ::ThreadHeaderViewHolder, R.layout.conversation_item_banner)
|
||||
|
||||
registerFactory(ConversationUpdate::class.java) { parent ->
|
||||
val view = CachedInflater.from(parent.context).inflate<View>(R.layout.conversation_item_update, parent, false)
|
||||
ConversationUpdateViewHolder(view)
|
||||
@@ -91,14 +102,14 @@ class ConversationAdapterV2(
|
||||
}
|
||||
}
|
||||
|
||||
fun getAdapterPositionForMessagePosition(startPosition: Int): Int {
|
||||
return startPosition - 1
|
||||
/** [messagePosition] is one-based index and adapter is zero-based. */
|
||||
fun getAdapterPositionForMessagePosition(messagePosition: Int): Int {
|
||||
return messagePosition - 1
|
||||
}
|
||||
|
||||
fun getLastVisibleConversationMessage(position: Int): ConversationMessage? {
|
||||
return try {
|
||||
// todo [cody] handle conversation banner adjustment
|
||||
getConversationMessage(position)
|
||||
getConversationMessage(position) ?: getConversationMessage(position - 1)
|
||||
} catch (e: IndexOutOfBoundsException) {
|
||||
Log.w(TAG, "Race condition changed size of conversation", e)
|
||||
null
|
||||
@@ -131,6 +142,7 @@ class ConversationAdapterV2(
|
||||
override fun getConversationMessage(position: Int): ConversationMessage? {
|
||||
return when (val item = getItem(position)) {
|
||||
is ConversationMessageElement -> item.conversationMessage
|
||||
is ThreadHeader -> null
|
||||
null -> null
|
||||
else -> throw AssertionError("Invalid item: ${item.javaClass}")
|
||||
}
|
||||
@@ -326,4 +338,75 @@ class ConversationAdapterV2(
|
||||
return bindable.getColorizerProjections(coordinateRoot)
|
||||
}
|
||||
}
|
||||
|
||||
inner class ThreadHeaderViewHolder(itemView: View) : MappingViewHolder<ThreadHeader>(itemView) {
|
||||
private val conversationBanner: ConversationBannerView = itemView as ConversationBannerView
|
||||
|
||||
override fun bind(model: ThreadHeader) {
|
||||
val (recipient, groupInfo, sharedGroups, messageRequestState) = model.recipientInfo
|
||||
val isSelf = recipient.id == Recipient.self().id
|
||||
|
||||
conversationBanner.setAvatar(glideRequests, recipient)
|
||||
conversationBanner.showBackgroundBubble(recipient.hasWallpaper())
|
||||
val title: String = conversationBanner.setTitle(recipient)
|
||||
conversationBanner.setAbout(recipient)
|
||||
|
||||
if (recipient.isGroup) {
|
||||
if (groupInfo.pendingMemberCount > 0) {
|
||||
val invited = context.resources.getQuantityString(R.plurals.MessageRequestProfileView_invited, groupInfo.pendingMemberCount, groupInfo.pendingMemberCount)
|
||||
conversationBanner.setSubtitle(context.resources.getQuantityString(R.plurals.MessageRequestProfileView_members_and_invited, groupInfo.fullMemberCount, groupInfo.fullMemberCount, invited))
|
||||
} else if (groupInfo.fullMemberCount > 0) {
|
||||
conversationBanner.setSubtitle(context.resources.getQuantityString(R.plurals.MessageRequestProfileView_members, groupInfo.fullMemberCount, groupInfo.fullMemberCount))
|
||||
} else {
|
||||
conversationBanner.setSubtitle(null)
|
||||
}
|
||||
} else if (isSelf) {
|
||||
conversationBanner.setSubtitle(context.getString(R.string.ConversationFragment__you_can_add_notes_for_yourself_in_this_conversation))
|
||||
} else {
|
||||
val subtitle: String? = recipient.e164.map { e164: String? -> PhoneNumberFormatter.prettyPrint(e164!!) }.orElse(null)
|
||||
if (subtitle == null || subtitle == title) {
|
||||
conversationBanner.hideSubtitle()
|
||||
} else {
|
||||
conversationBanner.setSubtitle(subtitle)
|
||||
}
|
||||
}
|
||||
|
||||
if (sharedGroups.isEmpty() || isSelf) {
|
||||
if (TextUtils.isEmpty(groupInfo.description)) {
|
||||
conversationBanner.setLinkifyDescription(false)
|
||||
conversationBanner.hideDescription()
|
||||
} else {
|
||||
conversationBanner.setLinkifyDescription(true)
|
||||
val linkifyWebLinks = messageRequestState == MessageRequestState.NONE
|
||||
conversationBanner.showDescription()
|
||||
|
||||
GroupDescriptionUtil.setText(
|
||||
context,
|
||||
conversationBanner.description,
|
||||
groupInfo.description,
|
||||
linkifyWebLinks
|
||||
) {
|
||||
clickListener.onShowGroupDescriptionClicked(recipient.getDisplayName(context), groupInfo.description, linkifyWebLinks)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
val description: String = when (sharedGroups.size) {
|
||||
1 -> context.getString(R.string.MessageRequestProfileView_member_of_one_group, HtmlUtil.bold(sharedGroups[0]))
|
||||
2 -> context.getString(R.string.MessageRequestProfileView_member_of_two_groups, HtmlUtil.bold(sharedGroups[0]), HtmlUtil.bold(sharedGroups[1]))
|
||||
3 -> context.getString(R.string.MessageRequestProfileView_member_of_many_groups, HtmlUtil.bold(sharedGroups[0]), HtmlUtil.bold(sharedGroups[1]), HtmlUtil.bold(sharedGroups[2]))
|
||||
else -> {
|
||||
val others: Int = sharedGroups.size - 2
|
||||
context.getString(
|
||||
R.string.MessageRequestProfileView_member_of_many_groups,
|
||||
HtmlUtil.bold(sharedGroups[0]),
|
||||
HtmlUtil.bold(sharedGroups[1]),
|
||||
context.resources.getQuantityString(R.plurals.MessageRequestProfileView_member_of_d_additional_groups, others, others)
|
||||
)
|
||||
}
|
||||
}
|
||||
conversationBanner.setDescription(HtmlCompat.fromHtml(description, 0))
|
||||
conversationBanner.showDescription()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,15 +247,16 @@ class ConversationFragment : LoggingFragment(R.layout.v2_conversation_fragment)
|
||||
.flatMapObservable { it.items.data }
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeBy(onNext = {
|
||||
SignalLocalMetrics.ConversationOpen.onDataPostedToMain()
|
||||
if (firstRender) {
|
||||
SignalLocalMetrics.ConversationOpen.onDataPostedToMain()
|
||||
}
|
||||
|
||||
adapter.submitList(it) {
|
||||
scrollToPositionDelegate.notifyListCommitted()
|
||||
|
||||
binding.conversationItemRecycler.doAfterNextLayout {
|
||||
SignalLocalMetrics.ConversationOpen.onRenderFinished()
|
||||
|
||||
if (firstRender) {
|
||||
if (firstRender) {
|
||||
binding.conversationItemRecycler.doAfterNextLayout {
|
||||
SignalLocalMetrics.ConversationOpen.onRenderFinished()
|
||||
firstRender = false
|
||||
doAfterFirstRender()
|
||||
animationsAllowed = true
|
||||
@@ -891,6 +892,10 @@ class ConversationFragment : LoggingFragment(R.layout.v2_conversation_fragment)
|
||||
override fun onItemLongClick(itemView: View?, item: MultiselectPart?) {
|
||||
// TODO [alex] -- ("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun onShowGroupDescriptionClicked(groupName: String, description: String, shouldLinkifyWebLinks: Boolean) {
|
||||
GroupDescriptionDialog.show(childFragmentManager, groupName, description, shouldLinkifyWebLinks)
|
||||
}
|
||||
}
|
||||
|
||||
private inner class ConversationOptionsMenuCallback : ConversationOptionsMenu.Callback {
|
||||
|
||||
@@ -17,6 +17,7 @@ class ConversationRecipientRepository(threadId: Long) {
|
||||
.flatMapObservable { Recipient.observable(it) }
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(Schedulers.io())
|
||||
.distinctUntilChanged { previous, next -> previous === next || previous.hasSameContent(next) }
|
||||
.replay(1)
|
||||
.refCount()
|
||||
.observeOn(Schedulers.io())
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
/*
|
||||
* Copyright 2023 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.conversation.v2
|
||||
|
||||
import android.content.Context
|
||||
@@ -29,9 +34,12 @@ class ConversationRepository(context: Context) {
|
||||
*/
|
||||
fun getConversationThreadState(threadId: Long, requestedStartPosition: Int): Single<ConversationThreadState> {
|
||||
return Single.fromCallable {
|
||||
SignalLocalMetrics.ConversationOpen.onMetadataLoadStarted()
|
||||
val recipient = SignalDatabase.threads.getRecipientForThreadId(threadId)!!
|
||||
|
||||
SignalLocalMetrics.ConversationOpen.onMetadataLoadStarted()
|
||||
val metadata = oldConversationRepository.getConversationData(threadId, recipient, requestedStartPosition)
|
||||
SignalLocalMetrics.ConversationOpen.onMetadataLoaded()
|
||||
|
||||
val messageRequestData = metadata.messageRequestData
|
||||
val dataSource = ConversationDataSource(
|
||||
applicationContext,
|
||||
@@ -48,9 +56,7 @@ class ConversationRepository(context: Context) {
|
||||
ConversationThreadState(
|
||||
items = PagedData.createForObservable(dataSource, config),
|
||||
meta = metadata
|
||||
).apply {
|
||||
SignalLocalMetrics.ConversationOpen.onMetadataLoaded()
|
||||
}
|
||||
)
|
||||
}.subscribeOn(Schedulers.io())
|
||||
}
|
||||
|
||||
|
||||
@@ -79,6 +79,11 @@ class ConversationViewModel(
|
||||
_recipient.onNext(it)
|
||||
})
|
||||
|
||||
disposables += recipientRepository
|
||||
.conversationRecipient
|
||||
.skip(1) // We can safely skip the first emission since this is used for updating the header on future changes
|
||||
.subscribeBy { pagingController.onDataItemChanged(ConversationElementKey.threadHeader) }
|
||||
|
||||
disposables += repository.getConversationThreadState(threadId, requestedStartingPosition)
|
||||
.subscribeBy(onSuccess = {
|
||||
pagingController.set(it.items.controller)
|
||||
|
||||
@@ -12,10 +12,10 @@ import io.reactivex.rxjava3.subjects.PublishSubject
|
||||
import org.signal.core.util.concurrent.subscribeWithSubject
|
||||
import org.thoughtcrime.securesms.groups.ui.GroupChangeFailureReason
|
||||
import org.thoughtcrime.securesms.messagerequests.GroupInfo
|
||||
import org.thoughtcrime.securesms.messagerequests.MessageRequestRecipientInfo
|
||||
import org.thoughtcrime.securesms.messagerequests.MessageRequestRepository
|
||||
import org.thoughtcrime.securesms.messagerequests.MessageRequestState
|
||||
import org.thoughtcrime.securesms.messagerequests.MessageRequestViewModel.MessageData
|
||||
import org.thoughtcrime.securesms.messagerequests.MessageRequestViewModel.RecipientInfo
|
||||
import org.thoughtcrime.securesms.messagerequests.MessageRequestViewModel.RequestReviewDisplayState
|
||||
import org.thoughtcrime.securesms.messagerequests.MessageRequestViewModel.Status
|
||||
import org.thoughtcrime.securesms.profiles.spoofing.ReviewUtil
|
||||
@@ -70,12 +70,12 @@ class MessageRequestViewModel(
|
||||
}
|
||||
}.subscribeWithSubject(BehaviorSubject.create(), disposables)
|
||||
|
||||
val recipientInfo: Observable<RecipientInfo> = Observable.combineLatest(
|
||||
val recipientInfo: Observable<MessageRequestRecipientInfo> = Observable.combineLatest(
|
||||
recipientRepository.conversationRecipient,
|
||||
groupInfo,
|
||||
groups,
|
||||
messageDataSubject.map { it.messageState },
|
||||
::RecipientInfo
|
||||
::MessageRequestRecipientInfo
|
||||
)
|
||||
|
||||
override fun onCleared() {
|
||||
|
||||
@@ -23,6 +23,7 @@ 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.dependencies.ApplicationDependencies
|
||||
import org.thoughtcrime.securesms.messagerequests.MessageRequestRepository
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingModel
|
||||
@@ -33,10 +34,12 @@ private typealias ConversationElement = MappingModel<*>
|
||||
sealed interface ConversationElementKey {
|
||||
companion object {
|
||||
fun forMessage(id: Long): ConversationElementKey = MessageBackedKey(id)
|
||||
val threadHeader: ConversationElementKey = ThreadHeaderKey
|
||||
}
|
||||
}
|
||||
|
||||
private data class MessageBackedKey(val id: Long) : ConversationElementKey
|
||||
private object ThreadHeaderKey : ConversationElementKey
|
||||
|
||||
/**
|
||||
* ConversationDataSource for V2. Assumes that ThreadId is never -1L.
|
||||
@@ -46,11 +49,13 @@ class ConversationDataSource(
|
||||
private val threadId: Long,
|
||||
private val messageRequestData: ConversationData.MessageRequestData,
|
||||
private val showUniversalExpireTimerUpdate: Boolean,
|
||||
private var baseSize: Int
|
||||
private var baseSize: Int,
|
||||
private val messageRequestRepository: MessageRequestRepository = MessageRequestRepository(context)
|
||||
) : PagedDataSource<ConversationElementKey, ConversationElement> {
|
||||
|
||||
companion object {
|
||||
private val TAG = Log.tag(ConversationDataSource::class.java)
|
||||
private const val THREAD_HEADER_COUNT = 1
|
||||
}
|
||||
|
||||
init {
|
||||
@@ -64,6 +69,7 @@ class ConversationDataSource(
|
||||
override fun size(): Int {
|
||||
val startTime = System.currentTimeMillis()
|
||||
val size: Int = getSizeInternal() +
|
||||
THREAD_HEADER_COUNT +
|
||||
messageRequestData.includeWarningUpdateMessage().toInt() +
|
||||
messageRequestData.isHidden.toInt() +
|
||||
showUniversalExpireTimerUpdate.toInt()
|
||||
@@ -85,7 +91,7 @@ class ConversationDataSource(
|
||||
return SignalDatabase.messages.getMessageCountForThread(threadId)
|
||||
}
|
||||
|
||||
override fun load(start: Int, length: Int, cancellationSignal: PagedDataSource.CancellationSignal): List<ConversationElement> {
|
||||
override fun load(start: Int, length: Int, totalSize: Int, cancellationSignal: PagedDataSource.CancellationSignal): List<ConversationElement> {
|
||||
val stopwatch = Stopwatch("load($start, $length), thread $threadId")
|
||||
var records: MutableList<MessageRecord> = ArrayList(length)
|
||||
val mentionHelper = MentionHelper()
|
||||
@@ -115,11 +121,11 @@ class ConversationDataSource(
|
||||
}
|
||||
}
|
||||
|
||||
if (messageRequestData.includeWarningUpdateMessage() && (start + length >= size())) {
|
||||
if (messageRequestData.includeWarningUpdateMessage() && (start + length >= totalSize)) {
|
||||
records.add(NoGroupsInCommon(threadId, messageRequestData.isGroup))
|
||||
}
|
||||
|
||||
if (messageRequestData.isHidden && (start + length >= size())) {
|
||||
if (messageRequestData.isHidden && (start + length >= totalSize)) {
|
||||
records.add(RemovedContactHidden(threadId))
|
||||
}
|
||||
|
||||
@@ -174,12 +180,26 @@ class ConversationDataSource(
|
||||
}
|
||||
|
||||
stopwatch.split("conversion")
|
||||
|
||||
val threadHeaderIndex = totalSize - THREAD_HEADER_COUNT
|
||||
|
||||
val threadHeaders: List<ConversationElement> = if (start + length > threadHeaderIndex) {
|
||||
listOf(loadThreadHeader())
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
|
||||
stopwatch.split("header")
|
||||
stopwatch.stop(TAG)
|
||||
|
||||
return messages
|
||||
return if (threadHeaders.isNotEmpty()) messages + threadHeaders else messages
|
||||
}
|
||||
|
||||
override fun load(key: ConversationElementKey): ConversationElement? {
|
||||
if (key is ThreadHeaderKey) {
|
||||
return loadThreadHeader()
|
||||
}
|
||||
|
||||
if (key !is MessageBackedKey) {
|
||||
Log.w(TAG, "Loading non-message related id $key")
|
||||
return null
|
||||
@@ -249,10 +269,15 @@ class ConversationDataSource(
|
||||
override fun getKey(conversationMessage: ConversationElement): ConversationElementKey {
|
||||
return when (conversationMessage) {
|
||||
is ConversationMessageElement -> MessageBackedKey(conversationMessage.conversationMessage.messageRecord.id)
|
||||
is ThreadHeader -> ThreadHeaderKey
|
||||
else -> throw AssertionError()
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadThreadHeader(): ThreadHeader {
|
||||
return ThreadHeader(messageRequestRepository.getRecipientInfo(threadRecipient.id, threadId))
|
||||
}
|
||||
|
||||
private fun ConversationMessage.toMappingModel(): MappingModel<*> {
|
||||
return if (messageRecord.isUpdate) {
|
||||
ConversationUpdate(this)
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package org.thoughtcrime.securesms.conversation.v2.data
|
||||
|
||||
import org.thoughtcrime.securesms.conversation.ConversationMessage
|
||||
import org.thoughtcrime.securesms.messagerequests.MessageRequestRecipientInfo
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingModel
|
||||
|
||||
sealed interface ConversationMessageElement {
|
||||
@@ -71,3 +72,13 @@ data class IncomingMedia(
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
data class ThreadHeader(val recipientInfo: MessageRequestRecipientInfo) : MappingModel<ThreadHeader> {
|
||||
override fun areItemsTheSame(newItem: ThreadHeader): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun areContentsTheSame(newItem: ThreadHeader): Boolean {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user