mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-25 02:55:23 +00:00
feat: buffer the last read when in conversation
This commit is contained in:
parent
055d37db5f
commit
164810e533
@ -36,9 +36,11 @@ import androidx.annotation.DimenRes
|
|||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.core.view.drawToBitmap
|
import androidx.core.view.drawToBitmap
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
|
import androidx.lifecycle.Lifecycle
|
||||||
import androidx.lifecycle.Observer
|
import androidx.lifecycle.Observer
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.lifecycle.repeatOnLifecycle
|
||||||
import androidx.loader.app.LoaderManager
|
import androidx.loader.app.LoaderManager
|
||||||
import androidx.loader.content.Loader
|
import androidx.loader.content.Loader
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
@ -46,7 +48,13 @@ import androidx.recyclerview.widget.RecyclerView
|
|||||||
import com.annimon.stream.Stream
|
import com.annimon.stream.Stream
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.channels.BufferOverflow
|
||||||
|
import kotlinx.coroutines.channels.Channel
|
||||||
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
|
import kotlinx.coroutines.flow.consumeAsFlow
|
||||||
|
import kotlinx.coroutines.flow.debounce
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
import network.loki.messenger.databinding.ActivityConversationV2Binding
|
import network.loki.messenger.databinding.ActivityConversationV2Binding
|
||||||
import network.loki.messenger.databinding.ViewVisibleMessageBinding
|
import network.loki.messenger.databinding.ViewVisibleMessageBinding
|
||||||
@ -70,6 +78,7 @@ import org.session.libsession.messaging.sending_receiving.attachments.Attachment
|
|||||||
import org.session.libsession.messaging.sending_receiving.link_preview.LinkPreview
|
import org.session.libsession.messaging.sending_receiving.link_preview.LinkPreview
|
||||||
import org.session.libsession.messaging.sending_receiving.quotes.QuoteModel
|
import org.session.libsession.messaging.sending_receiving.quotes.QuoteModel
|
||||||
import org.session.libsession.messaging.utilities.SessionId
|
import org.session.libsession.messaging.utilities.SessionId
|
||||||
|
import org.session.libsession.snode.SnodeAPI
|
||||||
import org.session.libsession.utilities.Address
|
import org.session.libsession.utilities.Address
|
||||||
import org.session.libsession.utilities.Address.Companion.fromSerialized
|
import org.session.libsession.utilities.Address.Companion.fromSerialized
|
||||||
import org.session.libsession.utilities.GroupUtil
|
import org.session.libsession.utilities.GroupUtil
|
||||||
@ -166,6 +175,7 @@ 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.Companion.seconds
|
||||||
|
|
||||||
// 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
|
||||||
@ -252,6 +262,8 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|||||||
val searchViewModel: SearchViewModel by viewModels()
|
val searchViewModel: SearchViewModel by viewModels()
|
||||||
var searchViewItem: MenuItem? = null
|
var searchViewItem: MenuItem? = null
|
||||||
|
|
||||||
|
private val bufferedLastSeenChannel = Channel<Unit>(capacity = Channel.RENDEZVOUS, onBufferOverflow = BufferOverflow.DROP_OLDEST)
|
||||||
|
|
||||||
private val isScrolledToBottom: Boolean
|
private val isScrolledToBottom: Boolean
|
||||||
get() {
|
get() {
|
||||||
val position = layoutManager?.findFirstCompletelyVisibleItemPosition() ?: 0
|
val position = layoutManager?.findFirstCompletelyVisibleItemPosition() ?: 0
|
||||||
@ -403,16 +415,25 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|||||||
ViewUtil.findStubById(this, R.id.conversation_reaction_scrubber_stub)
|
ViewUtil.findStubById(this, R.id.conversation_reaction_scrubber_stub)
|
||||||
reactionDelegate = ConversationReactionDelegate(reactionOverlayStub)
|
reactionDelegate = ConversationReactionDelegate(reactionOverlayStub)
|
||||||
reactionDelegate.setOnReactionSelectedListener(this)
|
reactionDelegate.setOnReactionSelectedListener(this)
|
||||||
|
lifecycleScope.launch {
|
||||||
|
lifecycle.repeatOnLifecycle(Lifecycle.State.RESUMED) {
|
||||||
|
// only update the conversation every 3 seconds maximum
|
||||||
|
// channel is rendezvous and shouldn't block on try send calls as often as we want
|
||||||
|
val bufferedFlow = bufferedLastSeenChannel.consumeAsFlow()
|
||||||
|
.debounce(3.seconds)
|
||||||
|
bufferedFlow.collectLatest {
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
storage.markConversationAsRead(viewModel.threadId, SnodeAPI.nowWithOffset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
ApplicationContext.getInstance(this).messageNotifier.setVisibleThread(viewModel.threadId)
|
ApplicationContext.getInstance(this).messageNotifier.setVisibleThread(viewModel.threadId)
|
||||||
|
|
||||||
lifecycleScope.launch(Dispatchers.IO) {
|
|
||||||
storage.markConversationAsRead(viewModel.threadId, System.currentTimeMillis())
|
|
||||||
}
|
|
||||||
|
|
||||||
contentResolver.registerContentObserver(
|
contentResolver.registerContentObserver(
|
||||||
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
|
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
|
||||||
true,
|
true,
|
||||||
@ -454,6 +475,8 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|||||||
if (author != null && messageTimestamp >= 0) {
|
if (author != null && messageTimestamp >= 0) {
|
||||||
jumpToMessage(author, messageTimestamp, null)
|
jumpToMessage(author, messageTimestamp, null)
|
||||||
}
|
}
|
||||||
|
// TODO: buffer this
|
||||||
|
bufferedLastSeenChannel.trySend(Unit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user