Skip to content

Commit

Permalink
Merge pull request #52 from emreesen27/develop
Browse files Browse the repository at this point in the history
v1.0.0-beta6 is completed
  • Loading branch information
emreesen27 committed Apr 24, 2024
2 parents 55081ca + 2c148eb commit 9a82e95
Show file tree
Hide file tree
Showing 38 changed files with 673 additions and 319 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## v1.0.0-beta6 (24.04.2024)
* The "Rename" feature added.
* Dialogs UI improvement
* The issue of license URLs redirecting to the wrong address fixed
* The 'Access Denied' error in the function calculating file count and size fixed.

## v1.0.0-beta5 (08.04.2024)

* The 'Select All' feature added
Expand Down
4 changes: 2 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ android {
applicationId "com.sn.snfilemanager"
minSdk 26
targetSdk 34
versionCode 5
versionName "1.0.0-beta5"
versionCode 6
versionName "1.0.0-beta6"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
Expand Down
59 changes: 59 additions & 0 deletions app/src/main/java/com/sn/snfilemanager/core/base/BaseDialog.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package com.sn.snfilemanager.core.base

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.FragmentManager
import androidx.viewbinding.ViewBinding
import com.sn.snfilemanager.R

abstract class BaseDialog<VBinding : ViewBinding> : DialogFragment() {
protected lateinit var binding: VBinding

protected abstract fun getViewBinding(): VBinding

open var setCancelable: Boolean = true

protected abstract val dialogTag: String

open fun setupViews() {}

fun showDialog(fragmentManager: FragmentManager) {
show(fragmentManager, dialogTag)
}

override fun onStart() {
super.onStart()
dialog?.window?.setLayout(
ConstraintLayout.LayoutParams.MATCH_PARENT,
ConstraintLayout.LayoutParams.WRAP_CONTENT,
)
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = getViewBinding()
isCancelable = setCancelable
setStyle(STYLE_NO_TITLE, R.style.DialogTheme_transparent)
dialog?.window?.setBackgroundDrawableResource(R.drawable.dialog_rounded)
}

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?,
): View? {
return binding.root
}

override fun onViewCreated(
view: View,
savedInstanceState: Bundle?,
) {
super.onViewCreated(view, savedInstanceState)
setupViews()
}
}
23 changes: 23 additions & 0 deletions app/src/main/java/com/sn/snfilemanager/core/util/FileUtils.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.sn.snfilemanager.core.util

import com.sn.snfilemanager.feature.files.data.FileModel
import com.sn.snfilemanager.feature.files.data.toFileModel
import java.nio.file.Files
import java.nio.file.Paths
import java.util.stream.Collectors

