From 89a3a4e9c189e968942e01e4ca0925c140a48ec9 Mon Sep 17 00:00:00 2001 From: Janne Koschinski <janne@kuschku.de> Date: Sun, 25 Feb 2018 16:02:55 +0100 Subject: [PATCH] Fixed the selection bug in the account selector --- .../persistence/AccountDatabase.kt | 4 +- .../ui/setup/accounts/AccountAdapter.kt | 117 +++++++++++------- .../accounts/AccountSelectionActivity.kt | 8 +- .../setup/accounts/AccountSelectionSlide.kt | 17 +-- .../ui/setup/accounts/AccountViewModel.kt | 7 +- 5 files changed, 89 insertions(+), 64 deletions(-) diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/persistence/AccountDatabase.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/persistence/AccountDatabase.kt index 3be55470e..e62a5c189 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/persistence/AccountDatabase.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/persistence/AccountDatabase.kt @@ -1,6 +1,6 @@ package de.kuschku.quasseldroid_ng.persistence -import android.arch.paging.DataSource +import android.arch.lifecycle.LiveData 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(): DataSource.Factory<Int, Account> + fun all(): LiveData<List<Account>> @Delete fun delete(account: AccountDatabase.Account) diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/accounts/AccountAdapter.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/accounts/AccountAdapter.kt index 542ce9a8a..4c6453927 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/accounts/AccountAdapter.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/accounts/AccountAdapter.kt @@ -1,8 +1,11 @@ package de.kuschku.quasseldroid_ng.ui.setup.accounts import android.annotation.SuppressLint -import android.arch.paging.PagedListAdapter -import android.support.v7.recyclerview.extensions.DiffCallback +import android.arch.lifecycle.LifecycleOwner +import android.arch.lifecycle.LiveData +import android.arch.lifecycle.MutableLiveData +import android.arch.lifecycle.Observer +import android.support.v7.util.DiffUtil import android.support.v7.widget.AppCompatImageButton import android.support.v7.widget.AppCompatRadioButton import android.support.v7.widget.RecyclerView @@ -14,16 +17,19 @@ import butterknife.BindView import butterknife.ButterKnife import de.kuschku.quasseldroid_ng.R import de.kuschku.quasseldroid_ng.persistence.AccountDatabase +import de.kuschku.quasseldroid_ng.util.helper.zip -class AccountAdapter : - PagedListAdapter<AccountDatabase.Account, AccountAdapter.AccountViewHolder>(DIFF_CALLBACK) { +class AccountAdapter( + owner: LifecycleOwner, + val liveData: LiveData<List<AccountDatabase.Account>>, + val selectedItem: MutableLiveData<Pair<Long, Long>> +) : RecyclerView.Adapter<AccountAdapter.AccountViewHolder>() { private val actionListeners = mutableSetOf<(Long) -> Unit>() private val addListeners = mutableSetOf<() -> Unit>() private val selectionListeners = mutableSetOf<(Long) -> Unit>() private val clickListener = object : ItemListener { override fun onAction(id: Long, pos: Int) { - notifySelectionChanged(selectedItemView, pos) selectionListener.invoke(id) } } @@ -36,16 +42,65 @@ class AccountAdapter : } } + private fun updateSelection(id: Long) { + selectedItem.value = Pair(selectedItem.value?.second ?: -1, id) + } + private val selectionListener = { id: Long -> - selectedItemId = id + updateSelection(id) for (selectionListener in selectionListeners) { selectionListener.invoke(id) } } - private var selectedItemView = -1 - var selectedItemId = -1L - private set + val selectedItemId + get() = selectedItem.value?.second + + private var list: List<Pair<Boolean, AccountDatabase.Account>> = emptyList() + + init { + selectedItem.value = Pair(-1, -1) + + liveData.zip(selectedItem).observe(owner, Observer { it -> + val list = it?.first + val oldSelected = it?.second?.first ?: -1 + val selected = it?.second?.second ?: -1 + + val oldList = this.list + val newList: List<Pair<Boolean, AccountDatabase.Account>> = list.orEmpty().map { + Pair(selected == it.id, it) + } + this.list = newList + + DiffUtil.calculateDiff(object : DiffUtil.Callback() { + override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + val oldItem = oldList[oldItemPosition].second + val newItem = newList[newItemPosition].second + + return oldItem.id == newItem.id + } + + override fun getOldListSize(): Int { + return oldList.size + } + + override fun getNewListSize(): Int { + return newList.size + } + + override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + val oldItem = oldList[oldItemPosition].second + val newItem = newList[newItemPosition].second + + return oldItem == newItem && + oldItem.id != selected && + newItem.id != selected && + oldItem.id != oldSelected && + newItem.id != oldSelected + } + }).dispatchUpdatesTo(this) + }) + } private val addListener = { for (addListener in addListeners) { @@ -81,16 +136,8 @@ class AccountAdapter : @SuppressLint("RecyclerView") position: Int) { when (holder) { is AccountViewHolder.Item -> { - val account = getItem(position) - if (account == null) { - holder.clear() - } else { - val selected = account.id == selectedItemId - if (selected) { - selectedItemView = position - } - holder.bind(account, selected) - } + val item = list[position] + holder.bind(item.second, item.first) } is AccountViewHolder.Add -> { } @@ -98,8 +145,8 @@ class AccountAdapter : } override fun getItemViewType(position: Int) = when (position) { - super.getItemCount() -> TYPE_ADD - else -> TYPE_ACCOUNT + list.size -> TYPE_ADD + else -> TYPE_ACCOUNT } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AccountViewHolder { @@ -117,44 +164,18 @@ class AccountAdapter : } override fun getItemCount(): Int { - return super.getItemCount() + 1 + return list.size + 1 } companion object { private const val TYPE_ACCOUNT = 0 private const val TYPE_ADD = 1 - - private val DIFF_CALLBACK = object : DiffCallback<AccountDatabase.Account>() { - override fun areContentsTheSame(oldItem: AccountDatabase.Account, - newItem: AccountDatabase.Account): Boolean { - return oldItem == newItem - } - - override fun areItemsTheSame(oldItem: AccountDatabase.Account, - newItem: AccountDatabase.Account): Boolean { - return oldItem.id == newItem.id - } - } } fun selectAccount(id: Long) { - selectedItemView = -1 selectionListener(id) } - fun notifySelectionChanged(from: Int?, to: Int?) { - val _from = from ?: -1 - val _to = to ?: -1 - - if (_from != -1) - notifyItemChanged(_from) - - selectedItemView = _to - - if (_to != -1) - notifyItemChanged(_to) - } - interface ItemListener { fun onAction(id: Long, pos: Int) } diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/accounts/AccountSelectionActivity.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/accounts/AccountSelectionActivity.kt index cb6891877..525ae03d1 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/accounts/AccountSelectionActivity.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/accounts/AccountSelectionActivity.kt @@ -27,7 +27,9 @@ class AccountSelectionActivity : SetupActivity() { putLong(Keys.Status.selectedAccount, data.getLong(Keys.Status.selectedAccount, -1)) putBoolean(Keys.Status.reconnect, true) } - startActivityForResult(Intent(this, ChatActivity::class.java), REQUEST_CHAT) + val intent = Intent(this, ChatActivity::class.java) + intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP + startActivityForResult(intent, REQUEST_CHAT) } override fun onCreate(savedInstanceState: Bundle?) { @@ -39,7 +41,9 @@ class AccountSelectionActivity : SetupActivity() { setInitData(data) if (statusPreferences.getBoolean(Keys.Status.reconnect, false) && selectedAccount != -1L) { - startActivityForResult(Intent(this, ChatActivity::class.java), REQUEST_CHAT) + val intent = Intent(this, ChatActivity::class.java) + intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP + startActivityForResult(intent, REQUEST_CHAT) } } diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/accounts/AccountSelectionSlide.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/accounts/AccountSelectionSlide.kt index 78b14161a..6699c44eb 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/accounts/AccountSelectionSlide.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/accounts/AccountSelectionSlide.kt @@ -3,7 +3,6 @@ package de.kuschku.quasseldroid_ng.ui.setup.accounts import android.app.Activity import android.arch.lifecycle.Observer import android.arch.lifecycle.ViewModelProviders -import android.arch.paging.PagedList import android.content.Intent import android.os.Bundle import android.support.v7.widget.DefaultItemAnimator @@ -24,21 +23,21 @@ class AccountSelectionSlide : SlideFragment() { @BindView(R.id.account_list) lateinit var accountList: RecyclerView - override fun isValid() = adapter.selectedItemId != -1L + override fun isValid() = adapter?.selectedItemId ?: -1L != -1L override val title = R.string.slideAccountSelectTitle override val description = R.string.slideAccountSelectDescription override fun setData(data: Bundle) { if (data.containsKey("selectedAccount")) - adapter.selectAccount(data.getLong("selectedAccount")) + adapter?.selectAccount(data.getLong("selectedAccount")) } override fun getData(data: Bundle) { - data.putLong("selectedAccount", adapter.selectedItemId) + data.putLong("selectedAccount", adapter?.selectedItemId ?: -1L) } - private val adapter = AccountAdapter() + private var adapter: AccountAdapter? = null override fun onCreateContent(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { val view = inflater.inflate(R.layout.setup_select_account, container, false) @@ -46,8 +45,8 @@ class AccountSelectionSlide : SlideFragment() { val accountViewModel = ViewModelProviders.of(this).get( AccountViewModel::class.java ) - val firstObserver = object : Observer<PagedList<AccountDatabase.Account>?> { - override fun onChanged(t: PagedList<AccountDatabase.Account>?) { + val firstObserver = object : Observer<List<AccountDatabase.Account>?> { + override fun onChanged(t: List<AccountDatabase.Account>?) { if (t?.isEmpty() != false) startActivityForResult( Intent(context, AccountSetupActivity::class.java), @@ -57,10 +56,12 @@ class AccountSelectionSlide : SlideFragment() { } } accountViewModel.accounts.observe(this, firstObserver) - accountViewModel.accounts.observe(this, Observer(adapter::setList)) accountList.layoutManager = LinearLayoutManager(context) accountList.itemAnimator = DefaultItemAnimator() + val adapter = AccountAdapter(this, accountViewModel.accounts, accountViewModel.selectedItem) + this.adapter = adapter accountList.adapter = adapter + adapter.addAddListener { startActivityForResult(Intent(context, AccountSetupActivity::class.java), -1) } diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/accounts/AccountViewModel.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/accounts/AccountViewModel.kt index d873980ca..087b38577 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/accounts/AccountViewModel.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/accounts/AccountViewModel.kt @@ -3,14 +3,13 @@ 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 android.arch.lifecycle.MutableLiveData import de.kuschku.quasseldroid_ng.persistence.AccountDatabase class AccountViewModel(application: Application) : AndroidViewModel(application) { private val database: AccountDatabase = AccountDatabase.Creator.init( getApplication() ) - val accounts: LiveData<PagedList<AccountDatabase.Account>> - = LivePagedListBuilder(database.accounts().all(), 20).build() + val accounts: LiveData<List<AccountDatabase.Account>> = database.accounts().all() + val selectedItem = MutableLiveData<Pair<Long, Long>>() } -- GitLab