Extract 'manage folders' screen to ManageFoldersFragment
This commit is contained in:
parent
0e1804ff3e
commit
1bd52ae417
5 changed files with 228 additions and 145 deletions
|
@ -1,171 +1,59 @@
|
|||
package com.fsck.k9.ui.managefolders
|
||||
|
||||
import android.content.Context
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import androidx.appcompat.app.ActionBar
|
||||
import androidx.appcompat.widget.SearchView
|
||||
import androidx.appcompat.widget.SearchView.OnQueryTextListener
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.ui.AppBarConfiguration
|
||||
import androidx.navigation.ui.setupActionBarWithNavController
|
||||
import com.fsck.k9.Account
|
||||
import com.fsck.k9.Account.FolderMode
|
||||
import com.fsck.k9.Preferences
|
||||
import com.fsck.k9.activity.K9Activity
|
||||
import com.fsck.k9.activity.setup.FolderSettings
|
||||
import com.fsck.k9.controller.MessagingController
|
||||
import com.fsck.k9.mailstore.DisplayFolder
|
||||
import com.fsck.k9.ui.R
|
||||
import com.fsck.k9.ui.folders.FolderIconProvider
|
||||
import com.fsck.k9.ui.folders.FolderNameFormatter
|
||||
import com.fsck.k9.ui.observeNotNull
|
||||
import com.mikepenz.fastadapter.FastAdapter
|
||||
import com.mikepenz.fastadapter.adapters.ItemAdapter
|
||||
import java.util.Locale
|
||||
import org.koin.android.ext.android.inject
|
||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||
import org.koin.core.parameter.parametersOf
|
||||
import com.fsck.k9.ui.findNavController
|
||||
|
||||
class ManageFoldersActivity : K9Activity() {
|
||||
private val viewModel: ManageFoldersViewModel by viewModel()
|
||||
private val folderNameFormatter: FolderNameFormatter by inject { parametersOf(this) }
|
||||
private val messagingController: MessagingController by inject()
|
||||
private val preferences: Preferences by inject()
|
||||
private val folderIconProvider by lazy { FolderIconProvider(theme) }
|
||||
|
||||
private lateinit var account: Account
|
||||
private lateinit var actionBar: ActionBar
|
||||
private lateinit var itemAdapter: ItemAdapter<FolderListItem>
|
||||
private lateinit var navController: NavController
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setLayout(R.layout.folder_list)
|
||||
setLayout(R.layout.activity_manage_folders)
|
||||
|
||||
if (!decodeArguments()) {
|
||||
finish()
|
||||
return
|
||||
}
|
||||
val accountUuid = intent.getStringExtra(EXTRA_ACCOUNT) ?: error("Missing Intent extra '$EXTRA_ACCOUNT'")
|
||||
|
||||
initializeActionBar()
|
||||
initializeFolderList()
|
||||
|
||||
viewModel.getFolders(account).observeNotNull(this) { folders ->
|
||||
updateFolderList(folders)
|
||||
}
|
||||
initializeNavController(accountUuid)
|
||||
}
|
||||
|
||||
private fun decodeArguments(): Boolean {
|
||||
val accountUuid = intent.getStringExtra(EXTRA_ACCOUNT) ?: return false
|
||||
account = preferences.getAccount(accountUuid) ?: return false
|
||||
private fun initializeNavController(accountUuid: String) {
|
||||
navController = findNavController(R.id.nav_host_fragment)
|
||||
|
||||
val fragmentArguments = bundleOf(
|
||||
ManageFoldersFragment.EXTRA_ACCOUNT to accountUuid
|
||||
)
|
||||
navController.setGraph(R.navigation.navigation_manage_folders, fragmentArguments)
|
||||
|
||||
val appBarConfiguration = AppBarConfiguration(topLevelDestinationIds = emptySet())
|
||||
setupActionBarWithNavController(navController, appBarConfiguration)
|
||||
}
|
||||
|
||||
override fun onSupportNavigateUp(): Boolean {
|
||||
return navController.navigateUp() || super.onSupportNavigateUp() || navigateUpBySimulatedBackButtonPress()
|
||||
}
|
||||
|
||||
private fun navigateUpBySimulatedBackButtonPress(): Boolean {
|
||||
onBackPressed()
|
||||
return true
|
||||
}
|
||||
|
||||
private fun initializeActionBar() {
|
||||
actionBar = supportActionBar!!
|
||||
actionBar.setDisplayHomeAsUpEnabled(true)
|
||||
}
|
||||
|
||||
private fun initializeFolderList() {
|
||||
itemAdapter = ItemAdapter()
|
||||
itemAdapter.itemFilter.filterPredicate = ::folderListFilter
|
||||
|
||||
val folderListAdapter = FastAdapter.with(itemAdapter).apply {
|
||||
setHasStableIds(true)
|
||||
onClickListener = { _, _, item: FolderListItem, _ ->
|
||||
openFolderSettings(item.serverId)
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
val recyclerView = findViewById<RecyclerView>(R.id.folderList)
|
||||
recyclerView.adapter = folderListAdapter
|
||||
}
|
||||
|
||||
private fun updateFolderList(displayFolders: List<DisplayFolder>) {
|
||||
val folderListItems = displayFolders.map { displayFolder ->
|
||||
val databaseId = displayFolder.folder.id
|
||||
val folderIconResource = folderIconProvider.getFolderIcon(displayFolder.folder.type)
|
||||
val displayName = folderNameFormatter.displayName(displayFolder.folder)
|
||||
val serverId = displayFolder.folder.serverId
|
||||
|
||||
FolderListItem(databaseId, folderIconResource, displayName, serverId)
|
||||
}
|
||||
|
||||
itemAdapter.set(folderListItems)
|
||||
}
|
||||
|
||||
private fun openFolderSettings(folderServerId: String) {
|
||||
FolderSettings.actionSettings(this, account, folderServerId)
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
super.onCreateOptionsMenu(menu)
|
||||
menuInflater.inflate(R.menu.folder_list_option, menu)
|
||||
configureFolderSearchView(menu)
|
||||
return true
|
||||
}
|
||||
|
||||
private fun configureFolderSearchView(menu: Menu) {
|
||||
val folderMenuItem = menu.findItem(R.id.filter_folders)
|
||||
val folderSearchView = folderMenuItem.actionView as SearchView
|
||||
folderSearchView.queryHint = getString(R.string.folder_list_filter_hint)
|
||||
folderSearchView.setOnQueryTextListener(object : OnQueryTextListener {
|
||||
override fun onQueryTextSubmit(query: String): Boolean {
|
||||
itemAdapter.filter(query)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onQueryTextChange(newText: String): Boolean {
|
||||
itemAdapter.filter(newText)
|
||||
return true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
android.R.id.home -> onBackPressed()
|
||||
R.id.list_folders -> refreshFolderList()
|
||||
R.id.display_1st_class -> setDisplayMode(FolderMode.FIRST_CLASS)
|
||||
R.id.display_1st_and_2nd_class -> setDisplayMode(FolderMode.FIRST_AND_SECOND_CLASS)
|
||||
R.id.display_not_second_class -> setDisplayMode(FolderMode.NOT_SECOND_CLASS)
|
||||
R.id.display_all -> setDisplayMode(FolderMode.ALL)
|
||||
else -> return super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private fun refreshFolderList() {
|
||||
messagingController.refreshFolderList(account)
|
||||
}
|
||||
|
||||
private fun setDisplayMode(newMode: FolderMode) {
|
||||
account.folderDisplayMode = newMode
|
||||
preferences.saveAccount(account)
|
||||
|
||||
itemAdapter.filter(null)
|
||||
}
|
||||
|
||||
private fun folderListFilter(item: FolderListItem, constraint: CharSequence?): Boolean {
|
||||
if (constraint.isNullOrEmpty()) return true
|
||||
|
||||
val locale = Locale.getDefault()
|
||||
val displayName = item.displayName.toLowerCase(locale)
|
||||
return constraint.splitToSequence(" ")
|
||||
.map { it.toLowerCase(locale) }
|
||||
.any { it in displayName }
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val EXTRA_ACCOUNT = "account"
|
||||
|
||||
@JvmStatic
|
||||
fun launch(context: Context, account: Account) {
|
||||
val intent = Intent(context, ManageFoldersActivity::class.java)
|
||||
intent.putExtra(EXTRA_ACCOUNT, account.uuid)
|
||||
context.startActivity(intent)
|
||||
fun launch(activity: Activity, account: Account) {
|
||||
val intent = Intent(activity, ManageFoldersActivity::class.java).apply {
|
||||
putExtra(EXTRA_ACCOUNT, account.uuid)
|
||||
}
|
||||
activity.startActivity(intent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,152 @@
|
|||
package com.fsck.k9.ui.managefolders
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.Menu
|
||||
import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.widget.SearchView
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.fsck.k9.Account
|
||||
import com.fsck.k9.Preferences
|
||||
import com.fsck.k9.activity.setup.FolderSettings
|
||||
import com.fsck.k9.controller.MessagingController
|
||||
import com.fsck.k9.mailstore.DisplayFolder
|
||||
import com.fsck.k9.ui.R
|
||||
import com.fsck.k9.ui.folders.FolderIconProvider
|
||||
import com.fsck.k9.ui.folders.FolderNameFormatter
|
||||
import com.fsck.k9.ui.observeNotNull
|
||||
import com.mikepenz.fastadapter.FastAdapter
|
||||
import com.mikepenz.fastadapter.adapters.ItemAdapter
|
||||
import org.koin.android.ext.android.inject
|
||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||
import org.koin.core.parameter.parametersOf
|
||||
import java.util.Locale
|
||||
|
||||
class ManageFoldersFragment : Fragment() {
|
||||
private val viewModel: ManageFoldersViewModel by viewModel()
|
||||
private val folderNameFormatter: FolderNameFormatter by inject { parametersOf(requireActivity()) }
|
||||
private val messagingController: MessagingController by inject()
|
||||
private val preferences: Preferences by inject()
|
||||
private val folderIconProvider by lazy { FolderIconProvider(requireActivity().theme) }
|
||||
|
||||
private lateinit var account: Account
|
||||
private lateinit var itemAdapter: ItemAdapter<FolderListItem>
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setHasOptionsMenu(true)
|
||||
|
||||
val arguments = arguments ?: error("Missing arguments")
|
||||
val accountUuid = arguments.getString(EXTRA_ACCOUNT) ?: error("Missing argument '$EXTRA_ACCOUNT'")
|
||||
account = preferences.getAccount(accountUuid) ?: error("Missing account: $accountUuid")
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
return inflater.inflate(R.layout.fragment_manage_folders, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
initializeFolderList()
|
||||
|
||||
viewModel.getFolders(account).observeNotNull(this) { folders ->
|
||||
updateFolderList(folders)
|
||||
}
|
||||
}
|
||||
|
||||
private fun initializeFolderList() {
|
||||
itemAdapter = ItemAdapter()
|
||||
itemAdapter.itemFilter.filterPredicate = ::folderListFilter
|
||||
|
||||
val folderListAdapter = FastAdapter.with(itemAdapter).apply {
|
||||
setHasStableIds(true)
|
||||
onClickListener = { _, _, item: FolderListItem, _ ->
|
||||
openFolderSettings(item.serverId)
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
val recyclerView = requireView().findViewById<RecyclerView>(R.id.folderList)
|
||||
recyclerView.adapter = folderListAdapter
|
||||
}
|
||||
|
||||
private fun updateFolderList(displayFolders: List<DisplayFolder>) {
|
||||
val folderListItems = displayFolders.map { displayFolder ->
|
||||
val databaseId = displayFolder.folder.id
|
||||
val folderIconResource = folderIconProvider.getFolderIcon(displayFolder.folder.type)
|
||||
val displayName = folderNameFormatter.displayName(displayFolder.folder)
|
||||
val serverId = displayFolder.folder.serverId
|
||||
|
||||
FolderListItem(databaseId, folderIconResource, displayName, serverId)
|
||||
}
|
||||
|
||||
itemAdapter.set(folderListItems)
|
||||
}
|
||||
|
||||
private fun openFolderSettings(folderServerId: String) {
|
||||
FolderSettings.actionSettings(requireActivity(), account, folderServerId)
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||
inflater.inflate(R.menu.folder_list_option, menu)
|
||||
configureFolderSearchView(menu)
|
||||
}
|
||||
|
||||
private fun configureFolderSearchView(menu: Menu) {
|
||||
val folderMenuItem = menu.findItem(R.id.filter_folders)
|
||||
val folderSearchView = folderMenuItem.actionView as SearchView
|
||||
folderSearchView.queryHint = getString(R.string.folder_list_filter_hint)
|
||||
folderSearchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
|
||||
override fun onQueryTextSubmit(query: String): Boolean {
|
||||
itemAdapter.filter(query)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onQueryTextChange(newText: String): Boolean {
|
||||
itemAdapter.filter(newText)
|
||||
return true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
R.id.list_folders -> refreshFolderList()
|
||||
R.id.display_1st_class -> setDisplayMode(Account.FolderMode.FIRST_CLASS)
|
||||
R.id.display_1st_and_2nd_class -> setDisplayMode(Account.FolderMode.FIRST_AND_SECOND_CLASS)
|
||||
R.id.display_not_second_class -> setDisplayMode(Account.FolderMode.NOT_SECOND_CLASS)
|
||||
R.id.display_all -> setDisplayMode(Account.FolderMode.ALL)
|
||||
else -> return super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private fun refreshFolderList() {
|
||||
messagingController.refreshFolderList(account)
|
||||
}
|
||||
|
||||
private fun setDisplayMode(newMode: Account.FolderMode) {
|
||||
account.folderDisplayMode = newMode
|
||||
preferences.saveAccount(account)
|
||||
|
||||
itemAdapter.filter(null)
|
||||
}
|
||||
|
||||
private fun folderListFilter(item: FolderListItem, constraint: CharSequence?): Boolean {
|
||||
if (constraint.isNullOrEmpty()) return true
|
||||
|
||||
val locale = Locale.getDefault()
|
||||
val displayName = item.displayName.toLowerCase(locale)
|
||||
return constraint.splitToSequence(" ")
|
||||
.map { it.toLowerCase(locale) }
|
||||
.any { it in displayName }
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val EXTRA_ACCOUNT = "account"
|
||||
}
|
||||
}
|
19
app/ui/src/main/res/layout/activity_manage_folders.xml
Normal file
19
app/ui/src/main/res/layout/activity_manage_folders.xml
Normal file
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<include layout="@layout/toolbar" />
|
||||
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/nav_host_fragment"
|
||||
android:name="androidx.navigation.fragment.NavHostFragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
app:defaultNavHost="true" />
|
||||
|
||||
</LinearLayout>
|
9
app/ui/src/main/res/layout/fragment_manage_folders.xml
Normal file
9
app/ui/src/main/res/layout/fragment_manage_folders.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/folderList"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
tools:listitem="@layout/folder_list_item" />
|
15
app/ui/src/main/res/navigation/navigation_manage_folders.xml
Normal file
15
app/ui/src/main/res/navigation/navigation_manage_folders.xml
Normal file
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/navigation_onboarding"
|
||||
app:startDestination="@id/manageFoldersScreen">
|
||||
|
||||
<fragment
|
||||
android:id="@+id/manageFoldersScreen"
|
||||
android:name="com.fsck.k9.ui.managefolders.ManageFoldersFragment"
|
||||
android:label="@string/folders_action"
|
||||
tools:layout="@layout/fragment_manage_folders">
|
||||
</fragment>
|
||||
|
||||
</navigation>
|
Loading…
Reference in a new issue