Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move RootPicker to filepicker module #114

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ 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
Expand Down Expand Up @@ -191,9 +192,8 @@ internal class ArkFilePickerViewModel(
val rootsWithFavorites = container.stateFlow.value.rootsWithFavs
val roots = rootsWithFavorites.keys
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)
Expand All @@ -203,10 +203,14 @@ 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
val favorites = rootsWithFavorites.map { (root, relativeFavorites) ->
relativeFavorites.map {
root.resolve(it)
}
}.flatten()
val foundAsFavorite = favorites.any { it == file }

if (!foundAsFavorite) {
addFavorite(file)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
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.components.utils.hasNestedRoot
import dev.arkbuilders.components.utils.isInternalStorage
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.isInternalStorage() || 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) }
root?.let {
if (root == currentFolder) {
rootNotFavorite = true
binding.btnPick.text = getString(R.string.ark_file_picker_root)
binding.btnPick.isEnabled = false
} else {
val favorites = folders.map { (root, relativeFavorites) ->
relativeFavorites.map {
root.resolve(it)
}
}.flatten()
val foundAsFavorite = favorites.any { it == currentFolder }
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"
)
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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)
)
}
}
2 changes: 2 additions & 0 deletions filepicker/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
<string name="ark_file_picker_pin_folder_only">Only folder can be pinned.</string>
<string name="ark_file_nested_root_inside">There\'s already nested root(s) inside.</string>
<string name="ark_file_picker_pin">Pin</string>
<string name="ark_file_picker_root">Root</string>
<string name="ark_file_picker_favorite">Favorite</string>
<plurals name="ark_file_picker_items">
<item quantity="one">%d item</item>
<item quantity="other">%d items</item>
Expand Down
3 changes: 2 additions & 1 deletion sample/src/main/java/dev/arkbuilders/sample/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -39,7 +40,7 @@ class MainActivity : AppCompatActivity() {

findViewById<MaterialButton>(R.id.btn_root_picker).setOnClickListener {
resolvePermissions()
RootFavPickerDialog
ArkRootPickerFragment
.newInstance()
.show(supportFragmentManager, null)
}
Expand Down
58 changes: 0 additions & 58 deletions sample/src/main/java/dev/arkbuilders/sample/RootFavPickerDialog.kt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
package dev.arkbuilders.components.utils

import java.nio.file.Path
import kotlin.io.path.Path

val INTERNAL_STORAGE = Path("/storage/emulated/0")

fun Path.hasNestedOrParentalRoot(roots: Iterable<Path>): Boolean {
val hasNestedRoot = roots.any { path ->
this.startsWith(path) || path.startsWith(this)
}
return hasNestedRoot
}
}

fun Path.hasNestedRoot(roots: Iterable<Path>) = roots.any { it.startsWith(this) }

fun Path.isInternalStorage() = this == INTERNAL_STORAGE