diff --git a/filepicker/src/main/java/dev/arkbuilders/components/filepicker/ArkFilePickerConfig.kt b/filepicker/src/main/java/dev/arkbuilders/components/filepicker/ArkFilePickerConfig.kt index ed01069..b0719e8 100644 --- a/filepicker/src/main/java/dev/arkbuilders/components/filepicker/ArkFilePickerConfig.kt +++ b/filepicker/src/main/java/dev/arkbuilders/components/filepicker/ArkFilePickerConfig.kt @@ -6,7 +6,7 @@ import androidx.annotation.StyleRes import dev.arkbuilders.components.filepicker.R import java.nio.file.Path -class ArkFilePickerConfig( +data class ArkFilePickerConfig( @StringRes val titleStringId: Int = R.string.ark_file_picker_pick_title, @StringRes diff --git a/filepicker/src/main/java/dev/arkbuilders/components/filepicker/ArkFilePickerFragment.kt b/filepicker/src/main/java/dev/arkbuilders/components/filepicker/ArkFilePickerFragment.kt index 27166dd..c6d1862 100644 --- a/filepicker/src/main/java/dev/arkbuilders/components/filepicker/ArkFilePickerFragment.kt +++ b/filepicker/src/main/java/dev/arkbuilders/components/filepicker/ArkFilePickerFragment.kt @@ -41,7 +41,6 @@ import com.mikepenz.fastadapter.binding.AbstractBindingItem import dev.arkbuilders.arklib.utils.DeviceStorageUtils import dev.arkbuilders.arklib.utils.INTERNAL_STORAGE import org.orbitmvi.orbit.viewmodel.observe -import dev.arkbuilders.components.filepicker.R import dev.arkbuilders.components.filepicker.databinding.ArkFilePickerDialogNewFolderBinding import dev.arkbuilders.components.filepicker.databinding.ArkFilePickerHostFragmentBinding import dev.arkbuilders.components.filepicker.databinding.ArkFilePickerItemFileBinding @@ -211,7 +210,7 @@ open class ArkFilePickerFragment : if (newFolder.mkdirs()) { if (isARKMode()) { - viewModel.pinFile(newFolder.toPath()) + viewModel.pinFolder(newFolder.toPath()) } //Reload current files tree currentFolder?.let { viewModel.onItemClick(it) } @@ -486,7 +485,7 @@ internal class FilesPage( val popupMenu = PopupMenu(fragment.activity, anchor, Gravity.END) popupMenu.menuInflater.inflate(R.menu.file_select_menu, popupMenu.menu) popupMenu.setOnMenuItemClickListener { - viewModel.pinFile(file) + viewModel.pinFolder(file) true } popupMenu.show() diff --git a/filepicker/src/main/java/dev/arkbuilders/components/filepicker/ArkFilePickerViewModel.kt b/filepicker/src/main/java/dev/arkbuilders/components/filepicker/ArkFilePickerViewModel.kt index cafe146..797582c 100644 --- a/filepicker/src/main/java/dev/arkbuilders/components/filepicker/ArkFilePickerViewModel.kt +++ b/filepicker/src/main/java/dev/arkbuilders/components/filepicker/ArkFilePickerViewModel.kt @@ -14,7 +14,7 @@ import org.orbitmvi.orbit.viewmodel.container import dev.arkbuilders.arklib.data.folders.FoldersRepo import dev.arkbuilders.arklib.utils.DeviceStorageUtils import dev.arkbuilders.arklib.utils.listChildren -import dev.arkbuilders.components.utils.hasNestedOrParentalRoot +import dev.arkbuilders.components.utils.hasNestedRoot import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import java.nio.file.Path @@ -182,7 +182,7 @@ internal class ArkFilePickerViewModel( return arkGlobal?.exists() == true } - fun pinFile(file: Path) = intent { + fun pinFolder(file: Path) = intent { if (!file.isDirectory()) { postSideEffect(FilePickerSideEffect.CannotPinFile) return@intent @@ -193,7 +193,7 @@ internal class ArkFilePickerViewModel( val root = roots.find { root -> file.startsWith(root) } val favorites = rootsWithFavorites[root]?.flatten() - val hasNestedRoot = file.hasNestedOrParentalRoot(roots) + val hasNestedRoot = file.hasNestedRoot(roots) if (hasNestedRoot) { postSideEffect(FilePickerSideEffect.NestedRootProhibited) @@ -203,7 +203,6 @@ internal class ArkFilePickerViewModel( val haveRoot = haveRoot() root?.let { - //Make sure file isn't inside a root folder if (root != file) { val foundAsFavorite = favorites?.any { file.endsWith(it) } ?: false diff --git a/filepicker/src/main/java/dev/arkbuilders/components/filepicker/ArkRootPickerFragment.kt b/filepicker/src/main/java/dev/arkbuilders/components/filepicker/ArkRootPickerFragment.kt new file mode 100644 index 0000000..1b71dba --- /dev/null +++ b/filepicker/src/main/java/dev/arkbuilders/components/filepicker/ArkRootPickerFragment.kt @@ -0,0 +1,93 @@ +package dev.arkbuilders.components.filepicker + +import androidx.core.os.bundleOf +import androidx.fragment.app.setFragmentResult +import androidx.lifecycle.lifecycleScope +import dev.arkbuilders.arklib.data.folders.FoldersRepo +import dev.arkbuilders.arklib.utils.INTERNAL_STORAGE +import dev.arkbuilders.components.utils.hasNestedRoot +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import java.nio.file.Path + +class ArkRootPickerFragment : ArkFilePickerFragment() { + private var rootNotFavorite = false + + override fun onFolderChanged(currentFolder: Path) { + lifecycleScope.launch { + val folders = FoldersRepo.instance.provideFolders() + val roots = folders.keys + + if (currentFolder == INTERNAL_STORAGE || currentFolder.hasNestedRoot(roots)) { + rootNotFavorite = true + binding.btnPick.text = getString(R.string.ark_file_picker_root) + binding.btnPick.isEnabled = false + return@launch + } + + val root = roots.find { root -> currentFolder.startsWith(root) } + val favorites = folders[root]?.flatten() + root?.let { + if (root == currentFolder) { + rootNotFavorite = true + binding.btnPick.text = getString(R.string.ark_file_picker_root) + binding.btnPick.isEnabled = false + } else { + val foundAsFavorite = favorites?.any { currentFolder.endsWith(it) } ?: false + rootNotFavorite = false + binding.btnPick.text = getString(R.string.ark_file_picker_favorite) + binding.btnPick.isEnabled = !foundAsFavorite + } + } ?: let { + rootNotFavorite = true + binding.btnPick.text = getString(R.string.ark_file_picker_root) + binding.btnPick.isEnabled = true + } + } + } + + override fun onPick(pickedPath: Path) { + lifecycleScope.launch(Dispatchers.IO) { + addRootOrFavorite(pickedPath) + setFragmentResult( + ROOT_PICKED_REQUEST_KEY, + bundleOf().apply { + putString(PICKED_PATH_BUNDLE_KEY, pickedPath.toString()) + putBoolean(ROOT_NOT_FAV_BUNDLE_KEY, rootNotFavorite) + } + ) + } + } + + private suspend fun addRootOrFavorite(pickedPath: Path) { + val folders = FoldersRepo.instance.provideFolders() + if (rootNotFavorite) { + FoldersRepo.instance.addRoot(pickedPath) + } else { + val root = folders.keys.find { pickedPath.startsWith(it) } + ?: throw IllegalStateException( + "Can't add favorite if it's root is not added" + ) + val favoriteRelativePath = root.relativize(pickedPath) + FoldersRepo.instance.addFavorite(root, favoriteRelativePath) + } + } + + companion object { + const val ROOT_PICKED_REQUEST_KEY = "rootPicked" + const val PICKED_PATH_BUNDLE_KEY = "pickedPath" + const val ROOT_NOT_FAV_BUNDLE_KEY = "rootNotFav" + + fun newInstance( + config: ArkFilePickerConfig = ArkFilePickerConfig() + ) = ArkRootPickerFragment().apply { + setConfig( + config.copy( + showRoots = false, + mode = ArkFilePickerMode.FOLDER, + pathPickedRequestKey = "notUsed" + ) + ) + } + } +} \ No newline at end of file diff --git a/filepicker/src/main/java/dev/arkbuilders/components/filepicker/FragmentManagerUtils.kt b/filepicker/src/main/java/dev/arkbuilders/components/filepicker/FragmentManagerUtils.kt index a198434..5e451e1 100644 --- a/filepicker/src/main/java/dev/arkbuilders/components/filepicker/FragmentManagerUtils.kt +++ b/filepicker/src/main/java/dev/arkbuilders/components/filepicker/FragmentManagerUtils.kt @@ -20,4 +20,21 @@ fun FragmentManager.onArkPathPicked( ) ) } +} + +fun FragmentManager.onArkRootOrFavPicked( + lifecycleOwner: LifecycleOwner, + listener: (path: Path, rootNotFavorite: Boolean) -> Unit +) { + setFragmentResultListener( + ArkRootPickerFragment.ROOT_PICKED_REQUEST_KEY, + lifecycleOwner + ) { _, bundle -> + listener( + Path( + bundle.getString(ArkRootPickerFragment.PICKED_PATH_BUNDLE_KEY)!! + ), + bundle.getBoolean(ArkRootPickerFragment.ROOT_NOT_FAV_BUNDLE_KEY) + ) + } } \ No newline at end of file diff --git a/filepicker/src/main/res/values/strings.xml b/filepicker/src/main/res/values/strings.xml index 20116db..3ba7705 100644 --- a/filepicker/src/main/res/values/strings.xml +++ b/filepicker/src/main/res/values/strings.xml @@ -18,6 +18,8 @@ Only folder can be pinned. There\'s already nested root(s) inside. Pin + Root + Favorite %d item %d items diff --git a/sample/src/main/java/dev/arkbuilders/sample/MainActivity.kt b/sample/src/main/java/dev/arkbuilders/sample/MainActivity.kt index db201bd..cef3940 100644 --- a/sample/src/main/java/dev/arkbuilders/sample/MainActivity.kt +++ b/sample/src/main/java/dev/arkbuilders/sample/MainActivity.kt @@ -16,6 +16,7 @@ import com.google.android.material.button.MaterialButton import dev.arkbuilders.components.filepicker.ArkFilePickerConfig import dev.arkbuilders.components.filepicker.ArkFilePickerFragment import dev.arkbuilders.components.filepicker.ArkFilePickerMode +import dev.arkbuilders.components.filepicker.ArkRootPickerFragment import dev.arkbuilders.components.filepicker.onArkPathPicked import dev.arkbuilders.sample.about.AboutActivity import dev.arkbuilders.sample.storage.StorageDemoFragment @@ -39,7 +40,7 @@ class MainActivity : AppCompatActivity() { findViewById(R.id.btn_root_picker).setOnClickListener { resolvePermissions() - RootFavPickerDialog + ArkRootPickerFragment .newInstance() .show(supportFragmentManager, null) } diff --git a/sample/src/main/java/dev/arkbuilders/sample/RootFavPickerDialog.kt b/sample/src/main/java/dev/arkbuilders/sample/RootFavPickerDialog.kt deleted file mode 100644 index bea52c3..0000000 --- a/sample/src/main/java/dev/arkbuilders/sample/RootFavPickerDialog.kt +++ /dev/null @@ -1,58 +0,0 @@ -package dev.arkbuilders.sample - -import android.widget.Toast -import androidx.lifecycle.lifecycleScope -import kotlinx.coroutines.launch -import dev.arkbuilders.arklib.data.folders.FoldersRepo -import dev.arkbuilders.components.filepicker.ArkFilePickerConfig -import dev.arkbuilders.components.filepicker.ArkFilePickerFragment -import java.nio.file.Path - -class RootFavPickerDialog : ArkFilePickerFragment() { - var rootNotFavorite = false - - override fun onFolderChanged(currentFolder: Path) { - lifecycleScope.launch { - val folders = FoldersRepo.instance.provideFolders() - val roots = folders.keys - val favorites = folders.values.flatten() - val root = roots.find { root -> currentFolder.startsWith(root) } - root?.let { - if (root == currentFolder) { - rootNotFavorite = true - binding.btnPick.text = "Root" - binding.btnPick.isEnabled = false - } else { - var foundAsFavorite = false - favorites.forEach { - if (currentFolder.endsWith(it)) { - foundAsFavorite = true - return@forEach - } - } - rootNotFavorite = false - binding.btnPick.text = "Favorite" - binding.btnPick.isEnabled = !foundAsFavorite - } - } ?: let { - rootNotFavorite = true - binding.btnPick.text = "Root" - binding.btnPick.isEnabled = true - } - } - } - - override fun onPick(pickedPath: Path) { - Toast.makeText( - requireContext(), - "rootNotFavorite [$rootNotFavorite]", - Toast.LENGTH_SHORT - ).show() - } - - companion object { - fun newInstance() = RootFavPickerDialog().apply { - setConfig(ArkFilePickerConfig()) - } - } -} \ No newline at end of file diff --git a/utils/src/main/java/dev/arkbuilders/components/utils/PathExt.kt b/utils/src/main/java/dev/arkbuilders/components/utils/PathExt.kt index df0d9a9..232433b 100644 --- a/utils/src/main/java/dev/arkbuilders/components/utils/PathExt.kt +++ b/utils/src/main/java/dev/arkbuilders/components/utils/PathExt.kt @@ -7,4 +7,6 @@ fun Path.hasNestedOrParentalRoot(roots: Iterable): Boolean { this.startsWith(path) || path.startsWith(this) } return hasNestedRoot -} \ No newline at end of file +} + +fun Path.hasNestedRoot(roots: Iterable) = roots.any { it.startsWith(this) } \ No newline at end of file