Format some code

No functionality changes.
This commit is contained in:
Naveen Singh 2025-03-11 21:36:02 +05:30
parent be9003788c
commit 8347e680a8
No known key found for this signature in database
GPG key ID: AF5D43C216778C0B
4 changed files with 791 additions and 237 deletions

View file

@ -1,6 +1,5 @@
package org.fossify.gallery.activities package org.fossify.gallery.activities
import android.app.Activity
import android.content.ClipData import android.content.ClipData
import android.content.Intent import android.content.Intent
import android.net.Uri import android.net.Uri
@ -173,8 +172,13 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
private var mWasMediaManagementPromptShown = false private var mWasMediaManagementPromptShown = false
private var mLatestMediaId = 0L private var mLatestMediaId = 0L
private var mLatestMediaDateId = 0L private var mLatestMediaDateId = 0L
private var mCurrentPathPrefix = "" // used at "Group direct subfolders" for navigation
private var mOpenedSubfolders = arrayListOf("") // used at "Group direct subfolders" for navigating Up with the back button // used at "Group direct subfolders" for navigation
private var mCurrentPathPrefix = ""
// used at "Group direct subfolders" for navigating Up with the back button
private var mOpenedSubfolders = arrayListOf("")
private var mDateFormat = "" private var mDateFormat = ""
private var mTimeFormat = "" private var mTimeFormat = ""
private var mLastMediaHandler = Handler() private var mLastMediaHandler = Handler()
@ -215,15 +219,19 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
mIsGetAnyContentIntent = isGetAnyContentIntent(intent) mIsGetAnyContentIntent = isGetAnyContentIntent(intent)
mIsSetWallpaperIntent = isSetWallpaperIntent(intent) mIsSetWallpaperIntent = isSetWallpaperIntent(intent)
mAllowPickingMultiple = intent.getBooleanExtra(Intent.EXTRA_ALLOW_MULTIPLE, false) mAllowPickingMultiple = intent.getBooleanExtra(Intent.EXTRA_ALLOW_MULTIPLE, false)
mIsThirdPartyIntent = mIsPickImageIntent || mIsPickVideoIntent || mIsGetImageContentIntent || mIsGetVideoContentIntent || mIsThirdPartyIntent = mIsPickImageIntent
mIsGetAnyContentIntent || mIsSetWallpaperIntent || mIsPickVideoIntent
|| mIsGetImageContentIntent
|| mIsGetVideoContentIntent
|| mIsGetAnyContentIntent
|| mIsSetWallpaperIntent
setupOptionsMenu() setupOptionsMenu()
refreshMenuItems() refreshMenuItems()
updateMaterialActivityViews( updateMaterialActivityViews(
binding.directoriesCoordinator, mainCoordinatorLayout = binding.directoriesCoordinator,
binding.directoriesGrid, nestedView = binding.directoriesGrid,
useTransparentNavigation = !config.scrollHorizontally, useTransparentNavigation = !config.scrollHorizontally,
useTopSearchMenu = true useTopSearchMenu = true
) )
@ -314,7 +322,8 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
getRecyclerAdapter()?.updatePrimaryColor() getRecyclerAdapter()?.updatePrimaryColor()
} }
val styleString = "${config.folderStyle}${config.showFolderMediaCount}${config.limitFolderTitle}" val styleString =
"${config.folderStyle}${config.showFolderMediaCount}${config.limitFolderTitle}"
if (mStoredStyleString != styleString) { if (mStoredStyleString != styleString) {
setupAdapter(mDirs, forceRecreate = true) setupAdapter(mDirs, forceRecreate = true)
} }
@ -403,17 +412,21 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
} }
override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) { override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) {
if (resultCode == Activity.RESULT_OK) { if (resultCode == RESULT_OK) {
if (requestCode == PICK_MEDIA && resultData != null) { if (requestCode == PICK_MEDIA && resultData != null) {
val resultIntent = Intent() val resultIntent = Intent()
var resultUri: Uri? = null var resultUri: Uri? = null
if (mIsThirdPartyIntent) { if (mIsThirdPartyIntent) {
when { when {
intent.extras?.containsKey(MediaStore.EXTRA_OUTPUT) == true && intent.flags and Intent.FLAG_GRANT_WRITE_URI_PERMISSION != 0 -> { intent.extras?.containsKey(MediaStore.EXTRA_OUTPUT) == true
&& intent.flags and Intent.FLAG_GRANT_WRITE_URI_PERMISSION != 0 -> {
resultUri = fillExtraOutput(resultData) resultUri = fillExtraOutput(resultData)
} }
resultData.extras?.containsKey(PICKED_PATHS) == true -> fillPickedPaths(resultData, resultIntent) resultData.extras?.containsKey(PICKED_PATHS) == true -> {
fillPickedPaths(resultData, resultIntent)
}
else -> fillIntentPath(resultData, resultIntent) else -> fillIntentPath(resultData, resultIntent)
} }
} }
@ -423,10 +436,10 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
resultIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) resultIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
} }
setResult(Activity.RESULT_OK, resultIntent) setResult(RESULT_OK, resultIntent)
finish() finish()
} else if (requestCode == PICK_WALLPAPER) { } else if (requestCode == PICK_WALLPAPER) {
setResult(Activity.RESULT_OK) setResult(RESULT_OK)
finish() finish()
} }
} }
@ -438,14 +451,17 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
binding.mainMenu.getToolbar().menu.apply { binding.mainMenu.getToolbar().menu.apply {
findItem(R.id.column_count).isVisible = config.viewTypeFolders == VIEW_TYPE_GRID findItem(R.id.column_count).isVisible = config.viewTypeFolders == VIEW_TYPE_GRID
findItem(R.id.set_as_default_folder).isVisible = !config.defaultFolder.isEmpty() findItem(R.id.set_as_default_folder).isVisible = !config.defaultFolder.isEmpty()
findItem(R.id.open_recycle_bin).isVisible = config.useRecycleBin && !config.showRecycleBinAtFolders findItem(R.id.open_recycle_bin).isVisible =
findItem(R.id.more_apps_from_us).isVisible = !resources.getBoolean(org.fossify.commons.R.bool.hide_google_relations) config.useRecycleBin && !config.showRecycleBinAtFolders
findItem(R.id.more_apps_from_us).isVisible =
!resources.getBoolean(org.fossify.commons.R.bool.hide_google_relations)
} }
} }
binding.mainMenu.getToolbar().menu.apply { binding.mainMenu.getToolbar().menu.apply {
findItem(R.id.temporarily_show_hidden).isVisible = !config.shouldShowHidden findItem(R.id.temporarily_show_hidden).isVisible = !config.shouldShowHidden
findItem(R.id.stop_showing_hidden).isVisible = (!isRPlus() || isExternalStorageManager()) && config.temporarilyShowHidden findItem(R.id.stop_showing_hidden).isVisible =
(!isRPlus() || isExternalStorageManager()) && config.temporarilyShowHidden
findItem(R.id.temporarily_show_excluded).isVisible = !config.temporarilyShowExcluded findItem(R.id.temporarily_show_excluded).isVisible = !config.temporarilyShowExcluded
findItem(R.id.stop_showing_excluded).isVisible = config.temporarilyShowExcluded findItem(R.id.stop_showing_excluded).isVisible = config.temporarilyShowExcluded
@ -471,7 +487,8 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
binding.mainMenu.onSearchTextChangedListener = { text -> binding.mainMenu.onSearchTextChangedListener = { text ->
setupAdapter(mDirsIgnoringSearch, text) setupAdapter(mDirsIgnoringSearch, text)
binding.directoriesRefreshLayout.isEnabled = text.isEmpty() && config.enablePullToRefresh binding.directoriesRefreshLayout.isEnabled =
text.isEmpty() && config.enablePullToRefresh
binding.directoriesSwitchSearching.beVisibleIf(text.isNotEmpty()) binding.directoriesSwitchSearching.beVisibleIf(text.isNotEmpty())
} }
@ -528,8 +545,17 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
if (config.tempFolderPath.isNotEmpty()) { if (config.tempFolderPath.isNotEmpty()) {
val newFolder = File(config.tempFolderPath) val newFolder = File(config.tempFolderPath)
if (getDoesFilePathExist(newFolder.absolutePath) && newFolder.isDirectory) { if (getDoesFilePathExist(newFolder.absolutePath) && newFolder.isDirectory) {
if (newFolder.getProperSize(true) == 0L && newFolder.getFileCount(true) == 0 && newFolder.list()?.isEmpty() == true) { if (
toast(String.format(getString(org.fossify.commons.R.string.deleting_folder), config.tempFolderPath), Toast.LENGTH_LONG) newFolder.getProperSize(true) == 0L
&& newFolder.getFileCount(true) == 0
&& newFolder.list()?.isEmpty() == true
) {
toast(
String.format(
getString(org.fossify.commons.R.string.deleting_folder),
config.tempFolderPath
), Toast.LENGTH_LONG
)
tryDeleteFileDirItem(newFolder.toFileDirItem(applicationContext), true, true) tryDeleteFileDirItem(newFolder.toFileDirItem(applicationContext), true, true)
} }
} }
@ -540,7 +566,10 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
private fun checkOTGPath() { private fun checkOTGPath() {
ensureBackgroundThread { ensureBackgroundThread {
if (!config.wasOTGHandled && hasPermission(getPermissionToRequest()) && hasOTGConnected() && config.OTGPath.isEmpty()) { if (!config.wasOTGHandled && hasPermission(getPermissionToRequest()) && hasOTGConnected() && config.OTGPath.isEmpty()) {
getStorageDirectories().firstOrNull { it.trimEnd('/') != internalStoragePath && it.trimEnd('/') != sdCardPath }?.apply { getStorageDirectories().firstOrNull {
it.trimEnd('/') != internalStoragePath
&& it.trimEnd('/') != sdCardPath
}?.apply {
config.wasOTGHandled = true config.wasOTGHandled = true
val otgPath = trimEnd('/') val otgPath = trimEnd('/')
config.OTGPath = otgPath config.OTGPath = otgPath
@ -568,7 +597,8 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
private fun tryLoadGallery() { private fun tryLoadGallery() {
// avoid calling anything right after granting the permission, it will be called from onResume() // avoid calling anything right after granting the permission, it will be called from onResume()
val wasMissingPermission = config.appRunCount == 1 && !hasAllPermissions(getPermissionsToRequest()) val wasMissingPermission =
config.appRunCount == 1 && !hasAllPermissions(getPermissionsToRequest())
handleMediaPermissions { handleMediaPermissions {
if (wasMissingPermission) { if (wasMissingPermission) {
return@handleMediaPermissions return@handleMediaPermissions
@ -707,23 +737,39 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
} }
override fun deleteFolders(folders: ArrayList<File>) { override fun deleteFolders(folders: ArrayList<File>) {
val fileDirItems = val fileDirItems = folders
folders.asSequence().filter { it.isDirectory }.map { FileDirItem(it.absolutePath, it.name, true) }.toMutableList() as ArrayList<FileDirItem> .asSequence()
.filter { it.isDirectory }
.map { FileDirItem(it.absolutePath, it.name, true) }
.toMutableList() as ArrayList<FileDirItem>
when { when {
fileDirItems.isEmpty() -> return fileDirItems.isEmpty() -> return
fileDirItems.size == 1 -> { fileDirItems.size == 1 -> {
try { try {
toast(String.format(getString(org.fossify.commons.R.string.deleting_folder), fileDirItems.first().name)) toast(
String.format(
getString(org.fossify.commons.R.string.deleting_folder),
fileDirItems.first().name
)
)
} catch (e: Exception) { } catch (e: Exception) {
showErrorToast(e) showErrorToast(e)
} }
} }
else -> { else -> {
val baseString = val baseString = if (config.useRecycleBin && !config.tempSkipRecycleBin) {
if (config.useRecycleBin && !config.tempSkipRecycleBin) org.fossify.commons.R.plurals.moving_items_into_bin else org.fossify.commons.R.plurals.delete_items org.fossify.commons.R.plurals.moving_items_into_bin
val deletingItems = resources.getQuantityString(baseString, fileDirItems.size, fileDirItems.size) } else {
toast(deletingItems) org.fossify.commons.R.plurals.delete_items
}
toast(
msg = resources.getQuantityString(
baseString, fileDirItems.size, fileDirItems.size
)
)
} }
} }
@ -733,12 +779,13 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
fileDirItems.filter { it.isDirectory }.forEach { fileDirItems.filter { it.isDirectory }.forEach {
val files = File(it.path).listFiles() val files = File(it.path).listFiles()
files?.filter { files?.filter {
it.absolutePath.isMediaFile() && (showHidden || !it.name.startsWith('.')) && it.absolutePath.isMediaFile()
((it.isImageFast() && filter and TYPE_IMAGES != 0) || && (showHidden || !it.name.startsWith('.'))
(it.isVideoFast() && filter and TYPE_VIDEOS != 0) || && ((it.isImageFast() && filter and TYPE_IMAGES != 0)
(it.isGif() && filter and TYPE_GIFS != 0) || || (it.isVideoFast() && filter and TYPE_VIDEOS != 0)
(it.isRawFast() && filter and TYPE_RAWS != 0) || || (it.isGif() && filter and TYPE_GIFS != 0)
(it.isSvg() && filter and TYPE_SVGS != 0)) || (it.isRawFast() && filter and TYPE_RAWS != 0)
|| (it.isSvg() && filter and TYPE_SVGS != 0))
}?.mapTo(itemsToDelete) { it.toFileDirItem(applicationContext) } }?.mapTo(itemsToDelete) { it.toFileDirItem(applicationContext) }
} }
@ -758,7 +805,10 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
} }
} }
private fun deleteFilteredFileDirItems(fileDirItems: ArrayList<FileDirItem>, folders: ArrayList<File>) { private fun deleteFilteredFileDirItems(
fileDirItems: ArrayList<FileDirItem>,
folders: ArrayList<File>
) {
val OTGPath = config.OTGPath val OTGPath = config.OTGPath
deleteFiles(fileDirItems) { deleteFiles(fileDirItems) {
runOnUiThread { runOnUiThread {
@ -771,7 +821,11 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
} }
if (config.deleteEmptyFolders) { if (config.deleteEmptyFolders) {
folders.filter { !it.absolutePath.isDownloadsFolder() && it.isDirectory && it.toFileDirItem(this).getProperFileCount(this, true) == 0 } folders.filter {
!it.absolutePath.isDownloadsFolder()
&& it.isDirectory
&& it.toFileDirItem(this).getProperFileCount(this, true) == 0
}
.forEach { .forEach {
tryDeleteFileDirItem(it.toFileDirItem(this), true, true) tryDeleteFileDirItem(it.toFileDirItem(this), true, true)
} }
@ -787,7 +841,8 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
setupListLayoutManager() setupListLayoutManager()
} }
(binding.directoriesRefreshLayout.layoutParams as RelativeLayout.LayoutParams).addRule(RelativeLayout.BELOW, R.id.directories_switch_searching) (binding.directoriesRefreshLayout.layoutParams as RelativeLayout.LayoutParams)
.addRule(RelativeLayout.BELOW, R.id.directories_switch_searching)
} }
private fun setupGridLayoutManager() { private fun setupGridLayoutManager() {
@ -795,11 +850,17 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
if (config.scrollHorizontally) { if (config.scrollHorizontally) {
layoutManager.orientation = RecyclerView.HORIZONTAL layoutManager.orientation = RecyclerView.HORIZONTAL
binding.directoriesRefreshLayout.layoutParams = binding.directoriesRefreshLayout.layoutParams =
RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT) RelativeLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
} else { } else {
layoutManager.orientation = RecyclerView.VERTICAL layoutManager.orientation = RecyclerView.VERTICAL
binding.directoriesRefreshLayout.layoutParams = binding.directoriesRefreshLayout.layoutParams =
RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) RelativeLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT
)
} }
layoutManager.spanCount = config.dirColumnCnt layoutManager.spanCount = config.dirColumnCnt
@ -809,7 +870,10 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
val layoutManager = binding.directoriesGrid.layoutManager as MyGridLayoutManager val layoutManager = binding.directoriesGrid.layoutManager as MyGridLayoutManager
layoutManager.spanCount = 1 layoutManager.spanCount = 1
layoutManager.orientation = RecyclerView.VERTICAL layoutManager.orientation = RecyclerView.VERTICAL
binding.directoriesRefreshLayout.layoutParams = RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) binding.directoriesRefreshLayout.layoutParams = RelativeLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT
)
mZoomListener = null mZoomListener = null
} }
@ -850,10 +914,18 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
private fun changeColumnCount() { private fun changeColumnCount() {
val items = ArrayList<RadioItem>() val items = ArrayList<RadioItem>()
for (i in 1..MAX_COLUMN_COUNT) { for (i in 1..MAX_COLUMN_COUNT) {
items.add(RadioItem(i, resources.getQuantityString(org.fossify.commons.R.plurals.column_counts, i, i))) items.add(
RadioItem(
id = i,
title = resources.getQuantityString(
org.fossify.commons.R.plurals.column_counts, i, i
)
)
)
} }
val currentColumnCount = (binding.directoriesGrid.layoutManager as MyGridLayoutManager).spanCount val currentColumnCount =
(binding.directoriesGrid.layoutManager as MyGridLayoutManager).spanCount
RadioGroupDialog(this, items, currentColumnCount) { RadioGroupDialog(this, items, currentColumnCount) {
val newColumnCount = it as Int val newColumnCount = it as Int
if (currentColumnCount != newColumnCount) { if (currentColumnCount != newColumnCount) {
@ -874,40 +946,69 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
} }
private fun columnCountChanged() { private fun columnCountChanged() {
(binding.directoriesGrid.layoutManager as MyGridLayoutManager).spanCount = config.dirColumnCnt (binding.directoriesGrid.layoutManager as MyGridLayoutManager).spanCount =
config.dirColumnCnt
refreshMenuItems() refreshMenuItems()
getRecyclerAdapter()?.apply { getRecyclerAdapter()?.apply {
notifyItemRangeChanged(0, dirs.size) notifyItemRangeChanged(0, dirs.size)
} }
} }
private fun isPickImageIntent(intent: Intent) = isPickIntent(intent) && (hasImageContentData(intent) || isImageType(intent)) private fun isPickImageIntent(intent: Intent): Boolean {
return isPickIntent(intent) && (hasImageContentData(intent) || isImageType(intent))
}
private fun isPickVideoIntent(intent: Intent) = isPickIntent(intent) && (hasVideoContentData(intent) || isVideoType(intent)) private fun isPickVideoIntent(intent: Intent): Boolean {
return isPickIntent(intent) && (hasVideoContentData(intent) || isVideoType(intent))
}
private fun isPickIntent(intent: Intent) = intent.action == Intent.ACTION_PICK private fun isPickIntent(intent: Intent): Boolean {
return intent.action == Intent.ACTION_PICK
}
private fun isGetContentIntent(intent: Intent) = intent.action == Intent.ACTION_GET_CONTENT && intent.type != null private fun isGetContentIntent(intent: Intent): Boolean {
return intent.action == Intent.ACTION_GET_CONTENT && intent.type != null
}
private fun isGetImageContentIntent(intent: Intent) = isGetContentIntent(intent) && private fun isGetImageContentIntent(intent: Intent): Boolean {
(intent.type!!.startsWith("image/") || intent.type == Images.Media.CONTENT_TYPE) return isGetContentIntent(intent)
&& (intent.type!!.startsWith("image/")
|| intent.type == Images.Media.CONTENT_TYPE)
}
private fun isGetVideoContentIntent(intent: Intent) = isGetContentIntent(intent) && private fun isGetVideoContentIntent(intent: Intent): Boolean {
(intent.type!!.startsWith("video/") || intent.type == Video.Media.CONTENT_TYPE) return isGetContentIntent(intent)
&& (intent.type!!.startsWith("video/")
|| intent.type == Video.Media.CONTENT_TYPE)
}
private fun isGetAnyContentIntent(intent: Intent) = isGetContentIntent(intent) && intent.type == "*/*" private fun isGetAnyContentIntent(intent: Intent): Boolean {
return isGetContentIntent(intent) && intent.type == "*/*"
}
private fun isSetWallpaperIntent(intent: Intent?) = intent?.action == Intent.ACTION_SET_WALLPAPER private fun isSetWallpaperIntent(intent: Intent?): Boolean {
return intent?.action == Intent.ACTION_SET_WALLPAPER
}
private fun hasImageContentData(intent: Intent) = (intent.data == Images.Media.EXTERNAL_CONTENT_URI || private fun hasImageContentData(intent: Intent): Boolean {
intent.data == Images.Media.INTERNAL_CONTENT_URI) return intent.data == Images.Media.EXTERNAL_CONTENT_URI
|| intent.data == Images.Media.INTERNAL_CONTENT_URI
}
private fun hasVideoContentData(intent: Intent) = (intent.data == Video.Media.EXTERNAL_CONTENT_URI || private fun hasVideoContentData(intent: Intent): Boolean {
intent.data == Video.Media.INTERNAL_CONTENT_URI) return intent.data == Video.Media.EXTERNAL_CONTENT_URI
|| intent.data == Video.Media.INTERNAL_CONTENT_URI
}
private fun isImageType(intent: Intent) = (intent.type?.startsWith("image/") == true || intent.type == Images.Media.CONTENT_TYPE) private fun isImageType(intent: Intent): Boolean {
return (intent.type?.startsWith("image/") == true
|| intent.type == Images.Media.CONTENT_TYPE)
}
private fun isVideoType(intent: Intent) = (intent.type?.startsWith("video/") == true || intent.type == Video.Media.CONTENT_TYPE) private fun isVideoType(intent: Intent): Boolean {
return (intent.type?.startsWith("video/") == true
|| intent.type == Video.Media.CONTENT_TYPE)
}
private fun fillExtraOutput(resultData: Intent): Uri? { private fun fillExtraOutput(resultData: Intent): Uri? {
val file = File(resultData.data!!.path!!) val file = File(resultData.data!!.path!!)
@ -932,8 +1033,13 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
private fun fillPickedPaths(resultData: Intent, resultIntent: Intent) { private fun fillPickedPaths(resultData: Intent, resultIntent: Intent) {
val paths = resultData.extras!!.getStringArrayList(PICKED_PATHS) val paths = resultData.extras!!.getStringArrayList(PICKED_PATHS)
val uris = paths!!.map { getFilePublicUri(File(it), BuildConfig.APPLICATION_ID) } as ArrayList val uris = paths!!
val clipData = ClipData("Attachment", arrayOf("image/*", "video/*"), ClipData.Item(uris.removeAt(0))) .map { getFilePublicUri(File(it), BuildConfig.APPLICATION_ID) } as ArrayList
val clipData = ClipData(
"Attachment",
arrayOf("image/*", "video/*"),
ClipData.Item(uris.removeAt(0))
)
uris.forEach { uris.forEach {
clipData.addItem(ClipData.Item(it)) clipData.addItem(ClipData.Item(it))
@ -987,7 +1093,10 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
// if hidden item showing is disabled but all Favorite items are hidden, hide the Favorites folder // if hidden item showing is disabled but all Favorite items are hidden, hide the Favorites folder
if (!config.shouldShowHidden) { if (!config.shouldShowHidden) {
val favoritesFolder = newDirs.firstOrNull { it.areFavorites() } val favoritesFolder = newDirs.firstOrNull { it.areFavorites() }
if (favoritesFolder != null && favoritesFolder.tmb.getFilenameFromPath().startsWith('.')) { if (
favoritesFolder != null
&& favoritesFolder.tmb.getFilenameFromPath().startsWith('.')
) {
newDirs.remove(favoritesFolder) newDirs.remove(favoritesFolder)
} }
} }
@ -1020,7 +1129,11 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
val lastModifieds = mLastMediaFetcher!!.getLastModifieds() val lastModifieds = mLastMediaFetcher!!.getLastModifieds()
val dateTakens = mLastMediaFetcher!!.getDateTakens() val dateTakens = mLastMediaFetcher!!.getDateTakens()
if (config.showRecycleBinAtFolders && !config.showRecycleBinLast && !dirs.map { it.path }.contains(RECYCLE_BIN)) { if (
config.showRecycleBinAtFolders
&& !config.showRecycleBinLast
&& !dirs.map { it.path }.contains(RECYCLE_BIN)
) {
try { try {
if (mediaDB.getDeletedMediaCount() > 0) { if (mediaDB.getDeletedMediaCount() > 0) {
val recycleBin = Directory().apply { val recycleBin = Directory().apply {
@ -1048,7 +1161,14 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
} }
// fetch files from MediaStore only, unless the app has the MANAGE_EXTERNAL_STORAGE permission on Android 11+ // fetch files from MediaStore only, unless the app has the MANAGE_EXTERNAL_STORAGE permission on Android 11+
val android11Files = mLastMediaFetcher?.getAndroid11FolderMedia(getImagesOnly, getVideosOnly, favoritePaths, false, true, dateTakens) val android11Files = mLastMediaFetcher?.getAndroid11FolderMedia(
isPickImage = getImagesOnly,
isPickVideo = getVideosOnly,
favoritePaths = favoritePaths,
getFavoritePathsOnly = false,
getProperDateTaken = true,
dateTakens = dateTakens
)
try { try {
for (directory in dirs) { for (directory in dirs) {
if (mShouldStopFetching || isDestroyed || isFinishing) { if (mShouldStopFetching || isDestroyed || isFinishing) {
@ -1057,19 +1177,29 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
val sorting = config.getFolderSorting(directory.path) val sorting = config.getFolderSorting(directory.path)
val grouping = config.getFolderGrouping(directory.path) val grouping = config.getFolderGrouping(directory.path)
val getProperDateTaken = config.directorySorting and SORT_BY_DATE_TAKEN != 0 || val getProperDateTaken = config.directorySorting and SORT_BY_DATE_TAKEN != 0
sorting and SORT_BY_DATE_TAKEN != 0 || || sorting and SORT_BY_DATE_TAKEN != 0
grouping and GROUP_BY_DATE_TAKEN_DAILY != 0 || || grouping and GROUP_BY_DATE_TAKEN_DAILY != 0
grouping and GROUP_BY_DATE_TAKEN_MONTHLY != 0 || grouping and GROUP_BY_DATE_TAKEN_MONTHLY != 0
val getProperLastModified = config.directorySorting and SORT_BY_DATE_MODIFIED != 0 || val getProperLastModified =
sorting and SORT_BY_DATE_MODIFIED != 0 || config.directorySorting and SORT_BY_DATE_MODIFIED != 0
grouping and GROUP_BY_LAST_MODIFIED_DAILY != 0 || || sorting and SORT_BY_DATE_MODIFIED != 0
grouping and GROUP_BY_LAST_MODIFIED_MONTHLY != 0 || grouping and GROUP_BY_LAST_MODIFIED_DAILY != 0
|| grouping and GROUP_BY_LAST_MODIFIED_MONTHLY != 0
val curMedia = mLastMediaFetcher!!.getFilesFrom( val curMedia = mLastMediaFetcher!!.getFilesFrom(
directory.path, getImagesOnly, getVideosOnly, getProperDateTaken, getProperLastModified, curPath = directory.path,
getProperFileSize, favoritePaths, false, lastModifieds, dateTakens, android11Files isPickImage = getImagesOnly,
isPickVideo = getVideosOnly,
getProperDateTaken = getProperDateTaken,
getProperLastModified = getProperLastModified,
getProperFileSize = getProperFileSize,
favoritePaths = favoritePaths,
getVideoDurations = false,
lastModifieds = lastModifieds,
dateTakens = dateTakens,
android11Files = android11Files
) )
val newDir = if (curMedia.isEmpty()) { val newDir = if (curMedia.isEmpty()) {
@ -1078,7 +1208,15 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
} }
directory directory
} else { } else {
createDirectoryFromMedia(directory.path, curMedia, albumCovers, hiddenString, includedFolders, getProperFileSize, noMediaFolders) createDirectoryFromMedia(
path = directory.path,
curMedia = curMedia,
albumCovers = albumCovers,
hiddenString = hiddenString,
includedFolders = includedFolders,
getProperFileSize = getProperFileSize,
noMediaFolders = noMediaFolders
)
} }
// we are looping through the already displayed folders looking for changes, do not do anything if nothing changed // we are looping through the already displayed folders looking for changes, do not do anything if nothing changed
@ -1164,19 +1302,28 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
val sorting = config.getFolderSorting(folder) val sorting = config.getFolderSorting(folder)
val grouping = config.getFolderGrouping(folder) val grouping = config.getFolderGrouping(folder)
val getProperDateTaken = config.directorySorting and SORT_BY_DATE_TAKEN != 0 || val getProperDateTaken = config.directorySorting and SORT_BY_DATE_TAKEN != 0
sorting and SORT_BY_DATE_TAKEN != 0 || || sorting and SORT_BY_DATE_TAKEN != 0
grouping and GROUP_BY_DATE_TAKEN_DAILY != 0 || || grouping and GROUP_BY_DATE_TAKEN_DAILY != 0
grouping and GROUP_BY_DATE_TAKEN_MONTHLY != 0 || grouping and GROUP_BY_DATE_TAKEN_MONTHLY != 0
val getProperLastModified = config.directorySorting and SORT_BY_DATE_MODIFIED != 0 || val getProperLastModified = config.directorySorting and SORT_BY_DATE_MODIFIED != 0
sorting and SORT_BY_DATE_MODIFIED != 0 || || sorting and SORT_BY_DATE_MODIFIED != 0
grouping and GROUP_BY_LAST_MODIFIED_DAILY != 0 || || grouping and GROUP_BY_LAST_MODIFIED_DAILY != 0
grouping and GROUP_BY_LAST_MODIFIED_MONTHLY != 0 || grouping and GROUP_BY_LAST_MODIFIED_MONTHLY != 0
val newMedia = mLastMediaFetcher!!.getFilesFrom( val newMedia = mLastMediaFetcher!!.getFilesFrom(
folder, getImagesOnly, getVideosOnly, getProperDateTaken, getProperLastModified, curPath = folder,
getProperFileSize, favoritePaths, false, lastModifieds, dateTakens, android11Files isPickImage = getImagesOnly,
isPickVideo = getVideosOnly,
getProperDateTaken = getProperDateTaken,
getProperLastModified = getProperLastModified,
getProperFileSize = getProperFileSize,
favoritePaths = favoritePaths,
getVideoDurations = false,
lastModifieds = lastModifieds,
dateTakens = dateTakens,
android11Files = android11Files
) )
if (newMedia.isEmpty()) { if (newMedia.isEmpty()) {
@ -1192,7 +1339,15 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
} }
} }
val newDir = createDirectoryFromMedia(folder, newMedia, albumCovers, hiddenString, includedFolders, getProperFileSize, noMediaFolders) val newDir = createDirectoryFromMedia(
path = folder,
curMedia = newMedia,
albumCovers = albumCovers,
hiddenString = hiddenString,
includedFolders = includedFolders,
getProperFileSize = getProperFileSize,
noMediaFolders = noMediaFolders
)
dirs.add(newDir) dirs.add(newDir)
setupAdapter(dirs) setupAdapter(dirs)
@ -1274,11 +1429,13 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
binding.directoriesEmptyPlaceholder2.beVisibleIf(dirs.isEmpty() && mLoadedInitialPhotos) binding.directoriesEmptyPlaceholder2.beVisibleIf(dirs.isEmpty() && mLoadedInitialPhotos)
if (binding.mainMenu.isSearchOpen) { if (binding.mainMenu.isSearchOpen) {
binding.directoriesEmptyPlaceholder.text = getString(org.fossify.commons.R.string.no_items_found) binding.directoriesEmptyPlaceholder.text =
getString(org.fossify.commons.R.string.no_items_found)
binding.directoriesEmptyPlaceholder2.beGone() binding.directoriesEmptyPlaceholder2.beGone()
} else if (dirs.isEmpty() && config.filterMedia == getDefaultFileFilter()) { } else if (dirs.isEmpty() && config.filterMedia == getDefaultFileFilter()) {
if (isRPlus() && !isExternalStorageManager()) { if (isRPlus() && !isExternalStorageManager()) {
binding.directoriesEmptyPlaceholder.text = getString(org.fossify.commons.R.string.no_items_found) binding.directoriesEmptyPlaceholder.text =
getString(org.fossify.commons.R.string.no_items_found)
binding.directoriesEmptyPlaceholder2.beGone() binding.directoriesEmptyPlaceholder2.beGone()
} else { } else {
binding.directoriesEmptyPlaceholder.text = getString(R.string.no_media_add_included) binding.directoriesEmptyPlaceholder.text = getString(R.string.no_media_add_included)
@ -1292,7 +1449,8 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
} }
} else { } else {
binding.directoriesEmptyPlaceholder.text = getString(R.string.no_media_with_filters) binding.directoriesEmptyPlaceholder.text = getString(R.string.no_media_with_filters)
binding.directoriesEmptyPlaceholder2.text = getString(R.string.change_filters_underlined) binding.directoriesEmptyPlaceholder2.text =
getString(R.string.change_filters_underlined)
binding.directoriesEmptyPlaceholder2.setOnClickListener { binding.directoriesEmptyPlaceholder2.setOnClickListener {
showFilterMediaDialog() showFilterMediaDialog()
@ -1303,11 +1461,22 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
binding.directoriesFastscroller.beVisibleIf(binding.directoriesEmptyPlaceholder.isGone()) binding.directoriesFastscroller.beVisibleIf(binding.directoriesEmptyPlaceholder.isGone())
} }
private fun setupAdapter(dirs: ArrayList<Directory>, textToSearch: String = binding.mainMenu.getCurrentQuery(), forceRecreate: Boolean = false) { private fun setupAdapter(
dirs: ArrayList<Directory>,
textToSearch: String = binding.mainMenu.getCurrentQuery(),
forceRecreate: Boolean = false
) {
val currAdapter = binding.directoriesGrid.adapter val currAdapter = binding.directoriesGrid.adapter
val distinctDirs = dirs.distinctBy { it.path.getDistinctPath() }.toMutableList() as ArrayList<Directory> val distinctDirs = dirs
.distinctBy { it.path.getDistinctPath() }
.toMutableList() as ArrayList<Directory>
val sortedDirs = getSortedDirectories(distinctDirs) val sortedDirs = getSortedDirectories(distinctDirs)
var dirsToShow = getDirsToShow(sortedDirs, mDirs, mCurrentPathPrefix).clone() as ArrayList<Directory> var dirsToShow = getDirsToShow(
dirs = sortedDirs,
allDirs = mDirs,
currentPathPrefix = mCurrentPathPrefix
).clone() as ArrayList<Directory>
if (currAdapter == null || forceRecreate) { if (currAdapter == null || forceRecreate) {
mDirsIgnoringSearch = dirs mDirsIgnoringSearch = dirs
@ -1345,7 +1514,9 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
} else { } else {
runOnUiThread { runOnUiThread {
if (textToSearch.isNotEmpty()) { if (textToSearch.isNotEmpty()) {
dirsToShow = dirsToShow.filter { it.name.contains(textToSearch, true) }.sortedBy { !it.name.startsWith(textToSearch, true) } dirsToShow = dirsToShow
.filter { it.name.contains(textToSearch, true) }
.sortedBy { !it.name.startsWith(textToSearch, true) }
.toMutableList() as ArrayList .toMutableList() as ArrayList
} }
checkPlaceholderVisibility(dirsToShow) checkPlaceholderVisibility(dirsToShow)
@ -1361,7 +1532,8 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
} }
private fun setupScrollDirection() { private fun setupScrollDirection() {
val scrollHorizontally = config.scrollHorizontally && config.viewTypeFolders == VIEW_TYPE_GRID val scrollHorizontally =
config.scrollHorizontally && config.viewTypeFolders == VIEW_TYPE_GRID
binding.directoriesFastscroller.setScrollVertically(!scrollHorizontally) binding.directoriesFastscroller.setScrollVertically(!scrollHorizontally)
} }
@ -1380,8 +1552,12 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
} }
val hasMediaFile = children?.any { val hasMediaFile = children?.any {
it != null && (it.isMediaFile() || (it.startsWith("img_", true) && File(it).isDirectory)) it != null && (
} ?: false it.isMediaFile()
|| (it.startsWith("img_", true)
&& File(it).isDirectory)
)
} == true
if (!hasMediaFile) { if (!hasMediaFile) {
invalidDirs.add(it) invalidDirs.add(it)
@ -1458,7 +1634,9 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
Handler().postDelayed({ Handler().postDelayed({
ensureBackgroundThread { ensureBackgroundThread {
try { try {
val filesToDelete = mediaDB.getOldRecycleBinItems(System.currentTimeMillis() - MONTH_MILLISECONDS) val filesToDelete = mediaDB.getOldRecycleBinItems(
System.currentTimeMillis() - MONTH_MILLISECONDS
)
filesToDelete.forEach { filesToDelete.forEach {
if (File(it.path.replaceFirst(RECYCLE_BIN, recycleBinPath)).delete()) { if (File(it.path.replaceFirst(RECYCLE_BIN, recycleBinPath)).delete()) {
mediaDB.deleteMediumPath(it.path) mediaDB.deleteMediumPath(it.path)
@ -1480,7 +1658,9 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
val internalPath = internalStoragePath val internalPath = internalStoragePath
val checkedPaths = ArrayList<String>() val checkedPaths = ArrayList<String>()
val oftenRepeatedPaths = ArrayList<String>() val oftenRepeatedPaths = ArrayList<String>()
val paths = mDirs.map { it.path.removePrefix(internalPath) }.toMutableList() as ArrayList<String> val paths = mDirs
.map { it.path.removePrefix(internalPath) }
.toMutableList() as ArrayList<String>
paths.forEach { paths.forEach {
val parts = it.split("/") val parts = it.split("/")
var currentString = "" var currentString = ""

View file

@ -17,8 +17,41 @@ import com.bumptech.glide.request.target.SimpleTarget
import com.bumptech.glide.request.transition.Transition import com.bumptech.glide.request.transition.Transition
import org.fossify.commons.dialogs.CreateNewFolderDialog import org.fossify.commons.dialogs.CreateNewFolderDialog
import org.fossify.commons.dialogs.RadioGroupDialog import org.fossify.commons.dialogs.RadioGroupDialog
import org.fossify.commons.extensions.* import org.fossify.commons.extensions.appLockManager
import org.fossify.commons.helpers.* import org.fossify.commons.extensions.areSystemAnimationsEnabled
import org.fossify.commons.extensions.beGone
import org.fossify.commons.extensions.beVisible
import org.fossify.commons.extensions.beVisibleIf
import org.fossify.commons.extensions.deleteFiles
import org.fossify.commons.extensions.getDoesFilePathExist
import org.fossify.commons.extensions.getFilenameFromPath
import org.fossify.commons.extensions.getIsPathDirectory
import org.fossify.commons.extensions.getLatestMediaByDateId
import org.fossify.commons.extensions.getLatestMediaId
import org.fossify.commons.extensions.getProperBackgroundColor
import org.fossify.commons.extensions.getProperPrimaryColor
import org.fossify.commons.extensions.getProperTextColor
import org.fossify.commons.extensions.getTimeFormat
import org.fossify.commons.extensions.handleHiddenFolderPasswordProtection
import org.fossify.commons.extensions.handleLockedFolderOpening
import org.fossify.commons.extensions.hideKeyboard
import org.fossify.commons.extensions.isExternalStorageManager
import org.fossify.commons.extensions.isGone
import org.fossify.commons.extensions.isMediaFile
import org.fossify.commons.extensions.isVideoFast
import org.fossify.commons.extensions.isVisible
import org.fossify.commons.extensions.recycleBinPath
import org.fossify.commons.extensions.showErrorToast
import org.fossify.commons.extensions.toast
import org.fossify.commons.extensions.viewBinding
import org.fossify.commons.helpers.FAVORITES
import org.fossify.commons.helpers.IS_FROM_GALLERY
import org.fossify.commons.helpers.REQUEST_EDIT_IMAGE
import org.fossify.commons.helpers.SORT_BY_RANDOM
import org.fossify.commons.helpers.VIEW_TYPE_GRID
import org.fossify.commons.helpers.VIEW_TYPE_LIST
import org.fossify.commons.helpers.ensureBackgroundThread
import org.fossify.commons.helpers.isRPlus
import org.fossify.commons.models.FileDirItem import org.fossify.commons.models.FileDirItem
import org.fossify.commons.models.RadioItem import org.fossify.commons.models.RadioItem
import org.fossify.commons.views.MyGridLayoutManager import org.fossify.commons.views.MyGridLayoutManager
@ -28,9 +61,49 @@ import org.fossify.gallery.adapters.MediaAdapter
import org.fossify.gallery.asynctasks.GetMediaAsynctask import org.fossify.gallery.asynctasks.GetMediaAsynctask
import org.fossify.gallery.databases.GalleryDatabase import org.fossify.gallery.databases.GalleryDatabase
import org.fossify.gallery.databinding.ActivityMediaBinding import org.fossify.gallery.databinding.ActivityMediaBinding
import org.fossify.gallery.dialogs.* import org.fossify.gallery.dialogs.ChangeGroupingDialog
import org.fossify.gallery.extensions.* import org.fossify.gallery.dialogs.ChangeSortingDialog
import org.fossify.gallery.helpers.* import org.fossify.gallery.dialogs.ChangeViewTypeDialog
import org.fossify.gallery.dialogs.FilterMediaDialog
import org.fossify.gallery.dialogs.GrantAllFilesDialog
import org.fossify.gallery.extensions.config
import org.fossify.gallery.extensions.deleteDBPath
import org.fossify.gallery.extensions.directoryDB
import org.fossify.gallery.extensions.emptyAndDisableTheRecycleBin
import org.fossify.gallery.extensions.emptyTheRecycleBin
import org.fossify.gallery.extensions.favoritesDB
import org.fossify.gallery.extensions.getCachedMedia
import org.fossify.gallery.extensions.getHumanizedFilename
import org.fossify.gallery.extensions.isDownloadsFolder
import org.fossify.gallery.extensions.launchAbout
import org.fossify.gallery.extensions.launchCamera
import org.fossify.gallery.extensions.launchSettings
import org.fossify.gallery.extensions.mediaDB
import org.fossify.gallery.extensions.movePathsInRecycleBin
import org.fossify.gallery.extensions.openPath
import org.fossify.gallery.extensions.openRecycleBin
import org.fossify.gallery.extensions.restoreRecycleBinPaths
import org.fossify.gallery.extensions.showRecycleBinEmptyingDialog
import org.fossify.gallery.extensions.tryDeleteFileDirItem
import org.fossify.gallery.extensions.updateWidgets
import org.fossify.gallery.helpers.DIRECTORY
import org.fossify.gallery.helpers.GET_ANY_INTENT
import org.fossify.gallery.helpers.GET_IMAGE_INTENT
import org.fossify.gallery.helpers.GET_VIDEO_INTENT
import org.fossify.gallery.helpers.GridSpacingItemDecoration
import org.fossify.gallery.helpers.IS_IN_RECYCLE_BIN
import org.fossify.gallery.helpers.MAX_COLUMN_COUNT
import org.fossify.gallery.helpers.MediaFetcher
import org.fossify.gallery.helpers.PATH
import org.fossify.gallery.helpers.PICKED_PATHS
import org.fossify.gallery.helpers.RECYCLE_BIN
import org.fossify.gallery.helpers.SET_WALLPAPER_INTENT
import org.fossify.gallery.helpers.SHOW_ALL
import org.fossify.gallery.helpers.SHOW_FAVORITES
import org.fossify.gallery.helpers.SHOW_RECYCLE_BIN
import org.fossify.gallery.helpers.SHOW_TEMP_HIDDEN_DURATION
import org.fossify.gallery.helpers.SKIP_AUTHENTICATION
import org.fossify.gallery.helpers.SLIDESHOW_START_ON_ENTER
import org.fossify.gallery.interfaces.MediaOperationsListener import org.fossify.gallery.interfaces.MediaOperationsListener
import org.fossify.gallery.models.Medium import org.fossify.gallery.models.Medium
import org.fossify.gallery.models.ThumbnailItem import org.fossify.gallery.models.ThumbnailItem
@ -99,7 +172,12 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
setupOptionsMenu() setupOptionsMenu()
refreshMenuItems() refreshMenuItems()
storeStateVariables() storeStateVariables()
updateMaterialActivityViews(binding.mediaCoordinator, binding.mediaGrid, useTransparentNavigation = !config.scrollHorizontally, useTopSearchMenu = true) updateMaterialActivityViews(
mainCoordinatorLayout = binding.mediaCoordinator,
nestedView = binding.mediaGrid,
useTransparentNavigation = !config.scrollHorizontally,
useTopSearchMenu = true
)
if (mShowAll) { if (mShowAll) {
registerFileUpdateListener() registerFileUpdateListener()
@ -249,7 +327,8 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
} }
private fun refreshMenuItems() { private fun refreshMenuItems() {
val isDefaultFolder = !config.defaultFolder.isEmpty() && File(config.defaultFolder).compareTo(File(mPath)) == 0 val isDefaultFolder = !config.defaultFolder.isEmpty()
&& File(config.defaultFolder).compareTo(File(mPath)) == 0
binding.mediaMenu.getToolbar().menu.apply { binding.mediaMenu.getToolbar().menu.apply {
findItem(R.id.group).isVisible = !config.scrollHorizontally findItem(R.id.group).isVisible = !config.scrollHorizontally
@ -261,11 +340,13 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
findItem(R.id.folder_view).isVisible = mShowAll findItem(R.id.folder_view).isVisible = mShowAll
findItem(R.id.open_camera).isVisible = mShowAll findItem(R.id.open_camera).isVisible = mShowAll
findItem(R.id.about).isVisible = mShowAll findItem(R.id.about).isVisible = mShowAll
findItem(R.id.create_new_folder).isVisible = !mShowAll && mPath != RECYCLE_BIN && mPath != FAVORITES findItem(R.id.create_new_folder).isVisible =
!mShowAll && mPath != RECYCLE_BIN && mPath != FAVORITES
findItem(R.id.open_recycle_bin).isVisible = config.useRecycleBin && mPath != RECYCLE_BIN findItem(R.id.open_recycle_bin).isVisible = config.useRecycleBin && mPath != RECYCLE_BIN
findItem(R.id.temporarily_show_hidden).isVisible = !config.shouldShowHidden findItem(R.id.temporarily_show_hidden).isVisible = !config.shouldShowHidden
findItem(R.id.stop_showing_hidden).isVisible = (!isRPlus() || isExternalStorageManager()) && config.temporarilyShowHidden findItem(R.id.stop_showing_hidden).isVisible =
(!isRPlus() || isExternalStorageManager()) && config.temporarilyShowHidden
findItem(R.id.set_as_default_folder).isVisible = !isDefaultFolder findItem(R.id.set_as_default_folder).isVisible = !isDefaultFolder
findItem(R.id.unset_as_default_folder).isVisible = isDefaultFolder findItem(R.id.unset_as_default_folder).isVisible = isDefaultFolder
@ -352,12 +433,16 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
private fun searchQueryChanged(text: String) { private fun searchQueryChanged(text: String) {
ensureBackgroundThread { ensureBackgroundThread {
try { try {
val filtered = mMedia.filter { it is Medium && it.name.contains(text, true) } as ArrayList val filtered = mMedia
.filter { it is Medium && it.name.contains(text, true) } as ArrayList
filtered.sortBy { it is Medium && !it.name.startsWith(text, true) } filtered.sortBy { it is Medium && !it.name.startsWith(text, true) }
val grouped = MediaFetcher(applicationContext).groupMedia(filtered as ArrayList<Medium>, mPath) val grouped = MediaFetcher(applicationContext).groupMedia(
media = filtered as ArrayList<Medium>, path = mPath
)
runOnUiThread { runOnUiThread {
if (grouped.isEmpty()) { if (grouped.isEmpty()) {
binding.mediaEmptyTextPlaceholder.text = getString(org.fossify.commons.R.string.no_items_found) binding.mediaEmptyTextPlaceholder.text =
getString(org.fossify.commons.R.string.no_items_found)
binding.mediaEmptyTextPlaceholder.beVisible() binding.mediaEmptyTextPlaceholder.beVisible()
binding.mediaFastscroller.beGone() binding.mediaFastscroller.beGone()
} else { } else {
@ -417,8 +502,13 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
if (currAdapter == null) { if (currAdapter == null) {
initZoomListener() initZoomListener()
MediaAdapter( MediaAdapter(
this, mMedia.clone() as ArrayList<ThumbnailItem>, this, mIsGetImageIntent || mIsGetVideoIntent || mIsGetAnyIntent, activity = this,
mAllowPickingMultiple, mPath, binding.mediaGrid media = mMedia.clone() as ArrayList<ThumbnailItem>,
listener = this,
isAGetIntent = mIsGetImageIntent || mIsGetVideoIntent || mIsGetAnyIntent,
allowMultiplePicks = mAllowPickingMultiple,
path = mPath,
recyclerView = binding.mediaGrid
) { ) {
if (it is Medium && !isFinishing) { if (it is Medium && !isFinishing) {
itemClicked(it.path) itemClicked(it.path)
@ -585,7 +675,13 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
private fun startAsyncTask() { private fun startAsyncTask() {
mCurrAsyncTask?.stopFetching() mCurrAsyncTask?.stopFetching()
mCurrAsyncTask = GetMediaAsynctask(applicationContext, mPath, mIsGetImageIntent, mIsGetVideoIntent, mShowAll) { mCurrAsyncTask = GetMediaAsynctask(
context = applicationContext,
mPath = mPath,
isPickImage = mIsGetImageIntent,
isPickVideo = mIsGetVideoIntent,
showAll = mShowAll
) {
ensureBackgroundThread { ensureBackgroundThread {
val oldMedia = mMedia.clone() as ArrayList<ThumbnailItem> val oldMedia = mMedia.clone() as ArrayList<ThumbnailItem>
val newMedia = it val newMedia = it
@ -594,7 +690,10 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
// remove cached files that are no longer valid for whatever reason // remove cached files that are no longer valid for whatever reason
val newPaths = newMedia.mapNotNull { it as? Medium }.map { it.path } val newPaths = newMedia.mapNotNull { it as? Medium }.map { it.path }
oldMedia.mapNotNull { it as? Medium }.filter { !newPaths.contains(it.path) }.forEach { oldMedia
.mapNotNull { it as? Medium }
.filter { !newPaths.contains(it.path) }
.forEach {
if (mPath == FAVORITES && getDoesFilePathExist(it.path)) { if (mPath == FAVORITES && getDoesFilePathExist(it.path)) {
favoritesDB.deleteFavoritePath(it.path) favoritesDB.deleteFavoritePath(it.path)
mediaDB.updateFavorite(it.path, false) mediaDB.updateFavorite(it.path, false)
@ -611,7 +710,7 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
} }
private fun isDirEmpty(): Boolean { private fun isDirEmpty(): Boolean {
return if (mMedia.size <= 0 && config.filterMedia > 0) { return if (mMedia.isEmpty() && config.filterMedia > 0) {
if (mPath != FAVORITES && mPath != RECYCLE_BIN) { if (mPath != FAVORITES && mPath != RECYCLE_BIN) {
deleteDirectoryIfEmpty() deleteDirectoryIfEmpty()
deleteDBDirectory() deleteDBDirectory()
@ -686,10 +785,16 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
val layoutManager = binding.mediaGrid.layoutManager as MyGridLayoutManager val layoutManager = binding.mediaGrid.layoutManager as MyGridLayoutManager
if (config.scrollHorizontally) { if (config.scrollHorizontally) {
layoutManager.orientation = RecyclerView.HORIZONTAL layoutManager.orientation = RecyclerView.HORIZONTAL
binding.mediaRefreshLayout.layoutParams = RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT) binding.mediaRefreshLayout.layoutParams = RelativeLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
} else { } else {
layoutManager.orientation = RecyclerView.VERTICAL layoutManager.orientation = RecyclerView.VERTICAL
binding.mediaRefreshLayout.layoutParams = RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) binding.mediaRefreshLayout.layoutParams = RelativeLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT
)
} }
layoutManager.spanCount = config.mediaColumnCnt layoutManager.spanCount = config.mediaColumnCnt
@ -709,7 +814,10 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
val layoutManager = binding.mediaGrid.layoutManager as MyGridLayoutManager val layoutManager = binding.mediaGrid.layoutManager as MyGridLayoutManager
layoutManager.spanCount = 1 layoutManager.spanCount = 1
layoutManager.orientation = RecyclerView.VERTICAL layoutManager.orientation = RecyclerView.VERTICAL
binding.mediaRefreshLayout.layoutParams = RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) binding.mediaRefreshLayout.layoutParams = RelativeLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT
)
mZoomListener = null mZoomListener = null
} }
@ -722,11 +830,19 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
var currentGridDecoration: GridSpacingItemDecoration? = null var currentGridDecoration: GridSpacingItemDecoration? = null
if (binding.mediaGrid.itemDecorationCount > 0) { if (binding.mediaGrid.itemDecorationCount > 0) {
currentGridDecoration = binding.mediaGrid.getItemDecorationAt(0) as GridSpacingItemDecoration currentGridDecoration =
binding.mediaGrid.getItemDecorationAt(0) as GridSpacingItemDecoration
currentGridDecoration.items = media currentGridDecoration.items = media
} }
val newGridDecoration = GridSpacingItemDecoration(spanCount, spacing, config.scrollHorizontally, config.fileRoundedCorners, media, useGridPosition) val newGridDecoration = GridSpacingItemDecoration(
spanCount = spanCount,
spacing = spacing,
isScrollingHorizontally = config.scrollHorizontally,
addSideSpacing = config.fileRoundedCorners,
items = media,
useGridPosition = useGridPosition
)
if (currentGridDecoration.toString() != newGridDecoration.toString()) { if (currentGridDecoration.toString() != newGridDecoration.toString()) {
if (currentGridDecoration != null) { if (currentGridDecoration != null) {
binding.mediaGrid.removeItemDecoration(currentGridDecoration) binding.mediaGrid.removeItemDecoration(currentGridDecoration)
@ -763,7 +879,14 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
private fun changeColumnCount() { private fun changeColumnCount() {
val items = ArrayList<RadioItem>() val items = ArrayList<RadioItem>()
for (i in 1..MAX_COLUMN_COUNT) { for (i in 1..MAX_COLUMN_COUNT) {
items.add(RadioItem(i, resources.getQuantityString(org.fossify.commons.R.plurals.column_counts, i, i))) items.add(
RadioItem(
id = i,
title = resources.getQuantityString(
org.fossify.commons.R.plurals.column_counts, i, i
)
)
)
} }
val currentColumnCount = (binding.mediaGrid.layoutManager as MyGridLayoutManager).spanCount val currentColumnCount = (binding.mediaGrid.layoutManager as MyGridLayoutManager).spanCount
@ -815,7 +938,10 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
.load(File(path)) .load(File(path))
.apply(options) .apply(options)
.into(object : SimpleTarget<Bitmap>() { .into(object : SimpleTarget<Bitmap>() {
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) { override fun onResourceReady(
resource: Bitmap,
transition: Transition<in Bitmap>?
) {
try { try {
WallpaperManager.getInstance(applicationContext).setBitmap(resource) WallpaperManager.getInstance(applicationContext).setBitmap(resource)
setResult(Activity.RESULT_OK) setResult(Activity.RESULT_OK)
@ -880,7 +1006,8 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
mLatestMediaId = getLatestMediaId() mLatestMediaId = getLatestMediaId()
mLatestMediaDateId = getLatestMediaByDateId() mLatestMediaDateId = getLatestMediaByDateId()
if (!isFromCache) { if (!isFromCache) {
val mediaToInsert = (mMedia).filter { it is Medium && it.deletedTS == 0L }.map { it as Medium } val mediaToInsert = mMedia
.filter { it is Medium && it.deletedTS == 0L }.map { it as Medium }
Thread { Thread {
try { try {
mediaDB.insertAll(mediaToInsert) mediaDB.insertAll(mediaToInsert)
@ -891,13 +1018,22 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
} }
override fun tryDeleteFiles(fileDirItems: ArrayList<FileDirItem>, skipRecycleBin: Boolean) { override fun tryDeleteFiles(fileDirItems: ArrayList<FileDirItem>, skipRecycleBin: Boolean) {
val filtered = fileDirItems.filter { !getIsPathDirectory(it.path) && it.path.isMediaFile() } as ArrayList val filtered = fileDirItems
.filter { !getIsPathDirectory(it.path) && it.path.isMediaFile() } as ArrayList
if (filtered.isEmpty()) { if (filtered.isEmpty()) {
return return
} }
if (config.useRecycleBin && !skipRecycleBin && !filtered.first().path.startsWith(recycleBinPath)) { if (
val movingItems = resources.getQuantityString(org.fossify.commons.R.plurals.moving_items_into_bin, filtered.size, filtered.size) config.useRecycleBin
&& !skipRecycleBin
&& !filtered.first().path.startsWith(recycleBinPath)
) {
val movingItems = resources.getQuantityString(
org.fossify.commons.R.plurals.moving_items_into_bin,
filtered.size,
filtered.size
)
toast(movingItems) toast(movingItems)
movePathsInRecycleBin(filtered.map { it.path } as ArrayList<String>) { movePathsInRecycleBin(filtered.map { it.path } as ArrayList<String>) {
@ -908,13 +1044,19 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
} }
} }
} else { } else {
val deletingItems = resources.getQuantityString(org.fossify.commons.R.plurals.deleting_items, filtered.size, filtered.size) val deletingItems = resources.getQuantityString(
org.fossify.commons.R.plurals.deleting_items,
filtered.size,
filtered.size
)
toast(deletingItems) toast(deletingItems)
deleteFilteredFiles(filtered) deleteFilteredFiles(filtered)
} }
} }
private fun shouldSkipAuthentication() = intent.getBooleanExtra(SKIP_AUTHENTICATION, false) private fun shouldSkipAuthentication(): Boolean {
return intent.getBooleanExtra(SKIP_AUTHENTICATION, false)
}
private fun deleteFilteredFiles(filtered: ArrayList<FileDirItem>) { private fun deleteFilteredFiles(filtered: ArrayList<FileDirItem>) {
deleteFiles(filtered) { deleteFiles(filtered) {
@ -965,7 +1107,8 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
} }
if (binding.mediaGrid.itemDecorationCount > 0) { if (binding.mediaGrid.itemDecorationCount > 0) {
val currentGridDecoration = binding.mediaGrid.getItemDecorationAt(0) as GridSpacingItemDecoration val currentGridDecoration =
binding.mediaGrid.getItemDecorationAt(0) as GridSpacingItemDecoration
currentGridDecoration.items = media currentGridDecoration.items = media
} }
} }

View file

@ -2,16 +2,32 @@ package org.fossify.gallery.dialogs
import android.content.DialogInterface import android.content.DialogInterface
import org.fossify.commons.activities.BaseSimpleActivity import org.fossify.commons.activities.BaseSimpleActivity
import org.fossify.commons.extensions.* import org.fossify.commons.extensions.beGoneIf
import org.fossify.commons.helpers.* import org.fossify.commons.extensions.beVisibleIf
import org.fossify.commons.extensions.getAlertDialogBuilder
import org.fossify.commons.extensions.isVisible
import org.fossify.commons.extensions.setupDialogStuff
import org.fossify.commons.helpers.SORT_BY_COUNT
import org.fossify.commons.helpers.SORT_BY_CUSTOM
import org.fossify.commons.helpers.SORT_BY_DATE_MODIFIED
import org.fossify.commons.helpers.SORT_BY_DATE_TAKEN
import org.fossify.commons.helpers.SORT_BY_NAME
import org.fossify.commons.helpers.SORT_BY_PATH
import org.fossify.commons.helpers.SORT_BY_RANDOM
import org.fossify.commons.helpers.SORT_BY_SIZE
import org.fossify.commons.helpers.SORT_DESCENDING
import org.fossify.commons.helpers.SORT_USE_NUMERIC_VALUE
import org.fossify.gallery.R import org.fossify.gallery.R
import org.fossify.gallery.databinding.DialogChangeSortingBinding import org.fossify.gallery.databinding.DialogChangeSortingBinding
import org.fossify.gallery.extensions.config import org.fossify.gallery.extensions.config
import org.fossify.gallery.helpers.SHOW_ALL import org.fossify.gallery.helpers.SHOW_ALL
class ChangeSortingDialog( class ChangeSortingDialog(
val activity: BaseSimpleActivity, val isDirectorySorting: Boolean, val showFolderCheckbox: Boolean, val activity: BaseSimpleActivity,
val path: String = "", val callback: () -> Unit val isDirectorySorting: Boolean,
val showFolderCheckbox: Boolean,
val path: String = "",
val callback: () -> Unit
) : ) :
DialogInterface.OnClickListener { DialogInterface.OnClickListener {
private var currSorting = 0 private var currSorting = 0
@ -20,12 +36,24 @@ class ChangeSortingDialog(
private val binding: DialogChangeSortingBinding private val binding: DialogChangeSortingBinding
init { init {
currSorting = if (isDirectorySorting) config.directorySorting else config.getFolderSorting(pathToUse) currSorting = if (isDirectorySorting) {
config.directorySorting
} else {
config.getFolderSorting(pathToUse)
}
binding = DialogChangeSortingBinding.inflate(activity.layoutInflater).apply { binding = DialogChangeSortingBinding.inflate(activity.layoutInflater).apply {
sortingDialogRadioNumberOfItems.beVisibleIf(isDirectorySorting) sortingDialogRadioNumberOfItems.beVisibleIf(isDirectorySorting)
sortingDialogOrderDivider.beVisibleIf(showFolderCheckbox || (currSorting and SORT_BY_NAME != 0 || currSorting and SORT_BY_PATH != 0)) sortingDialogOrderDivider.beVisibleIf(
beVisible = showFolderCheckbox
|| (currSorting and SORT_BY_NAME != 0 || currSorting and SORT_BY_PATH != 0)
)
sortingDialogNumericSorting.beVisibleIf(
beVisible = showFolderCheckbox
&& (currSorting and SORT_BY_NAME != 0 || currSorting and SORT_BY_PATH != 0)
)
sortingDialogNumericSorting.beVisibleIf(showFolderCheckbox && (currSorting and SORT_BY_NAME != 0 || currSorting and SORT_BY_PATH != 0))
sortingDialogNumericSorting.isChecked = currSorting and SORT_USE_NUMERIC_VALUE != 0 sortingDialogNumericSorting.isChecked = currSorting and SORT_USE_NUMERIC_VALUE != 0
sortingDialogUseForThisFolder.beVisibleIf(showFolderCheckbox) sortingDialogUseForThisFolder.beVisibleIf(showFolderCheckbox)
@ -48,11 +76,20 @@ class ChangeSortingDialog(
private fun setupSortRadio() { private fun setupSortRadio() {
val sortingRadio = binding.sortingDialogRadioSorting val sortingRadio = binding.sortingDialogRadioSorting
sortingRadio.setOnCheckedChangeListener { _, checkedId -> sortingRadio.setOnCheckedChangeListener { _, checkedId ->
val isSortingByNameOrPath = checkedId == binding.sortingDialogRadioName.id || checkedId == binding.sortingDialogRadioPath.id val isSortingByNameOrPath =
binding.sortingDialogNumericSorting.beVisibleIf(isSortingByNameOrPath) checkedId == binding.sortingDialogRadioName.id
binding.sortingDialogOrderDivider.beVisibleIf(binding.sortingDialogNumericSorting.isVisible() || binding.sortingDialogUseForThisFolder.isVisible()) || checkedId == binding.sortingDialogRadioPath.id
binding.sortingDialogNumericSorting.beVisibleIf(isSortingByNameOrPath)
binding.sortingDialogOrderDivider.beVisibleIf(
binding.sortingDialogNumericSorting.isVisible()
|| binding.sortingDialogUseForThisFolder.isVisible()
)
val hideSortOrder =
checkedId == binding.sortingDialogRadioCustom.id
|| checkedId == binding.sortingDialogRadioRandom.id
val hideSortOrder = checkedId == binding.sortingDialogRadioCustom.id || checkedId == binding.sortingDialogRadioRandom.id
binding.sortingDialogRadioOrder.beGoneIf(hideSortOrder) binding.sortingDialogRadioOrder.beGoneIf(hideSortOrder)
binding.sortingDialogSortingDivider.beGoneIf(hideSortOrder) binding.sortingDialogSortingDivider.beGoneIf(hideSortOrder)
} }

View file

@ -117,6 +117,7 @@ import java.nio.ByteBuffer
import java.nio.channels.FileChannel import java.nio.channels.FileChannel
import java.util.Locale import java.util.Locale
import kotlin.math.max import kotlin.math.max
import kotlin.math.min
val Context.audioManager get() = getSystemService(Context.AUDIO_SERVICE) as AudioManager val Context.audioManager get() = getSystemService(Context.AUDIO_SERVICE) as AudioManager
@ -127,15 +128,19 @@ fun Context.getHumanizedFilename(path: String): String {
val Context.config: Config get() = Config.newInstance(applicationContext) val Context.config: Config get() = Config.newInstance(applicationContext)
val Context.widgetsDB: WidgetsDao get() = GalleryDatabase.getInstance(applicationContext).WidgetsDao() val Context.widgetsDB: WidgetsDao
get() = GalleryDatabase.getInstance(applicationContext).WidgetsDao()
val Context.mediaDB: MediumDao get() = GalleryDatabase.getInstance(applicationContext).MediumDao() val Context.mediaDB: MediumDao get() = GalleryDatabase.getInstance(applicationContext).MediumDao()
val Context.directoryDB: DirectoryDao get() = GalleryDatabase.getInstance(applicationContext).DirectoryDao() val Context.directoryDB: DirectoryDao
get() = GalleryDatabase.getInstance(applicationContext).DirectoryDao()
val Context.favoritesDB: FavoritesDao get() = GalleryDatabase.getInstance(applicationContext).FavoritesDao() val Context.favoritesDB: FavoritesDao
get() = GalleryDatabase.getInstance(applicationContext).FavoritesDao()
val Context.dateTakensDB: DateTakensDao get() = GalleryDatabase.getInstance(applicationContext).DateTakensDao() val Context.dateTakensDB: DateTakensDao
get() = GalleryDatabase.getInstance(applicationContext).DateTakensDao()
val Context.recycleBin: File get() = filesDir val Context.recycleBin: File get() = filesDir
@ -207,11 +212,12 @@ fun Context.getSortedDirectories(source: ArrayList<Directory>): ArrayList<Direct
if (sorting and SORT_USE_NUMERIC_VALUE != 0) { if (sorting and SORT_USE_NUMERIC_VALUE != 0) {
AlphanumericComparator().compare( AlphanumericComparator().compare(
o1.sortValue.normalizeString().lowercase(Locale.getDefault()), string1 = o1.sortValue.normalizeString().lowercase(Locale.getDefault()),
o2.sortValue.normalizeString().lowercase(Locale.getDefault()) string2 = o2.sortValue.normalizeString().lowercase(Locale.getDefault())
) )
} else { } else {
o1.sortValue.normalizeString().lowercase(Locale.getDefault()).compareTo(o2.sortValue.normalizeString().lowercase(Locale.getDefault())) o1.sortValue.normalizeString().lowercase(Locale.getDefault())
.compareTo(o2.sortValue.normalizeString().lowercase(Locale.getDefault()))
} }
} }
@ -225,9 +231,13 @@ fun Context.getSortedDirectories(source: ArrayList<Directory>): ArrayList<Direct
} }
if (sorting and SORT_USE_NUMERIC_VALUE != 0) { if (sorting and SORT_USE_NUMERIC_VALUE != 0) {
AlphanumericComparator().compare(o1.sortValue.lowercase(Locale.getDefault()), o2.sortValue.lowercase(Locale.getDefault())) AlphanumericComparator().compare(
string1 = o1.sortValue.lowercase(Locale.getDefault()),
string2 = o2.sortValue.lowercase(Locale.getDefault())
)
} else { } else {
o1.sortValue.lowercase(Locale.getDefault()).compareTo(o2.sortValue.lowercase(Locale.getDefault())) o1.sortValue.lowercase(Locale.getDefault())
.compareTo(o2.sortValue.lowercase(Locale.getDefault()))
} }
} }
@ -244,7 +254,11 @@ fun Context.getSortedDirectories(source: ArrayList<Directory>): ArrayList<Direct
return movePinnedDirectoriesToFront(dirs) return movePinnedDirectoriesToFront(dirs)
} }
fun Context.getDirsToShow(dirs: ArrayList<Directory>, allDirs: ArrayList<Directory>, currentPathPrefix: String): ArrayList<Directory> { fun Context.getDirsToShow(
dirs: ArrayList<Directory>,
allDirs: ArrayList<Directory>,
currentPathPrefix: String
): ArrayList<Directory> {
return if (config.groupDirectSubfolders) { return if (config.groupDirectSubfolders) {
dirs.forEach { dirs.forEach {
it.subfoldersCount = 0 it.subfoldersCount = 0
@ -257,8 +271,12 @@ fun Context.getDirsToShow(dirs: ArrayList<Directory>, allDirs: ArrayList<Directo
// show the current folder as an available option too, not just subfolders // show the current folder as an available option too, not just subfolders
if (currentPathPrefix.isNotEmpty()) { if (currentPathPrefix.isNotEmpty()) {
val currentFolder = val currentFolder = allDirs.firstOrNull {
allDirs.firstOrNull { parentDirs.firstOrNull { it.path.equals(currentPathPrefix, true) } == null && it.path.equals(currentPathPrefix, true) } parentDirs.firstOrNull {
it.path.equals(currentPathPrefix, true)
} == null && it.path.equals(currentPathPrefix, true)
}
currentFolder?.apply { currentFolder?.apply {
subfoldersCount = 1 subfoldersCount = 1
parentDirs.add(this) parentDirs.add(this)
@ -295,17 +313,17 @@ private fun Context.addParentWithoutMediaFiles(into: ArrayList<Directory>, path:
} }
val directory = Directory( val directory = Directory(
newDirId + 1, id = newDirId + 1,
path, path = path,
subDirs.first().tmb, tmb = subDirs.first().tmb,
getFolderNameFromPath(path), name = getFolderNameFromPath(path),
subDirs.sumOf { it.mediaCnt }, mediaCnt = subDirs.sumOf { it.mediaCnt },
lastModified, modified = lastModified,
dateTaken, taken = dateTaken,
subDirs.sumByLong { it.size }, size = subDirs.sumByLong { it.size },
getPathLocation(path), location = getPathLocation(path),
mediaTypes, types = mediaTypes,
"" sortValue = ""
) )
directory.containsMediaFilesDirectly = false directory.containsMediaFilesDirectly = false
@ -335,7 +353,10 @@ fun Context.fillWithSharedDirectParents(dirs: ArrayList<Directory>): ArrayList<D
return allDirs return allDirs
} }
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>() val currentPaths = LinkedHashSet<String>()
val foldersWithoutMediaFiles = ArrayList<String>() val foldersWithoutMediaFiles = ArrayList<String>()
@ -355,15 +376,28 @@ fun Context.getDirectParentSubfolders(dirs: ArrayList<Directory>, currentPathPre
} }
} }
if (currentPathPrefix.isNotEmpty() && path.equals(currentPathPrefix, true) || File(path).parent.equals(currentPathPrefix, true)) { if (
currentPathPrefix.isNotEmpty() &&
path.equals(currentPathPrefix, true)
|| File(path).parent.equals(currentPathPrefix, true)
) {
currentPaths.add(path) currentPaths.add(path)
} else if (folders.any { !it.equals(path, true) && (File(path).parent.equals(it, true) || File(it).parent.equals(File(path).parent, true)) }) { } else if (
folders.any {
!it.equals(path, true) && (File(path).parent.equals(it, true)
|| File(it).parent.equals(File(path).parent, true))
}
) {
// if we have folders like // if we have folders like
// /storage/emulated/0/Pictures/Images and // /storage/emulated/0/Pictures/Images and
// /storage/emulated/0/Pictures/Screenshots, // /storage/emulated/0/Pictures/Screenshots,
// but /storage/emulated/0/Pictures is empty, still Pictures with the first folders thumbnails and proper other info // but /storage/emulated/0/Pictures is empty, still Pictures with the first folders thumbnails and proper other info
val parent = File(path).parent val parent = File(path).parent
if (parent != null && !folders.contains(parent) && dirs.none { it.path.equals(parent, true) }) { if (
parent != null
&& !folders.contains(parent)
&& dirs.none { it.path.equals(parent, true) }
) {
currentPaths.add(parent) currentPaths.add(parent)
if (addParentWithoutMediaFiles(dirs, parent)) { if (addParentWithoutMediaFiles(dirs, parent)) {
foldersWithoutMediaFiles.add(parent) foldersWithoutMediaFiles.add(parent)
@ -378,7 +412,11 @@ fun Context.getDirectParentSubfolders(dirs: ArrayList<Directory>, currentPathPre
currentPaths.forEach { currentPaths.forEach {
val path = it val path = it
currentPaths.forEach { currentPaths.forEach {
if (!foldersWithoutMediaFiles.contains(it) && !it.equals(path, true) && File(it).parent?.equals(path, true) == true) { if (
!foldersWithoutMediaFiles.contains(it)
&& !it.equals(path, true)
&& File(it).parent?.equals(path, true) == true
) {
areDirectSubfoldersAvailable = true areDirectSubfoldersAvailable = true
} }
} }
@ -407,7 +445,10 @@ fun Context.getDirectParentSubfolders(dirs: ArrayList<Directory>, currentPathPre
} }
} }
fun Context.updateSubfolderCounts(children: ArrayList<Directory>, parentDirs: ArrayList<Directory>) { fun Context.updateSubfolderCounts(
children: ArrayList<Directory>,
parentDirs: ArrayList<Directory>
) {
for (child in children) { for (child in children) {
var longestSharedPath = "" var longestSharedPath = ""
for (parentDir in parentDirs) { for (parentDir in parentDirs) {
@ -416,14 +457,21 @@ fun Context.updateSubfolderCounts(children: ArrayList<Directory>, parentDirs: Ar
continue continue
} }
if (child.path.startsWith(parentDir.path, true) && parentDir.path.length > longestSharedPath.length) { if (
child.path.startsWith(parentDir.path, true)
&& parentDir.path.length > longestSharedPath.length
) {
longestSharedPath = parentDir.path longestSharedPath = parentDir.path
} }
} }
// make sure we count only the proper direct subfolders, grouped the same way as on the main screen // make sure we count only the proper direct subfolders, grouped the same way as on the main screen
parentDirs.firstOrNull { it.path == longestSharedPath }?.apply { parentDirs.firstOrNull { it.path == longestSharedPath }?.apply {
if (path.equals(child.path, true) || path.equals(File(child.path).parent, true) || children.any { it.path.equals(File(child.path).parent, true) }) { if (
path.equals(child.path, true)
|| path.equals(File(child.path).parent, true)
|| children.any { it.path.equals(File(child.path).parent, true) }
) {
if (child.containsMediaFilesDirectly) { if (child.containsMediaFilesDirectly) {
subfoldersCount++ subfoldersCount++
} }
@ -459,7 +507,10 @@ fun Context.getNoMediaFoldersSync(): ArrayList<String> {
do { do {
val path = cursor.getStringValue(Files.FileColumns.DATA) ?: continue val path = cursor.getStringValue(Files.FileColumns.DATA) ?: continue
val noMediaFile = File(path) val noMediaFile = File(path)
if (getDoesFilePathExist(noMediaFile.absolutePath, OTGPath) && noMediaFile.name == NOMEDIA) { if (
getDoesFilePathExist(noMediaFile.absolutePath, OTGPath)
&& noMediaFile.name == NOMEDIA
) {
folders.add(noMediaFile.parent) folders.add(noMediaFile.parent)
} }
} while (cursor.moveToNext()) } while (cursor.moveToNext())
@ -480,7 +531,13 @@ fun Context.rescanFolderMedia(path: String) {
fun Context.rescanFolderMediaSync(path: String) { fun Context.rescanFolderMediaSync(path: String) {
getCachedMedia(path) { cached -> getCachedMedia(path) { cached ->
GetMediaAsynctask(applicationContext, path, isPickImage = false, isPickVideo = false, showAll = false) { newMedia -> GetMediaAsynctask(
context = applicationContext,
mPath = path,
isPickImage = false,
isPickVideo = false,
showAll = false
) { newMedia ->
ensureBackgroundThread { ensureBackgroundThread {
val media = newMedia.filterIsInstance<Medium>() as ArrayList<Medium> val media = newMedia.filterIsInstance<Medium>() as ArrayList<Medium>
try { try {
@ -507,14 +564,22 @@ fun Context.storeDirectoryItems(items: ArrayList<Directory>) {
} }
} }
fun Context.checkAppendingHidden(path: String, hidden: String, includedFolders: MutableSet<String>, noMediaFolders: ArrayList<String>): String { fun Context.checkAppendingHidden(
path: String,
hidden: String,
includedFolders: MutableSet<String>,
noMediaFolders: ArrayList<String>
): String {
val dirName = getFolderNameFromPath(path) val dirName = getFolderNameFromPath(path)
val folderNoMediaStatuses = HashMap<String, Boolean>() val folderNoMediaStatuses = HashMap<String, Boolean>()
noMediaFolders.forEach { folder -> noMediaFolders.forEach { folder ->
folderNoMediaStatuses["$folder/$NOMEDIA"] = true folderNoMediaStatuses["$folder/$NOMEDIA"] = true
} }
return if (path.doesThisOrParentHaveNoMedia(folderNoMediaStatuses, null) && !path.isThisOrParentIncluded(includedFolders)) { return if (
path.doesThisOrParentHaveNoMedia(folderNoMediaStatuses, null)
&& !path.isThisOrParentIncluded(includedFolders)
) {
"$dirName $hidden" "$dirName $hidden"
} else { } else {
dirName dirName
@ -572,7 +637,19 @@ fun Context.addTempFolderIfNeeded(dirs: ArrayList<Directory>): ArrayList<Directo
val tempFolderPath = config.tempFolderPath val tempFolderPath = config.tempFolderPath
return if (tempFolderPath.isNotEmpty()) { return if (tempFolderPath.isNotEmpty()) {
val directories = ArrayList<Directory>() val directories = ArrayList<Directory>()
val newFolder = Directory(null, tempFolderPath, "", tempFolderPath.getFilenameFromPath(), 0, 0, 0, 0L, getPathLocation(tempFolderPath), 0, "") val newFolder = Directory(
id = null,
path = tempFolderPath,
tmb = "",
name = tempFolderPath.getFilenameFromPath(),
mediaCnt = 0,
modified = 0,
taken = 0,
size = 0L,
location = getPathLocation(tempFolderPath),
types = 0,
sortValue = ""
)
directories.add(newFolder) directories.add(newFolder)
directories.addAll(dirs) directories.addAll(dirs)
directories directories
@ -611,7 +688,10 @@ fun Context.loadImageBase(
if (cropThumbnails) { if (cropThumbnails) {
options.optionalTransform(CenterCrop()) options.optionalTransform(CenterCrop())
options.optionalTransform(WebpDrawable::class.java, WebpDrawableTransformation(CenterCrop())) options.optionalTransform(
WebpDrawable::class.java,
WebpDrawableTransformation(CenterCrop())
)
} else { } else {
options.optionalTransform(FitCenter()) options.optionalTransform(FitCenter())
options.optionalTransform(WebpDrawable::class.java, WebpDrawableTransformation(FitCenter())) options.optionalTransform(WebpDrawable::class.java, WebpDrawableTransformation(FitCenter()))
@ -636,7 +716,10 @@ fun Context.loadImageBase(
options.optionalTransform(MultiTransformation(CenterCrop(), roundedCornersTransform)) options.optionalTransform(MultiTransformation(CenterCrop(), roundedCornersTransform))
options.optionalTransform( options.optionalTransform(
WebpDrawable::class.java, WebpDrawable::class.java,
MultiTransformation(WebpDrawableTransformation(CenterCrop()), WebpDrawableTransformation(roundedCornersTransform)) MultiTransformation(
WebpDrawableTransformation(CenterCrop()),
WebpDrawableTransformation(roundedCornersTransform)
)
) )
} }
@ -648,7 +731,12 @@ fun Context.loadImageBase(
.transition(getOptionalCrossFadeTransition(crossFadeDuration)) .transition(getOptionalCrossFadeTransition(crossFadeDuration))
builder = builder.listener(object : RequestListener<Drawable> { builder = builder.listener(object : RequestListener<Drawable> {
override fun onLoadFailed(e: GlideException?, model: Any?, targetBitmap: Target<Drawable>, isFirstResource: Boolean): Boolean { override fun onLoadFailed(
e: GlideException?,
model: Any?,
targetBitmap: Target<Drawable>,
isFirstResource: Boolean
): Boolean {
if (tryLoadingWithPicasso) { if (tryLoadingWithPicasso) {
tryLoadingWithPicasso(path, target, cropThumbnails, roundCorners, signature) tryLoadingWithPicasso(path, target, cropThumbnails, roundCorners, signature)
} else { } else {
@ -678,7 +766,11 @@ fun Context.loadSVG(
signature: ObjectKey, signature: ObjectKey,
crossFadeDuration: Int = THUMBNAIL_FADE_DURATION_MS, crossFadeDuration: Int = THUMBNAIL_FADE_DURATION_MS,
) { ) {
target.scaleType = if (cropThumbnails) ImageView.ScaleType.CENTER_CROP else ImageView.ScaleType.FIT_CENTER target.scaleType = if (cropThumbnails) {
ImageView.ScaleType.CENTER_CROP
} else {
ImageView.ScaleType.FIT_CENTER
}
val options = RequestOptions().signature(signature) val options = RequestOptions().signature(signature)
var builder = Glide.with(applicationContext) var builder = Glide.with(applicationContext)
@ -702,7 +794,13 @@ fun Context.loadSVG(
} }
// intended mostly for Android 11 issues, that fail loading PNG files bigger than 10 MB // intended mostly for Android 11 issues, that fail loading PNG files bigger than 10 MB
fun Context.tryLoadingWithPicasso(path: String, view: MySquareImageView, cropThumbnails: Boolean, roundCorners: Int, signature: ObjectKey) { fun Context.tryLoadingWithPicasso(
path: String,
view: MySquareImageView,
cropThumbnails: Boolean,
roundCorners: Int,
signature: ObjectKey
) {
var pathToLoad = "file://$path" var pathToLoad = "file://$path"
pathToLoad = pathToLoad.replace("%", "%25").replace("#", "%23") pathToLoad = pathToLoad.replace("%", "%25").replace("#", "%23")
@ -768,22 +866,27 @@ fun Context.getCachedDirectories(
} }
var filteredDirectories = directories.filter { var filteredDirectories = directories.filter {
it.path.shouldFolderBeVisible(excludedPaths, includedPaths, shouldShowHidden, folderNoMediaStatuses) { path, hasNoMedia -> it.path.shouldFolderBeVisible(
excludedPaths = excludedPaths,
includedPaths = includedPaths,
showHidden = shouldShowHidden,
folderNoMediaStatuses = folderNoMediaStatuses
) { path, hasNoMedia ->
folderNoMediaStatuses[path] = hasNoMedia folderNoMediaStatuses[path] = hasNoMedia
} }
} as ArrayList<Directory> } as ArrayList<Directory>
val filterMedia = config.filterMedia
val filterMedia = config.filterMedia
filteredDirectories = (when { filteredDirectories = (when {
getVideosOnly -> filteredDirectories.filter { it.types and TYPE_VIDEOS != 0 } getVideosOnly -> filteredDirectories.filter { it.types and TYPE_VIDEOS != 0 }
getImagesOnly -> filteredDirectories.filter { it.types and TYPE_IMAGES != 0 } getImagesOnly -> filteredDirectories.filter { it.types and TYPE_IMAGES != 0 }
else -> filteredDirectories.filter { else -> filteredDirectories.filter {
(filterMedia and TYPE_IMAGES != 0 && it.types and TYPE_IMAGES != 0) || (filterMedia and TYPE_IMAGES != 0 && it.types and TYPE_IMAGES != 0)
(filterMedia and TYPE_VIDEOS != 0 && it.types and TYPE_VIDEOS != 0) || || (filterMedia and TYPE_VIDEOS != 0 && it.types and TYPE_VIDEOS != 0)
(filterMedia and TYPE_GIFS != 0 && it.types and TYPE_GIFS != 0) || || (filterMedia and TYPE_GIFS != 0 && it.types and TYPE_GIFS != 0)
(filterMedia and TYPE_RAWS != 0 && it.types and TYPE_RAWS != 0) || || (filterMedia and TYPE_RAWS != 0 && it.types and TYPE_RAWS != 0)
(filterMedia and TYPE_SVGS != 0 && it.types and TYPE_SVGS != 0) || || (filterMedia and TYPE_SVGS != 0 && it.types and TYPE_SVGS != 0)
(filterMedia and TYPE_PORTRAITS != 0 && it.types and TYPE_PORTRAITS != 0) || (filterMedia and TYPE_PORTRAITS != 0 && it.types and TYPE_PORTRAITS != 0)
} }
}) as ArrayList<Directory> }) as ArrayList<Directory>
@ -814,10 +917,20 @@ fun Context.getCachedDirectories(
} }
} }
fun Context.getCachedMedia(path: String, getVideosOnly: Boolean = false, getImagesOnly: Boolean = false, callback: (ArrayList<ThumbnailItem>) -> Unit) { fun Context.getCachedMedia(
path: String,
getVideosOnly: Boolean = false,
getImagesOnly: Boolean = false,
callback: (ArrayList<ThumbnailItem>) -> Unit
) {
ensureBackgroundThread { ensureBackgroundThread {
val mediaFetcher = MediaFetcher(this) val mediaFetcher = MediaFetcher(this)
val foldersToScan = if (path.isEmpty()) mediaFetcher.getFoldersToScan() else arrayListOf(path) val foldersToScan = if (path.isEmpty()) {
mediaFetcher.getFoldersToScan()
} else {
arrayListOf(path)
}
var media = ArrayList<Medium>() var media = ArrayList<Medium>()
if (path == FAVORITES) { if (path == FAVORITES) {
media.addAll(mediaDB.getFavorites()) media.addAll(mediaDB.getFavorites())
@ -856,12 +969,12 @@ fun Context.getCachedMedia(path: String, getVideosOnly: Boolean = false, getImag
getVideosOnly -> media.filter { it.type == TYPE_VIDEOS } getVideosOnly -> media.filter { it.type == TYPE_VIDEOS }
getImagesOnly -> media.filter { it.type == TYPE_IMAGES } getImagesOnly -> media.filter { it.type == TYPE_IMAGES }
else -> media.filter { else -> media.filter {
(filterMedia and TYPE_IMAGES != 0 && it.type == TYPE_IMAGES) || (filterMedia and TYPE_IMAGES != 0 && it.type == TYPE_IMAGES)
(filterMedia and TYPE_VIDEOS != 0 && it.type == TYPE_VIDEOS) || || (filterMedia and TYPE_VIDEOS != 0 && it.type == TYPE_VIDEOS)
(filterMedia and TYPE_GIFS != 0 && it.type == TYPE_GIFS) || || (filterMedia and TYPE_GIFS != 0 && it.type == TYPE_GIFS)
(filterMedia and TYPE_RAWS != 0 && it.type == TYPE_RAWS) || || (filterMedia and TYPE_RAWS != 0 && it.type == TYPE_RAWS)
(filterMedia and TYPE_SVGS != 0 && it.type == TYPE_SVGS) || || (filterMedia and TYPE_SVGS != 0 && it.type == TYPE_SVGS)
(filterMedia and TYPE_PORTRAITS != 0 && it.type == TYPE_PORTRAITS) || (filterMedia and TYPE_PORTRAITS != 0 && it.type == TYPE_PORTRAITS)
} }
}) as ArrayList<Medium> }) as ArrayList<Medium>
@ -902,7 +1015,12 @@ fun Context.getCachedMedia(path: String, getVideosOnly: Boolean = false, getImag
fun Context.removeInvalidDBDirectories(dirs: ArrayList<Directory>? = null) { fun Context.removeInvalidDBDirectories(dirs: ArrayList<Directory>? = null) {
val dirsToCheck = dirs ?: directoryDB.getAll() val dirsToCheck = dirs ?: directoryDB.getAll()
val OTGPath = config.OTGPath val OTGPath = config.OTGPath
dirsToCheck.filter { !it.areFavorites() && !it.isRecycleBin() && !getDoesFilePathExist(it.path, OTGPath) && it.path != config.tempFolderPath }.forEach { dirsToCheck.filter {
!it.areFavorites()
&& !it.isRecycleBin()
&& !getDoesFilePathExist(it.path, OTGPath)
&& it.path != config.tempFolderPath
}.forEach {
try { try {
directoryDB.deleteDirPath(it.path) directoryDB.deleteDirPath(it.path)
} catch (ignored: Exception) { } catch (ignored: Exception) {
@ -923,14 +1041,14 @@ fun Context.updateDBMediaPath(oldPath: String, newPath: String) {
fun Context.updateDBDirectory(directory: Directory) { fun Context.updateDBDirectory(directory: Directory) {
try { try {
directoryDB.updateDirectory( directoryDB.updateDirectory(
directory.path, path = directory.path,
directory.tmb, thumbnail = directory.tmb,
directory.mediaCnt, mediaCnt = directory.mediaCnt,
directory.modified, lastModified = directory.modified,
directory.taken, dateTaken = directory.taken,
directory.size, size = directory.size,
directory.types, mediaTypes = directory.types,
directory.sortValue sortValue = directory.sortValue
) )
} catch (ignored: Exception) { } catch (ignored: Exception) {
} }
@ -938,7 +1056,9 @@ fun Context.updateDBDirectory(directory: Directory) {
fun Context.getOTGFolderChildren(path: String) = getDocumentFile(path)?.listFiles() fun Context.getOTGFolderChildren(path: String) = getDocumentFile(path)?.listFiles()
fun Context.getOTGFolderChildrenNames(path: String) = getOTGFolderChildren(path)?.map { it.name }?.toMutableList() fun Context.getOTGFolderChildrenNames(path: String): MutableList<String?>? {
return getOTGFolderChildren(path)?.map { it.name }?.toMutableList()
}
fun Context.getFavoritePaths(): ArrayList<String> { fun Context.getFavoritePaths(): ArrayList<String> {
return try { return try {
@ -948,7 +1068,9 @@ fun Context.getFavoritePaths(): ArrayList<String> {
} }
} }
fun Context.getFavoriteFromPath(path: String) = Favorite(null, path, path.getFilenameFromPath(), path.getParentPath()) fun Context.getFavoriteFromPath(path: String): Favorite {
return Favorite(null, path, path.getFilenameFromPath(), path.getParentPath())
}
fun Context.updateFavorite(path: String, isFavorite: Boolean) { fun Context.updateFavorite(path: String, isFavorite: Boolean) {
try { try {
@ -988,8 +1110,10 @@ fun Context.deleteMediumWithPath(path: String) {
} }
fun Context.updateWidgets() { fun Context.updateWidgets() {
val widgetIDs = AppWidgetManager.getInstance(applicationContext)?.getAppWidgetIds(ComponentName(applicationContext, MyWidgetProvider::class.java)) val widgetIDs = AppWidgetManager.getInstance(applicationContext)
?.getAppWidgetIds(ComponentName(applicationContext, MyWidgetProvider::class.java))
?: return ?: return
if (widgetIDs.isNotEmpty()) { if (widgetIDs.isNotEmpty()) {
Intent(applicationContext, MyWidgetProvider::class.java).apply { Intent(applicationContext, MyWidgetProvider::class.java).apply {
action = AppWidgetManager.ACTION_APPWIDGET_UPDATE action = AppWidgetManager.ACTION_APPWIDGET_UPDATE
@ -1000,8 +1124,15 @@ fun Context.updateWidgets() {
} }
// based on https://github.com/sannies/mp4parser/blob/master/examples/src/main/java/com/google/code/mp4parser/example/PrintStructure.java // based on https://github.com/sannies/mp4parser/blob/master/examples/src/main/java/com/google/code/mp4parser/example/PrintStructure.java
fun Context.parseFileChannel(path: String, fc: FileChannel, level: Int, start: Long, end: Long, callback: () -> Unit) { fun Context.parseFileChannel(
val FILE_CHANNEL_CONTAINERS = arrayListOf("moov", "trak", "mdia", "minf", "udta", "stbl") path: String,
fc: FileChannel,
level: Int,
start: Long,
end: Long,
callback: () -> Unit
) {
val fileChannelContainers = arrayListOf("moov", "trak", "mdia", "minf", "udta", "stbl")
try { try {
var iteration = 0 var iteration = 0
var currEnd = end var currEnd = end
@ -1040,13 +1171,16 @@ fun Context.parseFileChannel(path: String, fc: FileChannel, level: Int, start: L
} }
val xmlString = sb.toString().lowercase(Locale.getDefault()) val xmlString = sb.toString().lowercase(Locale.getDefault())
if (xmlString.contains("gspherical:projectiontype>equirectangular") || xmlString.contains("gspherical:projectiontype=\"equirectangular\"")) { if (
xmlString.contains("gspherical:projectiontype>equirectangular")
|| xmlString.contains("gspherical:projectiontype=\"equirectangular\"")
) {
callback.invoke() callback.invoke()
} }
return return
} }
if (FILE_CHANNEL_CONTAINERS.contains(type)) { if (fileChannelContainers.contains(type)) {
parseFileChannel(path, fc, level + 1, begin + 8, newEnd, callback) parseFileChannel(path, fc, level + 1, begin + 8, newEnd, callback)
} }
@ -1075,8 +1209,18 @@ fun Context.addPathToDB(path: String) {
val isFavorite = favoritesDB.isFavorite(path) val isFavorite = favoritesDB.isFavorite(path)
val videoDuration = if (type == TYPE_VIDEOS) getDuration(path) ?: 0 else 0 val videoDuration = if (type == TYPE_VIDEOS) getDuration(path) ?: 0 else 0
val medium = Medium( val medium = Medium(
null, path.getFilenameFromPath(), path, path.getParentPath(), System.currentTimeMillis(), System.currentTimeMillis(), id = null,
File(path).length(), type, videoDuration, isFavorite, 0L, 0L name = path.getFilenameFromPath(),
path = path,
parentPath = path.getParentPath(),
modified = System.currentTimeMillis(),
taken = System.currentTimeMillis(),
size = File(path).length(),
type = type,
videoDuration = videoDuration,
isFavorite = isFavorite,
deletedTS = 0L,
mediaStoreId = 0L
) )
mediaDB.insert(medium) mediaDB.insert(medium)
@ -1118,16 +1262,44 @@ fun Context.createDirectoryFromMedia(
val firstItem = curMedia.firstOrNull() ?: defaultMedium val firstItem = curMedia.firstOrNull() ?: defaultMedium
val lastItem = curMedia.lastOrNull() ?: defaultMedium val lastItem = curMedia.lastOrNull() ?: defaultMedium
val dirName = checkAppendingHidden(path, hiddenString, includedFolders, noMediaFolders) val dirName = checkAppendingHidden(path, hiddenString, includedFolders, noMediaFolders)
val lastModified = if (isSortingAscending) Math.min(firstItem.modified, lastItem.modified) else Math.max(firstItem.modified, lastItem.modified) val lastModified = if (isSortingAscending) {
val dateTaken = if (isSortingAscending) Math.min(firstItem.taken, lastItem.taken) else Math.max(firstItem.taken, lastItem.taken) min(firstItem.modified, lastItem.modified)
} else {
max(firstItem.modified, lastItem.modified)
}
val dateTaken = if (isSortingAscending) {
min(firstItem.taken, lastItem.taken)
} else {
max(firstItem.taken, lastItem.taken)
}
val size = if (getProperFileSize) curMedia.sumByLong { it.size } else 0L val size = if (getProperFileSize) curMedia.sumByLong { it.size } else 0L
val mediaTypes = curMedia.getDirMediaTypes() val mediaTypes = curMedia.getDirMediaTypes()
val count = curMedia.size val count = curMedia.size
val sortValue = getDirectorySortingValue(curMedia, path, dirName, size, count) val sortValue = getDirectorySortingValue(curMedia, path, dirName, size, count)
return Directory(null, path, thumbnail!!, dirName, curMedia.size, lastModified, dateTaken, size, getPathLocation(path), mediaTypes, sortValue) return Directory(
id = null,
path = path,
tmb = thumbnail!!,
name = dirName,
mediaCnt = curMedia.size,
modified = lastModified,
taken = dateTaken,
size = size,
location = getPathLocation(path),
types = mediaTypes,
sortValue = sortValue
)
} }
fun Context.getDirectorySortingValue(media: ArrayList<Medium>, path: String, name: String, size: Long, count: Int): String { fun Context.getDirectorySortingValue(
media: ArrayList<Medium>,
path: String,
name: String,
size: Long,
count: Int
): String {
val sorting = config.directorySorting val sorting = config.directorySorting
val sorted = when { val sorted = when {
sorting and SORT_BY_NAME != 0 -> return name sorting and SORT_BY_NAME != 0 -> return name
@ -1165,26 +1337,48 @@ fun Context.updateDirectoryPath(path: String) {
val sorting = config.getFolderSorting(path) val sorting = config.getFolderSorting(path)
val grouping = config.getFolderGrouping(path) val grouping = config.getFolderGrouping(path)
val getProperDateTaken = config.directorySorting and SORT_BY_DATE_TAKEN != 0 || val getProperDateTaken = config.directorySorting and SORT_BY_DATE_TAKEN != 0
sorting and SORT_BY_DATE_TAKEN != 0 || || sorting and SORT_BY_DATE_TAKEN != 0
grouping and GROUP_BY_DATE_TAKEN_DAILY != 0 || || grouping and GROUP_BY_DATE_TAKEN_DAILY != 0
grouping and GROUP_BY_DATE_TAKEN_MONTHLY != 0 || grouping and GROUP_BY_DATE_TAKEN_MONTHLY != 0
val getProperLastModified = config.directorySorting and SORT_BY_DATE_MODIFIED != 0 || val getProperLastModified = config.directorySorting and SORT_BY_DATE_MODIFIED != 0
sorting and SORT_BY_DATE_MODIFIED != 0 || || sorting and SORT_BY_DATE_MODIFIED != 0
grouping and GROUP_BY_LAST_MODIFIED_DAILY != 0 || || grouping and GROUP_BY_LAST_MODIFIED_DAILY != 0
grouping and GROUP_BY_LAST_MODIFIED_MONTHLY != 0 || grouping and GROUP_BY_LAST_MODIFIED_MONTHLY != 0
val getProperFileSize = config.directorySorting and SORT_BY_SIZE != 0 val getProperFileSize = config.directorySorting and SORT_BY_SIZE != 0
val lastModifieds = if (getProperLastModified) mediaFetcher.getFolderLastModifieds(path) else HashMap() val lastModifieds = if (getProperLastModified) {
mediaFetcher.getFolderLastModifieds(path)
} else {
HashMap()
}
val dateTakens = mediaFetcher.getFolderDateTakens(path) val dateTakens = mediaFetcher.getFolderDateTakens(path)
val favoritePaths = getFavoritePaths() val favoritePaths = getFavoritePaths()
val curMedia = mediaFetcher.getFilesFrom( val curMedia = mediaFetcher.getFilesFrom(
path, getImagesOnly, getVideosOnly, getProperDateTaken, getProperLastModified, getProperFileSize, curPath = path,
favoritePaths, false, lastModifieds, dateTakens, null isPickImage = getImagesOnly,
isPickVideo = getVideosOnly,
getProperDateTaken = getProperDateTaken,
getProperLastModified = getProperLastModified,
getProperFileSize = getProperFileSize,
favoritePaths = favoritePaths,
getVideoDurations = false,
lastModifieds = lastModifieds,
dateTakens = dateTakens,
android11Files = null
)
val directory = createDirectoryFromMedia(
path = path,
curMedia = curMedia,
albumCovers = albumCovers,
hiddenString = hiddenString,
includedFolders = includedFolders,
getProperFileSize = getProperFileSize,
noMediaFolders = noMediaFolders
) )
val directory = createDirectoryFromMedia(path, curMedia, albumCovers, hiddenString, includedFolders, getProperFileSize, noMediaFolders)
updateDBDirectory(directory) updateDBDirectory(directory)
} }