diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageListFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageListFragment.kt index ea1cfb87b8aec9596bb53940aa80d0fb48d10117..b0b50ffb7e188646c767b600e0a3e97db4003fcd 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageListFragment.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageListFragment.kt @@ -27,6 +27,8 @@ import de.kuschku.quasseldroid.util.helper.* import de.kuschku.quasseldroid.util.service.ServiceBoundFragment import de.kuschku.quasseldroid.util.ui.SpanFormatter import de.kuschku.quasseldroid.viewmodel.QuasselViewModel +import io.reactivex.BackpressureStrategy +import java.util.concurrent.TimeUnit import javax.inject.Inject class MessageListFragment : ServiceBoundFragment() { @@ -163,6 +165,17 @@ class MessageListFragment : ServiceBoundFragment() { messageList.itemAnimator = null messageList.setItemViewCacheSize(20) + val senderColors = requireContext().theme.styledAttributes( + R.attr.senderColor0, R.attr.senderColor1, R.attr.senderColor2, R.attr.senderColor3, + R.attr.senderColor4, R.attr.senderColor5, R.attr.senderColor6, R.attr.senderColor7, + R.attr.senderColor8, R.attr.senderColor9, R.attr.senderColorA, R.attr.senderColorB, + R.attr.senderColorC, R.attr.senderColorD, R.attr.senderColorE, R.attr.senderColorF + ) { + IntArray(16) { + getColor(it, 0) + } + } + var isScrolling = false messageList.addOnScrollListener( object : RecyclerView.OnScrollListener() { @@ -189,7 +202,6 @@ class MessageListFragment : ServiceBoundFragment() { viewModel.markerLine) .toLiveData().switchMapNotNull { (buffer, selected, expanded, markerLine) -> database.filtered().listen(accountId, buffer).switchMapNotNull { filtered -> - LivePagedListBuilder( database.message().findByBufferIdPagedWithDayChange(buffer, filtered).map { DisplayMessage( @@ -213,7 +225,31 @@ class MessageListFragment : ServiceBoundFragment() { database.message().lastMsgId(it) } - viewModel.sessionManager_liveData.zip(lastMessageId).observe( + var previousVisible = -1 + viewModel.buffer.toFlowable(BackpressureStrategy.LATEST).switchMap { buffer -> + database.filtered().listenRx(accountId, buffer).switchMap { filtered -> + database.message().firstMsgId(buffer).map { + Pair(it, database.message().firstVisibleMsgId(buffer, filtered)) + } + } + }.distinctUntilChanged() + .throttleLast(1, TimeUnit.SECONDS) + .toLiveData().observe(this, Observer { + runInBackground { + val first = it?.first + val visible = it?.second ?: -1 + + if (first != null) { + if (previousVisible == visible) { + loadMore() + } + + previousVisible = visible + } + } + }) + + viewModel.session.toLiveData().zip(lastMessageId).observe( this, Observer { runInBackground { val session = it?.first?.orNull() diff --git a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselDatabase.kt b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselDatabase.kt index 3f9a80bb92362c04729174751512b926569d39f5..4a302cadbcd021fe5ada329eee6a0d760e9f046f 100644 --- a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselDatabase.kt +++ b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselDatabase.kt @@ -11,8 +11,10 @@ import android.content.Context import android.support.annotation.IntRange import de.kuschku.libquassel.protocol.Message_Flag import de.kuschku.libquassel.protocol.Message_Type +import de.kuschku.libquassel.protocol.MsgId import de.kuschku.quasseldroid.persistence.QuasselDatabase.DatabaseMessage import de.kuschku.quasseldroid.persistence.QuasselDatabase.Filtered +import io.reactivex.Flowable import org.threeten.bp.Instant @Database(entities = [DatabaseMessage::class, Filtered::class], version = 3) @@ -77,6 +79,12 @@ abstract class QuasselDatabase : RoomDatabase() { @Query("SELECT * FROM message WHERE bufferId = :bufferId ORDER BY messageId DESC LIMIT 1") fun lastMsgId(bufferId: Int): LiveData<DatabaseMessage> + @Query("SELECT messageId FROM message WHERE bufferId = :bufferId ORDER BY messageId ASC LIMIT 1") + fun firstMsgId(bufferId: Int): Flowable<MsgId> + + @Query("SELECT messageId FROM message WHERE bufferId = :bufferId AND type & ~ :type > 0 ORDER BY messageId ASC LIMIT 1") + fun firstVisibleMsgId(bufferId: Int, type: Int): MsgId? + @Query("SELECT * FROM message WHERE bufferId = :bufferId ORDER BY messageId ASC LIMIT 1") fun findFirstByBufferId(bufferId: Int): DatabaseMessage? @@ -123,6 +131,11 @@ abstract class QuasselDatabase : RoomDatabase() { ) fun listen(accountId: Long, bufferId: Int): LiveData<Int> + @Query( + "SELECT filtered FROM filtered WHERE bufferId = :bufferId AND accountId = :accountId UNION SELECT 0 as filtered ORDER BY filtered DESC LIMIT 1" + ) + fun listenRx(accountId: Long, bufferId: Int): Flowable<Int> + @Query("SELECT * FROM filtered WHERE accountId = :accountId") fun listen(accountId: Long): LiveData<List<Filtered>> diff --git a/viewmodel/src/main/java/de/kuschku/quasseldroid/util/helper/ObservableHelper.kt b/viewmodel/src/main/java/de/kuschku/quasseldroid/util/helper/ObservableHelper.kt index 42d72e1277a95769584b78e9730c80f5044f4dc9..260f85978a1b7198edcee15136bdba1f136bbb37 100644 --- a/viewmodel/src/main/java/de/kuschku/quasseldroid/util/helper/ObservableHelper.kt +++ b/viewmodel/src/main/java/de/kuschku/quasseldroid/util/helper/ObservableHelper.kt @@ -3,6 +3,7 @@ package de.kuschku.quasseldroid.util.helper import android.arch.lifecycle.LiveData import android.arch.lifecycle.LiveDataReactiveStreams import io.reactivex.BackpressureStrategy +import io.reactivex.Flowable import io.reactivex.Observable import io.reactivex.ObservableSource import io.reactivex.functions.BiFunction @@ -11,6 +12,8 @@ inline fun <T> Observable<T>.toLiveData( strategy: BackpressureStrategy = BackpressureStrategy.LATEST ): LiveData<T> = LiveDataReactiveStreams.fromPublisher(toFlowable(strategy)) +inline fun <T> Flowable<T>.toLiveData(): LiveData<T> = LiveDataReactiveStreams.fromPublisher(this) + inline fun <reified A, B> combineLatest( a: ObservableSource<A>, b: ObservableSource<B>