From 79361db39228c640413eabcd721b768993e13ca7 Mon Sep 17 00:00:00 2001 From: Emre Esen Date: Mon, 15 Apr 2024 23:14:44 +0300 Subject: [PATCH 1/9] [DEV][v1.0.0-beta6 created] --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 0f74bd9..29caeff 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -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" } From 0aa08ad4c6bb02294c2ab0921cdbbb15349ed617 Mon Sep 17 00:00:00 2001 From: Emre Esen Date: Tue, 16 Apr 2024 22:16:55 +0300 Subject: [PATCH 2/9] [FIX][lint fix] --- .../feature/files/adapter/FileItemAdapter.kt | 6 + .../files/presentation/FilesListFragment.kt | 42 +++++- .../files/presentation/FilesListViewModel.kt | 14 ++ .../feature/media/adapter/MediaItemAdapter.kt | 10 +- .../media/presentation/MediaFragment.kt | 31 ++++- .../media/presentation/MediaViewModel.kt | 34 ++++- .../com/sn/snfilemanager/job/JobService.kt | 10 ++ .../java/com/sn/snfilemanager/job/JobType.kt | 1 + .../snfilemanager/job/file/CreateDirectory.kt | 2 + .../snfilemanager/job/file/RenameFileJob.kt | 40 ++++++ .../mediastore/MediaStoreProvider.kt | 18 +++ .../view/dialog/CreateDirectoryDialog.kt | 3 +- .../dialog/FilterBottomSheetDialog.kt} | 10 +- .../view/dialog/RenameFileDialog.kt | 123 ++++++++++++++++ app/src/main/res/drawable/ic_warning.xml | 23 +++ .../main/res/layout/dialog_rename_file.xml | 131 ++++++++++++++++++ app/src/main/res/menu/menu_action.xml | 5 + app/src/main/res/values-tr/strings.xml | 5 + app/src/main/res/values/strings.xml | 5 + 19 files changed, 494 insertions(+), 19 deletions(-) create mode 100644 app/src/main/java/com/sn/snfilemanager/job/file/RenameFileJob.kt rename app/src/main/java/com/sn/snfilemanager/{feature/filter/FilterBottomSheet.kt => view/dialog/FilterBottomSheetDialog.kt} (95%) create mode 100644 app/src/main/java/com/sn/snfilemanager/view/dialog/RenameFileDialog.kt create mode 100644 app/src/main/res/drawable/ic_warning.xml create mode 100644 app/src/main/res/layout/dialog_rename_file.xml diff --git a/app/src/main/java/com/sn/snfilemanager/feature/files/adapter/FileItemAdapter.kt b/app/src/main/java/com/sn/snfilemanager/feature/files/adapter/FileItemAdapter.kt index b265448..aed3371 100644 --- a/app/src/main/java/com/sn/snfilemanager/feature/files/adapter/FileItemAdapter.kt +++ b/app/src/main/java/com/sn/snfilemanager/feature/files/adapter/FileItemAdapter.kt @@ -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) { for (fileToRemove in filesToRemove) { val position = fileItems.indexOf(fileToRemove) diff --git a/app/src/main/java/com/sn/snfilemanager/feature/files/presentation/FilesListFragment.kt b/app/src/main/java/com/sn/snfilemanager/feature/files/presentation/FilesListFragment.kt index 5c619aa..6422c62 100644 --- a/app/src/main/java/com/sn/snfilemanager/feature/files/presentation/FilesListFragment.kt +++ b/app/src/main/java/com/sn/snfilemanager/feature/files/presentation/FilesListFragment.kt @@ -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 @@ -133,6 +134,10 @@ class FilesListFragment : R.id.action_select_all -> { adapter?.selectAll() } + + R.id.action_rename -> { + showRenameDialog() + } } return true @@ -189,6 +194,14 @@ class FilesListFragment : } } } + + JobType.RENAME -> { + activity?.runOnUiThread { + data?.filterIsInstance()?.firstOrNull()?.let { file -> + adapter?.updateItem(file) + } + } + } } activity?.runOnUiThread { context?.infoToast(getString(R.string.completed)) } } @@ -220,7 +233,7 @@ class FilesListFragment : } observe(viewModel.startCreateFolderJob) { event -> event.getContentIfNotHandled()?.let { path -> - startCreateDirectory(path) + startCreateDirectoryService(path) } } observe(viewModel.updateListLiveData) { event -> @@ -242,6 +255,12 @@ class FilesListFragment : } } } + observe(viewModel.startRenameFileJob) { event -> + event.getContentIfNotHandled()?.let { data -> + actionMode?.finish() + startRenameService(data.first, data.second) + } + } } private fun initFirstList() { @@ -303,6 +322,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() { @@ -364,6 +384,12 @@ class FilesListFragment : }).show(childFragmentManager, CreateDirectoryDialog.TAG) } + private fun showRenameDialog() { + RenameFileDialog(file = viewModel.getSelectedItem().first(), onRename = { newName -> + viewModel.renameFile(newName) + }).show(childFragmentManager, RenameFileDialog.TAG) + } + private fun actionDetail() { DetailDialog(requireContext(), viewModel.getSelectedItem()).show( childFragmentManager, @@ -423,7 +449,7 @@ class FilesListFragment : ) } - private fun startCreateDirectory(destinationPath: Path) { + private fun startCreateDirectoryService(destinationPath: Path) { JobService.createDirectory( destinationPath, this@FilesListFragment, @@ -431,6 +457,18 @@ class FilesListFragment : ) } + 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 diff --git a/app/src/main/java/com/sn/snfilemanager/feature/files/presentation/FilesListViewModel.kt b/app/src/main/java/com/sn/snfilemanager/feature/files/presentation/FilesListViewModel.kt index 15d35c3..aac4690 100644 --- a/app/src/main/java/com/sn/snfilemanager/feature/files/presentation/FilesListViewModel.kt +++ b/app/src/main/java/com/sn/snfilemanager/feature/files/presentation/FilesListViewModel.kt @@ -73,6 +73,9 @@ class FilesListViewModel private val _startCreateFolderJob: MutableLiveData> = MutableLiveData() val startCreateFolderJob: LiveData> = _startCreateFolderJob + private val _startRenameFileJob: MutableLiveData>> = MutableLiveData() + val startRenameFileJob: LiveData>> = _startRenameFileJob + var conflictDialogDeferred = CompletableDeferred>() companion object { @@ -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) diff --git a/app/src/main/java/com/sn/snfilemanager/feature/media/adapter/MediaItemAdapter.kt b/app/src/main/java/com/sn/snfilemanager/feature/media/adapter/MediaItemAdapter.kt index ebbb39c..05db852 100644 --- a/app/src/main/java/com/sn/snfilemanager/feature/media/adapter/MediaItemAdapter.kt +++ b/app/src/main/java/com/sn/snfilemanager/feature/media/adapter/MediaItemAdapter.kt @@ -32,9 +32,9 @@ class MediaItemAdapter( ) : RecyclerView.Adapter() { private val selectedItems: MutableList = mutableListOf() private var isSelectionModeActive = false - private var mediaItems: List = emptyList() + private var mediaItems: MutableList = mutableListOf() - fun setItems(newItems: List) { + fun setItems(newItems: MutableList) { val diffResult = DiffUtil.calculateDiff(MediaDiffCallback(mediaItems, newItems)) mediaItems = newItems diffResult.dispatchUpdatesTo(this) @@ -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) diff --git a/app/src/main/java/com/sn/snfilemanager/feature/media/presentation/MediaFragment.kt b/app/src/main/java/com/sn/snfilemanager/feature/media/presentation/MediaFragment.kt index e1ab3bf..f35b349 100644 --- a/app/src/main/java/com/sn/snfilemanager/feature/media/presentation/MediaFragment.kt +++ b/app/src/main/java/com/sn/snfilemanager/feature/media/presentation/MediaFragment.kt @@ -19,7 +19,6 @@ import com.sn.snfilemanager.core.extensions.shareFiles import com.sn.snfilemanager.core.extensions.warningToast import com.sn.snfilemanager.core.util.DocumentType import com.sn.snfilemanager.databinding.FragmentMediaBinding -import com.sn.snfilemanager.feature.filter.FilterBottomSheet import com.sn.snfilemanager.feature.media.adapter.MediaItemAdapter import com.sn.snfilemanager.feature.pathpicker.presentation.PathPickerFragment import com.sn.snfilemanager.job.JobCompletedCallback @@ -27,6 +26,8 @@ import com.sn.snfilemanager.job.JobService import com.sn.snfilemanager.job.JobType import com.sn.snfilemanager.view.dialog.ConfirmationDialog import com.sn.snfilemanager.view.dialog.ConflictDialog +import com.sn.snfilemanager.view.dialog.FilterBottomSheetDialog +import com.sn.snfilemanager.view.dialog.RenameFileDialog import com.sn.snfilemanager.view.dialog.detail.DetailDialog import dagger.hilt.android.AndroidEntryPoint import java.nio.file.Path @@ -124,6 +125,10 @@ class MediaFragment : R.id.action_select_all -> { adapter?.selectAll() } + + R.id.action_rename -> { + showRenameDialog() + } } return true @@ -176,6 +181,7 @@ class MediaFragment : } } JobType.CREATE -> {} + JobType.RENAME -> {} } activity?.runOnUiThread { context?.infoToast(getString(R.string.completed)) } } @@ -184,7 +190,7 @@ class MediaFragment : viewModel.run { observe(getMediaLiveData) { event -> event.getContentIfNotHandled()?.let { data -> - adapter?.setItems(data) + adapter?.setItems(data.toMutableList()) } } observe(conflictQuestionLiveData) { event -> @@ -216,6 +222,13 @@ class MediaFragment : context?.warningToast(getString(R.string.path_conflict_warning)) } } + observe(viewModel.completedRenameMediaJob) { event -> + event.getContentIfNotHandled()?.let { media -> + adapter?.updateItem(media) + viewModel.updateFilterList(media) + context?.infoToast(getString(R.string.completed)) + } + } } } @@ -277,6 +290,8 @@ class MediaFragment : private fun checkActionMenuStatus() { actionMode?.menu?.findItem(R.id.action_open_with)?.isVisible = viewModel.isSingleItemSelected() + actionMode?.menu?.findItem(R.id.action_rename)?.isVisible = + viewModel.isSingleItemSelected() } private fun showPathSelectionDialog() { @@ -293,6 +308,14 @@ class MediaFragment : ) } + private fun showRenameDialog() { + val media = viewModel.getSelectedItem().first() + RenameFileDialog(file = media, onRename = { newName -> + actionMode?.finish() + viewModel.renameMedia(media, newName) + }).show(childFragmentManager, RenameFileDialog.TAG) + } + private fun clearSelection() { adapter?.finishSelectionAndReset() viewModel.clearSelectionList() @@ -337,11 +360,11 @@ class MediaFragment : private fun showFilterBottomSheet() { viewModel.getMimeByMediaType()?.let { type -> - FilterBottomSheet.newInstance(type).apply { + FilterBottomSheetDialog.newInstance(type).apply { onFilterApplyClick = { filters -> viewModel.applyFilter(filters) } - }.show(childFragmentManager, FilterBottomSheet.TAG) + }.show(childFragmentManager, FilterBottomSheetDialog.TAG) } } diff --git a/app/src/main/java/com/sn/snfilemanager/feature/media/presentation/MediaViewModel.kt b/app/src/main/java/com/sn/snfilemanager/feature/media/presentation/MediaViewModel.kt index 8257ddc..c823b55 100644 --- a/app/src/main/java/com/sn/snfilemanager/feature/media/presentation/MediaViewModel.kt +++ b/app/src/main/java/com/sn/snfilemanager/feature/media/presentation/MediaViewModel.kt @@ -32,7 +32,7 @@ class MediaViewModel ) : ViewModel() { private var fullMediaList: List? = null private var selectedItemList: MutableList = mutableListOf() - private var filteredMediaList: List? = null + private var filteredMediaList: MutableList? = null private var mediaType: MediaType? = null private var documentType: String? = null @@ -54,6 +54,9 @@ class MediaViewModel private val _startDeleteJobLiveData: MutableLiveData>> = MutableLiveData() val startDeleteJobLiveData: LiveData>> = _startDeleteJobLiveData + private val _completedRenameMediaJob: MutableLiveData> = MutableLiveData() + val completedRenameMediaJob: LiveData> = _completedRenameMediaJob + var conflictDialogDeferred = CompletableDeferred>() private fun getFilteredMediaTypes(): MutableSet? = @@ -92,7 +95,7 @@ class MediaViewModel applyFilter(filteredMediaTypes) } else { _getMediaLiveData.value = Event(mediaList) - filteredMediaList = mediaList + filteredMediaList = mediaList.toMutableList() } } } @@ -153,6 +156,29 @@ class MediaViewModel _startDeleteJobLiveData.postValue(Event(operationItemList)) } + fun renameMedia( + media: Media, + newName: String, + ) { + viewModelScope.launch { + when (val result = mediaStoreProvider.renameMedia(media, newName)) { + is BaseResult.Success -> { + _completedRenameMediaJob.postValue(Event(result.data)) + } + is BaseResult.Failure -> { + println("err:${result.exception}") + } + } + } + } + + fun updateFilterList(media: Media) { + filteredMediaList?.let { list -> + val index = list.indexOfFirst { it.id == media.id } + list[index] = media + } + } + fun getMimeByMediaType() = when (mediaType) { MediaType.IMAGES -> MimeTypes.IMAGES @@ -189,12 +215,12 @@ class MediaViewModel fun applyFilter(filter: MutableSet) { if (filter.isEmpty()) { fullMediaList?.let { - filteredMediaList = it + filteredMediaList = it.toMutableList() _getMediaLiveData.value = Event(it) } } else { fullMediaList?.filter { filter.contains(it.ext) }?.let { filteredList -> - filteredMediaList = filteredList + filteredMediaList = filteredList.toMutableList() _getMediaLiveData.value = Event(filteredList) } } diff --git a/app/src/main/java/com/sn/snfilemanager/job/JobService.kt b/app/src/main/java/com/sn/snfilemanager/job/JobService.kt index c1d7311..277eaaf 100644 --- a/app/src/main/java/com/sn/snfilemanager/job/JobService.kt +++ b/app/src/main/java/com/sn/snfilemanager/job/JobService.kt @@ -14,6 +14,7 @@ import com.sn.snfilemanager.feature.files.data.FileModel import com.sn.snfilemanager.job.file.CopyFileJob import com.sn.snfilemanager.job.file.CreateDirectory import com.sn.snfilemanager.job.file.DeleteFileJob +import com.sn.snfilemanager.job.file.RenameFileJob import com.sn.snfilemanager.job.media.DeleteMediaJob import com.sn.snfilemanager.job.media.MoveMediaJob import kotlinx.coroutines.CoroutineScope @@ -160,6 +161,15 @@ class JobService : Service() { startJob(CreateDirectory(targetPath, completed), context) } + fun rename( + file: FileModel, + newName: String, + callback: JobCompletedCallback, + context: Context, + ) { + startJob(RenameFileJob(file, newName, callback), context) + } + @MainThread fun cancelJob(id: Int) { pendingJobs.removeFirst { it.id == id } diff --git a/app/src/main/java/com/sn/snfilemanager/job/JobType.kt b/app/src/main/java/com/sn/snfilemanager/job/JobType.kt index 0b256f7..1aa6b85 100644 --- a/app/src/main/java/com/sn/snfilemanager/job/JobType.kt +++ b/app/src/main/java/com/sn/snfilemanager/job/JobType.kt @@ -4,4 +4,5 @@ enum class JobType { COPY, DELETE, CREATE, + RENAME, } diff --git a/app/src/main/java/com/sn/snfilemanager/job/file/CreateDirectory.kt b/app/src/main/java/com/sn/snfilemanager/job/file/CreateDirectory.kt index 7319942..9edbc3d 100644 --- a/app/src/main/java/com/sn/snfilemanager/job/file/CreateDirectory.kt +++ b/app/src/main/java/com/sn/snfilemanager/job/file/CreateDirectory.kt @@ -1,6 +1,7 @@ package com.sn.snfilemanager.job.file import com.sn.snfilemanager.core.base.BaseJob +import com.sn.snfilemanager.core.extensions.scanFile import com.sn.snfilemanager.job.JobCompletedCallback import com.sn.snfilemanager.job.JobType import java.nio.file.Files @@ -18,6 +19,7 @@ class CreateDirectory( } override fun onCompleted() { + scanFile(listOf(targetPath.toFile().absolutePath)) completed.jobOnCompleted(JobType.CREATE, directory) } } diff --git a/app/src/main/java/com/sn/snfilemanager/job/file/RenameFileJob.kt b/app/src/main/java/com/sn/snfilemanager/job/file/RenameFileJob.kt new file mode 100644 index 0000000..de72e92 --- /dev/null +++ b/app/src/main/java/com/sn/snfilemanager/job/file/RenameFileJob.kt @@ -0,0 +1,40 @@ +package com.sn.snfilemanager.job.file + +import com.sn.snfilemanager.core.base.BaseJob +import com.sn.snfilemanager.core.extensions.scanFile +import com.sn.snfilemanager.core.extensions.toFormattedDate +import com.sn.snfilemanager.feature.files.data.FileModel +import com.sn.snfilemanager.job.JobCompletedCallback +import com.sn.snfilemanager.job.JobType +import java.nio.file.Files +import java.nio.file.Paths +import java.nio.file.attribute.FileTime + +class RenameFileJob( + private val file: FileModel, + private val newName: String, + private val callback: JobCompletedCallback, +) : BaseJob() { + private lateinit var newFile: FileModel + + override fun run() { + val sourcePath = Paths.get(file.absolutePath) + val targetPath = sourcePath.resolveSibling(newName) + val newPath = Files.move(sourcePath, targetPath) + + val lastModifiedTime = FileTime.fromMillis(System.currentTimeMillis()) + Files.setLastModifiedTime(newPath, lastModifiedTime) + + newFile = + file.copy( + name = newPath.fileName.toString(), + absolutePath = newPath.toAbsolutePath().toString(), + lastModified = lastModifiedTime.toMillis().toFormattedDate(), + ) + } + + override fun onCompleted() { + scanFile(listOf(newFile.absolutePath)) + callback.jobOnCompleted(JobType.RENAME, listOf(newFile)) + } +} diff --git a/app/src/main/java/com/sn/snfilemanager/providers/mediastore/MediaStoreProvider.kt b/app/src/main/java/com/sn/snfilemanager/providers/mediastore/MediaStoreProvider.kt index a8ba0c8..ff4a9af 100644 --- a/app/src/main/java/com/sn/snfilemanager/providers/mediastore/MediaStoreProvider.kt +++ b/app/src/main/java/com/sn/snfilemanager/providers/mediastore/MediaStoreProvider.kt @@ -39,4 +39,22 @@ class MediaStoreProvider BaseResult.Failure(e) } } + + suspend fun renameMedia( + media: Media, + newName: String, + ): BaseResult { + return try { + withContext(Dispatchers.IO) { + val updatedMedia = mediaStoreBuilder.build().renameMedia(media, newName) + if (updatedMedia != null) { + BaseResult.Success(updatedMedia) + } else { + BaseResult.Failure(Exception("Media renaming failed")) + } + } + } catch (e: Exception) { + BaseResult.Failure(e) + } + } } diff --git a/app/src/main/java/com/sn/snfilemanager/view/dialog/CreateDirectoryDialog.kt b/app/src/main/java/com/sn/snfilemanager/view/dialog/CreateDirectoryDialog.kt index 1b4bb90..085e15a 100644 --- a/app/src/main/java/com/sn/snfilemanager/view/dialog/CreateDirectoryDialog.kt +++ b/app/src/main/java/com/sn/snfilemanager/view/dialog/CreateDirectoryDialog.kt @@ -17,8 +17,7 @@ import java.nio.file.Paths class CreateDirectoryDialog( private val path: String, private val onCreate: ((Path) -> Unit)? = null, -) : - DialogFragment() { +) : DialogFragment() { private val binding: DialogCreateDirectoryBinding by lazy { DialogCreateDirectoryBinding.inflate(layoutInflater) } diff --git a/app/src/main/java/com/sn/snfilemanager/feature/filter/FilterBottomSheet.kt b/app/src/main/java/com/sn/snfilemanager/view/dialog/FilterBottomSheetDialog.kt similarity index 95% rename from app/src/main/java/com/sn/snfilemanager/feature/filter/FilterBottomSheet.kt rename to app/src/main/java/com/sn/snfilemanager/view/dialog/FilterBottomSheetDialog.kt index 018f89b..284d6c5 100644 --- a/app/src/main/java/com/sn/snfilemanager/feature/filter/FilterBottomSheet.kt +++ b/app/src/main/java/com/sn/snfilemanager/view/dialog/FilterBottomSheetDialog.kt @@ -1,4 +1,4 @@ -package com.sn.snfilemanager.feature.filter +package com.sn.snfilemanager.view.dialog import android.os.Bundle import android.view.LayoutInflater @@ -18,7 +18,7 @@ import dagger.hilt.android.AndroidEntryPoint import javax.inject.Inject @AndroidEntryPoint -class FilterBottomSheet : BottomSheetDialogFragment() { +class FilterBottomSheetDialog : BottomSheetDialogFragment() { @Inject lateinit var sharedPreferences: MySharedPreferences @@ -33,10 +33,10 @@ class FilterBottomSheet : BottomSheetDialogFragment() { companion object { private const val ARG_MIME_TYPE = "ARG_CHIP" - const val TAG = "FilterBottomSheet" + const val TAG = "FILTER_BOTTOM_SHEET_DIALOG" - fun newInstance(mimeTypes: MimeTypes): FilterBottomSheet { - return FilterBottomSheet().apply { + fun newInstance(mimeTypes: MimeTypes): FilterBottomSheetDialog { + return FilterBottomSheetDialog().apply { arguments = Bundle().apply { putParcelable(ARG_MIME_TYPE, mimeTypes) diff --git a/app/src/main/java/com/sn/snfilemanager/view/dialog/RenameFileDialog.kt b/app/src/main/java/com/sn/snfilemanager/view/dialog/RenameFileDialog.kt new file mode 100644 index 0000000..ab33a8d --- /dev/null +++ b/app/src/main/java/com/sn/snfilemanager/view/dialog/RenameFileDialog.kt @@ -0,0 +1,123 @@ +package com.sn.snfilemanager.view.dialog + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.constraintlayout.widget.ConstraintLayout +import androidx.core.widget.addTextChangedListener +import androidx.fragment.app.DialogFragment +import com.sn.mediastorepv.data.Media +import com.sn.snfilemanager.R +import com.sn.snfilemanager.core.extensions.click +import com.sn.snfilemanager.core.extensions.gone +import com.sn.snfilemanager.core.extensions.visible +import com.sn.snfilemanager.databinding.DialogRenameFileBinding +import com.sn.snfilemanager.feature.files.data.FileModel +import java.nio.file.Files +import java.nio.file.Paths +import kotlin.io.path.extension +import kotlin.io.path.isDirectory +import kotlin.io.path.name +import kotlin.io.path.nameWithoutExtension + +class RenameFileDialog( + private val file: T, + private val onRename: ((String) -> Unit)? = null, +) : DialogFragment() { + private val binding: DialogRenameFileBinding by lazy { + DialogRenameFileBinding.inflate(layoutInflater) + } + + val nameExtractor: (T) -> String = { item -> + when (item) { + is FileModel -> item.absolutePath + is Media -> item.data + else -> throw IllegalArgumentException() + } + } + + companion object { + const val TAG = "RENAME_FILE_DIALOG" + } + + override fun onStart() { + super.onStart() + dialog?.window?.setLayout( + ConstraintLayout.LayoutParams.MATCH_PARENT, + ConstraintLayout.LayoutParams.WRAP_CONTENT, + ) + } + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle?, + ): View { + return binding.root + } + + override fun onViewCreated( + view: View, + savedInstanceState: Bundle?, + ) { + super.onViewCreated(view, savedInstanceState) + + binding.btnCancel.click { dismiss() } + val path = Paths.get(nameExtractor(file)) + + if (path.isDirectory()) { + binding.inputLayoutExt.gone() + } else { + binding.inputLayoutExt.visible() + binding.etExt.setText(path.extension) + } + + with(binding.etName) { + requestFocus() + setText(path.nameWithoutExtension) + text?.length?.let { setSelection(0, it) } + } + + binding.btnRename.isEnabled = !binding.etName.text.isNullOrEmpty() && + (binding.inputLayoutExt.visibility == View.GONE || !binding.etExt.text.isNullOrEmpty()) + + binding.btnRename.click { + val name = binding.etName.text.toString() + val ext = binding.etExt.text.toString().takeIf { it.isNotBlank() }?.let { ".$it" } ?: "" + val newName = if (ext.isNotEmpty()) "$name$ext" else name + + if (newName == path.name) { + binding.inputLayout.error = getString(R.string.current_file_name_warning) + return@click + } + + if (isNameExists(newName)) { + binding.inputLayout.error = getString(R.string.file_exists_warning) + } else { + onRename?.invoke(newName) + dismiss() + } + } + + binding.etName.addTextChangedListener { text -> + binding.btnRename.isEnabled = + !text.isNullOrEmpty() && ( + binding.inputLayoutExt.visibility == View.GONE || + !binding.etExt.text.isNullOrEmpty() + ) + binding.inputLayout.error = null + } + + binding.etExt.addTextChangedListener { text -> + binding.btnRename.isEnabled = + !binding.etName.text.isNullOrEmpty() && !text.isNullOrEmpty() + binding.tvInfo.visible() + } + } + + private fun isNameExists(name: String): Boolean { + val targetPath = Paths.get(nameExtractor(file)).resolveSibling(name) + return Files.exists(targetPath) + } +} diff --git a/app/src/main/res/drawable/ic_warning.xml b/app/src/main/res/drawable/ic_warning.xml new file mode 100644 index 0000000..69ccc43 --- /dev/null +++ b/app/src/main/res/drawable/ic_warning.xml @@ -0,0 +1,23 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_rename_file.xml b/app/src/main/res/layout/dialog_rename_file.xml new file mode 100644 index 0000000..05b6b5c --- /dev/null +++ b/app/src/main/res/layout/dialog_rename_file.xml @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/menu_action.xml b/app/src/main/res/menu/menu_action.xml index 29ef6ce..febcbf4 100644 --- a/app/src/main/res/menu/menu_action.xml +++ b/app/src/main/res/menu/menu_action.xml @@ -39,4 +39,9 @@ android:title="@string/select_all" app:showAsAction="never" /> + + \ No newline at end of file diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 741d4e8..ab6ead8 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -104,4 +104,9 @@ Klasör adı Bu ada sahip klasör zaten mevcut Görüntülenecek bir klasör yok + Yeniden adlandır + Uzantı + Uzantıyı değiştirmek dosyanın kullanılamaz hale gelmesine neden olabilir + Mevcut dosya adını girdiniz + Bu isimde dosya zaten mevcut \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9561236..fb1373e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -108,4 +108,9 @@ Folder name The folder with this name already exists There is no folder to display + Rename + Extension + Changing the extension may cause the file to become unusable + "You entered the current file name" + The file with this name already exists \ No newline at end of file From c7cd30f2015782df612b4135ee10f3d9a80219cd Mon Sep 17 00:00:00 2001 From: Emre Esen Date: Wed, 17 Apr 2024 16:07:10 +0300 Subject: [PATCH 3/9] [FIX][unnecessary list update removed] --- .../feature/files/presentation/FilesListFragment.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/src/main/java/com/sn/snfilemanager/feature/files/presentation/FilesListFragment.kt b/app/src/main/java/com/sn/snfilemanager/feature/files/presentation/FilesListFragment.kt index 6422c62..df545c6 100644 --- a/app/src/main/java/com/sn/snfilemanager/feature/files/presentation/FilesListFragment.kt +++ b/app/src/main/java/com/sn/snfilemanager/feature/files/presentation/FilesListFragment.kt @@ -182,7 +182,6 @@ class FilesListFragment : JobType.DELETE -> { activity?.runOnUiThread { data?.filterIsInstance()?.let { adapter?.removeItems(it) } - adapter?.getItems()?.let { viewModel.setUpdateList(it) } } } @@ -190,7 +189,6 @@ class FilesListFragment : activity?.runOnUiThread { data?.filterIsInstance()?.firstOrNull()?.toFileModel()?.let { file -> adapter?.addItem(file) - adapter?.getItems()?.let { viewModel.setUpdateList(it) } } } } From adf5a71325e8ffc85bf2847a9853eb40cdecb384 Mon Sep 17 00:00:00 2001 From: Emre Esen Date: Wed, 17 Apr 2024 16:17:25 +0300 Subject: [PATCH 4/9] [FIX][file search exists control added] --- .../feature/files/presentation/FilesListViewModel.kt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/sn/snfilemanager/feature/files/presentation/FilesListViewModel.kt b/app/src/main/java/com/sn/snfilemanager/feature/files/presentation/FilesListViewModel.kt index aac4690..8ff4aa0 100644 --- a/app/src/main/java/com/sn/snfilemanager/feature/files/presentation/FilesListViewModel.kt +++ b/app/src/main/java/com/sn/snfilemanager/feature/files/presentation/FilesListViewModel.kt @@ -284,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())) } From 81debd846337cb0c5c64291b72fc6e078678299c Mon Sep 17 00:00:00 2001 From: Emre Esen Date: Fri, 19 Apr 2024 11:09:50 +0300 Subject: [PATCH 5/9] [FIX][acces denied fixed] --- .../sn/snfilemanager/core/util/FileUtils.kt | 23 +++++++++++++++++++ .../sn/snfilemanager/job/file/CopyFileJob.kt | 22 ++++++------------ .../snfilemanager/job/file/DeleteFileJob.kt | 18 +++------------ .../dialog/detail/DetailDialogViewModel.kt | 19 +-------------- 4 files changed, 34 insertions(+), 48 deletions(-) create mode 100644 app/src/main/java/com/sn/snfilemanager/core/util/FileUtils.kt diff --git a/app/src/main/java/com/sn/snfilemanager/core/util/FileUtils.kt b/app/src/main/java/com/sn/snfilemanager/core/util/FileUtils.kt new file mode 100644 index 0000000..4487381 --- /dev/null +++ b/app/src/main/java/com/sn/snfilemanager/core/util/FileUtils.kt @@ -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): Pair = + 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) + } + } +} diff --git a/app/src/main/java/com/sn/snfilemanager/job/file/CopyFileJob.kt b/app/src/main/java/com/sn/snfilemanager/job/file/CopyFileJob.kt index ac2632a..f868eba 100644 --- a/app/src/main/java/com/sn/snfilemanager/job/file/CopyFileJob.kt +++ b/app/src/main/java/com/sn/snfilemanager/job/file/CopyFileJob.kt @@ -7,6 +7,7 @@ import com.sn.snfilemanager.core.extensions.getUniqueFileNameWithCounter import com.sn.snfilemanager.core.extensions.infoToast import com.sn.snfilemanager.core.extensions.postNotification import com.sn.snfilemanager.core.extensions.scanFile +import com.sn.snfilemanager.core.util.FileUtils.getTotalSizeAndFileCount import com.sn.snfilemanager.feature.files.data.FileModel import com.sn.snfilemanager.job.JobCompletedCallback import com.sn.snfilemanager.job.JobType @@ -28,11 +29,12 @@ class CopyFileJob( ) : BaseJob() { private var movedItemCount: Int = 0 private var title = if (isCopy) R.string.copying else R.string.moving - private val totalItemCount: Long = calculateItemCount(sourceFiles) + private var totalItemCount: Long = 0 private val movedItemPathList: MutableList = mutableListOf() override fun run() { handler.post { service.infoToast(service.getString(title)) } + totalItemCount = getTotalSizeAndFileCount(sourceFiles).second moveFilesAndDirectories() } @@ -46,6 +48,10 @@ class CopyFileJob( private fun moveFilesAndDirectories() { for (sourceFile in sourceFiles) { val sourcePath = Paths.get(sourceFile.absolutePath) + if (!Files.isReadable(sourcePath)) { + continue + } + var targetPath = targetPath.resolve(sourcePath.fileName) if (Files.exists(targetPath)) { if (sourceFile.conflictStrategy == ConflictStrategy.SKIP) { @@ -128,20 +134,6 @@ class CopyFileJob( } } - private fun calculateItemCount(items: List): Long { - return items.sumOf { - if (Files.isDirectory(Paths.get(it.absolutePath))) { - Files.walk( - Paths.get( - it.absolutePath, - ), - ).count() - } else { - 1 - } - } - } - private fun updateProgress() { val progress = ((movedItemCount.toDouble() / totalItemCount.toDouble()) * 100).toInt() postNotification(title, progress) diff --git a/app/src/main/java/com/sn/snfilemanager/job/file/DeleteFileJob.kt b/app/src/main/java/com/sn/snfilemanager/job/file/DeleteFileJob.kt index 25438be..c922569 100644 --- a/app/src/main/java/com/sn/snfilemanager/job/file/DeleteFileJob.kt +++ b/app/src/main/java/com/sn/snfilemanager/job/file/DeleteFileJob.kt @@ -5,6 +5,7 @@ import com.sn.snfilemanager.core.base.BaseJob import com.sn.snfilemanager.core.extensions.infoToast import com.sn.snfilemanager.core.extensions.postNotification import com.sn.snfilemanager.core.extensions.scanFile +import com.sn.snfilemanager.core.util.FileUtils.getTotalSizeAndFileCount import com.sn.snfilemanager.feature.files.data.FileModel import com.sn.snfilemanager.job.JobCompletedCallback import com.sn.snfilemanager.job.JobType @@ -20,11 +21,12 @@ class DeleteFileJob( private val completed: JobCompletedCallback, ) : BaseJob() { private var deletedCount: Long = 0 - private val totalItemCount = calculateItemCount(sourceFiles) + private var totalItemCount: Long = 0 private val deletedItemPathList: MutableList = mutableListOf() override fun run() { handler.post { service.infoToast(service.getString(R.string.deleting)) } + totalItemCount = getTotalSizeAndFileCount(sourceFiles).second delete() } @@ -79,20 +81,6 @@ class DeleteFileJob( ) } - private fun calculateItemCount(items: List): Long { - return items.sumOf { - if (Files.isDirectory(Paths.get(it.absolutePath))) { - Files.walk( - Paths.get( - it.absolutePath, - ), - ).count() - } else { - 1 - } - } - } - private fun updateProgress() { val progress = ((deletedCount.toDouble() / totalItemCount.toDouble()) * 100).toInt() postNotification(R.string.delete, progress) diff --git a/app/src/main/java/com/sn/snfilemanager/view/dialog/detail/DetailDialogViewModel.kt b/app/src/main/java/com/sn/snfilemanager/view/dialog/detail/DetailDialogViewModel.kt index ac17546..5aec95a 100644 --- a/app/src/main/java/com/sn/snfilemanager/view/dialog/detail/DetailDialogViewModel.kt +++ b/app/src/main/java/com/sn/snfilemanager/view/dialog/detail/DetailDialogViewModel.kt @@ -10,15 +10,12 @@ import com.sn.snfilemanager.R import com.sn.snfilemanager.core.extensions.getDirectoryNameFromPath import com.sn.snfilemanager.core.extensions.toFormattedDateFromUnixTime import com.sn.snfilemanager.core.extensions.toHumanReadableByteCount +import com.sn.snfilemanager.core.util.FileUtils.getTotalSizeAndFileCount import com.sn.snfilemanager.core.util.StringValue import com.sn.snfilemanager.feature.files.data.FileModel -import com.sn.snfilemanager.feature.files.data.toFileModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import java.nio.file.Files -import java.nio.file.Paths -import java.util.stream.Collectors class DetailDialogViewModel : ViewModel() { private val _detailItemLiveData: MutableLiveData> = MutableLiveData() @@ -114,20 +111,6 @@ class DetailDialogViewModel : ViewModel() { _detailItemLiveData.postValue(detailItemList) } - private fun getTotalSizeAndFileCount(itemList: List): Pair = - itemList.fold(Pair(0L, 0)) { 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) - } - } - private fun itemsContainsFolder(itemList: List): Boolean = itemList.any { it.isDirectory } private fun createDetailItemList(vararg pairs: Pair): List { From 120f840be0b191419d23b4bd289c66df752b04ac Mon Sep 17 00:00:00 2001 From: Emre Esen Date: Fri, 19 Apr 2024 20:15:46 +0300 Subject: [PATCH 6/9] [FIX][dialog design imp and license url fix] --- .../sn/snfilemanager/core/base/BaseDialog.kt | 59 +++++++++++++++++++ .../feature/about/AboutFragment.kt | 2 +- .../files/presentation/FilesListFragment.kt | 24 ++++---- .../feature/home/HomeFragment.kt | 11 ++-- .../media/presentation/MediaFragment.kt | 18 +++--- .../presentation/PathPickerFragment.kt | 37 +++--------- .../view/dialog/ConfirmationDialog.kt | 30 +++------- .../view/dialog/ConflictDialog.kt | 40 ++++--------- .../view/dialog/CreateDirectoryDialog.kt | 40 ++----------- .../view/dialog/RenameFileDialog.kt | 42 +++---------- .../view/dialog/RootSelectorDialog.kt | 11 ++++ .../view/dialog/detail/DetailDialog.kt | 32 +++------- .../view/dialog/license/LicenseAdapter.kt | 2 +- .../view/dialog/license/LicenseDialog.kt | 47 ++------------- .../dialog/permission/PermissionDialog.kt | 36 +++++------ app/src/main/res/drawable/dialog_rounded.xml | 4 +- app/src/main/res/layout/dialog_permission.xml | 3 +- .../main/res/layout/dialog_root_selector.xml | 25 ++++++++ 18 files changed, 191 insertions(+), 272 deletions(-) create mode 100644 app/src/main/java/com/sn/snfilemanager/core/base/BaseDialog.kt create mode 100644 app/src/main/java/com/sn/snfilemanager/view/dialog/RootSelectorDialog.kt create mode 100644 app/src/main/res/layout/dialog_root_selector.xml diff --git a/app/src/main/java/com/sn/snfilemanager/core/base/BaseDialog.kt b/app/src/main/java/com/sn/snfilemanager/core/base/BaseDialog.kt new file mode 100644 index 0000000..5df1baf --- /dev/null +++ b/app/src/main/java/com/sn/snfilemanager/core/base/BaseDialog.kt @@ -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 : 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() + } +} diff --git a/app/src/main/java/com/sn/snfilemanager/feature/about/AboutFragment.kt b/app/src/main/java/com/sn/snfilemanager/feature/about/AboutFragment.kt index 52ba261..d421688 100644 --- a/app/src/main/java/com/sn/snfilemanager/feature/about/AboutFragment.kt +++ b/app/src/main/java/com/sn/snfilemanager/feature/about/AboutFragment.kt @@ -28,6 +28,6 @@ class AboutFragment : BaseFragment() { } private fun showLicensesDialog() { - LicenseDialog().show(childFragmentManager, LicenseDialog.TAG) + LicenseDialog().showDialog(childFragmentManager) } } diff --git a/app/src/main/java/com/sn/snfilemanager/feature/files/presentation/FilesListFragment.kt b/app/src/main/java/com/sn/snfilemanager/feature/files/presentation/FilesListFragment.kt index df545c6..83a13ac 100644 --- a/app/src/main/java/com/sn/snfilemanager/feature/files/presentation/FilesListFragment.kt +++ b/app/src/main/java/com/sn/snfilemanager/feature/files/presentation/FilesListFragment.kt @@ -207,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 -> @@ -370,29 +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) - }).show(childFragmentManager, RenameFileDialog.TAG) + }).showDialog(childFragmentManager) } private fun actionDetail() { - DetailDialog(requireContext(), viewModel.getSelectedItem()).show( - childFragmentManager, - DetailDialog.TAG, - ) + DetailDialog( + requireContext(), + viewModel.getSelectedItem(), + ).showDialog(childFragmentManager) } private fun actionOpenWith() { @@ -412,7 +409,6 @@ class FilesListFragment : private fun actionDelete() { ConfirmationDialog( - requireContext(), getString(R.string.are_you_sure), getString(R.string.delete_warning), ).apply { @@ -423,7 +419,7 @@ class FilesListFragment : actionMode?.finish() } } - }.show() + }.showDialog(childFragmentManager) } private fun startCopyService( diff --git a/app/src/main/java/com/sn/snfilemanager/feature/home/HomeFragment.kt b/app/src/main/java/com/sn/snfilemanager/feature/home/HomeFragment.kt index 92d2427..81b8964 100644 --- a/app/src/main/java/com/sn/snfilemanager/feature/home/HomeFragment.kt +++ b/app/src/main/java/com/sn/snfilemanager/feature/home/HomeFragment.kt @@ -161,20 +161,19 @@ class HomeFragment : BaseFragment() { } 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 { @@ -184,7 +183,7 @@ class HomeFragment : BaseFragment() { } } } - confirmationDialog?.show() + confirmationDialog?.showDialog(childFragmentManager) } } diff --git a/app/src/main/java/com/sn/snfilemanager/feature/media/presentation/MediaFragment.kt b/app/src/main/java/com/sn/snfilemanager/feature/media/presentation/MediaFragment.kt index f35b349..ecbb9be 100644 --- a/app/src/main/java/com/sn/snfilemanager/feature/media/presentation/MediaFragment.kt +++ b/app/src/main/java/com/sn/snfilemanager/feature/media/presentation/MediaFragment.kt @@ -180,6 +180,7 @@ class MediaFragment : data?.filterIsInstance()?.let { adapter?.removeItems(it) } } } + JobType.CREATE -> {} JobType.RENAME -> {} } @@ -195,12 +196,12 @@ class MediaFragment : } observe(conflictQuestionLiveData) { event -> event.getContentIfNotHandled()?.let { mediaName -> - ConflictDialog(requireContext(), mediaName).apply { + ConflictDialog(mediaName).apply { onSelected = { strategy: ConflictStrategy, isAll: Boolean -> viewModel.conflictDialogDeferred.complete(Pair(strategy, isAll)) } onDismiss = { actionMode?.finish() } - }.show() + }.showDialog(childFragmentManager) } } observe(viewModel.startMoveJobLiveData) { event -> @@ -239,7 +240,6 @@ class MediaFragment : private fun actionDelete() { ConfirmationDialog( - requireContext(), getString(R.string.are_you_sure), getString(R.string.delete_warning), ).apply { @@ -250,7 +250,7 @@ class MediaFragment : actionMode?.finish() } } - }.show() + }.showDialog(childFragmentManager) } private fun startCopyService( @@ -275,9 +275,8 @@ class MediaFragment : } private fun actionDetail() { - DetailDialog(requireContext(), viewModel.getSelectedItem()).show( + DetailDialog(requireContext(), viewModel.getSelectedItem()).showDialog( childFragmentManager, - DetailDialog.TAG, ) } @@ -302,10 +301,7 @@ class MediaFragment : } else { viewModel.moveMedia(Paths.get(path)) } - }).show( - childFragmentManager, - DetailDialog.TAG, - ) + }).showDialog(childFragmentManager) } private fun showRenameDialog() { @@ -313,7 +309,7 @@ class MediaFragment : RenameFileDialog(file = media, onRename = { newName -> actionMode?.finish() viewModel.renameMedia(media, newName) - }).show(childFragmentManager, RenameFileDialog.TAG) + }).showDialog(childFragmentManager) } private fun clearSelection() { diff --git a/app/src/main/java/com/sn/snfilemanager/feature/pathpicker/presentation/PathPickerFragment.kt b/app/src/main/java/com/sn/snfilemanager/feature/pathpicker/presentation/PathPickerFragment.kt index 39f3643..d1897b9 100644 --- a/app/src/main/java/com/sn/snfilemanager/feature/pathpicker/presentation/PathPickerFragment.kt +++ b/app/src/main/java/com/sn/snfilemanager/feature/pathpicker/presentation/PathPickerFragment.kt @@ -1,14 +1,10 @@ package com.sn.snfilemanager.feature.pathpicker.presentation -import android.os.Bundle import android.view.KeyEvent -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.viewModels import com.sn.snfilemanager.R +import com.sn.snfilemanager.core.base.BaseDialog import com.sn.snfilemanager.core.extensions.click import com.sn.snfilemanager.core.extensions.gone import com.sn.snfilemanager.core.extensions.visible @@ -22,12 +18,15 @@ import dagger.hilt.android.AndroidEntryPoint import java.io.File @AndroidEntryPoint -class PathPickerFragment(private val pathCallback: ((String?) -> Unit)? = null) : DialogFragment() { +class PathPickerFragment(private val pathCallback: ((String?) -> Unit)? = null) : + BaseDialog() { private var adapter: DirectoryItemAdapter? = null private val viewModel: PathPickerViewModel by viewModels() - private val binding: FragmentPathPickerBinding by lazy { - FragmentPathPickerBinding.inflate(layoutInflater) - } + + override fun getViewBinding() = FragmentPathPickerBinding.inflate(layoutInflater) + + override val dialogTag: String + get() = "PATH_PICKER_DIALOG" override fun onStart() { super.onStart() @@ -37,25 +36,7 @@ class PathPickerFragment(private val pathCallback: ((String?) -> Unit)? = null) ) } - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - 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) + override fun setupViews() { initAdapter() handleBackPressed() initBreadListener() diff --git a/app/src/main/java/com/sn/snfilemanager/view/dialog/ConfirmationDialog.kt b/app/src/main/java/com/sn/snfilemanager/view/dialog/ConfirmationDialog.kt index 41090c1..8e070e3 100644 --- a/app/src/main/java/com/sn/snfilemanager/view/dialog/ConfirmationDialog.kt +++ b/app/src/main/java/com/sn/snfilemanager/view/dialog/ConfirmationDialog.kt @@ -1,30 +1,23 @@ package com.sn.snfilemanager.view.dialog -import android.app.Dialog -import android.content.Context -import android.os.Bundle -import android.view.Gravity -import android.view.ViewGroup +import com.sn.snfilemanager.core.base.BaseDialog import com.sn.snfilemanager.core.extensions.click import com.sn.snfilemanager.databinding.DialogConfirmationBinding class ConfirmationDialog( - context: Context, private val title: String, private val question: String, -) : Dialog(context) { +) : BaseDialog() { var onSelected: ((Boolean) -> Unit)? = null - private val binding: DialogConfirmationBinding by lazy { - DialogConfirmationBinding.inflate(layoutInflater) - } + override val dialogTag: String + get() = "CONFIRMATION_DIALOG" + + override fun getViewBinding() = DialogConfirmationBinding.inflate(layoutInflater) - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(binding.root) - setCancelable(false) - setWindowProperty() + override var setCancelable: Boolean = false + override fun setupViews() { binding.tvTitle.text = title binding.tvQuestion.text = question @@ -37,11 +30,4 @@ class ConfirmationDialog( dismiss() } } - - private fun setWindowProperty() { - window?.apply { - setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) - setGravity(Gravity.CENTER) - } - } } diff --git a/app/src/main/java/com/sn/snfilemanager/view/dialog/ConflictDialog.kt b/app/src/main/java/com/sn/snfilemanager/view/dialog/ConflictDialog.kt index 8e2bcdb..9d5e389 100644 --- a/app/src/main/java/com/sn/snfilemanager/view/dialog/ConflictDialog.kt +++ b/app/src/main/java/com/sn/snfilemanager/view/dialog/ConflictDialog.kt @@ -1,47 +1,29 @@ package com.sn.snfilemanager.view.dialog -import android.app.Dialog -import android.content.Context -import android.os.Bundle -import android.view.Gravity -import android.view.ViewGroup +import android.content.DialogInterface import com.sn.mediastorepv.data.ConflictStrategy +import com.sn.snfilemanager.core.base.BaseDialog import com.sn.snfilemanager.core.extensions.click import com.sn.snfilemanager.databinding.DialogConflictBinding class ConflictDialog( - context: Context, private val fileName: String, -) : Dialog(context) { - private val binding: DialogConflictBinding by lazy { - DialogConflictBinding.inflate(layoutInflater) - } - +) : BaseDialog() { var onSelected: ((ConflictStrategy, Boolean) -> Unit)? = null var onDismiss: (() -> Unit)? = null - init { - setOnDismissListener { - onDismiss?.invoke() - } - } + override fun getViewBinding() = DialogConflictBinding.inflate(layoutInflater) - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(binding.root) - setCancelable(false) - setWindowProperty() - initView() - } + override var setCancelable: Boolean = false + override val dialogTag: String + get() = "CONFLICT_DIALOG" - private fun setWindowProperty() { - window?.apply { - setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) - setGravity(Gravity.CENTER) - } + override fun onDismiss(dialog: DialogInterface) { + super.onDismiss(dialog) + onDismiss?.invoke() } - private fun initView() { + override fun setupViews() { with(binding) { tvFileName.text = fileName btnSkip.click { diff --git a/app/src/main/java/com/sn/snfilemanager/view/dialog/CreateDirectoryDialog.kt b/app/src/main/java/com/sn/snfilemanager/view/dialog/CreateDirectoryDialog.kt index 085e15a..b391bb2 100644 --- a/app/src/main/java/com/sn/snfilemanager/view/dialog/CreateDirectoryDialog.kt +++ b/app/src/main/java/com/sn/snfilemanager/view/dialog/CreateDirectoryDialog.kt @@ -1,13 +1,8 @@ package com.sn.snfilemanager.view.dialog -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.widget.addTextChangedListener -import androidx.fragment.app.DialogFragment import com.sn.snfilemanager.R +import com.sn.snfilemanager.core.base.BaseDialog import com.sn.snfilemanager.core.extensions.click import com.sn.snfilemanager.databinding.DialogCreateDirectoryBinding import java.nio.file.Files @@ -17,36 +12,13 @@ import java.nio.file.Paths class CreateDirectoryDialog( private val path: String, private val onCreate: ((Path) -> Unit)? = null, -) : DialogFragment() { - private val binding: DialogCreateDirectoryBinding by lazy { - DialogCreateDirectoryBinding.inflate(layoutInflater) - } - - companion object { - const val TAG = "CREATE_DIRECTORY_DIALOG" - } +) : BaseDialog() { + override val dialogTag: String + get() = "CREATE_DIRECTORY_DIALOG" - override fun onStart() { - super.onStart() - dialog?.window?.setLayout( - ConstraintLayout.LayoutParams.MATCH_PARENT, - ConstraintLayout.LayoutParams.WRAP_CONTENT, - ) - } - - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle?, - ): View { - return binding.root - } + override fun getViewBinding() = DialogCreateDirectoryBinding.inflate(layoutInflater) - override fun onViewCreated( - view: View, - savedInstanceState: Bundle?, - ) { - super.onViewCreated(view, savedInstanceState) + override fun setupViews() { binding.etFolderName.requestFocus() binding.btnCancel.click { dismiss() } binding.btnCreate.click { diff --git a/app/src/main/java/com/sn/snfilemanager/view/dialog/RenameFileDialog.kt b/app/src/main/java/com/sn/snfilemanager/view/dialog/RenameFileDialog.kt index ab33a8d..1f071cb 100644 --- a/app/src/main/java/com/sn/snfilemanager/view/dialog/RenameFileDialog.kt +++ b/app/src/main/java/com/sn/snfilemanager/view/dialog/RenameFileDialog.kt @@ -1,14 +1,10 @@ package com.sn.snfilemanager.view.dialog -import android.os.Bundle -import android.view.LayoutInflater import android.view.View -import android.view.ViewGroup -import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.widget.addTextChangedListener -import androidx.fragment.app.DialogFragment import com.sn.mediastorepv.data.Media import com.sn.snfilemanager.R +import com.sn.snfilemanager.core.base.BaseDialog import com.sn.snfilemanager.core.extensions.click import com.sn.snfilemanager.core.extensions.gone import com.sn.snfilemanager.core.extensions.visible @@ -24,10 +20,11 @@ import kotlin.io.path.nameWithoutExtension class RenameFileDialog( private val file: T, private val onRename: ((String) -> Unit)? = null, -) : DialogFragment() { - private val binding: DialogRenameFileBinding by lazy { - DialogRenameFileBinding.inflate(layoutInflater) - } +) : BaseDialog() { + override fun getViewBinding() = DialogRenameFileBinding.inflate(layoutInflater) + + override val dialogTag: String + get() = "RENAME_FILE_DIALOG" val nameExtractor: (T) -> String = { item -> when (item) { @@ -37,32 +34,7 @@ class RenameFileDialog( } } - companion object { - const val TAG = "RENAME_FILE_DIALOG" - } - - override fun onStart() { - super.onStart() - dialog?.window?.setLayout( - ConstraintLayout.LayoutParams.MATCH_PARENT, - ConstraintLayout.LayoutParams.WRAP_CONTENT, - ) - } - - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle?, - ): View { - return binding.root - } - - override fun onViewCreated( - view: View, - savedInstanceState: Bundle?, - ) { - super.onViewCreated(view, savedInstanceState) - + override fun setupViews() { binding.btnCancel.click { dismiss() } val path = Paths.get(nameExtractor(file)) diff --git a/app/src/main/java/com/sn/snfilemanager/view/dialog/RootSelectorDialog.kt b/app/src/main/java/com/sn/snfilemanager/view/dialog/RootSelectorDialog.kt new file mode 100644 index 0000000..5a63124 --- /dev/null +++ b/app/src/main/java/com/sn/snfilemanager/view/dialog/RootSelectorDialog.kt @@ -0,0 +1,11 @@ +package com.sn.snfilemanager.view.dialog + +import com.sn.snfilemanager.core.base.BaseDialog +import com.sn.snfilemanager.databinding.DialogRootSelectorBinding + +class RootSelectorDialog : BaseDialog() { + override fun getViewBinding() = DialogRootSelectorBinding.inflate(layoutInflater) + + override val dialogTag: String + get() = "ROOT_SELECTOR_DIALOG" +} diff --git a/app/src/main/java/com/sn/snfilemanager/view/dialog/detail/DetailDialog.kt b/app/src/main/java/com/sn/snfilemanager/view/dialog/detail/DetailDialog.kt index c756f06..a54af08 100644 --- a/app/src/main/java/com/sn/snfilemanager/view/dialog/detail/DetailDialog.kt +++ b/app/src/main/java/com/sn/snfilemanager/view/dialog/detail/DetailDialog.kt @@ -1,12 +1,8 @@ package com.sn.snfilemanager.view.dialog.detail import android.content.Context -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.fragment.app.DialogFragment import androidx.fragment.app.viewModels +import com.sn.snfilemanager.core.base.BaseDialog import com.sn.snfilemanager.core.extensions.click import com.sn.snfilemanager.core.extensions.observe import com.sn.snfilemanager.databinding.DialogDetailBinding @@ -14,30 +10,16 @@ import com.sn.snfilemanager.databinding.DialogDetailBinding class DetailDialog( private val context: Context, private val itemList: MutableList, -) : DialogFragment() { - private var adapter: DetailItemAdapter? = null +) : BaseDialog() { private val viewModel: DetailDialogViewModel by viewModels() - private val binding: DialogDetailBinding by lazy { - DialogDetailBinding.inflate(layoutInflater) - } + private var adapter: DetailItemAdapter? = null - companion object { - const val TAG = "DETAIL_DIALOG" - } + override fun getViewBinding() = DialogDetailBinding.inflate(layoutInflater) - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle?, - ): View { - return binding.root - } + override val dialogTag: String + get() = "DETAIL_DIALOG" - override fun onViewCreated( - view: View, - savedInstanceState: Bundle?, - ) { - super.onViewCreated(view, savedInstanceState) + override fun setupViews() { binding.vm = viewModel binding.lifecycleOwner = viewLifecycleOwner isCancelable = true diff --git a/app/src/main/java/com/sn/snfilemanager/view/dialog/license/LicenseAdapter.kt b/app/src/main/java/com/sn/snfilemanager/view/dialog/license/LicenseAdapter.kt index 319536b..fffa674 100644 --- a/app/src/main/java/com/sn/snfilemanager/view/dialog/license/LicenseAdapter.kt +++ b/app/src/main/java/com/sn/snfilemanager/view/dialog/license/LicenseAdapter.kt @@ -76,7 +76,7 @@ class LicenseAdapter(private val context: Context) : binding.mtvLicense.click { if (adapterPosition != RecyclerView.NO_POSITION) { val clickedLicense = licenses[adapterPosition] - context.openUrl(clickedLicense.url) + context.openUrl(clickedLicense.license) } } } diff --git a/app/src/main/java/com/sn/snfilemanager/view/dialog/license/LicenseDialog.kt b/app/src/main/java/com/sn/snfilemanager/view/dialog/license/LicenseDialog.kt index 3cf9418..fdecf8a 100644 --- a/app/src/main/java/com/sn/snfilemanager/view/dialog/license/LicenseDialog.kt +++ b/app/src/main/java/com/sn/snfilemanager/view/dialog/license/LicenseDialog.kt @@ -1,51 +1,16 @@ package com.sn.snfilemanager.view.dialog.license -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 com.sn.snfilemanager.R +import com.sn.snfilemanager.core.base.BaseDialog import com.sn.snfilemanager.core.extensions.click import com.sn.snfilemanager.databinding.DialogLicenseBinding -class LicenseDialog : DialogFragment() { - companion object { - const val TAG = "LICENSE_DIALOG" - } - - private val binding: DialogLicenseBinding by lazy { - DialogLicenseBinding.inflate(layoutInflater) - } - - override fun onStart() { - super.onStart() - dialog?.window?.setLayout( - ConstraintLayout.LayoutParams.MATCH_PARENT, - ConstraintLayout.LayoutParams.MATCH_PARENT, - ) - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setStyle(STYLE_NO_TITLE, R.style.DialogTheme_transparent) - dialog?.window?.setBackgroundDrawableResource(R.drawable.dialog_rounded) - } +class LicenseDialog : BaseDialog() { + override fun getViewBinding() = DialogLicenseBinding.inflate(layoutInflater) - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle?, - ): View { - return binding.root - } + override val dialogTag: String + get() = "LICENSE_DIALOG" - override fun onViewCreated( - view: View, - savedInstanceState: Bundle?, - ) { - super.onViewCreated(view, savedInstanceState) + override fun setupViews() { binding.recycler.adapter = LicenseAdapter(requireContext()) binding.ivClose.click { dismiss() } } diff --git a/app/src/main/java/com/sn/snfilemanager/view/dialog/permission/PermissionDialog.kt b/app/src/main/java/com/sn/snfilemanager/view/dialog/permission/PermissionDialog.kt index 34c3fa6..8d6472b 100644 --- a/app/src/main/java/com/sn/snfilemanager/view/dialog/permission/PermissionDialog.kt +++ b/app/src/main/java/com/sn/snfilemanager/view/dialog/permission/PermissionDialog.kt @@ -1,33 +1,25 @@ package com.sn.snfilemanager.view.dialog.permission -import android.app.Dialog -import android.content.Context -import android.os.Bundle -import android.view.Gravity -import android.view.ViewGroup -import com.google.android.material.button.MaterialButton -import com.google.android.material.textview.MaterialTextView import com.sn.snfilemanager.R +import com.sn.snfilemanager.core.base.BaseDialog import com.sn.snfilemanager.core.extensions.click +import com.sn.snfilemanager.databinding.DialogPermissionBinding class PermissionDialog( - context: Context, private val type: PermissionDialogType, -) : Dialog(context) { +) : BaseDialog() { var onAllow: (() -> Unit)? = null - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.dialog_permission) + override fun getViewBinding() = DialogPermissionBinding.inflate(layoutInflater) - window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) - window?.setGravity(Gravity.CENTER) - - setCancelable(false) + override var setCancelable: Boolean = false + override val dialogTag: String + get() = "PERMISSION_DIALOG" + override fun setupViews() { val values = getValuesByType() - findViewById(R.id.tv_permission_info).text = values.first - findViewById(R.id.btn_allow).apply { + binding.tvPermissionInfo.text = values.first + binding.btnAllow.apply { text = values.second click { onAllow?.invoke() @@ -39,13 +31,13 @@ class PermissionDialog( private fun getValuesByType(): Pair = if (type == PermissionDialogType.DEFAULT) { Pair( - context.getString(R.string.permission_message), - context.getString(R.string.click_to_allow), + requireContext().getString(R.string.permission_message), + requireContext().getString(R.string.click_to_allow), ) } else { Pair( - context.getString(R.string.permission_warning_message), - context.getString(R.string.go_to_settings), + requireContext().getString(R.string.permission_warning_message), + requireContext().getString(R.string.go_to_settings), ) } } diff --git a/app/src/main/res/drawable/dialog_rounded.xml b/app/src/main/res/drawable/dialog_rounded.xml index 349d63f..3690831 100644 --- a/app/src/main/res/drawable/dialog_rounded.xml +++ b/app/src/main/res/drawable/dialog_rounded.xml @@ -1,8 +1,8 @@ + android:insetBottom="20dp"> diff --git a/app/src/main/res/layout/dialog_permission.xml b/app/src/main/res/layout/dialog_permission.xml index 8e2fe35..40ae726 100644 --- a/app/src/main/res/layout/dialog_permission.xml +++ b/app/src/main/res/layout/dialog_permission.xml @@ -3,10 +3,11 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/container" android:layout_width="match_parent" - android:layout_height="@dimen/_300sdp" + android:layout_height="wrap_content" android:layout_gravity="center" android:background="@color/bg_color" android:elevation="@dimen/_5sdp" + android:minHeight="@dimen/_230sdp" app:layout_constraintCircleRadius="@dimen/_20sdp"> + + + + + + + \ No newline at end of file From e2fe1f4e8cbac8ae3732550649c668018cc797a0 Mon Sep 17 00:00:00 2001 From: Emre Esen Date: Fri, 19 Apr 2024 20:27:53 +0300 Subject: [PATCH 7/9] [FIX][permission and detail dialog design imp] --- app/src/main/res/layout/dialog_detail.xml | 4 ++-- app/src/main/res/layout/dialog_permission.xml | 23 +++++++++---------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/app/src/main/res/layout/dialog_detail.xml b/app/src/main/res/layout/dialog_detail.xml index 3b05452..a277de0 100644 --- a/app/src/main/res/layout/dialog_detail.xml +++ b/app/src/main/res/layout/dialog_detail.xml @@ -48,8 +48,8 @@ + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> - + app:layout_constraintStart_toStartOf="@+id/container" + app:layout_constraintTop_toBottomOf="@+id/tv_permission_info" /> \ No newline at end of file From 25c030baef706c63985523e90f59cedd9811177d Mon Sep 17 00:00:00 2001 From: Emre Esen Date: Sat, 20 Apr 2024 20:23:55 +0300 Subject: [PATCH 8/9] [FIX][root selector dialog removed] --- .../view/dialog/RootSelectorDialog.kt | 11 -------- .../main/res/layout/dialog_root_selector.xml | 25 ------------------- 2 files changed, 36 deletions(-) delete mode 100644 app/src/main/java/com/sn/snfilemanager/view/dialog/RootSelectorDialog.kt delete mode 100644 app/src/main/res/layout/dialog_root_selector.xml diff --git a/app/src/main/java/com/sn/snfilemanager/view/dialog/RootSelectorDialog.kt b/app/src/main/java/com/sn/snfilemanager/view/dialog/RootSelectorDialog.kt deleted file mode 100644 index 5a63124..0000000 --- a/app/src/main/java/com/sn/snfilemanager/view/dialog/RootSelectorDialog.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.sn.snfilemanager.view.dialog - -import com.sn.snfilemanager.core.base.BaseDialog -import com.sn.snfilemanager.databinding.DialogRootSelectorBinding - -class RootSelectorDialog : BaseDialog() { - override fun getViewBinding() = DialogRootSelectorBinding.inflate(layoutInflater) - - override val dialogTag: String - get() = "ROOT_SELECTOR_DIALOG" -} diff --git a/app/src/main/res/layout/dialog_root_selector.xml b/app/src/main/res/layout/dialog_root_selector.xml deleted file mode 100644 index b76bdfb..0000000 --- a/app/src/main/res/layout/dialog_root_selector.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - \ No newline at end of file From 2c148ebcd17a4836fd9ab242d842ac592309377e Mon Sep 17 00:00:00 2001 From: emreesen27 <45034416+emreesen27@users.noreply.github.com> Date: Wed, 24 Apr 2024 22:54:28 +0300 Subject: [PATCH 9/9] [DEV][Update CHANGELOG.md] --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ef5b869..5f7a251 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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