Some performance improvements
This commit is contained in:
parent
9dd1b457e3
commit
1e8b71e43b
@ -166,18 +166,17 @@ class MessageDetailFragment : Fragment() {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
R.id.delete -> {
|
R.id.delete -> {
|
||||||
|
Singleton.labeler.delete(item)
|
||||||
if (isInTrash(item)) {
|
if (isInTrash(item)) {
|
||||||
messageRepo.remove(item)
|
messageRepo.remove(item)
|
||||||
} else {
|
} else {
|
||||||
item.labels.clear()
|
|
||||||
item.addLabels(messageRepo.getLabels(Label.Type.TRASH))
|
|
||||||
messageRepo.save(item)
|
messageRepo.save(item)
|
||||||
}
|
}
|
||||||
activity.onBackPressed()
|
activity.onBackPressed()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
R.id.mark_unread -> {
|
R.id.mark_unread -> {
|
||||||
item.addLabels(messageRepo.getLabels(Label.Type.UNREAD))
|
Singleton.labeler.markAsUnread(item)
|
||||||
messageRepo.save(item)
|
messageRepo.save(item)
|
||||||
if (activity is MainActivity) {
|
if (activity is MainActivity) {
|
||||||
(activity as MainActivity).updateUnread()
|
(activity as MainActivity).updateUnread()
|
||||||
@ -188,7 +187,7 @@ class MessageDetailFragment : Fragment() {
|
|||||||
if (item.isUnread() && activity is MainActivity) {
|
if (item.isUnread() && activity is MainActivity) {
|
||||||
(activity as MainActivity).updateUnread()
|
(activity as MainActivity).updateUnread()
|
||||||
}
|
}
|
||||||
item.labels.clear()
|
Singleton.labeler.archive(item)
|
||||||
messageRepo.save(item)
|
messageRepo.save(item)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -17,11 +17,14 @@
|
|||||||
package ch.dissem.apps.abit
|
package ch.dissem.apps.abit
|
||||||
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.support.v4.app.Fragment
|
import android.support.v4.app.Fragment
|
||||||
import android.support.v4.content.ContextCompat
|
import android.support.v4.content.ContextCompat
|
||||||
import android.support.v7.widget.LinearLayoutManager
|
import android.support.v7.widget.LinearLayoutManager
|
||||||
import android.support.v7.widget.RecyclerView
|
import android.support.v7.widget.RecyclerView
|
||||||
|
import android.support.v7.widget.RecyclerView.OnScrollListener
|
||||||
import android.view.*
|
import android.view.*
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import ch.dissem.apps.abit.ComposeMessageActivity.Companion.EXTRA_BROADCAST
|
import ch.dissem.apps.abit.ComposeMessageActivity.Companion.EXTRA_BROADCAST
|
||||||
@ -29,6 +32,7 @@ import ch.dissem.apps.abit.ComposeMessageActivity.Companion.EXTRA_IDENTITY
|
|||||||
import ch.dissem.apps.abit.adapter.SwipeableMessageAdapter
|
import ch.dissem.apps.abit.adapter.SwipeableMessageAdapter
|
||||||
import ch.dissem.apps.abit.listener.ListSelectionListener
|
import ch.dissem.apps.abit.listener.ListSelectionListener
|
||||||
import ch.dissem.apps.abit.repository.AndroidMessageRepository
|
import ch.dissem.apps.abit.repository.AndroidMessageRepository
|
||||||
|
import ch.dissem.apps.abit.repository.AndroidMessageRepository.Companion.LABEL_ARCHIVE
|
||||||
import ch.dissem.apps.abit.service.Singleton
|
import ch.dissem.apps.abit.service.Singleton
|
||||||
import ch.dissem.apps.abit.util.FabUtils
|
import ch.dissem.apps.abit.util.FabUtils
|
||||||
import ch.dissem.bitmessage.entity.Plaintext
|
import ch.dissem.bitmessage.entity.Plaintext
|
||||||
@ -41,9 +45,12 @@ import com.h6ah4i.android.widget.advrecyclerview.utils.WrapperAdapterUtils
|
|||||||
import io.github.kobakei.materialfabspeeddial.FabSpeedDialMenu
|
import io.github.kobakei.materialfabspeeddial.FabSpeedDialMenu
|
||||||
import kotlinx.android.synthetic.main.fragment_message_list.*
|
import kotlinx.android.synthetic.main.fragment_message_list.*
|
||||||
import org.jetbrains.anko.doAsync
|
import org.jetbrains.anko.doAsync
|
||||||
|
import org.jetbrains.anko.support.v4.onUiThread
|
||||||
import org.jetbrains.anko.uiThread
|
import org.jetbrains.anko.uiThread
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
private const val PAGE_SIZE = 15
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A list fragment representing a list of Messages. This fragment
|
* A list fragment representing a list of Messages. This fragment
|
||||||
* also supports tablet devices by allowing list items to be given an
|
* also supports tablet devices by allowing list items to be given an
|
||||||
@ -56,12 +63,33 @@ import java.util.*
|
|||||||
*/
|
*/
|
||||||
class MessageListFragment : Fragment(), ListHolder<Label> {
|
class MessageListFragment : Fragment(), ListHolder<Label> {
|
||||||
|
|
||||||
private var layoutManager: RecyclerView.LayoutManager? = null
|
private var isLoading = false
|
||||||
|
private var isLastPage = false
|
||||||
|
|
||||||
|
private var layoutManager: LinearLayoutManager? = null
|
||||||
private var swipeableMessageAdapter: SwipeableMessageAdapter? = null
|
private var swipeableMessageAdapter: SwipeableMessageAdapter? = null
|
||||||
private var wrappedAdapter: RecyclerView.Adapter<*>? = null
|
private var wrappedAdapter: RecyclerView.Adapter<*>? = null
|
||||||
private var recyclerViewSwipeManager: RecyclerViewSwipeManager? = null
|
private var recyclerViewSwipeManager: RecyclerViewSwipeManager? = null
|
||||||
private var recyclerViewTouchActionGuardManager: RecyclerViewTouchActionGuardManager? = null
|
private var recyclerViewTouchActionGuardManager: RecyclerViewTouchActionGuardManager? = null
|
||||||
|
|
||||||
|
private val recyclerViewOnScrollListener = object : OnScrollListener() {
|
||||||
|
override fun onScrolled(recyclerView: RecyclerView?, dx: Int, dy: Int) {
|
||||||
|
layoutManager?.let { layoutManager ->
|
||||||
|
val visibleItemCount = layoutManager.childCount
|
||||||
|
val totalItemCount = layoutManager.itemCount
|
||||||
|
val firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition()
|
||||||
|
|
||||||
|
if (!isLoading && !isLastPage) {
|
||||||
|
if (visibleItemCount + firstVisibleItemPosition >= totalItemCount - 5
|
||||||
|
&& firstVisibleItemPosition >= 0
|
||||||
|
&& totalItemCount >= PAGE_SIZE) {
|
||||||
|
loadMoreItems()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override var currentLabel: Label? = null
|
override var currentLabel: Label? = null
|
||||||
|
|
||||||
private var emptyTrashMenuItem: MenuItem? = null
|
private var emptyTrashMenuItem: MenuItem? = null
|
||||||
@ -70,6 +98,20 @@ class MessageListFragment : Fragment(), ListHolder<Label> {
|
|||||||
|
|
||||||
private val backStack = Stack<Label>()
|
private val backStack = Stack<Label>()
|
||||||
|
|
||||||
|
fun loadMoreItems() {
|
||||||
|
isLoading = true
|
||||||
|
swipeableMessageAdapter?.let { messageAdapter ->
|
||||||
|
doAsync {
|
||||||
|
val messages = messageRepo.findMessages(currentLabel, messageAdapter.itemCount, PAGE_SIZE)
|
||||||
|
onUiThread {
|
||||||
|
messageAdapter.addAll(messages)
|
||||||
|
isLoading = false
|
||||||
|
isLastPage = messages.size < PAGE_SIZE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
@ -82,10 +124,8 @@ class MessageListFragment : Fragment(), ListHolder<Label> {
|
|||||||
initFab(activity)
|
initFab(activity)
|
||||||
messageRepo = Singleton.getMessageRepository(activity)
|
messageRepo = Singleton.getMessageRepository(activity)
|
||||||
|
|
||||||
if (backStack.isEmpty()) {
|
if (backStack.isEmpty() && currentLabel == null) {
|
||||||
doUpdateList(activity.selectedLabel)
|
doUpdateList(activity.selectedLabel)
|
||||||
} else {
|
|
||||||
doUpdateList(backStack.peek())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,13 +159,7 @@ class MessageListFragment : Fragment(), ListHolder<Label> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
doAsync {
|
loadMoreItems()
|
||||||
messageRepo.findMessageIds(label)
|
|
||||||
.map { messageRepo.getMessage(it) }
|
|
||||||
.forEach { message ->
|
|
||||||
uiThread { swipeableMessageAdapter?.add(message) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
|
||||||
@ -189,6 +223,7 @@ class MessageListFragment : Fragment(), ListHolder<Label> {
|
|||||||
recycler_view.layoutManager = layoutManager
|
recycler_view.layoutManager = layoutManager
|
||||||
recycler_view.adapter = wrappedAdapter // requires *wrapped* swipeableMessageAdapter
|
recycler_view.adapter = wrappedAdapter // requires *wrapped* swipeableMessageAdapter
|
||||||
recycler_view.itemAnimator = animator
|
recycler_view.itemAnimator = animator
|
||||||
|
recycler_view.addOnScrollListener(recyclerViewOnScrollListener)
|
||||||
|
|
||||||
recycler_view.addItemDecoration(SimpleListDividerDecorator(
|
recycler_view.addItemDecoration(SimpleListDividerDecorator(
|
||||||
ContextCompat.getDrawable(context, R.drawable.list_divider_h), true))
|
ContextCompat.getDrawable(context, R.drawable.list_divider_h), true))
|
||||||
@ -204,6 +239,17 @@ class MessageListFragment : Fragment(), ListHolder<Label> {
|
|||||||
recyclerViewTouchActionGuardManager = touchActionGuardManager
|
recyclerViewTouchActionGuardManager = touchActionGuardManager
|
||||||
recyclerViewSwipeManager = swipeManager
|
recyclerViewSwipeManager = swipeManager
|
||||||
this.swipeableMessageAdapter = adapter
|
this.swipeableMessageAdapter = adapter
|
||||||
|
|
||||||
|
Singleton.labeler.listener = { message, added, removed ->
|
||||||
|
if (added.contains(currentLabel)) {
|
||||||
|
// TODO: add to current list, at correct position
|
||||||
|
} else if (removed.contains(currentLabel)) {
|
||||||
|
swipeableMessageAdapter?.remove(message)
|
||||||
|
} else if (removed.any { it.type == Label.Type.UNREAD } || added.any { it.type == Label.Type.UNREAD }) {
|
||||||
|
// TODO: update if in current list, maybe update unread badges
|
||||||
|
swipeableMessageAdapter?.update(message)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initFab(context: MainActivity) {
|
private fun initFab(context: MainActivity) {
|
||||||
@ -295,4 +341,10 @@ class MessageListFragment : Fragment(), ListHolder<Label> {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun addMessage(message: Plaintext) {
|
||||||
|
if (message.labels.contains(currentLabel) || (currentLabel == LABEL_ARCHIVE && message.labels.isEmpty())) {
|
||||||
|
swipeableMessageAdapter?.addFirst(message)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -96,6 +96,35 @@ class SwipeableMessageAdapter : RecyclerView.Adapter<SwipeableMessageAdapter.Vie
|
|||||||
notifyDataSetChanged()
|
notifyDataSetChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun addFirst(item: Plaintext) {
|
||||||
|
val index = data.size
|
||||||
|
data.addFirst(item)
|
||||||
|
notifyItemInserted(index)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addAll(items: Collection<Plaintext>) {
|
||||||
|
val index = data.size
|
||||||
|
data.addAll(items)
|
||||||
|
notifyItemRangeInserted(index, items.size)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun remove(item: Plaintext) {
|
||||||
|
val index = data.indexOf(item)
|
||||||
|
data.removeIf { it.id == item.id }
|
||||||
|
notifyItemRemoved(index)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun update(item: Plaintext) {
|
||||||
|
data.replaceAll {
|
||||||
|
if (it.id == item.id) {
|
||||||
|
item
|
||||||
|
} else {
|
||||||
|
it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
notifyItemChanged(data.indexOf(item))
|
||||||
|
}
|
||||||
|
|
||||||
fun clear(newLabel: Label?) {
|
fun clear(newLabel: Label?) {
|
||||||
label = newLabel
|
label = newLabel
|
||||||
data.clear()
|
data.clear()
|
||||||
|
@ -17,16 +17,12 @@
|
|||||||
package ch.dissem.apps.abit.listener
|
package ch.dissem.apps.abit.listener
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
|
||||||
import java.util.Deque
|
|
||||||
import java.util.LinkedList
|
|
||||||
import java.util.concurrent.ExecutorService
|
|
||||||
import java.util.concurrent.Executors
|
|
||||||
|
|
||||||
import ch.dissem.apps.abit.MainActivity
|
import ch.dissem.apps.abit.MainActivity
|
||||||
import ch.dissem.apps.abit.notification.NewMessageNotification
|
import ch.dissem.apps.abit.notification.NewMessageNotification
|
||||||
import ch.dissem.bitmessage.BitmessageContext
|
import ch.dissem.bitmessage.BitmessageContext
|
||||||
import ch.dissem.bitmessage.entity.Plaintext
|
import ch.dissem.bitmessage.entity.Plaintext
|
||||||
|
import java.util.*
|
||||||
|
import java.util.concurrent.Executors
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Listens for decrypted Bitmessage messages. Does show a notification.
|
* Listens for decrypted Bitmessage messages. Does show a notification.
|
||||||
|
@ -42,10 +42,10 @@ import java.util.*
|
|||||||
*/
|
*/
|
||||||
class AndroidMessageRepository(private val sql: SqlHelper, private val context: Context) : AbstractMessageRepository() {
|
class AndroidMessageRepository(private val sql: SqlHelper, private val context: Context) : AbstractMessageRepository() {
|
||||||
|
|
||||||
override fun findMessages(label: Label?) = if (label === LABEL_ARCHIVE) {
|
override fun findMessages(label: Label?, offset: Int, limit: Int) = if (label === LABEL_ARCHIVE) {
|
||||||
super.findMessages(null as Label?)
|
super.findMessages(null as Label?, offset, limit)
|
||||||
} else {
|
} else {
|
||||||
super.findMessages(label)
|
super.findMessages(label, offset, limit)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun findMessageIds(label: Label) = if (label === LABEL_ARCHIVE) {
|
fun findMessageIds(label: Label) = if (label === LABEL_ARCHIVE) {
|
||||||
@ -224,7 +224,7 @@ class AndroidMessageRepository(private val sql: SqlHelper, private val context:
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun find(where: String): List<Plaintext> {
|
override fun find(where: String, offset: Int, limit: Int): List<Plaintext> {
|
||||||
val result = LinkedList<Plaintext>()
|
val result = LinkedList<Plaintext>()
|
||||||
|
|
||||||
// Define a projection that specifies which columns from the database
|
// Define a projection that specifies which columns from the database
|
||||||
@ -235,7 +235,8 @@ class AndroidMessageRepository(private val sql: SqlHelper, private val context:
|
|||||||
db.query(
|
db.query(
|
||||||
TABLE_NAME, projection,
|
TABLE_NAME, projection,
|
||||||
where, null, null, null,
|
where, null, null, null,
|
||||||
"$COLUMN_RECEIVED DESC, $COLUMN_SENT DESC"
|
"$COLUMN_RECEIVED DESC, $COLUMN_SENT DESC",
|
||||||
|
if (limit == 0) null else "$offset, $limit"
|
||||||
).use { c ->
|
).use { c ->
|
||||||
while (c.moveToNext()) {
|
while (c.moveToNext()) {
|
||||||
val iv = c.getBlob(c.getColumnIndex(COLUMN_IV))
|
val iv = c.getBlob(c.getColumnIndex(COLUMN_IV))
|
||||||
|
@ -30,6 +30,7 @@ import ch.dissem.bitmessage.BitmessageContext
|
|||||||
import ch.dissem.bitmessage.entity.BitmessageAddress
|
import ch.dissem.bitmessage.entity.BitmessageAddress
|
||||||
import ch.dissem.bitmessage.entity.payload.Pubkey
|
import ch.dissem.bitmessage.entity.payload.Pubkey
|
||||||
import ch.dissem.bitmessage.networking.nio.NioNetworkHandler
|
import ch.dissem.bitmessage.networking.nio.NioNetworkHandler
|
||||||
|
import ch.dissem.bitmessage.ports.DefaultLabeler
|
||||||
import ch.dissem.bitmessage.utils.ConversationService
|
import ch.dissem.bitmessage.utils.ConversationService
|
||||||
import ch.dissem.bitmessage.utils.TTL
|
import ch.dissem.bitmessage.utils.TTL
|
||||||
import ch.dissem.bitmessage.utils.UnixTime.DAY
|
import ch.dissem.bitmessage.utils.UnixTime.DAY
|
||||||
@ -40,6 +41,7 @@ import org.jetbrains.anko.uiThread
|
|||||||
* Provides singleton objects across the application.
|
* Provides singleton objects across the application.
|
||||||
*/
|
*/
|
||||||
object Singleton {
|
object Singleton {
|
||||||
|
val labeler = DefaultLabeler()
|
||||||
var bitmessageContext: BitmessageContext? = null
|
var bitmessageContext: BitmessageContext? = null
|
||||||
private set
|
private set
|
||||||
private var conversationService: ConversationService? = null
|
private var conversationService: ConversationService? = null
|
||||||
@ -69,6 +71,7 @@ object Singleton {
|
|||||||
.powRepo(powRepo)
|
.powRepo(powRepo)
|
||||||
.networkHandler(NioNetworkHandler())
|
.networkHandler(NioNetworkHandler())
|
||||||
.listener(getMessageListener(ctx))
|
.listener(getMessageListener(ctx))
|
||||||
|
.labeler(labeler)
|
||||||
.doNotSendPubkeyOnIdentityCreation()
|
.doNotSendPubkeyOnIdentityCreation()
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ configurations.all {
|
|||||||
}
|
}
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
ext.kotlin_version = '1.1.4-2'
|
ext.kotlin_version = '1.1.4-3'
|
||||||
ext.anko_version = '0.10.1'
|
ext.anko_version = '0.10.1'
|
||||||
repositories {
|
repositories {
|
||||||
jcenter()
|
jcenter()
|
||||||
|
Loading…
Reference in New Issue
Block a user