Skip to content

Commit

Permalink
* [feature] Pin folders from classical view into "Roots" tab: #49
Browse files Browse the repository at this point in the history
* [feature] Automatically pin folders (Make Root/Favorite) when creating new folder in ARK mode: #41 (comment)
  • Loading branch information
tuancoltech committed Jan 30, 2024
1 parent 45b9986 commit c009169
Show file tree
Hide file tree
Showing 6 changed files with 157 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ import android.graphics.drawable.ColorDrawable
import android.os.Build
import android.os.Bundle
import android.util.TypedValue
import android.view.Gravity
import android.view.KeyEvent
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import android.widget.PopupMenu
import android.widget.ScrollView
import android.widget.TextView
import android.widget.Toast
Expand Down Expand Up @@ -43,12 +45,15 @@ import dev.arkbuilders.components.databinding.ArkFilePickerDialogNewFolderBindin
import dev.arkbuilders.components.databinding.ArkFilePickerHostFragmentBinding
import dev.arkbuilders.components.databinding.ArkFilePickerItemFileBinding
import dev.arkbuilders.components.databinding.ArkFilePickerItemFilesRootsPageBinding
import dev.arkbuilders.components.filepicker.callback.OnFileItemLongClick
import dev.arkbuilders.components.filepicker.callback.PinFileCallback
import dev.arkbuilders.components.folderstree.FolderTreeView
import dev.arkbuilders.components.utils.args
import dev.arkbuilders.components.utils.dpToPx
import dev.arkbuilders.components.utils.formatSize
import dev.arkbuilders.components.utils.iconForExtension
import dev.arkbuilders.components.utils.setDragSensitivity
import dev.arkbuilders.components.utils.toast
import java.io.File
import java.lang.Exception
import java.nio.file.Path
Expand Down Expand Up @@ -87,6 +92,13 @@ open class ArkFilePickerFragment :
}

private val pagesAdapter = ItemAdapter<GenericItem>()
private var mCurrentRootsWithFavorites: Map<Path, List<Path>>? = null

private val mPinFileCallback = object : PinFileCallback {
override fun onPinFileClick(file: Path) {
pinFile(file)
}
}

open fun onFolderChanged(currentFolder: Path) {}
open fun onPick(pickedPath: Path) {}
Expand Down Expand Up @@ -162,6 +174,10 @@ open class ArkFilePickerFragment :
}
}

private fun isARKMode(): Boolean {
return binding.tabs.selectedTabPosition == 1
}

private fun showCreateFolderDialog() {
val builder = AlertDialog.Builder(activity, android.R.style.ThemeOverlay_Material_Dialog_Alert)
builder.setTitle(R.string.ark_file_picker_new_folder)
Expand All @@ -180,6 +196,9 @@ open class ArkFilePickerFragment :
}

if (newFolder.mkdirs()) {
if (isARKMode()) {
pinFile(newFolder.toPath())
}
//Reload current files tree
currentFolder?.let { viewModel.onItemClick(it) }
dialog.dismiss()
Expand All @@ -189,6 +208,8 @@ open class ArkFilePickerFragment :
}

private fun render(state: FilePickerState) = binding.apply {
mCurrentRootsWithFavorites = state.rootsWithFavs

displayPath(state)

val deviceText = if (state.currentDevice == INTERNAL_STORAGE)
Expand Down Expand Up @@ -325,7 +346,8 @@ open class ArkFilePickerFragment :
)
} else {
listOf(
FilesPage(this, viewModel, itemsPluralId!!),
FilesPage(this, viewModel, itemsPluralId!!,
pinFileCallback = mPinFileCallback),
RootsPage(this, viewModel)
)
}
Expand Down Expand Up @@ -363,6 +385,43 @@ open class ArkFilePickerFragment :
private const val DIALOG_WIDTH = 300f
private const val PATH_PART_PADDING = 4f
}

private fun pinFile(file: Path) {
val roots = mCurrentRootsWithFavorites?.keys
val root = roots?.find { root -> file.startsWith(root) }
val favorites = mCurrentRootsWithFavorites?.get(root)?.flatten()

root?.let {

//Make sure file isn't inside a root folder
if (root != file) {
var foundAsFavorite = false
favorites?.forEach {
if (file.endsWith(it)) {
foundAsFavorite = true
return@forEach
}
}

if (!foundAsFavorite) {
viewModel.addFavorite(file)
activity?.toast(R.string.ark_file_picker_pinned_as_favorite)
} else {
activity?.toast(R.string.ark_file_picker_already_a_favorite)
}
} else {
activity?.toast(R.string.ark_file_picker_already_be_a_root)
}
} ?: let {

if (mCurrentRootsWithFavorites?.keys?.contains(file) == true) {
activity?.toast(R.string.ark_file_picker_already_be_a_root)
} else {
viewModel.addRoot(file)
activity?.toast(R.string.ark_file_picker_pinned_as_root)
}
}
}
}

