Skip to content

Commit

Permalink
Merge pull request #55 from emreesen27/v1.0.0-beta8
Browse files Browse the repository at this point in the history
V1.0.0 beta8
  • Loading branch information
emreesen27 authored May 25, 2024
2 parents 83147d5 + 5d8dd8e commit b76d11a
Show file tree
Hide file tree
Showing 24 changed files with 453 additions and 24 deletions.
8 changes: 6 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
## v1.0.0-beta-8 (25.05.2024)
* Sorting feature added for file and media items
* The synchronization issue with the show hidden files setting button has been fixed

## v1.0.0-beta7 (26.04.2024)

* ActivityNotFoundException and ClassNotFoundException fixed.
* ActivityNotFoundException and ClassNotFoundException fixed

## 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.
* The 'Access Denied' error in the function calculating file count and size fixed

## v1.0.0-beta5 (08.04.2024)

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 7
versionName "1.0.0-beta7"
versionCode 8
versionName "1.0.0-beta8"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
Expand Down
17 changes: 17 additions & 0 deletions app/src/main/java/com/sn/snfilemanager/MainViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ package com.sn.snfilemanager
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.sn.snfilemanager.core.util.Config
import com.sn.snfilemanager.core.util.Event
import com.sn.snfilemanager.core.util.SortCriterion
import com.sn.snfilemanager.core.util.SortOrder
import com.sn.snfilemanager.providers.preferences.MySharedPreferences
import com.sn.snfilemanager.providers.preferences.PrefsTag
import dagger.hilt.android.lifecycle.HiltViewModel
Expand All @@ -20,10 +23,24 @@ class MainViewModel

init {
checkFirsRun()
getSortData()
}

private fun checkFirsRun() {
val firstRun: Boolean = mySharedPreferences.getBoolean(PrefsTag.FIRST_RUN)
_firstRunLiveData.postValue(Event(firstRun))
}

private fun getSortData() {
val criterionString = mySharedPreferences.getString(PrefsTag.SORT_CRITERION)
val sortOrderString = mySharedPreferences.getString(PrefsTag.SORT_ORDER)
val mediaCriterionString = mySharedPreferences.getString(PrefsTag.MEDIA_SORT_CRITERION)
val mediaSortOrderString = mySharedPreferences.getString(PrefsTag.MEDIA_SORT_ORDER)

Config.sortCriterion = SortCriterion.valueOf(criterionString ?: SortCriterion.NAME.name)
Config.sortOrder = SortOrder.valueOf(sortOrderString ?: SortOrder.ASCENDING.name)

Config.mediaSortCriterion = SortCriterion.valueOf(mediaCriterionString ?: SortCriterion.NAME.name)
Config.mediaSortOrder = SortOrder.valueOf(mediaSortOrderString ?: SortOrder.ASCENDING.name)
}
}
11 changes: 11 additions & 0 deletions app/src/main/java/com/sn/snfilemanager/core/extensions/String.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package com.sn.snfilemanager.core.extensions

import android.webkit.MimeTypeMap
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale

