fix: Update tabs when lists are renamed or deleted
If the user has tabs containing one or more lists, and any of those lists are renamed or deleted then the change should be reflected in the tabs. To do that: `MainActivity`: - Re-create tabs whenever lists are loaded and there's a list in a tab - Compare lists-in-tabs by the ID of the list when restoring the user's tab, so that a list rename doesn't lose their position. `NetworkListsRepository`: - Update the user's tab preferences whenever lists are loaded, removing tabs that contain lists that have been deleted, and updating the list's title for lists that have been renamed. Fixes #192
This commit is contained in:
parent
a973f67ac8
commit
7da4bc090b
|
@ -363,10 +363,18 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, MenuProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
listsRepository.lists.collect {
|
listsRepository.lists.collect { result ->
|
||||||
it.onSuccess { refreshMainDrawerItems(addSearchButton = hideTopToolbar) }
|
result.onSuccess { lists ->
|
||||||
|
// Update the list of lists in the main drawer
|
||||||
|
refreshMainDrawerItems(addSearchButton = hideTopToolbar)
|
||||||
|
|
||||||
it.onFailure {
|
// Any lists in tabs might have changed titles, update those
|
||||||
|
if (lists is Lists.Loaded && tabAdapter.tabs.any { it.tabData is TabData.UserList }) {
|
||||||
|
setupTabs(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result.onFailure {
|
||||||
Snackbar.make(binding.root, R.string.error_list_load, Snackbar.LENGTH_INDEFINITE)
|
Snackbar.make(binding.root, R.string.error_list_load, Snackbar.LENGTH_INDEFINITE)
|
||||||
.setAction(R.string.action_retry) { listsRepository.refresh() }
|
.setAction(R.string.action_retry) { listsRepository.refresh() }
|
||||||
.show()
|
.show()
|
||||||
|
@ -875,11 +883,20 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, MenuProvider {
|
||||||
// Selected tab is either
|
// Selected tab is either
|
||||||
// - Notification tab (if appropriate)
|
// - Notification tab (if appropriate)
|
||||||
// - The previously selected tab (if it hasn't been removed)
|
// - The previously selected tab (if it hasn't been removed)
|
||||||
|
// - Tabs containing lists are compared by list ID, in case the list was renamed
|
||||||
// - Left-most tab
|
// - Left-most tab
|
||||||
val position = if (selectNotificationTab) {
|
val position = if (selectNotificationTab) {
|
||||||
tabs.indexOfFirst { it.tabData is TabData.Notifications }
|
tabs.indexOfFirst { it.tabData is TabData.Notifications }
|
||||||
} else {
|
} else {
|
||||||
previousTab?.let { tabs.indexOfFirst { it == previousTab } }
|
previousTab?.let {
|
||||||
|
tabs.indexOfFirst {
|
||||||
|
if (it.tabData is TabData.UserList && previousTab.tabData is TabData.UserList) {
|
||||||
|
it.tabData.listId == previousTab.tabData.listId
|
||||||
|
} else {
|
||||||
|
it == previousTab
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}.takeIf { it != -1 } ?: 0
|
}.takeIf { it != -1 } ?: 0
|
||||||
binding.viewPager.setCurrentItem(position, false)
|
binding.viewPager.setCurrentItem(position, false)
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ import app.pachli.core.data.repository.ListsError.Delete
|
||||||
import app.pachli.core.data.repository.ListsError.GetListsWithAccount
|
import app.pachli.core.data.repository.ListsError.GetListsWithAccount
|
||||||
import app.pachli.core.data.repository.ListsError.Retrieve
|
import app.pachli.core.data.repository.ListsError.Retrieve
|
||||||
import app.pachli.core.data.repository.ListsError.Update
|
import app.pachli.core.data.repository.ListsError.Update
|
||||||
|
import app.pachli.core.database.model.TabData
|
||||||
import app.pachli.core.network.model.MastoList
|
import app.pachli.core.network.model.MastoList
|
||||||
import app.pachli.core.network.model.TimelineAccount
|
import app.pachli.core.network.model.TimelineAccount
|
||||||
import app.pachli.core.network.retrofit.MastodonApi
|
import app.pachli.core.network.retrofit.MastodonApi
|
||||||
|
@ -60,12 +61,67 @@ class NetworkListsRepository @Inject constructor(
|
||||||
_lists.value = Ok(Lists.Loading)
|
_lists.value = Ok(Lists.Loading)
|
||||||
_lists.value = api.getLists()
|
_lists.value = api.getLists()
|
||||||
.mapBoth(
|
.mapBoth(
|
||||||
{ Ok(Lists.Loaded(it.body)) },
|
{
|
||||||
|
updateTabPreferences(it.body.associateBy { it.id })
|
||||||
|
Ok(Lists.Loaded(it.body))
|
||||||
|
},
|
||||||
{ Err(Retrieve(it)) },
|
{ Err(Retrieve(it)) },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the user's tab preferences when lists are loaded.
|
||||||
|
*
|
||||||
|
* The user may have added one or more lists to tabs. If they have then:
|
||||||
|
*
|
||||||
|
* - A list-in-a-tab might have been deleted
|
||||||
|
* - A list-in-a-tab might have been renamed
|
||||||
|
*
|
||||||
|
* Handle both of those scenarios.
|
||||||
|
*
|
||||||
|
* @param lists Map of listId -> [MastoList]
|
||||||
|
*/
|
||||||
|
private fun updateTabPreferences(lists: Map<String, MastoList>) {
|
||||||
|
val account = accountManager.activeAccount ?: return
|
||||||
|
val oldTabPreferences = account.tabPreferences
|
||||||
|
var changed = false
|
||||||
|
val newTabPreferences = buildList {
|
||||||
|
for (oldPref in oldTabPreferences) {
|
||||||
|
if (oldPref !is TabData.UserList) {
|
||||||
|
add(oldPref)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// List has been deleted? Don't add this pref,
|
||||||
|
// record there's been a change, and move on to the
|
||||||
|
// next one.
|
||||||
|
if (oldPref.listId !in lists) {
|
||||||
|
changed = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Title changed? Update the title in the pref and
|
||||||
|
// add it.
|
||||||
|
if (oldPref.title != lists[oldPref.listId]?.title) {
|
||||||
|
changed = true
|
||||||
|
add(
|
||||||
|
oldPref.copy(
|
||||||
|
title = lists[oldPref.listId]?.title!!,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
add(oldPref)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (changed) {
|
||||||
|
account.tabPreferences = newTabPreferences
|
||||||
|
accountManager.saveAccount(account)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override suspend fun createList(title: String, exclusive: Boolean): Result<MastoList, Create> = binding {
|
override suspend fun createList(title: String, exclusive: Boolean): Result<MastoList, Create> = binding {
|
||||||
externalScope.async {
|
externalScope.async {
|
||||||
api.createList(title, exclusive).mapError { Create(it) }.bind().run {
|
api.createList(title, exclusive).mapError { Create(it) }.bind().run {
|
||||||
|
|
Loading…
Reference in New Issue