private fun pickerImageLoader(ctx: Context) = ImageLoader.Builder(ctx)
Expand All @@ -386,7 +445,8 @@ private fun pickerImageLoader(ctx: Context) = ImageLoader.Builder(ctx)
internal class FilesPage(
private val fragment: Fragment,
private val viewModel: ArkFilePickerViewModel,
private val itemsPluralId: Int
private val itemsPluralId: Int,
private val pinFileCallback: PinFileCallback? = null
) : AbstractBindingItem<ArkFilePickerItemFilesRootsPageBinding>() {
private val filesAdapter = ItemAdapter<FileItem>()
private var currentFiles = emptyList<Path>()
Expand All @@ -399,10 +459,13 @@ internal class FilesPage(
parent: ViewGroup?
) = ArkFilePickerItemFilesRootsPageBinding.inflate(inflater, parent, false)

private var mBinding: ArkFilePickerItemFilesRootsPageBinding? = null

override fun bindView(
binding: ArkFilePickerItemFilesRootsPageBinding,
payloads: List<Any>
) = with(binding) {
mBinding = binding
rvFiles.adapter = FastAdapter.with(filesAdapter)
viewModel.observe(fragment, state = ::render)
}
Expand All @@ -411,7 +474,29 @@ internal class FilesPage(
if (currentFiles == state.files) return

filesAdapter.setNewList(state.files.map {
FileItem(it, viewModel, itemsPluralId, imageLoader)
FileItem(it, viewModel, itemsPluralId, imageLoader,
onLongClick = object : OnFileItemLongClick {
override fun onLongClick(file: Path) {
val currentItem = filesAdapter.itemList.items.firstOrNull { item ->
item.getFile().toString() == file.toString()
}
currentItem?.let {
val anchorView = mBinding?.rvFiles?.findViewHolderForAdapterPosition(
filesAdapter.getAdapterPosition(currentItem))?.itemView
anchorView?.let { anchor ->
val popupMenu = PopupMenu(fragment.activity, anchor, Gravity.END)
popupMenu.menuInflater.inflate(R.menu.file_select_menu, popupMenu.menu)
popupMenu.setOnMenuItemClickListener {
pinFileCallback?.onPinFileClick(file)
true
}
popupMenu.show()
}


} ?: let { return@let }
}
})
})

currentFiles = state.files
Expand All @@ -423,6 +508,7 @@ internal class FileItem(
private val viewModel: ArkFilePickerViewModel,
private val itemsPluralId: Int,
private val imageLoader: ImageLoader,
private val onLongClick: OnFileItemLongClick? = null
) : AbstractBindingItem<ArkFilePickerItemFileBinding>() {
override val type = 0

Expand All @@ -438,6 +524,11 @@ internal class FileItem(
root.setOnClickListener {
viewModel.onItemClick(file)
}

root.setOnLongClickListener {
onLongClick?.onLongClick(file)
true
}
binding.tvName.text = file.name
if (file.isDirectory()) bindFolder(file, this)
else bindRegularFile(file, this)
Expand Down Expand Up @@ -474,6 +565,10 @@ internal class FileItem(
binding.iv.dispose()
binding.iv.setImageResource(R.drawable.ark_file_picker_ic_folder)
}

fun getFile(): Path {
return file
}
}

internal class RootsPage(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,39 @@ internal class ArkFilePickerViewModel(

init {
viewModelScope.launch {
val rootsWithFavs = foldersRepo.provideFolders()
intent {
reduce {
state.copy(rootsWithFavs = rootsWithFavs)
}
refreshRootsWithFavs()
}
}

fun addRoot(root:Path) {
viewModelScope.launch {
foldersRepo.addRoot(root)
refreshRootsWithFavs()
}
}

fun addFavorite(favorite: Path) {
viewModelScope.launch {
val favoritePath = favorite.toRealPath()
val folders = foldersRepo.provideFolders()
val root = folders.keys.find { favoritePath.startsWith(it) }
?: throw IllegalStateException(
"Can't add favorite if it's root is not added"
)
val favoriteRelativePath = root.relativize(favoritePath)
if (folders[root]?.contains(favoriteRelativePath) == true) {
throw AssertionError("Path must be checked in RootPicker")
}
foldersRepo.addFavorite(root, favoriteRelativePath)
refreshRootsWithFavs()
}
}

private suspend fun refreshRootsWithFavs() {
val rootsWithFavs = foldersRepo.provideFolders()
intent {
reduce {
state.copy(rootsWithFavs = rootsWithFavs)
}
}
}
Expand All @@ -77,7 +105,9 @@ internal class ArkFilePickerViewModel(
onPathPicked(path)
}

fun onPickBtnClick() = intent { onPathPicked(state.currentPath) }
fun onPickBtnClick() = intent {
onPathPicked(state.currentPath)
}

fun onDeviceSelected(selectedDevicePos: Int) = intent {
val selectedDevice = state.devices[selectedDevicePos]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package dev.arkbuilders.components.filepicker.callback

import java.nio.file.Path

interface OnFileItemLongClick {
fun onLongClick(file: Path)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package dev.arkbuilders.components.filepicker.callback

import java.nio.file.Path

interface PinFileCallback {
fun onPinFileClick(file: Path)
}
4 changes: 4 additions & 0 deletions components/src/main/res/menu/file_select_menu.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/menu_pin" android:title="@string/ark_file_picker_pin"/>
</menu>
5 changes: 5 additions & 0 deletions components/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@
<string name="ark_file_picker_new_folder">New folder</string>
<string name="ark_file_picker_folder_existing">Folder already exists!</string>
<string name="ark_file_picker_new_folder_hint">Name your folder</string>
<string name="ark_file_picker_pinned_as_favorite">Pinned as a Favorite folder!</string>
<string name="ark_file_picker_pinned_as_root">Pinned as a Root folder!</string>
<string name="ark_file_picker_already_a_favorite">Already be a Favorite folder!</string>
<string name="ark_file_picker_already_be_a_root">Already be a Root folder!</string>
<string name="ark_file_picker_pin">Pin</string>
<plurals name="ark_file_picker_items">
<item quantity="one">%d item</item>
<item quantity="other">%d items</item>
Expand Down

0 comments on commit c009169

Please sign in to comment.