Skip to content
Snippets Groups Projects
Commit f751b98a authored by Janne Mareike Koschinski's avatar Janne Mareike Koschinski
Browse files

Improved message view

- fixed scroll behaviour
- use Paging’s BoundaryCallback for loadMore detection
parent 6a544bd8
No related branches found
No related tags found
No related merge requests found
......@@ -106,9 +106,9 @@ dependencies {
implementation(appArch("lifecycle", "reactivestreams"))
kapt(appArch("lifecycle", "compiler"))
implementation(appArch("persistence.room", "runtime", "1.0.0"))
implementation(appArch("persistence.room", "rxjava2", "1.0.0"))
kapt(appArch("persistence.room", "compiler", "1.0.0"))
implementation(appArch("persistence.room", "runtime", "1.1.0-alpha2"))
implementation(appArch("persistence.room", "rxjava2", "1.1.0-alpha2"))
kapt(appArch("persistence.room", "compiler", "1.1.0-alpha2"))
implementation(appArch("paging", "runtime", version = "1.0.0-alpha5")) {
exclude(group = "junit", module = "junit")
......
package de.kuschku.quasseldroid_ng.persistence
import android.arch.paging.LivePagedListProvider
import android.arch.paging.DataSource
import android.arch.persistence.room.*
import android.content.Context
......@@ -32,7 +32,7 @@ abstract class AccountDatabase : RoomDatabase() {
fun findById(id: Long): AccountDatabase.Account?
@Query("SELECT * FROM account ORDER BY lastUsed DESC")
fun all(): LivePagedListProvider<Int, Account>
fun all(): DataSource.Factory<Int, Account>
@Delete
fun delete(account: AccountDatabase.Account)
......
package de.kuschku.quasseldroid_ng.persistence
import android.arch.paging.LivePagedListProvider
import android.arch.paging.DataSource
import android.arch.persistence.room.*
import android.content.Context
import android.support.annotation.IntRange
......@@ -60,8 +60,8 @@ abstract class QuasselDatabase : RoomDatabase() {
@Query("SELECT * FROM message WHERE bufferId = :bufferId ORDER BY messageId ASC")
fun findByBufferId(bufferId: Int): List<DatabaseMessage>
@Query("SELECT * FROM message WHERE bufferId = :bufferId ORDER BY messageId ASC")
fun findByBufferIdPaged(bufferId: Int): LivePagedListProvider<Int, DatabaseMessage>
@Query("SELECT * FROM message WHERE bufferId = :bufferId ORDER BY messageId DESC")
fun findByBufferIdPaged(bufferId: Int): DataSource.Factory<Int, DatabaseMessage>
@Query("SELECT * FROM message WHERE bufferId = :bufferId ORDER BY messageId DESC LIMIT 1")
fun findLastByBufferId(bufferId: Int): DatabaseMessage?
......
......@@ -21,10 +21,6 @@ class MessageAdapter(context: Context) :
private val messageCache = LruCache<Int, FormattedMessage>(512)
init {
setHasStableIds(true)
}
override fun onBindViewHolder(holder: QuasselMessageViewHolder, position: Int) {
getItem(position)?.let {
messageRenderer.bind(
......
......@@ -3,6 +3,7 @@ package de.kuschku.quasseldroid_ng.ui.chat
import android.arch.lifecycle.LiveData
import android.arch.lifecycle.MutableLiveData
import android.arch.lifecycle.Observer
import android.arch.paging.LivePagedListBuilder
import android.arch.paging.PagedList
import android.os.Bundle
import android.support.design.widget.FloatingActionButton
......@@ -14,13 +15,10 @@ import android.view.ViewGroup
import butterknife.BindView
import butterknife.ButterKnife
import de.kuschku.libquassel.protocol.BufferId
import de.kuschku.libquassel.session.Backend
import de.kuschku.libquassel.session.SessionManager
import de.kuschku.quasseldroid_ng.R
import de.kuschku.quasseldroid_ng.persistence.QuasselDatabase
import de.kuschku.quasseldroid_ng.util.AndroidHandlerThread
import de.kuschku.quasseldroid_ng.util.helper.invoke
import de.kuschku.quasseldroid_ng.util.helper.map
import de.kuschku.quasseldroid_ng.util.helper.switchMap
import de.kuschku.quasseldroid_ng.util.helper.toggle
import de.kuschku.quasseldroid_ng.util.service.ServiceBoundFragment
......@@ -39,37 +37,70 @@ class MessageListFragment : ServiceBoundFragment() {
@BindView(R.id.scrollDown)
lateinit var scrollDown: FloatingActionButton
private val sessionManager: LiveData<SessionManager?> = backend.map(Backend::sessionManager)
override fun onCreate(savedInstanceState: Bundle?) {
handler.onCreate()
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
}
private val boundaryCallback = object :
PagedList.BoundaryCallback<QuasselDatabase.DatabaseMessage>() {
override fun onItemAtFrontLoaded(itemAtFront: QuasselDatabase.DatabaseMessage)
= Unit
override fun onItemAtEndLoaded(itemAtEnd: QuasselDatabase.DatabaseMessage)
= loadMore()
}
override fun onCreateView(inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.fragment_messages, container, false)
ButterKnife.bind(this, view)
val adapter = MessageAdapter(context!!)
messageList.adapter = adapter
val linearLayoutManager = LinearLayoutManager(context)
linearLayoutManager.reverseLayout = true
messageList.layoutManager = linearLayoutManager
messageList.addOnScrollListener(
object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
val canScrollDown = recyclerView.canScrollVertically(1)
val isScrollingDown = dy > 0
scrollDown.visibility = View.VISIBLE
scrollDown.toggle(canScrollDown && isScrollingDown)
}
}
)
database = QuasselDatabase.Creator.init(context!!.applicationContext)
val data = buffer.switchMap {
database.message().findByBufferIdPaged(it).create(
Int.MAX_VALUE,
PagedList.Config.Builder()
.setPageSize(50)
.setEnablePlaceholders(false)
.setPrefetchDistance(50)
LivePagedListBuilder(database.message().findByBufferIdPaged(it), 20)
.setBoundaryCallback(boundaryCallback)
.setInitialLoadKey(null)
.build()
)
}
val adapter = MessageAdapter(context!!)
data.observe(
this, Observer { list ->
val findFirstVisibleItemPosition = linearLayoutManager.findFirstVisibleItemPosition()
adapter.setList(list)
if (findFirstVisibleItemPosition < 2) {
activity?.runOnUiThread {
messageList.smoothScrollToPosition(0)
}
handler.postDelayed(
{
activity?.runOnUiThread {
messageList.smoothScrollToPosition(0)
}
}, 16
)
}
}
)
......@@ -77,35 +108,22 @@ class MessageListFragment : ServiceBoundFragment() {
this, Observer {
handler.post {
// Try loading messages when switching to isEmpty buffer
if (it != null && database.message().bufferSize(it) == 0) {
if (it != null) {
if (database.message().bufferSize(it) == 0) {
loadMore()
}
activity?.runOnUiThread {
messageList.scrollToPosition(0)
}
}
)
var recyclerViewMeasuredHeight = 0
val scrollDownListener = object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
if (!recyclerView.canScrollVertically(-1)) {
loadMore()
}
if (recyclerViewMeasuredHeight == 0)
recyclerViewMeasuredHeight = recyclerView.measuredHeight
val canScrollDown = recyclerView.canScrollVertically(1)
val isScrollingDown = dy > 0
val scrollOffsetFromBottom = recyclerView.computeVerticalScrollRange() - recyclerView.computeVerticalScrollOffset() - recyclerViewMeasuredHeight
val isMoreThanOneScreenFromBottom = scrollOffsetFromBottom > recyclerViewMeasuredHeight
val smartVisibility = scrollDown.visibility == View.VISIBLE || isMoreThanOneScreenFromBottom
scrollDown.toggle(canScrollDown && isScrollingDown && smartVisibility)
}
}
)
messageList.adapter = adapter
messageList.layoutManager = LinearLayoutManager(context)
messageList.addOnScrollListener(scrollDownListener)
scrollDown.setOnClickListener { messageList.scrollToPosition(adapter.itemCount) }
scrollDown.hide()
scrollDown.setOnClickListener {
messageList.scrollToPosition(0)
}
return view
}
......
......@@ -3,6 +3,7 @@ package de.kuschku.quasseldroid_ng.ui.setup.accounts
import android.app.Application
import android.arch.lifecycle.AndroidViewModel
import android.arch.lifecycle.LiveData
import android.arch.paging.LivePagedListBuilder
import android.arch.paging.PagedList
import de.kuschku.quasseldroid_ng.persistence.AccountDatabase
......@@ -10,11 +11,6 @@ class AccountViewModel(application: Application) : AndroidViewModel(application)
private val database: AccountDatabase = AccountDatabase.Creator.init(
getApplication()
)
val accounts: LiveData<PagedList<AccountDatabase.Account>> = database.accounts().all().create(
0,
PagedList.Config.Builder()
.setPageSize(50)
.setPrefetchDistance(50)
.build()
)
val accounts: LiveData<PagedList<AccountDatabase.Account>>
= LivePagedListBuilder(database.accounts().all(), 20).build()
}
......@@ -24,6 +24,7 @@
android:layout_marginEnd="12dp"
android:layout_marginRight="12dp"
android:tint="@color/colorFillDark"
android:visibility="gone"
app:backgroundTint="#8A808080"
app:elevation="0dip"
app:fabSize="mini"
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment