mirror of
https://github.com/oxen-io/session-android.git
synced 2025-02-21 11:38:27 +00:00
Fix last seen channel being closed by consuming flow
This commit is contained in:
parent
a326c47e56
commit
a47bf230e2
@ -44,6 +44,7 @@ import androidx.fragment.app.DialogFragment
|
|||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
import androidx.lifecycle.Observer
|
import androidx.lifecycle.Observer
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import androidx.lifecycle.flowWithLifecycle
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.lifecycle.repeatOnLifecycle
|
import androidx.lifecycle.repeatOnLifecycle
|
||||||
import androidx.loader.app.LoaderManager
|
import androidx.loader.app.LoaderManager
|
||||||
@ -58,6 +59,7 @@ import kotlinx.coroutines.channels.Channel
|
|||||||
import kotlinx.coroutines.flow.collectLatest
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
import kotlinx.coroutines.flow.consumeAsFlow
|
import kotlinx.coroutines.flow.consumeAsFlow
|
||||||
import kotlinx.coroutines.flow.filter
|
import kotlinx.coroutines.flow.filter
|
||||||
|
import kotlinx.coroutines.flow.receiveAsFlow
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
@ -177,6 +179,8 @@ import org.thoughtcrime.securesms.util.push
|
|||||||
import org.thoughtcrime.securesms.util.show
|
import org.thoughtcrime.securesms.util.show
|
||||||
import org.thoughtcrime.securesms.util.toPx
|
import org.thoughtcrime.securesms.util.toPx
|
||||||
import java.lang.ref.WeakReference
|
import java.lang.ref.WeakReference
|
||||||
|
import java.time.Instant
|
||||||
|
import java.util.Date
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import java.util.concurrent.ExecutionException
|
import java.util.concurrent.ExecutionException
|
||||||
import java.util.concurrent.atomic.AtomicBoolean
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
@ -187,6 +191,10 @@ import kotlin.math.abs
|
|||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
import kotlin.math.sqrt
|
import kotlin.math.sqrt
|
||||||
|
import kotlin.time.Duration
|
||||||
|
import kotlin.time.Duration.Companion.milliseconds
|
||||||
|
|
||||||
|
private const val TAG = "ConversationActivityV2"
|
||||||
|
|
||||||
// Some things that seemingly belong to the input bar (e.g. the voice message recording UI) are actually
|
// Some things that seemingly belong to the input bar (e.g. the voice message recording UI) are actually
|
||||||
// part of the conversation activity layout. This is just because it makes the layout a lot simpler. The
|
// part of the conversation activity layout. This is just because it makes the layout a lot simpler. The
|
||||||
@ -451,18 +459,21 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|||||||
reactionDelegate = ConversationReactionDelegate(reactionOverlayStub)
|
reactionDelegate = ConversationReactionDelegate(reactionOverlayStub)
|
||||||
reactionDelegate.setOnReactionSelectedListener(this)
|
reactionDelegate.setOnReactionSelectedListener(this)
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
lifecycle.repeatOnLifecycle(Lifecycle.State.RESUMED) {
|
|
||||||
// only update the conversation every 3 seconds maximum
|
// only update the conversation every 3 seconds maximum
|
||||||
// channel is rendezvous and shouldn't block on try send calls as often as we want
|
// channel is rendezvous and shouldn't block on try send calls as often as we want
|
||||||
val bufferedFlow = bufferedLastSeenChannel.consumeAsFlow()
|
bufferedLastSeenChannel.receiveAsFlow()
|
||||||
bufferedFlow.filter {
|
.flowWithLifecycle(lifecycle, Lifecycle.State.RESUMED)
|
||||||
it > storage.getLastSeen(viewModel.threadId)
|
.collectLatest {
|
||||||
}.collectLatest { latestMessageRead ->
|
withContext(Dispatchers.IO) {
|
||||||
withContext(Dispatchers.IO) {
|
try {
|
||||||
storage.markConversationAsRead(viewModel.threadId, latestMessageRead)
|
if (it > storage.getLastSeen(viewModel.threadId)) {
|
||||||
|
storage.markConversationAsRead(viewModel.threadId, it)
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.d(TAG, "bufferedLastSeenChannel collectLatest", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1055,16 +1066,16 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|||||||
val maybeTargetVisiblePosition = if (reverseMessageList) layoutManager?.findFirstVisibleItemPosition() else layoutManager?.findLastVisibleItemPosition()
|
val maybeTargetVisiblePosition = if (reverseMessageList) layoutManager?.findFirstVisibleItemPosition() else layoutManager?.findLastVisibleItemPosition()
|
||||||
val targetVisiblePosition = maybeTargetVisiblePosition ?: RecyclerView.NO_POSITION
|
val targetVisiblePosition = maybeTargetVisiblePosition ?: RecyclerView.NO_POSITION
|
||||||
if (!firstLoad.get() && targetVisiblePosition != RecyclerView.NO_POSITION) {
|
if (!firstLoad.get() && targetVisiblePosition != RecyclerView.NO_POSITION) {
|
||||||
val visibleItemTimestamp = adapter.getTimestampForItemAt(targetVisiblePosition)
|
adapter.getTimestampForItemAt(targetVisiblePosition)?.let { visibleItemTimestamp ->
|
||||||
if (visibleItemTimestamp != null) {
|
bufferedLastSeenChannel.trySend(visibleItemTimestamp).apply {
|
||||||
bufferedLastSeenChannel.trySend(visibleItemTimestamp)
|
if (isFailure) Log.e(TAG, "trySend failed", exceptionOrNull())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reverseMessageList) {
|
if (reverseMessageList) {
|
||||||
unreadCount = min(unreadCount, targetVisiblePosition).coerceAtLeast(0)
|
unreadCount = min(unreadCount, targetVisiblePosition).coerceAtLeast(0)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
val layoutUnreadCount = layoutManager?.let { (it.itemCount - 1) - it.findLastVisibleItemPosition() }
|
val layoutUnreadCount = layoutManager?.let { (it.itemCount - 1) - it.findLastVisibleItemPosition() }
|
||||||
?: RecyclerView.NO_POSITION
|
?: RecyclerView.NO_POSITION
|
||||||
unreadCount = min(unreadCount, layoutUnreadCount).coerceAtLeast(0)
|
unreadCount = min(unreadCount, layoutUnreadCount).coerceAtLeast(0)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user