Merge pull request #2898 from esensar/fix/1886-subfolder-grouping-simplification

Make subfolder grouping follow file structure
This commit is contained in:
Tibor Kaputa 2023-07-21 21:33:36 +02:00 committed by GitHub
commit 02f302dda4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -23,7 +23,6 @@ import com.bumptech.glide.load.resource.bitmap.RoundedCorners
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
import com.bumptech.glide.request.RequestListener import com.bumptech.glide.request.RequestListener
import com.bumptech.glide.request.RequestOptions import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.request.target.Target
import com.bumptech.glide.signature.ObjectKey import com.bumptech.glide.signature.ObjectKey
import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.* import com.simplemobiletools.commons.helpers.*
@ -136,6 +135,7 @@ fun Context.getSortedDirectories(source: ArrayList<Directory>): ArrayList<Direct
o1.sortValue.normalizeString().toLowerCase().compareTo(o2.sortValue.normalizeString().toLowerCase()) o1.sortValue.normalizeString().toLowerCase().compareTo(o2.sortValue.normalizeString().toLowerCase())
} }
} }
sorting and SORT_BY_PATH != 0 -> { sorting and SORT_BY_PATH != 0 -> {
if (o1.sortValue.isEmpty()) { if (o1.sortValue.isEmpty()) {
o1.sortValue = o1.path.toLowerCase() o1.sortValue = o1.path.toLowerCase()
@ -151,6 +151,7 @@ fun Context.getSortedDirectories(source: ArrayList<Directory>): ArrayList<Direct
o1.sortValue.toLowerCase().compareTo(o2.sortValue.toLowerCase()) o1.sortValue.toLowerCase().compareTo(o2.sortValue.toLowerCase())
} }
} }
sorting and SORT_BY_PATH != 0 -> AlphanumericComparator().compare(o1.sortValue.toLowerCase(), o2.sortValue.toLowerCase()) sorting and SORT_BY_PATH != 0 -> AlphanumericComparator().compare(o1.sortValue.toLowerCase(), o2.sortValue.toLowerCase())
sorting and SORT_BY_SIZE != 0 -> (o1.sortValue.toLongOrNull() ?: 0).compareTo(o2.sortValue.toLongOrNull() ?: 0) sorting and SORT_BY_SIZE != 0 -> (o1.sortValue.toLongOrNull() ?: 0).compareTo(o2.sortValue.toLongOrNull() ?: 0)
sorting and SORT_BY_DATE_MODIFIED != 0 -> (o1.sortValue.toLongOrNull() ?: 0).compareTo(o2.sortValue.toLongOrNull() ?: 0) sorting and SORT_BY_DATE_MODIFIED != 0 -> (o1.sortValue.toLongOrNull() ?: 0).compareTo(o2.sortValue.toLongOrNull() ?: 0)
@ -195,90 +196,89 @@ fun Context.getDirsToShow(dirs: ArrayList<Directory>, allDirs: ArrayList<Directo
fun Context.getDirectParentSubfolders(dirs: ArrayList<Directory>, currentPathPrefix: String): ArrayList<Directory> { fun Context.getDirectParentSubfolders(dirs: ArrayList<Directory>, currentPathPrefix: String): ArrayList<Directory> {
val folders = dirs.map { it.path }.sorted().toMutableSet() as HashSet<String> val folders = dirs.map { it.path }.sorted().toMutableSet() as HashSet<String>
val currentPaths = LinkedHashSet<String>() // Sort by path length, to ensure that parents get processed first
val foldersWithoutMediaFiles = ArrayList<String>() val foldersByPathLength = dirs.filter {
currentPathPrefix.isEmpty() ||
(it.path.startsWith(currentPathPrefix, true) && it.path != currentPathPrefix)
}.sortedBy {
it.path.length
}
var newDirId = 1000L var newDirId = 1000L
val groups = mutableMapOf<String, MutableList<Directory>>()
for (path in folders) { for (folder in foldersByPathLength) {
if (path == RECYCLE_BIN || path == FAVORITES) { val parent = groups.keys.firstOrNull { folder.path.startsWith(it, true) }
continue if (parent != null) {
} // If we have parent in top level groups
// Add this folder to that group,
// but also add all folders in between which may not have media files
groups.getOrPut(parent, ::mutableListOf).apply {
var midParent = File(folder.path).parent
while (midParent != null && none { it.path.equals(midParent, true) }) {
val isSortingAscending = config.sorting.isSortingAscending()
val subDirs = dirs.filter { File(it.path).parent.equals(midParent, true) } as ArrayList<Directory>
if (subDirs.isNotEmpty()) {
val lastModified = if (isSortingAscending) {
subDirs.minByOrNull { it.modified }?.modified
} else {
subDirs.maxByOrNull { it.modified }?.modified
} ?: 0
if (currentPathPrefix.isNotEmpty()) { val dateTaken = if (isSortingAscending) {
if (!path.startsWith(currentPathPrefix, true)) { subDirs.minByOrNull { it.taken }?.taken
continue } else {
} subDirs.maxByOrNull { it.taken }?.taken
} ?: 0
if (!File(path).parent.equals(currentPathPrefix, true)) { var mediaTypes = 0
continue subDirs.forEach {
} mediaTypes = mediaTypes or it.types
} }
if (currentPathPrefix.isNotEmpty() && path.equals(currentPathPrefix, true) || File(path).parent.equals(currentPathPrefix, true)) { val directory = Directory(
currentPaths.add(path) newDirId++,
} else if (folders.any { !it.equals(path, true) && (File(path).parent.equals(it, true) || File(it).parent.equals(File(path).parent, true)) }) { midParent,
// if we have folders like subDirs.first().tmb,
// /storage/emulated/0/Pictures/Images and getFolderNameFromPath(midParent),
// /storage/emulated/0/Pictures/Screenshots, subDirs.sumBy { it.mediaCnt },
// but /storage/emulated/0/Pictures is empty, still Pictures with the first folders thumbnails and proper other info lastModified,
val parent = File(path).parent dateTaken,
if (parent != null && !folders.contains(parent) && dirs.none { it.path.equals(parent, true) }) { subDirs.sumByLong { it.size },
currentPaths.add(parent) getPathLocation(midParent),
val isSortingAscending = config.sorting.isSortingAscending() mediaTypes,
val subDirs = dirs.filter { File(it.path).parent.equals(File(path).parent, true) } as ArrayList<Directory> ""
if (subDirs.isNotEmpty()) { )
val lastModified = if (isSortingAscending) {
subDirs.minByOrNull { it.modified }?.modified
} else {
subDirs.maxByOrNull { it.modified }?.modified
} ?: 0
val dateTaken = if (isSortingAscending) { directory.containsMediaFilesDirectly = false
subDirs.minByOrNull { it.taken }?.taken dirs.add(directory)
} else { add(directory)
subDirs.maxByOrNull { it.taken }?.taken
} ?: 0
var mediaTypes = 0
subDirs.forEach {
mediaTypes = mediaTypes or it.types
} }
midParent = File(midParent).parent
val directory = Directory(
newDirId++,
parent,
subDirs.first().tmb,
getFolderNameFromPath(parent),
subDirs.sumBy { it.mediaCnt },
lastModified,
dateTaken,
subDirs.sumByLong { it.size },
getPathLocation(parent),
mediaTypes,
""
)
directory.containsMediaFilesDirectly = false
dirs.add(directory)
currentPaths.add(parent)
foldersWithoutMediaFiles.add(parent)
} }
add(folder)
} }
} else { } else {
currentPaths.add(path) // If we have don't have parent in top level groups
} // Set this folder as top level group if it is direct child
} if (currentPathPrefix.isEmpty() || File(folder.path).parent.equals(currentPathPrefix, true)) {
groups.getOrPut(folder.path, ::mutableListOf).add(folder)
var areDirectSubfoldersAvailable = false } else {
currentPaths.forEach { // Otherwise find its parent which is a direct child of current path prefix
val path = it // And create a group for it
currentPaths.forEach { var firstVisibleParent = File(folder.path).parent
if (!foldersWithoutMediaFiles.contains(it) && !it.equals(path, true) && File(it).parent?.equals(path, true) == true) { while (firstVisibleParent != null && !File(firstVisibleParent).parent.equals(currentPathPrefix, true)) {
areDirectSubfoldersAvailable = true firstVisibleParent = File(firstVisibleParent).parent
}
if (firstVisibleParent != null) {
groups.getOrPut(firstVisibleParent, ::mutableListOf).add(folder)
}
} }
} }
} }
val currentPaths = groups.keys.toMutableList()
if (currentPathPrefix.isEmpty() && folders.contains(RECYCLE_BIN)) { if (currentPathPrefix.isEmpty() && folders.contains(RECYCLE_BIN)) {
currentPaths.add(RECYCLE_BIN) currentPaths.add(RECYCLE_BIN)
} }
@ -294,12 +294,7 @@ fun Context.getDirectParentSubfolders(dirs: ArrayList<Directory>, currentPathPre
folders.clear() folders.clear()
folders.addAll(currentPaths) folders.addAll(currentPaths)
val dirsToShow = dirs.filter { folders.contains(it.path) } as ArrayList<Directory> return dirs.filter { folders.contains(it.path) } as ArrayList<Directory>
return if (areDirectSubfoldersAvailable) {
getDirectParentSubfolders(dirsToShow, currentPathPrefix)
} else {
dirsToShow
}
} }
fun Context.updateSubfolderCounts(children: ArrayList<Directory>, parentDirs: ArrayList<Directory>) { fun Context.updateSubfolderCounts(children: ArrayList<Directory>, parentDirs: ArrayList<Directory>) {