fun String.getDirectoryNameFromPath(): String {
val lastSeparatorIndex = this.lastIndexOf("/")
Expand All @@ -24,3 +27,11 @@ fun String.getMimeType(): String? {
val ext = if (extension.isNullOrEmpty()) this.getFileExtension() else extension
return MimeTypeMap.getSingleton().getMimeTypeFromExtension(ext)
}

fun String.toDate(format: String = "dd/MM/yyyy"): Date? {
return try {
SimpleDateFormat(format, Locale.getDefault()).parse(this)
} catch (e: Exception) {
null
}
}
4 changes: 4 additions & 0 deletions app/src/main/java/com/sn/snfilemanager/core/util/Config.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,8 @@ package com.sn.snfilemanager.core.util

object Config {
var hiddenFile: Boolean = false
var sortCriterion: SortCriterion = SortCriterion.NAME
var sortOrder: SortOrder = SortOrder.ASCENDING
var mediaSortCriterion: SortCriterion = SortCriterion.NAME
var mediaSortOrder: SortOrder = SortOrder.ASCENDING
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.sn.snfilemanager.core.util

enum class SortCriterion {
NAME,
LAST_MODIFIED,
}
6 changes: 6 additions & 0 deletions app/src/main/java/com/sn/snfilemanager/core/util/SortOrder.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.sn.snfilemanager.core.util

enum class SortOrder {
ASCENDING,
DESCENDING,
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import com.sn.snfilemanager.core.extensions.openFileWithOtherApp
import com.sn.snfilemanager.core.extensions.shareFiles
import com.sn.snfilemanager.core.extensions.visible
import com.sn.snfilemanager.core.extensions.warningToast
import com.sn.snfilemanager.core.util.Config.sortCriterion
import com.sn.snfilemanager.core.util.Config.sortOrder
import com.sn.snfilemanager.core.util.RootPath
import com.sn.snfilemanager.databinding.FragmentFilesListBinding
import com.sn.snfilemanager.feature.files.adapter.FileItemAdapter
Expand All @@ -37,6 +39,7 @@ 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 com.sn.snfilemanager.view.dialog.sort.SortDialog
import dagger.hilt.android.AndroidEntryPoint
import java.io.File
import java.nio.file.Files
Expand Down Expand Up @@ -68,6 +71,11 @@ class FilesListFragment :
true
}

R.id.sort -> {
showSortDialog()
true
}

R.id.create_folder -> {
viewModel.currentPath?.let { path ->
showCreateDirectoryDialog(path)
Expand Down Expand Up @@ -188,15 +196,21 @@ class FilesListFragment :
JobType.CREATE -> {
activity?.runOnUiThread {
data?.filterIsInstance<Path>()?.firstOrNull()?.toFileModel()?.let { file ->
adapter?.addItem(file)
// adapter?.addItem(file)
viewModel.currentPath?.let { path ->
viewModel.getFilesList(path)
}
}
}
}

JobType.RENAME -> {
activity?.runOnUiThread {
data?.filterIsInstance<FileModel>()?.firstOrNull()?.let { file ->
adapter?.updateItem(file)
// adapter?.updateItem(file)
viewModel.currentPath?.let { path ->
viewModel.getFilesList(path)
}
}
}
}
Expand Down Expand Up @@ -379,6 +393,14 @@ class FilesListFragment :
}).showDialog(childFragmentManager)
}

private fun showSortDialog() {
SortDialog(isMedia = false, onConfirm = { sortData ->
sortCriterion = sortData.first
sortOrder = sortData.second
with(viewModel) { currentPath?.let { getFilesList(it) } }
}).showDialog(childFragmentManager)
}

private fun showRenameDialog() {
RenameFileDialog(file = viewModel.getSelectedItem().first(), onRename = { newName ->
viewModel.renameFile(newName)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,14 @@ import androidx.lifecycle.viewModelScope
import com.sn.mediastorepv.data.ConflictStrategy
import com.sn.mediastorepv.data.MediaType
import com.sn.snfilemanager.core.base.BaseResult
import com.sn.snfilemanager.core.extensions.toDate
import com.sn.snfilemanager.core.util.Config
import com.sn.snfilemanager.core.util.Config.sortCriterion
import com.sn.snfilemanager.core.util.Config.sortOrder
import com.sn.snfilemanager.core.util.Event
import com.sn.snfilemanager.core.util.RootPath
import com.sn.snfilemanager.core.util.SortCriterion
import com.sn.snfilemanager.core.util.SortOrder
import com.sn.snfilemanager.feature.files.data.FileModel
import com.sn.snfilemanager.feature.files.data.toFileModel
import com.sn.snfilemanager.providers.filepath.FilePathProvider
Expand All @@ -28,6 +33,7 @@ import java.lang.Long.min
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
import java.util.Locale
import javax.inject.Inject

@HiltViewModel
Expand Down Expand Up @@ -73,7 +79,8 @@ class FilesListViewModel
private val _startCreateFolderJob: MutableLiveData<Event<Path>> = MutableLiveData()
val startCreateFolderJob: LiveData<Event<Path>> = _startCreateFolderJob

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

var conflictDialogDeferred = CompletableDeferred<Pair<ConflictStrategy, Boolean>>()
Expand Down Expand Up @@ -153,15 +160,13 @@ class FilesListViewModel
.limit(currentBatchSize)
.forEach { file ->
if (Files.isReadable(file) && (
Config.hiddenFile ||
!Files.isHidden(
file,
)
Config.hiddenFile || !Files.isHidden(file)
)
) {
fileList.add(file.toFileModel())
}
}
sortFileList(fileList)
}
withContext(Dispatchers.Main) {
_updateListLiveData.postValue(Event(fileList))
Expand All @@ -171,10 +176,6 @@ class FilesListViewModel
}
}

fun setUpdateList(files: MutableList<FileModel>) {
_updateListLiveData.postValue(Event(files))
}

fun cancelFileListJob() {
if (fileListJob != null && fileListJob?.isActive == true) {
fileListJob?.cancel()
Expand Down Expand Up @@ -222,7 +223,9 @@ class FilesListViewModel
}
}
job.await()
_startMoveJobLiveData.postValue(Event(Pair(operationItemList, destinationPath)))
if (operationItemList.isNotEmpty()) {
_startMoveJobLiveData.postValue(Event(Pair(operationItemList, destinationPath)))
}
}
}

Expand All @@ -247,6 +250,26 @@ class FilesListViewModel
_startDeleteJobLiveData.postValue(Event(operationItemList))
}