object FileUtils {
fun getTotalSizeAndFileCount(itemList: List<FileModel>): Pair<Long, Long> =
itemList.fold(Pair(0L, 0L)) { acc, item ->
if (item.isDirectory && Files.isReadable(Paths.get(item.absolutePath))) {
val childResult =
getTotalSizeAndFileCount(
Files.list(Paths.get(item.absolutePath)).collect(Collectors.toList())
.map { it.toFileModel() },
)
Pair(acc.first + childResult.first, acc.second + childResult.second)
} else {
Pair(acc.first + item.size, acc.second + 1)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,6 @@ class AboutFragment : BaseFragment<FragmentAboutBinding, AboutViewModel>() {
}

private fun showLicensesDialog() {
LicenseDialog().show(childFragmentManager, LicenseDialog.TAG)
LicenseDialog().showDialog(childFragmentManager)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ class FileItemAdapter(
notifyItemInserted(fileItems.size)
}

fun updateItem(item: FileModel) {
val index = fileItems.indexOfFirst { it.id == item.id }
fileItems[index] = item
notifyItemChanged(index)
}

fun removeItems(filesToRemove: List<FileModel>) {
for (fileToRemove in filesToRemove) {
val position = fileItems.indexOf(fileToRemove)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import com.sn.snfilemanager.view.component.breadcrumb.BreadItem
import com.sn.snfilemanager.view.dialog.ConfirmationDialog
import com.sn.snfilemanager.view.dialog.ConflictDialog
import com.sn.snfilemanager.view.dialog.CreateDirectoryDialog
import com.sn.snfilemanager.view.dialog.RenameFileDialog
import com.sn.snfilemanager.view.dialog.detail.DetailDialog
import dagger.hilt.android.AndroidEntryPoint
import java.io.File
Expand Down Expand Up @@ -133,6 +134,10 @@ class FilesListFragment :
R.id.action_select_all -> {
adapter?.selectAll()
}

R.id.action_rename -> {
showRenameDialog()
}
}

return true
Expand Down Expand Up @@ -177,15 +182,21 @@ class FilesListFragment :
JobType.DELETE -> {
activity?.runOnUiThread {
data?.filterIsInstance<FileModel>()?.let { adapter?.removeItems(it) }
adapter?.getItems()?.let { viewModel.setUpdateList(it) }
}
}

JobType.CREATE -> {
activity?.runOnUiThread {
data?.filterIsInstance<Path>()?.firstOrNull()?.toFileModel()?.let { file ->
adapter?.addItem(file)
adapter?.getItems()?.let { viewModel.setUpdateList(it) }
}
}
}

JobType.RENAME -> {
activity?.runOnUiThread {
data?.filterIsInstance<FileModel>()?.firstOrNull()?.let { file ->
adapter?.updateItem(file)
}
}
}
Expand All @@ -196,12 +207,12 @@ class FilesListFragment :
override fun observeData() {
observe(viewModel.conflictQuestionLiveData) { event ->
event.getContentIfNotHandled()?.let { fileName ->
ConflictDialog(requireContext(), fileName).apply {
ConflictDialog(fileName).apply {
onSelected = { strategy: ConflictStrategy, isAll: Boolean ->
viewModel.conflictDialogDeferred.complete(Pair(strategy, isAll))
}
onDismiss = { actionMode?.finish() }
}.show()
}.showDialog(childFragmentManager)
}
}
observe(viewModel.startMoveJobLiveData) { event ->
Expand All @@ -220,7 +231,7 @@ class FilesListFragment :
}
observe(viewModel.startCreateFolderJob) { event ->
event.getContentIfNotHandled()?.let { path ->
startCreateDirectory(path)
startCreateDirectoryService(path)
}
}
observe(viewModel.updateListLiveData) { event ->
Expand All @@ -242,6 +253,12 @@ class FilesListFragment :
}
}
}
observe(viewModel.startRenameFileJob) { event ->
event.getContentIfNotHandled()?.let { data ->
actionMode?.finish()
startRenameService(data.first, data.second)
}
}
}

private fun initFirstList() {
Expand Down Expand Up @@ -303,6 +320,7 @@ class FilesListFragment :
actionMode?.menu?.findItem(R.id.action_open_with)?.isVisible =
viewModel.isSingleItemSelected()
}
actionMode?.menu?.findItem(R.id.action_rename)?.isVisible = viewModel.isSingleItemSelected()
}

private fun initAdapter() {
Expand Down Expand Up @@ -352,23 +370,26 @@ class FilesListFragment :
} else {
viewModel.moveFilesAndDirectories(Paths.get(path))
}
}).show(
childFragmentManager,
DetailDialog.TAG,
)
}).showDialog(childFragmentManager)
}

private fun showCreateDirectoryDialog(path: String) {
CreateDirectoryDialog(path = path, onCreate = { folderName ->
viewModel.createFolder(folderName)
}).show(childFragmentManager, CreateDirectoryDialog.TAG)
}).showDialog(childFragmentManager)
}

private fun showRenameDialog() {
RenameFileDialog(file = viewModel.getSelectedItem().first(), onRename = { newName ->
viewModel.renameFile(newName)
}).showDialog(childFragmentManager)
}

private fun actionDetail() {
DetailDialog(requireContext(), viewModel.getSelectedItem()).show(
childFragmentManager,
DetailDialog.TAG,
)
DetailDialog(
requireContext(),
viewModel.getSelectedItem(),
).showDialog(childFragmentManager)
}

private fun actionOpenWith() {
Expand All @@ -388,7 +409,6 @@ class FilesListFragment :

private fun actionDelete() {
ConfirmationDialog(
requireContext(),
getString(R.string.are_you_sure),
getString(R.string.delete_warning),
).apply {
Expand All @@ -399,7 +419,7 @@ class FilesListFragment :
actionMode?.finish()
}
}
}.show()
}.showDialog(childFragmentManager)
}

private fun startCopyService(
Expand All @@ -423,14 +443,26 @@ class FilesListFragment :
)
}

