mirror of
https://github.com/oxen-io/session-android.git
synced 2025-01-03 13:47:45 +00:00
SES-212 - Always show delivery status of last sent message - FINAL! (#1418)
* Fixes #1408 * Addressed PR feedback * Cleanup * PR adjustments * Further PR adjustments * Updated libsession-util * Added fix for crash when no messages * Ignoring dirty submodules so they don't show up in git * Re-fixed display of delivery status on last sent message (got broken by disappearing messages) * Removed ignore dirty modules line in .gitmodules as it all seems to be playing nice now --------- Co-authored-by: AL-Session <160798022+AL-Session@users.noreply.github.com> Co-authored-by: Al Lansley <al@oxen.io>
This commit is contained in:
parent
54d6c025b1
commit
0febb0456e
@ -22,10 +22,12 @@ import kotlinx.coroutines.launch
|
||||
import network.loki.messenger.R
|
||||
import network.loki.messenger.databinding.ViewVisibleMessageBinding
|
||||
import org.session.libsession.messaging.contacts.Contact
|
||||
import org.session.libsession.utilities.TextSecurePreferences
|
||||
import org.thoughtcrime.securesms.conversation.v2.messages.ControlMessageView
|
||||
import org.thoughtcrime.securesms.conversation.v2.messages.VisibleMessageView
|
||||
import org.thoughtcrime.securesms.conversation.v2.messages.VisibleMessageViewDelegate
|
||||
import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter
|
||||
import org.thoughtcrime.securesms.database.MmsSmsColumns
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord
|
||||
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
||||
@ -57,6 +59,7 @@ class ConversationAdapter(
|
||||
private val contactCache = SparseArray<Contact>(100)
|
||||
private val contactLoadedCache = SparseBooleanArray(100)
|
||||
private val lastSeen = AtomicLong(originalLastSeen)
|
||||
private var lastSentMessageId: Long = -1L
|
||||
|
||||
init {
|
||||
lifecycleCoroutineScope.launch(IO) {
|
||||
@ -136,7 +139,8 @@ class ConversationAdapter(
|
||||
senderId,
|
||||
lastSeen.get(),
|
||||
visibleMessageViewDelegate,
|
||||
onAttachmentNeedsDownload
|
||||
onAttachmentNeedsDownload,
|
||||
lastSentMessageId
|
||||
)
|
||||
|
||||
if (!message.isDeleted) {
|
||||
@ -205,8 +209,23 @@ class ConversationAdapter(
|
||||
return messageDB.readerFor(cursor).current
|
||||
}
|
||||
|
||||
private fun getLastSentMessageId(cursor: Cursor): Long {
|
||||
// If we don't move to first (or at least step backwards) we can step off the end of the
|
||||
// cursor and any query will return an "Index = -1" error.
|
||||
val cursorHasContent = cursor.moveToFirst()
|
||||
if (cursorHasContent) {
|
||||
val thisThreadId = cursor.getLong(4) // Column index 4 is "thread_id"
|
||||
if (thisThreadId != -1L) {
|
||||
val thisUsersSessionId = TextSecurePreferences.getLocalNumber(context)
|
||||
return messageDB.getLastSentMessageFromSender(thisThreadId, thisUsersSessionId)
|
||||
}
|
||||
}
|
||||
return -1L
|
||||
}
|
||||
|
||||
override fun changeCursor(cursor: Cursor?) {
|
||||
super.changeCursor(cursor)
|
||||
|
||||
val toRemove = mutableSetOf<MessageRecord>()
|
||||
val toDeselect = mutableSetOf<Pair<Int, MessageRecord>>()
|
||||
for (selected in selectedItems) {
|
||||
@ -224,6 +243,11 @@ class ConversationAdapter(
|
||||
toDeselect.iterator().forEach { (pos, record) ->
|
||||
onDeselect(record, pos)
|
||||
}
|
||||
|
||||
// This value gets updated here ONLY when the cursor changes, and the value is then passed
|
||||
// through to `VisibleMessageView.bind` each time we bind via `onBindItemViewHolder`, above.
|
||||
// If there are no messages then lastSentMessageId is assigned the value -1L.
|
||||
if (cursor != null) { lastSentMessageId = getLastSentMessageId(cursor) }
|
||||
}
|
||||
|
||||
fun findLastSeenItemPosition(lastSeenTimestamp: Long): Int? {
|
||||
|
@ -32,6 +32,7 @@ import org.session.libsession.messaging.contacts.Contact
|
||||
import org.session.libsession.messaging.contacts.Contact.ContactContext
|
||||
import org.session.libsession.messaging.open_groups.OpenGroupApi
|
||||
import org.session.libsession.utilities.Address
|
||||
import org.session.libsession.utilities.TextSecurePreferences
|
||||
import org.session.libsession.utilities.ViewUtil
|
||||
import org.session.libsession.utilities.getColorFromAttr
|
||||
import org.session.libsession.utilities.modifyLayoutParams
|
||||
@ -131,7 +132,8 @@ class VisibleMessageView : LinearLayout {
|
||||
senderSessionID: String,
|
||||
lastSeen: Long,
|
||||
delegate: VisibleMessageViewDelegate? = null,
|
||||
onAttachmentNeedsDownload: (Long, Long) -> Unit
|
||||
onAttachmentNeedsDownload: (Long, Long) -> Unit,
|
||||
lastSentMessageId: Long
|
||||
) {
|
||||
val threadID = message.threadId
|
||||
val thread = threadDb.getRecipientForThreadId(threadID) ?: return
|
||||
@ -195,14 +197,18 @@ class VisibleMessageView : LinearLayout {
|
||||
val contactContext =
|
||||
if (thread.isOpenGroupRecipient) ContactContext.OPEN_GROUP else ContactContext.REGULAR
|
||||
binding.senderNameTextView.text = contact?.displayName(contactContext) ?: senderSessionID
|
||||
|
||||
// Unread marker
|
||||
binding.unreadMarkerContainer.isVisible = lastSeen != -1L && message.timestamp > lastSeen && (previous == null || previous.timestamp <= lastSeen) && !message.isOutgoing
|
||||
|
||||
// Date break
|
||||
val showDateBreak = isStartOfMessageCluster || snIsSelected
|
||||
binding.dateBreakTextView.text = if (showDateBreak) DateUtils.getDisplayFormattedTimeSpanString(context, Locale.getDefault(), message.timestamp) else null
|
||||
binding.dateBreakTextView.isVisible = showDateBreak
|
||||
|
||||
// Message status indicator
|
||||
showStatusMessage(message)
|
||||
|
||||
// Emoji Reactions
|
||||
val emojiLayoutParams = binding.emojiReactionsView.root.layoutParams as ConstraintLayout.LayoutParams
|
||||
emojiLayoutParams.horizontalBias = if (message.isOutgoing) 1f else 0f
|
||||
@ -238,7 +244,8 @@ class VisibleMessageView : LinearLayout {
|
||||
}
|
||||
|
||||
private fun showStatusMessage(message: MessageRecord) {
|
||||
val disappearing = message.expiresIn > 0
|
||||
|
||||
val scheduledToDisappear = message.expiresIn > 0
|
||||
|
||||
binding.messageInnerLayout.modifyLayoutParams<FrameLayout.LayoutParams> {
|
||||
gravity = if (message.isOutgoing) Gravity.END else Gravity.START
|
||||
@ -250,21 +257,22 @@ class VisibleMessageView : LinearLayout {
|
||||
|
||||
binding.expirationTimerView.isGone = true
|
||||
|
||||
if (message.isOutgoing || disappearing) {
|
||||
if (message.isOutgoing || scheduledToDisappear) {
|
||||
val (iconID, iconColor, textId) = getMessageStatusImage(message)
|
||||
textId?.let(binding.messageStatusTextView::setText)
|
||||
iconColor?.let(binding.messageStatusTextView::setTextColor)
|
||||
iconID?.let { ContextCompat.getDrawable(context, it) }
|
||||
?.run { iconColor?.let { mutate().apply { setTint(it) } } ?: this }
|
||||
?.let(binding.messageStatusImageView::setImageDrawable)
|
||||
|
||||
val lastMessageID = mmsSmsDb.getLastMessageID(message.threadId)
|
||||
val isLastMessage = message.id == lastMessageID
|
||||
binding.messageStatusTextView.isVisible =
|
||||
textId != null && (!message.isSent || isLastMessage || disappearing)
|
||||
val showTimer = disappearing && !message.isPending
|
||||
binding.messageStatusImageView.isVisible =
|
||||
iconID != null && !showTimer && (!message.isSent || isLastMessage)
|
||||
|
||||
// Always show the delivery status of the last sent message
|
||||
val thisUsersSessionId = TextSecurePreferences.getLocalNumber(context)
|
||||
val lastSentMessageId = mmsSmsDb.getLastSentMessageFromSender(message.threadId, thisUsersSessionId)
|
||||
val isLastSentMessage = lastSentMessageId == message.id
|
||||
|
||||
binding.messageStatusTextView.isVisible = textId != null && (isLastSentMessage || scheduledToDisappear)
|
||||
val showTimer = scheduledToDisappear && !message.isPending
|
||||
binding.messageStatusImageView.isVisible = iconID != null && !showTimer && (!message.isSent || isLastSentMessage)
|
||||
|
||||
binding.messageStatusImageView.bringToFront()
|
||||
binding.expirationTimerView.bringToFront()
|
||||
|
@ -209,6 +209,24 @@ public class MmsSmsDatabase extends Database {
|
||||
}
|
||||
}
|
||||
|
||||
public long getLastSentMessageFromSender(long threadId, String serializedAuthor) {
|
||||
String order = MmsSmsColumns.NORMALIZED_DATE_SENT + " DESC";
|
||||
String selection = MmsSmsColumns.THREAD_ID + " = " + threadId;
|
||||
|
||||
boolean isOwnNumber = Util.isOwnNumber(context, serializedAuthor);
|
||||
|
||||
// Try everything with resources so that they auto-close on end of scope
|
||||
try (Cursor cursor = queryTables(PROJECTION, selection, order, null)) {
|
||||
try (MmsSmsDatabase.Reader reader = readerFor(cursor)) {
|
||||
MessageRecord messageRecord;
|
||||
while ((messageRecord = reader.getNext()) != null) {
|
||||
if (isOwnNumber && messageRecord.isOutgoing()) { return messageRecord.id; }
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public Cursor getUnread() {
|
||||
String order = MmsSmsColumns.NORMALIZED_DATE_SENT + " ASC";
|
||||
String selection = "(" + MmsSmsColumns.READ + " = 0 OR " + MmsSmsColumns.REACTIONS_UNREAD + " = 1) AND " + MmsSmsColumns.NOTIFIED + " = 0";
|
||||
|
Loading…
x
Reference in New Issue
Block a user