From 6721b8d3d310d35ae9a50b7bf4593432db435666 Mon Sep 17 00:00:00 2001 From: huangxin <30554614+saxihuangxing@users.noreply.github.com> Date: Tue, 11 Apr 2023 01:50:00 +0800 Subject: [PATCH] #332,#334: UI improve (#342) * Aggregated mode must be disabled when there are no roots #332 * Resource Grid UI enhancements #334 Co-authored-by: jack Co-authored-by: huangxin <1229953844@qq.com> --- .../mvp/presenter/MainPresenter.kt | 17 ++- .../mvp/presenter/ResourcesPresenter.kt | 16 ++- .../presenter/dialog/SortDialogPresenter.kt | 10 -- .../taran/arknavigator/mvp/view/MainView.kt | 2 + .../arknavigator/mvp/view/ResourcesView.kt | 3 +- .../arknavigator/ui/activity/MainActivity.kt | 6 + .../ui/fragments/FoldersFragment.kt | 4 + .../ui/fragments/ResourcesFragment.kt | 121 +++++++++++------- .../dialog/RootsScanDialogFragment.kt | 61 ++++++++- .../ui/fragments/dialog/SortDialogFragment.kt | 51 -------- app/src/main/res/drawable/order_ascending.xml | 10 ++ .../main/res/drawable/order_descending.xml | 10 ++ .../main/res/layout/action_bar_resources.xml | 10 +- app/src/main/res/layout/dialog_roots_scan.xml | 30 ++++- app/src/main/res/layout/dialog_sort.xml | 36 ------ app/src/main/res/layout/fragment_folders.xml | 10 ++ .../main/res/layout/fragment_resources.xml | 30 ++++- app/src/main/res/values/strings.xml | 1 + 18 files changed, 270 insertions(+), 158 deletions(-) create mode 100644 app/src/main/res/drawable/order_ascending.xml create mode 100644 app/src/main/res/drawable/order_descending.xml diff --git a/app/src/main/java/space/taran/arknavigator/mvp/presenter/MainPresenter.kt b/app/src/main/java/space/taran/arknavigator/mvp/presenter/MainPresenter.kt index ce0aad29..8f5366e7 100644 --- a/app/src/main/java/space/taran/arknavigator/mvp/presenter/MainPresenter.kt +++ b/app/src/main/java/space/taran/arknavigator/mvp/presenter/MainPresenter.kt @@ -1,7 +1,10 @@ package space.taran.arknavigator.mvp.presenter import android.util.Log +import kotlinx.coroutines.launch import moxy.MvpPresenter +import moxy.presenterScope +import space.taran.arkfilepicker.folders.FoldersRepo import space.taran.arkfilepicker.folders.RootAndFav import space.taran.arknavigator.mvp.view.MainView import space.taran.arknavigator.navigation.AppRouter @@ -13,6 +16,9 @@ class MainPresenter : MvpPresenter() { @Inject lateinit var router: AppRouter + @Inject + lateinit var folders: FoldersRepo + override fun onFirstViewAttach() { Log.d(MAIN, "first view attached in MainPresenter") super.onFirstViewAttach() @@ -34,7 +40,16 @@ class MainPresenter : MvpPresenter() { fun goToResourcesScreen() { Log.d(MAIN, "creating Resources screen") - router.newRootScreen(Screens.ResourcesScreen(RootAndFav(null, null))) + presenterScope.launch { + val folders = folders.provideFolders() + if (folders.size < 1) { + viewState.enterResourceFragmentFailed() + } else { + Log.d(MAIN, "switching to Resources screen") + router.newRootScreen(Screens.ResourcesScreen(RootAndFav(null, null))) + } + true + } } fun goToSettingsScreen() { diff --git a/app/src/main/java/space/taran/arknavigator/mvp/presenter/ResourcesPresenter.kt b/app/src/main/java/space/taran/arknavigator/mvp/presenter/ResourcesPresenter.kt index d6248bb1..2b52f4f9 100644 --- a/app/src/main/java/space/taran/arknavigator/mvp/presenter/ResourcesPresenter.kt +++ b/app/src/main/java/space/taran/arknavigator/mvp/presenter/ResourcesPresenter.kt @@ -106,8 +106,10 @@ class ResourcesPresenter( Log.d(RESOURCES_SCREEN, "first view attached in ResourcesPresenter") super.onFirstViewAttach() - viewState.init() presenterScope.launch { + val ascending = preferences.get(PreferenceKey.IsSortingAscending) + val sortByScores = preferences.get(PreferenceKey.SortByScores) + viewState.init(ascending, sortByScores) viewState.setProgressVisibility(true, "Indexing") val folders = foldersRepo.provideWithMissing() Log.d(RESOURCES_SCREEN, "folders retrieved: $folders") @@ -216,6 +218,18 @@ class ResourcesPresenter( migrateTags(resourcesToCopy, directoryToCopy) } + fun onAscendingChanged(isAscending: Boolean) = presenterScope.launch { + viewState.updateOrderBtn(isAscending) + preferences.set( + PreferenceKey.IsSortingAscending, + isAscending + ) + } + + fun onScoresSwitched(enabled: Boolean) = presenterScope.launch { + preferences.set(PreferenceKey.SortByScores, enabled) + } + fun onShuffleSwitchedOn() = presenterScope.launch(Dispatchers.Default) { gridPresenter.shuffleResources() } diff --git a/app/src/main/java/space/taran/arknavigator/mvp/presenter/dialog/SortDialogPresenter.kt b/app/src/main/java/space/taran/arknavigator/mvp/presenter/dialog/SortDialogPresenter.kt index 632c5da0..bdd90440 100644 --- a/app/src/main/java/space/taran/arknavigator/mvp/presenter/dialog/SortDialogPresenter.kt +++ b/app/src/main/java/space/taran/arknavigator/mvp/presenter/dialog/SortDialogPresenter.kt @@ -26,14 +26,4 @@ class SortDialogPresenter : MvpPresenter() { preferences.set(PreferenceKey.Sorting, sorting.ordinal) viewState.closeDialog() } - - fun onAscendingSelected(ascending: Boolean) = presenterScope.launch { - preferences.set(PreferenceKey.IsSortingAscending, ascending) - viewState.closeDialog() - } - - fun onScoresSwitched(enabled: Boolean) = presenterScope.launch { - preferences.set(PreferenceKey.SortByScores, enabled) - viewState.closeDialog() - } } diff --git a/app/src/main/java/space/taran/arknavigator/mvp/view/MainView.kt b/app/src/main/java/space/taran/arknavigator/mvp/view/MainView.kt index 070f9b41..a4be71b8 100644 --- a/app/src/main/java/space/taran/arknavigator/mvp/view/MainView.kt +++ b/app/src/main/java/space/taran/arknavigator/mvp/view/MainView.kt @@ -11,4 +11,6 @@ interface MainView : MvpView { @StateStrategyType(SkipStrategy::class) fun requestPerms() + + fun enterResourceFragmentFailed() } diff --git a/app/src/main/java/space/taran/arknavigator/mvp/view/ResourcesView.kt b/app/src/main/java/space/taran/arknavigator/mvp/view/ResourcesView.kt index 26841421..e7082cf1 100644 --- a/app/src/main/java/space/taran/arknavigator/mvp/view/ResourcesView.kt +++ b/app/src/main/java/space/taran/arknavigator/mvp/view/ResourcesView.kt @@ -7,12 +7,13 @@ import java.nio.file.Path @StateStrategyType(AddToEndSingleStrategy::class) interface ResourcesView : CommonMvpView { - fun init() + fun init(ascending: Boolean, sortByScoresEnabled: Boolean) fun updateAdapter() fun setProgressVisibility(isVisible: Boolean, withText: String = "") fun setToolbarTitle(title: String) fun setKindTagsEnabled(enabled: Boolean) fun updateMenu() + fun updateOrderBtn(isAscending: Boolean) fun setSelectingEnabled(enabled: Boolean) fun setSelectingCount(selected: Int, all: Int) fun setTagsFilterEnabled(enabled: Boolean) diff --git a/app/src/main/java/space/taran/arknavigator/ui/activity/MainActivity.kt b/app/src/main/java/space/taran/arknavigator/ui/activity/MainActivity.kt index dbf62200..a8dd3d4e 100644 --- a/app/src/main/java/space/taran/arknavigator/ui/activity/MainActivity.kt +++ b/app/src/main/java/space/taran/arknavigator/ui/activity/MainActivity.kt @@ -24,6 +24,7 @@ import space.taran.arknavigator.mvp.presenter.MainPresenter import space.taran.arknavigator.mvp.view.MainView import space.taran.arknavigator.navigation.AppNavigator import space.taran.arknavigator.ui.App +import space.taran.arknavigator.ui.fragments.utils.toast import space.taran.arknavigator.utils.LogTags.MAIN import space.taran.arknavigator.utils.LogTags.PERMISSIONS import javax.inject.Inject @@ -161,6 +162,11 @@ class MainActivity : MvpAppCompatActivity(), MainView { super.onRequestPermissionsResult(requestCode, permissions, granted) } + override fun enterResourceFragmentFailed() { + toast(R.string.toast_add_paths) + binding.bottomNavigation.selectedItemId = R.id.page_roots + } + fun setBottomNavigationVisibility(isVisible: Boolean) { binding.bottomNavigation.isVisible = isVisible } diff --git a/app/src/main/java/space/taran/arknavigator/ui/fragments/FoldersFragment.kt b/app/src/main/java/space/taran/arknavigator/ui/fragments/FoldersFragment.kt index 4f7d5aac..104d0edc 100644 --- a/app/src/main/java/space/taran/arknavigator/ui/fragments/FoldersFragment.kt +++ b/app/src/main/java/space/taran/arknavigator/ui/fragments/FoldersFragment.kt @@ -111,6 +111,9 @@ class FoldersFragment : MvpAppCompatFragment(), FoldersView { devices: List, rootsWithFavs: Map> ) { + if (rootsWithFavs.size < 1) { + binding.noFolderHint.setVisibility(View.VISIBLE) + } else binding.noFolderHint.setVisibility(View.INVISIBLE) foldersTree?.set(devices, rootsWithFavs) } @@ -208,6 +211,7 @@ class FoldersFragment : MvpAppCompatFragment(), FoldersView { fun newInstance() = FoldersFragment().apply { arguments = bundleOf() } + fun newInstance(rescan: Boolean) = FoldersFragment().apply { arguments = bundleOf().apply { putBoolean(RESCAN_ROOTS_BUNDLE_KEY, rescan) diff --git a/app/src/main/java/space/taran/arknavigator/ui/fragments/ResourcesFragment.kt b/app/src/main/java/space/taran/arknavigator/ui/fragments/ResourcesFragment.kt index 276ef47a..d262a4a4 100644 --- a/app/src/main/java/space/taran/arknavigator/ui/fragments/ResourcesFragment.kt +++ b/app/src/main/java/space/taran/arknavigator/ui/fragments/ResourcesFragment.kt @@ -90,7 +90,7 @@ class ResourcesFragment : MvpAppCompatFragment(), ResourcesView { private var tagsSelectorAdapter: TagsSelectorAdapter? = null private var isShuffled = false - + private var isAscending = true override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -109,53 +109,66 @@ class ResourcesFragment : MvpAppCompatFragment(), ResourcesView { App.instance.appComponent.inject(this) } - override fun init() = with(binding) { - Log.d(RESOURCES_SCREEN, "initializing ResourcesFragment") - - initResultListeners() - initMenuListeners() - stackedToasts = StackedToasts(binding.rvToasts, lifecycleScope) - - FullscreenHelper.setStatusBarVisibility(true, requireActivity().window) - (activity as MainActivity).setSelectedTab(R.id.page_tags) - (requireActivity() as MainActivity).setBottomNavigationVisibility(true) - - resourcesAdapter = ResourcesRVAdapter(presenter.gridPresenter) - rvResources.adapter = resourcesAdapter - rvResources.setItemViewCacheSize(0) - rvResources.layoutManager = GridLayoutManager(context, 3) - tagsSelectorAdapter = TagsSelectorAdapter( - this@ResourcesFragment, - binding, - presenter.tagsSelectorPresenter - ).also { - App.instance.appComponent.inject(it) - } - - layoutDragHandler.setOnTouchListener(::dragHandlerTouchListener) - etTagsFilter.doAfterTextChanged { - presenter.tagsSelectorPresenter.onFilterChanged(it.toString()) - } - switchKind.setOnCheckedChangeListener { _, checked -> - presenter.tagsSelectorPresenter.onKindTagsToggle(checked) - } - btnClear.setOnClickListener { - presenter.tagsSelectorPresenter.onClearClick() - } - btnTagsSorting.setOnClickListener { - TagsSortDialogFragment - .newInstance(selectorNotEdit = true) - .show(childFragmentManager, null) - } + override fun init(ascending: Boolean, sortByScoresEnabled: Boolean) = + with(binding) { + Log.d(RESOURCES_SCREEN, "initializing ResourcesFragment") + + initResultListeners() + initMenuListeners() + stackedToasts = StackedToasts(binding.rvToasts, lifecycleScope) + + FullscreenHelper.setStatusBarVisibility(true, requireActivity().window) + (activity as MainActivity).setSelectedTab(R.id.page_tags) + (requireActivity() as MainActivity).setBottomNavigationVisibility(true) + + resourcesAdapter = ResourcesRVAdapter(presenter.gridPresenter) + rvResources.adapter = resourcesAdapter + rvResources.setItemViewCacheSize(0) + rvResources.layoutManager = GridLayoutManager(context, 3) + tagsSelectorAdapter = TagsSelectorAdapter( + this@ResourcesFragment, + binding, + presenter.tagsSelectorPresenter + ).also { + App.instance.appComponent.inject(it) + } - this@ResourcesFragment - .requireActivity() - .onBackPressedDispatcher - .addCallback(this@ResourcesFragment) { - presenter.onBackClick() + layoutDragHandler.setOnTouchListener(::dragHandlerTouchListener) + etTagsFilter.doAfterTextChanged { + presenter.tagsSelectorPresenter.onFilterChanged(it.toString()) + } + switchKind.setOnCheckedChangeListener { _, checked -> + presenter.tagsSelectorPresenter.onKindTagsToggle(checked) + } + btnClear.setOnClickListener { + presenter.tagsSelectorPresenter.onClearClick() + } + btnTagsSorting.setOnClickListener { + TagsSortDialogFragment + .newInstance(selectorNotEdit = true) + .show(childFragmentManager, null) + } + this@ResourcesFragment.updateOrderBtn(ascending) + if (sortByScoresEnabled) { + swScores.isChecked = true + swScores.jumpDrawablesToCurrentState() + } + swScores.setOnCheckedChangeListener { _, isChecked -> + Log.d( + RESOURCES_SCREEN, + "sorting by scores ${if (isChecked) "enabled" else "disabled"}" + ) + presenter.onScoresSwitched(isChecked) } - return@with - } + + this@ResourcesFragment + .requireActivity() + .onBackPressedDispatcher + .addCallback(this@ResourcesFragment) { + presenter.onBackClick() + } + return@with + } override fun onResume() { Log.d(RESOURCES_SCREEN, "resuming in ResourcesFragment") @@ -200,6 +213,15 @@ class ResourcesFragment : MvpAppCompatFragment(), ResourcesView { return@with } + override fun updateOrderBtn(isAscending: Boolean) = with(binding) { + this@ResourcesFragment.isAscending = isAscending + val drawable = + if (isAscending) resources.getDrawable(R.drawable.order_ascending) + else resources.getDrawable(R.drawable.order_descending) + actionBar.btnOrder.setImageDrawable(drawable) + return@with + } + override fun setSelectingEnabled(enabled: Boolean) = with(binding.actionBar) { tvTitle.isVisible = !enabled tvSelectedOf.isVisible = enabled @@ -308,10 +330,15 @@ class ResourcesFragment : MvpAppCompatFragment(), ResourcesView { actionBar.btnFocusMode.setOnClickListener { presenter.tagsSelectorPresenter.onQueryModeChanged(QueryMode.FOCUS) } - + actionBar.btnOrder.apply { + setOnClickListener { + presenter.onAscendingChanged(!isAscending) + } + } actionBar.btnShuffle.apply { setOnClickListener { val dice = this.drawable + @ColorInt val diceColor = resources .getColor(R.color.blue, requireContext().theme) diff --git a/app/src/main/java/space/taran/arknavigator/ui/fragments/dialog/RootsScanDialogFragment.kt b/app/src/main/java/space/taran/arknavigator/ui/fragments/dialog/RootsScanDialogFragment.kt index fe834e68..ad863446 100644 --- a/app/src/main/java/space/taran/arknavigator/ui/fragments/dialog/RootsScanDialogFragment.kt +++ b/app/src/main/java/space/taran/arknavigator/ui/fragments/dialog/RootsScanDialogFragment.kt @@ -1,9 +1,14 @@ package space.taran.arknavigator.ui.fragments.dialog +import android.content.res.ColorStateList +import android.graphics.Color import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.CheckBox +import android.widget.LinearLayout +import androidx.core.content.ContextCompat import androidx.fragment.app.setFragmentResult import moxy.MvpBottomSheetDialogFragment import moxy.ktx.moxyPresenter @@ -13,12 +18,16 @@ import space.taran.arknavigator.mvp.presenter.dialog.RootsScanDialogPresenter import space.taran.arknavigator.mvp.view.dialog.RootsScanView import space.taran.arknavigator.ui.fragments.utils.toast import java.nio.file.Path +import java.nio.file.Paths +import kotlin.io.path.exists class RootsScanDialogFragment : MvpBottomSheetDialogFragment(), RootsScanView { private lateinit var binding: DialogRootsScanBinding private val presenter by moxyPresenter { RootsScanDialogPresenter() } + private val defaultRootsFolders = + listOf("DCIM/Camera", "Documents", "Pictures", "Downloads") override fun onCreateView( inflater: LayoutInflater, @@ -47,6 +56,33 @@ class RootsScanDialogFragment : MvpBottomSheetDialogFragment(), RootsScanView { btnScan.setOnClickListener { presenter.onScanBtnClick() } + initDefaultRootsInfo(defaultRootsFolders) + } + + private fun initDefaultRootsInfo(rootsList: List) { + rootsList.forEach { root -> + val view = CheckBox(context) + val params = LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.WRAP_CONTENT + ) + view.layoutParams = params + view.text = root + view.isChecked = true + val selectColor = + ContextCompat.getColor(requireContext(), R.color.colorPrimary) + val normalColor = ContextCompat.getColor(requireContext(), R.color.gray) + view.setTextColor(selectColor) + view.buttonTintList = ColorStateList.valueOf(Color.BLUE) + view.setOnCheckedChangeListener { buttonView, isChecked -> + if (isChecked) { + view.setTextColor(selectColor) + } else { + view.setTextColor(normalColor) + } + } + binding.layoutDefaultRoot.addView(view) + } } override fun startScan() = with(binding) { @@ -76,10 +112,33 @@ class RootsScanDialogFragment : MvpBottomSheetDialogFragment(), RootsScanView { override fun closeDialog() = dismiss() override fun notifyRootsFound(roots: List) { + val finalRoots: MutableList = mutableListOf() + val checkedFolders: MutableList = mutableListOf() + val count = binding.layoutDefaultRoot.childCount + for (i in 0 until count) { + val child = binding.layoutDefaultRoot.getChildAt(i) as CheckBox + if (child.isChecked) { + checkedFolders.add(defaultRootsFolders[i]) + } + } + roots.forEach { root -> + var foundDefaultFolder = false + checkedFolders.forEach { + val defaultRoot = Paths.get(root.toString() + '/' + it) + if (defaultRoot.exists()) { + finalRoots.add(defaultRoot) + foundDefaultFolder = true + } + } + if (!foundDefaultFolder) { + finalRoots.add(root) + } + } + val bundle = Bundle().apply { putStringArray( RESULT_KEY_ROOTS, - roots.map(Path::toString).toTypedArray() + finalRoots.map(Path::toString).toTypedArray() ) } setFragmentResult(REQUEST_KEY_ROOTS_FOUND, bundle) diff --git a/app/src/main/java/space/taran/arknavigator/ui/fragments/dialog/SortDialogFragment.kt b/app/src/main/java/space/taran/arknavigator/ui/fragments/dialog/SortDialogFragment.kt index 4888189c..0c95fb02 100644 --- a/app/src/main/java/space/taran/arknavigator/ui/fragments/dialog/SortDialogFragment.kt +++ b/app/src/main/java/space/taran/arknavigator/ui/fragments/dialog/SortDialogFragment.kt @@ -17,7 +17,6 @@ import space.taran.arknavigator.ui.App import space.taran.arknavigator.ui.fragments.utils.toast import space.taran.arknavigator.utils.LogTags.RESOURCES_SCREEN import space.taran.arknavigator.utils.Sorting -import space.taran.arknavigator.utils.extensions.changeEnabledStatus class SortDialogFragment : MvpAppCompatDialogFragment(), SortDialogView { @@ -53,22 +52,6 @@ class SortDialogFragment : MvpAppCompatDialogFragment(), SortDialogView { selectedSortingBtn.isChecked = true selectedSortingBtn.jumpDrawablesToCurrentState() - if (sorting == Sorting.DEFAULT) { - changeSortOrderEnabledStatus(this, false) - } else { - if (ascending) { - rbAscending.isChecked = true - rbAscending.jumpDrawablesToCurrentState() - } else { - rbDescending.isChecked = true - rbDescending.jumpDrawablesToCurrentState() - } - } - if (sortByScoresEnabled) { - swScores.isChecked = true - swScores.jumpDrawablesToCurrentState() - } - rgSorting.setOnCheckedChangeListener { _, checkedId -> val newSorting = sortingCategorySelected(checkedId) @@ -86,29 +69,6 @@ class SortDialogFragment : MvpAppCompatDialogFragment(), SortDialogView { presenter.onSortingSelected(newSorting) } - - rgSortingDirection.setOnCheckedChangeListener { _, checkedId -> - var newAscending = false - when (checkedId) { - R.id.rb_ascending -> newAscending = true - R.id.rb_descending -> newAscending = false - } - - Log.d( - RESOURCES_SCREEN, - "sorting direction changed, ascending = $newAscending" - ) - - presenter.onAscendingSelected(newAscending) - } - - swScores.setOnCheckedChangeListener { _, isChecked -> - Log.d( - RESOURCES_SCREEN, - "sorting by scores ${if (isChecked) "enabled" else "disabled"}" - ) - presenter.onScoresSwitched(isChecked) - } } override fun closeDialog() { @@ -126,17 +86,6 @@ class SortDialogFragment : MvpAppCompatDialogFragment(), SortDialogView { } } - private fun changeSortOrderEnabledStatus( - dialogBinding: DialogSortBinding, - isEnabledStatus: Boolean - ) { - val childCount = dialogBinding.rgSortingDirection.childCount - for (radioButton in 0 until childCount) { - dialogBinding.rgSortingDirection.getChildAt(radioButton) - .changeEnabledStatus(isEnabledStatus) - } - } - companion object { fun newInstance() = SortDialogFragment() } diff --git a/app/src/main/res/drawable/order_ascending.xml b/app/src/main/res/drawable/order_ascending.xml new file mode 100644 index 00000000..b331939d --- /dev/null +++ b/app/src/main/res/drawable/order_ascending.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/order_descending.xml b/app/src/main/res/drawable/order_descending.xml new file mode 100644 index 00000000..282ebbfa --- /dev/null +++ b/app/src/main/res/drawable/order_descending.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/layout/action_bar_resources.xml b/app/src/main/res/layout/action_bar_resources.xml index 67e17e01..0792f71a 100644 --- a/app/src/main/res/layout/action_bar_resources.xml +++ b/app/src/main/res/layout/action_bar_resources.xml @@ -54,9 +54,17 @@ android:textColor="@color/white" android:textSize="18sp" android:textStyle="bold" - app:layout_constraintEnd_toStartOf="@id/btn_shuffle" + app:layout_constraintEnd_toStartOf="@id/btn_order" app:layout_constraintStart_toStartOf="parent" tools:text="Title" /> + - + + + app:layout_constraintTop_toBottomOf="@id/layout_default_root" + app:layout_constraintEnd_toStartOf="@id/btn_scan" /> - - - - - - - - - - - - diff --git a/app/src/main/res/layout/fragment_folders.xml b/app/src/main/res/layout/fragment_folders.xml index c15a5e02..65bec36d 100644 --- a/app/src/main/res/layout/fragment_folders.xml +++ b/app/src/main/res/layout/fragment_folders.xml @@ -4,6 +4,16 @@ android:layout_width="match_parent" android:layout_height="match_parent"> + + + + + + - + app:layout_constraintHorizontal_bias="1.0" + app:layout_constraintStart_toStartOf="@id/sw_scores" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintVertical_bias="0.448" /> %1$d resources selected\n(%2$d hidden by focus mode) Indexing of huge folders can take minutes Failed to verify the following paths:\n %1$s + Add at least one folder to start using the app Scan completed Scan Skip