mirror of
https://github.com/nextcloud/talk-android
synced 2025-07-29 07:35:11 +01:00
RemoteFileBrowser: move selected paths from activity to viewmodel
Signed-off-by: Álvaro Brey <alvaro.brey@nextcloud.com>
This commit is contained in:
parent
ffdadc6c01
commit
eba697b8f2
@ -40,15 +40,11 @@ import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||
import com.nextcloud.talk.databinding.ActivityRemoteFileBrowserBinding
|
||||
import com.nextcloud.talk.interfaces.SelectionInterface
|
||||
import com.nextcloud.talk.remotefilebrowser.adapters.RemoteFileBrowserItemsAdapter
|
||||
import com.nextcloud.talk.remotefilebrowser.model.RemoteFileBrowserItem
|
||||
import com.nextcloud.talk.remotefilebrowser.viewmodels.RemoteFileBrowserItemsViewModel
|
||||
import com.nextcloud.talk.ui.dialog.SortingOrderDialogFragment
|
||||
import com.nextcloud.talk.utils.DisplayUtils
|
||||
import com.nextcloud.talk.utils.FileSortOrder
|
||||
import com.nextcloud.talk.utils.database.user.UserUtils
|
||||
import java.io.File
|
||||
import java.util.Collections
|
||||
import java.util.TreeSet
|
||||
import javax.inject.Inject
|
||||
|
||||
@AutoInjector(NextcloudTalkApplication::class)
|
||||
@ -66,8 +62,6 @@ class RemoteFileBrowserActivity : AppCompatActivity(), SelectionInterface, Swipe
|
||||
|
||||
private var filesSelectionDoneMenuItem: MenuItem? = null
|
||||
|
||||
private val selectedPaths: MutableSet<String> = Collections.synchronizedSet(TreeSet())
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
|
||||
@ -132,13 +126,10 @@ class RemoteFileBrowserActivity : AppCompatActivity(), SelectionInterface, Swipe
|
||||
showGrid = showGrid,
|
||||
mimeTypeSelectionFilter = mimeTypeSelectionFilter,
|
||||
userEntity = userUtils.currentUser!!,
|
||||
selectionInterface = this
|
||||
) { remoteFileBrowserItem ->
|
||||
onItemClicked(remoteFileBrowserItem)
|
||||
}
|
||||
.apply {
|
||||
items = remoteFileBrowserItems
|
||||
}
|
||||
selectionInterface = this,
|
||||
onItemClicked = viewModel::onItemClicked
|
||||
)
|
||||
adapter.items = remoteFileBrowserItems
|
||||
|
||||
binding.recyclerView.adapter = adapter
|
||||
binding.recyclerView.layoutManager = layoutManager
|
||||
@ -146,6 +137,9 @@ class RemoteFileBrowserActivity : AppCompatActivity(), SelectionInterface, Swipe
|
||||
|
||||
showList()
|
||||
}
|
||||
is RemoteFileBrowserItemsViewModel.FinishState -> {
|
||||
finishWithResult(state.selectedPaths)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -160,24 +154,20 @@ class RemoteFileBrowserActivity : AppCompatActivity(), SelectionInterface, Swipe
|
||||
supportActionBar?.title = path
|
||||
}
|
||||
}
|
||||
|
||||
viewModel.selectedPaths.observe(this) { selectedPaths ->
|
||||
filesSelectionDoneMenuItem?.isVisible = !selectedPaths.isNullOrEmpty()
|
||||
binding.recyclerView.adapter?.notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
|
||||
super.onCreateOptionsMenu(menu)
|
||||
menuInflater.inflate(R.menu.menu_share_files, menu)
|
||||
filesSelectionDoneMenuItem = menu?.findItem(R.id.files_selection_done)
|
||||
filesSelectionDoneMenuItem?.isVisible = selectedPaths.size > 0
|
||||
return true
|
||||
}
|
||||
|
||||
private fun onItemClicked(remoteFileBrowserItem: RemoteFileBrowserItem) {
|
||||
if ("inode/directory" == remoteFileBrowserItem.mimeType) {
|
||||
viewModel.changePath(remoteFileBrowserItem.path!!)
|
||||
} else {
|
||||
toggleBrowserItemSelection(remoteFileBrowserItem.path!!)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
refreshCurrentPath()
|
||||
@ -199,7 +189,7 @@ class RemoteFileBrowserActivity : AppCompatActivity(), SelectionInterface, Swipe
|
||||
true
|
||||
}
|
||||
R.id.files_selection_done -> {
|
||||
onFileSelectionDone()
|
||||
viewModel.onSelectionDone()
|
||||
true
|
||||
}
|
||||
else -> {
|
||||
@ -208,7 +198,7 @@ class RemoteFileBrowserActivity : AppCompatActivity(), SelectionInterface, Swipe
|
||||
}
|
||||
}
|
||||
|
||||
private fun onFileSelectionDone() {
|
||||
private fun finishWithResult(selectedPaths: Set<String>) {
|
||||
val data = Intent()
|
||||
data.putStringArrayListExtra(EXTRA_SELECTED_PATHS, ArrayList(selectedPaths))
|
||||
setResult(Activity.RESULT_OK, data)
|
||||
@ -243,35 +233,6 @@ class RemoteFileBrowserActivity : AppCompatActivity(), SelectionInterface, Swipe
|
||||
viewModel.loadItems()
|
||||
}
|
||||
|
||||
private fun shouldPathBeSelectedDueToParent(currentPath: String): Boolean {
|
||||
var file = File(currentPath)
|
||||
if (selectedPaths.size > 0 && file.parent != "/") {
|
||||
while (file.parent != null) {
|
||||
var parent = file.parent!!
|
||||
if (File(file.parent!!).parent != null) {
|
||||
parent += "/"
|
||||
}
|
||||
if (selectedPaths.contains(parent)) {
|
||||
return true
|
||||
}
|
||||
file = File(file.parent!!)
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun checkAndRemoveAnySelectedParents(currentPath: String) {
|
||||
var file = File(currentPath)
|
||||
selectedPaths.remove(currentPath)
|
||||
while (file.parent != null) {
|
||||
selectedPaths.remove(file.parent!! + "/")
|
||||
file = File(file.parent!!)
|
||||
}
|
||||
runOnUiThread {
|
||||
binding.recyclerView.adapter!!.notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val TAG = RemoteFileBrowserActivity::class.simpleName
|
||||
const val SPAN_COUNT: Int = 4
|
||||
@ -280,20 +241,15 @@ class RemoteFileBrowserActivity : AppCompatActivity(), SelectionInterface, Swipe
|
||||
}
|
||||
|
||||
override fun toggleBrowserItemSelection(path: String) {
|
||||
if (selectedPaths.contains(path) || shouldPathBeSelectedDueToParent(path)) {
|
||||
checkAndRemoveAnySelectedParents(path)
|
||||
} else {
|
||||
// TODO if it's a folder, remove all the children we added manually
|
||||
selectedPaths.add(path)
|
||||
}
|
||||
filesSelectionDoneMenuItem?.isVisible = selectedPaths.size > 0
|
||||
// unused, viewmodel gets called directly
|
||||
}
|
||||
|
||||
override fun isPathSelected(path: String): Boolean {
|
||||
return selectedPaths.contains(path) || shouldPathBeSelectedDueToParent(path)
|
||||
// TODO figure out a better way to do this. Narrower interface?
|
||||
return viewModel.isPathSelected(path)
|
||||
}
|
||||
|
||||
override fun shouldOnlySelectOneImageFile(): Boolean {
|
||||
return true
|
||||
return true // unused
|
||||
}
|
||||
}
|
||||
|
@ -36,6 +36,19 @@ import net.orange_box.storebox.listeners.OnPreferenceValueChangedListener
|
||||
import java.io.File
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* @startuml
|
||||
* hide empty description
|
||||
* [*] --> InitialState
|
||||
* InitialState --> LoadingItemsState
|
||||
* LoadingItemsState --> NoRemoteFileItemsState
|
||||
* NoRemoteFileItemsState --> LoadingItemsState
|
||||
* LoadingItemsState --> LoadedState
|
||||
* LoadedState --> LoadingItemsState
|
||||
* LoadedState --> FinishState
|
||||
* FinishState --> [*]
|
||||
* @enduml
|
||||
*/
|
||||
class RemoteFileBrowserItemsViewModel @Inject constructor(
|
||||
private val repository: RemoteFileBrowserItemsRepository,
|
||||
private val appPreferences: AppPreferences
|
||||
@ -47,6 +60,7 @@ class RemoteFileBrowserItemsViewModel @Inject constructor(
|
||||
object NoRemoteFileItemsState : ViewState
|
||||
object LoadingItemsState : ViewState
|
||||
class LoadedState(val items: List<RemoteFileBrowserItem>) : ViewState
|
||||
class FinishState(val selectedPaths: Set<String>) : ViewState
|
||||
|
||||
private val initialSortOrder = FileSortOrderNew.getFileSortOrder(appPreferences.sorting)
|
||||
private val sortingPrefListener: SortChangeListener = SortChangeListener()
|
||||
@ -64,6 +78,10 @@ class RemoteFileBrowserItemsViewModel @Inject constructor(
|
||||
val currentPath: LiveData<String>
|
||||
get() = _currentPath
|
||||
|
||||
private val _selectedPaths: MutableLiveData<Set<String>> = MutableLiveData(emptySet())
|
||||
val selectedPaths: LiveData<Set<String>>
|
||||
get() = _selectedPaths
|
||||
|
||||
init {
|
||||
appPreferences.registerSortingChangeListener(sortingPrefListener)
|
||||
}
|
||||
@ -144,6 +162,65 @@ class RemoteFileBrowserItemsViewModel @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fun onSelectionDone() {
|
||||
val selection = selectedPaths.value
|
||||
if (!selection.isNullOrEmpty()) {
|
||||
_viewState.value = FinishState(selection)
|
||||
}
|
||||
}
|
||||
|
||||
fun onItemClicked(remoteFileBrowserItem: RemoteFileBrowserItem) {
|
||||
if (remoteFileBrowserItem.mimeType == MIME_DIRECTORY) {
|
||||
changePath(remoteFileBrowserItem.path!!)
|
||||
} else {
|
||||
toggleBrowserItemSelection(remoteFileBrowserItem.path!!)
|
||||
}
|
||||
}
|
||||
|
||||
private fun toggleBrowserItemSelection(path: String) {
|
||||
val paths = selectedPaths.value!!.toMutableSet()
|
||||
if (paths.contains(path) || shouldPathBeSelectedDueToParent(path)) {
|
||||
checkAndRemoveAnySelectedParents(path)
|
||||
} else {
|
||||
// TODO if it's a folder, remove all the children we added manually
|
||||
paths.add(path)
|
||||
_selectedPaths.value = paths
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkAndRemoveAnySelectedParents(currentPath: String) {
|
||||
var file = File(currentPath)
|
||||
val paths = selectedPaths.value!!.toMutableSet()
|
||||
paths.remove(currentPath)
|
||||
while (file.parent != null) {
|
||||
paths.remove(file.parent!! + File.pathSeparator)
|
||||
file = File(file.parent!!)
|
||||
}
|
||||
_selectedPaths.value = paths
|
||||
}
|
||||
|
||||
private fun shouldPathBeSelectedDueToParent(currentPath: String): Boolean {
|
||||
var file = File(currentPath)
|
||||
val paths = selectedPaths.value!!
|
||||
if (paths.isNotEmpty() && file.parent != ROOT_PATH) {
|
||||
while (file.parent != null) {
|
||||
var parent = file.parent!!
|
||||
if (File(file.parent!!).parent != null) {
|
||||
parent += File.pathSeparator
|
||||
}
|
||||
if (paths.contains(parent)) {
|
||||
return true
|
||||
}
|
||||
file = File(file.parent!!)
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun isPathSelected(path: String): Boolean {
|
||||
return selectedPaths.value?.contains(path) == true || shouldPathBeSelectedDueToParent(path)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val TAG = RemoteFileBrowserItemsViewModel::class.simpleName
|
||||
private const val ROOT_PATH = "/"
|
||||
|
Loading…
Reference in New Issue
Block a user