private fun startCreateDirectory(destinationPath: Path) {
private fun startCreateDirectoryService(destinationPath: Path) {
JobService.createDirectory(
destinationPath,
this@FilesListFragment,
requireContext(),
)
}

private fun startRenameService(
file: FileModel,
newName: String,
) {
JobService.rename(
file,
newName,
this@FilesListFragment,
requireContext(),
)
}

private fun initSearch() {
binding.toolbar.menu?.findItem(R.id.action_search)?.let { item ->
val searchView = item.actionView as? SearchView
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ class FilesListViewModel
private val _startCreateFolderJob: MutableLiveData<Event<Path>> = MutableLiveData()
val startCreateFolderJob: LiveData<Event<Path>> = _startCreateFolderJob

private val _startRenameFileJob: MutableLiveData<Event<Pair<FileModel, String>>> = MutableLiveData()
val startRenameFileJob: LiveData<Event<Pair<FileModel, String>>> = _startRenameFileJob

var conflictDialogDeferred = CompletableDeferred<Pair<ConflictStrategy, Boolean>>()

companion object {
Expand Down Expand Up @@ -223,6 +226,17 @@ class FilesListViewModel
}
}

fun renameFile(newName: String) {
val file = selectedItemList.firstOrNull()
file?.let {
if (Files.isWritable(Paths.get(file.absolutePath))) {
_startRenameFileJob.value = Event(Pair(file, newName))
} else {
// show toast
}
}
}

// Todo check free space
fun createFolder(targetPath: Path) {
_startCreateFolderJob.value = Event(targetPath)
Expand Down Expand Up @@ -270,7 +284,14 @@ class FilesListViewModel
)
) {
is BaseResult.Success -> {
val list = result.data.map { Paths.get(it).toFileModel() }
val list =
result.data.mapNotNull {
if (Files.exists(Paths.get(it))) {
Paths.get(it).toFileModel()
} else {
null
}
}
_searchStateLiveData.postValue(Event(Pair(false, false)))
_updateListLiveData.postValue(Event(list.toMutableList()))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,20 +161,19 @@ class HomeFragment : BaseFragment<FragmentHomeBinding, HomeViewModel>() {
}

private fun showPermissionDialog(type: PermissionDialogType = PermissionDialogType.DEFAULT) {
if (permissionDialog == null || permissionDialog?.isShowing == false) {
if (permissionDialog == null || permissionDialog?.isVisible == false) {
permissionDialog =
PermissionDialog(requireContext(), type).apply {
PermissionDialog(type).apply {
onAllow = { allowStoragePermission() }
}
permissionDialog?.show()
permissionDialog?.showDialog(childFragmentManager)
}
}

private fun showNotificationDialog() {
if (confirmationDialog == null || confirmationDialog?.isShowing == false) {
if (confirmationDialog == null || confirmationDialog?.isVisible == false) {
confirmationDialog =
ConfirmationDialog(
requireContext(),
getString(R.string.permission_warning_title),
getString(R.string.notification_permission_info),
).apply {
Expand All @@ -184,7 +183,7 @@ class HomeFragment : BaseFragment<FragmentHomeBinding, HomeViewModel>() {
}
}
}
confirmationDialog?.show()
confirmationDialog?.showDialog(childFragmentManager)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ class MediaItemAdapter(
) : RecyclerView.Adapter<MediaItemAdapter.AutoCompleteViewHolder>() {
private val selectedItems: MutableList<Media> = mutableListOf()
private var isSelectionModeActive = false
private var mediaItems: List<Media> = emptyList()
private var mediaItems: MutableList<Media> = mutableListOf()

fun setItems(newItems: List<Media>) {
fun setItems(newItems: MutableList<Media>) {
val diffResult = DiffUtil.calculateDiff(MediaDiffCallback(mediaItems, newItems))
mediaItems = newItems
diffResult.dispatchUpdatesTo(this)
Expand All @@ -50,6 +50,12 @@ class MediaItemAdapter(
}
}

fun updateItem(mediaFile: Media) {
val index = mediaItems.indexOfFirst { it.id == mediaFile.id }
mediaItems[index] = mediaFile
notifyItemChanged(index)
}

fun finishSelectionAndReset() {
for (selectedItem in selectedItems) {
val position = mediaItems.indexOf(selectedItem)
Expand Down
Loading

0 comments on commit 9a82e95

Please sign in to comment.