private fun sortFileList(fileList: MutableList<FileModel>) {
when (sortCriterion) {
SortCriterion.NAME -> {
if (sortOrder == SortOrder.ASCENDING) {
fileList.sortBy { it.name.lowercase(Locale.getDefault()) }
} else {
fileList.sortByDescending { it.name.lowercase(Locale.getDefault()) }
}
}

SortCriterion.LAST_MODIFIED -> {
if (sortOrder == SortOrder.ASCENDING) {
fileList.sortBy { it.lastModified.toDate() }
} else {
fileList.sortByDescending { it.lastModified.toDate() }
}
}
}
}

private fun removeSearchCallback() {
searchRunnable?.let { handler.removeCallbacks(it) }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import com.sn.snfilemanager.core.extensions.openFile
import com.sn.snfilemanager.core.extensions.openFileWithOtherApp
import com.sn.snfilemanager.core.extensions.shareFiles
import com.sn.snfilemanager.core.extensions.warningToast
import com.sn.snfilemanager.core.util.Config.mediaSortCriterion
import com.sn.snfilemanager.core.util.Config.mediaSortOrder
import com.sn.snfilemanager.core.util.DocumentType
import com.sn.snfilemanager.databinding.FragmentMediaBinding
import com.sn.snfilemanager.feature.media.adapter.MediaItemAdapter
Expand All @@ -29,6 +31,7 @@ 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 com.sn.snfilemanager.view.dialog.sort.SortDialog
import dagger.hilt.android.AndroidEntryPoint
import java.nio.file.Path
import java.nio.file.Paths
Expand Down Expand Up @@ -65,6 +68,10 @@ class MediaFragment :
true
}

R.id.sort -> {
showSortDialog()
true
}
else -> super.onMenuItemSelected(menuItemId)
}

Expand Down Expand Up @@ -192,6 +199,7 @@ class MediaFragment :
observe(getMediaLiveData) { event ->
event.getContentIfNotHandled()?.let { data ->
adapter?.setItems(data.toMutableList())
binding.recyclerView.scrollToPosition(0)
}
}
observe(conflictQuestionLiveData) { event ->
Expand Down Expand Up @@ -238,6 +246,16 @@ class MediaFragment :
context?.shareFiles(uris)
}

private fun showSortDialog() {
SortDialog(isMedia = true, onConfirm = { sortData ->
with(viewModel) {
mediaSortCriterion = sortData.first
mediaSortOrder = sortData.second
getMedia()
}
}).showDialog(childFragmentManager)
}

private fun actionDelete() {
ConfirmationDialog(
getString(R.string.are_you_sure),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,15 @@ import androidx.lifecycle.viewModelScope
import com.sn.mediastorepv.data.ConflictStrategy
import com.sn.mediastorepv.data.Media
import com.sn.mediastorepv.data.MediaType
import com.sn.mediastorepv.data.OrderStrategy
import com.sn.snfilemanager.core.base.BaseResult
import com.sn.snfilemanager.core.util.Config.mediaSortCriterion
import com.sn.snfilemanager.core.util.Config.mediaSortOrder
import com.sn.snfilemanager.core.util.DocumentType
import com.sn.snfilemanager.core.util.Event
import com.sn.snfilemanager.core.util.MimeTypes
import com.sn.snfilemanager.core.util.SortCriterion
import com.sn.snfilemanager.core.util.SortOrder
import com.sn.snfilemanager.providers.mediastore.MediaStoreProvider
import com.sn.snfilemanager.providers.preferences.MySharedPreferences
import com.sn.snfilemanager.providers.preferences.PrefsTag
Expand Down Expand Up @@ -83,11 +88,31 @@ class MediaViewModel
}
}

private fun getOrderStrategy(): String {
return when (mediaSortCriterion) {
SortCriterion.NAME -> {
if (mediaSortOrder == SortOrder.ASCENDING) {
OrderStrategy.name(OrderStrategy.ASC)
} else {
OrderStrategy.name(OrderStrategy.DESC)
}
}

SortCriterion.LAST_MODIFIED -> {
if (mediaSortOrder == SortOrder.ASCENDING) {
OrderStrategy.dateModified(OrderStrategy.ASC)
} else {
OrderStrategy.dateModified(OrderStrategy.DESC)
}
}
}
}

fun getMedia() =
viewModelScope.launch {
val filteredMediaTypes: MutableSet<String>? = getFilteredMediaTypes()
mediaType?.let {
when (val result = mediaStoreProvider.getMedia(it, getDocumentMime())) {
when (val result = mediaStoreProvider.getMedia(it, getDocumentMime(), order = getOrderStrategy())) {
is BaseResult.Success -> {
fullMediaList = result.data
fullMediaList?.let { mediaList ->
Expand Down Expand Up @@ -147,7 +172,9 @@ class MediaViewModel
}
}
job.await()
_startMoveJobLiveData.postValue(Event(Pair(operationItemList, destinationPath)))
if (operationItemList.isNotEmpty()) {
_startMoveJobLiveData.postValue(Event(Pair(operationItemList, destinationPath)))
}
}
}

Expand Down
Loading

0 comments on commit b76d11a

Please sign in to comment.