|
|
@ -298,6 +298,13 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|
|
|
private val reverseMessageList = false
|
|
|
|
private val reverseMessageList = false
|
|
|
|
|
|
|
|
|
|
|
|
private val adapter by lazy {
|
|
|
|
private val adapter by lazy {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// To prevent repeated attachment download jobs being spawned for any that fail we'll keep
|
|
|
|
|
|
|
|
// track of the attachment Ids we've attempted to download. Without this guard mechanism
|
|
|
|
|
|
|
|
// then when the retry limit for a failed job is reached another job is immediately spawned
|
|
|
|
|
|
|
|
// to download the same attachment (endlessly).
|
|
|
|
|
|
|
|
val alreadyAttemptedAttachmentDownloads = mutableSetOf<Long>()
|
|
|
|
|
|
|
|
|
|
|
|
val cursor = mmsSmsDb.getConversation(viewModel.threadId, reverseMessageList)
|
|
|
|
val cursor = mmsSmsDb.getConversation(viewModel.threadId, reverseMessageList)
|
|
|
|
val adapter = ConversationAdapter(
|
|
|
|
val adapter = ConversationAdapter(
|
|
|
|
this,
|
|
|
|
this,
|
|
|
@ -325,18 +332,23 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
onAttachmentNeedsDownload = { attachmentId, mmsId ->
|
|
|
|
onAttachmentNeedsDownload = { attachmentId, mmsId ->
|
|
|
|
// Start download (on IO thread)
|
|
|
|
|
|
|
|
|
|
|
|
alreadyAttemptedAttachmentDownloads.takeUnless {
|
|
|
|
|
|
|
|
attachmentId in alreadyAttemptedAttachmentDownloads
|
|
|
|
|
|
|
|
}.let {
|
|
|
|
|
|
|
|
alreadyAttemptedAttachmentDownloads += attachmentId
|
|
|
|
lifecycleScope.launch(Dispatchers.IO) {
|
|
|
|
lifecycleScope.launch(Dispatchers.IO) {
|
|
|
|
JobQueue.shared.add(AttachmentDownloadJob(attachmentId, mmsId))
|
|
|
|
JobQueue.shared.add(AttachmentDownloadJob(attachmentId, mmsId))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
glide = glide,
|
|
|
|
glide = glide,
|
|
|
|
lifecycleCoroutineScope = lifecycleScope
|
|
|
|
lifecycleCoroutineScope = lifecycleScope
|
|
|
|
)
|
|
|
|
)
|
|
|
|
adapter.visibleMessageViewDelegate = this
|
|
|
|
adapter.visibleMessageViewDelegate = this
|
|
|
|
|
|
|
|
|
|
|
|
// Register an AdapterDataObserver to scroll us to the bottom of the RecyclerView if we're
|
|
|
|
// Register an AdapterDataObserver to scroll us to the bottom of the RecyclerView for if
|
|
|
|
// already near the the bottom and the data changes.
|
|
|
|
// we're already near the the bottom and the data changes.
|
|
|
|
adapter.registerAdapterDataObserver(ConversationAdapterDataObserver(binding?.conversationRecyclerView!!, adapter))
|
|
|
|
adapter.registerAdapterDataObserver(ConversationAdapterDataObserver(binding?.conversationRecyclerView!!, adapter))
|
|
|
|
|
|
|
|
|
|
|
|
adapter
|
|
|
|
adapter
|
|
|
@ -360,6 +372,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|
|
|
private var currentLastVisibleRecyclerViewIndex: Int = RecyclerView.NO_POSITION
|
|
|
|
private var currentLastVisibleRecyclerViewIndex: Int = RecyclerView.NO_POSITION
|
|
|
|
private var recyclerScrollState: Int = RecyclerView.SCROLL_STATE_IDLE
|
|
|
|
private var recyclerScrollState: Int = RecyclerView.SCROLL_STATE_IDLE
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// region Settings
|
|
|
|
// region Settings
|
|
|
|
companion object {
|
|
|
|
companion object {
|
|
|
|
// Extras
|
|
|
|
// Extras
|
|
|
@ -375,6 +388,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|
|
|
const val PICK_FROM_LIBRARY = 12
|
|
|
|
const val PICK_FROM_LIBRARY = 12
|
|
|
|
const val INVITE_CONTACTS = 124
|
|
|
|
const val INVITE_CONTACTS = 124
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var lastSentMessageId = -1L;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// endregion
|
|
|
|
// endregion
|
|
|
|
|
|
|
|
|
|
|
@ -501,6 +515,9 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|
|
|
viewModel.run {
|
|
|
|
viewModel.run {
|
|
|
|
binding?.toolbarContent?.update(recipient ?: return, openGroup, expirationConfiguration)
|
|
|
|
binding?.toolbarContent?.update(recipient ?: return, openGroup, expirationConfiguration)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Update our last sent message Id on startup / resume (resume is called after onCreate)
|
|
|
|
|
|
|
|
lastSentMessageId = mmsSmsDb.getLastOutgoingMessage(viewModel.threadId)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
override fun onPause() {
|
|
|
|
override fun onPause() {
|
|
|
@ -2209,6 +2226,11 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|
|
|
// to the bottom of long messages as required by Jira SES-789 / GitHub 1364).
|
|
|
|
// to the bottom of long messages as required by Jira SES-789 / GitHub 1364).
|
|
|
|
recyclerView.scrollToPosition(adapter.itemCount)
|
|
|
|
recyclerView.scrollToPosition(adapter.itemCount)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Update our cached last sent message to ensure we have accurate details.
|
|
|
|
|
|
|
|
// Note: This `onChanged` method is not triggered when scrolling so should minimally
|
|
|
|
|
|
|
|
// affect performance.
|
|
|
|
|
|
|
|
lastSentMessageId = mmsSmsDb.getLastOutgoingMessage(viewModel.threadId)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|