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
import android.app.Activity
import android.content.ClipData
import android.content.Intent
import android.net.Uri
@ -173,8 +172,13 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
private var mWasMediaManagementPromptShown = false
private var mLatestMediaId = 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 mTimeFormat = ""
private var mLastMediaHandler = Handler()
@ -215,15 +219,19 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
mIsGetAnyContentIntent = isGetAnyContentIntent(intent)
mIsSetWallpaperIntent = isSetWallpaperIntent(intent)
mAllowPickingMultiple = intent.getBooleanExtra(Intent.EXTRA_ALLOW_MULTIPLE, false)
mIsThirdPartyIntent = mIsPickImageIntent || mIsPickVideoIntent || mIsGetImageContentIntent || mIsGetVideoContentIntent ||
mIsGetAnyContentIntent || mIsSetWallpaperIntent
mIsThirdPartyIntent = mIsPickImageIntent
|| mIsPickVideoIntent
|| mIsGetImageContentIntent
|| mIsGetVideoContentIntent
|| mIsGetAnyContentIntent
|| mIsSetWallpaperIntent
setupOptionsMenu()
refreshMenuItems()
updateMaterialActivityViews(
binding.directoriesCoordinator,
binding.directoriesGrid,
mainCoordinatorLayout = binding.directoriesCoordinator,
nestedView = binding.directoriesGrid,
useTransparentNavigation = !config.scrollHorizontally,
useTopSearchMenu = true
)
@ -314,7 +322,8 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
getRecyclerAdapter()?.updatePrimaryColor()
}
val styleString = "${config.folderStyle}${config.showFolderMediaCount}${config.limitFolderTitle}"
val styleString =
"${config.folderStyle}${config.showFolderMediaCount}${config.limitFolderTitle}"
if (mStoredStyleString != styleString) {
setupAdapter(mDirs, forceRecreate = true)
}
@ -403,17 +412,21 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
}
override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) {
if (resultCode == Activity.RESULT_OK) {
if (resultCode == RESULT_OK) {
if (requestCode == PICK_MEDIA && resultData != null) {
val resultIntent = Intent()
var resultUri: Uri? = null
if (mIsThirdPartyIntent) {
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)
}
resultData.extras?.containsKey(PICKED_PATHS) == true -> fillPickedPaths(resultData, resultIntent)
resultData.extras?.containsKey(PICKED_PATHS) == true -> {
fillPickedPaths(resultData, resultIntent)
}
else -> fillIntentPath(resultData, resultIntent)
}
}
@ -423,10 +436,10 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
resultIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
setResult(Activity.RESULT_OK, resultIntent)
setResult(RESULT_OK, resultIntent)
finish()
} else if (requestCode == PICK_WALLPAPER) {
setResult(Activity.RESULT_OK)
setResult(RESULT_OK)
finish()
}
}
@ -438,14 +451,17 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
binding.mainMenu.getToolbar().menu.apply {
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.open_recycle_bin).isVisible = config.useRecycleBin && !config.showRecycleBinAtFolders
findItem(R.id.more_apps_from_us).isVisible = !resources.getBoolean(org.fossify.commons.R.bool.hide_google_relations)
findItem(R.id.open_recycle_bin).isVisible =
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 {
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.stop_showing_excluded).isVisible = config.temporarilyShowExcluded
@ -471,7 +487,8 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
binding.mainMenu.onSearchTextChangedListener = { text ->
setupAdapter(mDirsIgnoringSearch, text)
binding.directoriesRefreshLayout.isEnabled = text.isEmpty() && config.enablePullToRefresh
binding.directoriesRefreshLayout.isEnabled =
text.isEmpty() && config.enablePullToRefresh
binding.directoriesSwitchSearching.beVisibleIf(text.isNotEmpty())
}
@ -528,8 +545,17 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
if (config.tempFolderPath.isNotEmpty()) {
val newFolder = File(config.tempFolderPath)
if (getDoesFilePathExist(newFolder.absolutePath) && newFolder.isDirectory) {
if (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)
if (
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)
}
}
@ -540,7 +566,10 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
private fun checkOTGPath() {
ensureBackgroundThread {
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
val otgPath = trimEnd('/')
config.OTGPath = otgPath
@ -568,7 +597,8 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
private fun tryLoadGallery() {
// 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 {
if (wasMissingPermission) {
return@handleMediaPermissions
@ -707,23 +737,39 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
}
override fun deleteFolders(folders: ArrayList<File>) {
val fileDirItems =
folders.asSequence().filter { it.isDirectory }.map { FileDirItem(it.absolutePath, it.name, true) }.toMutableList() as ArrayList<FileDirItem>
val fileDirItems = folders
.asSequence()
.filter { it.isDirectory }
.map { FileDirItem(it.absolutePath, it.name, true) }
.toMutableList() as ArrayList<FileDirItem>
when {
fileDirItems.isEmpty() -> return
fileDirItems.size == 1 -> {
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) {
showErrorToast(e)
}
}
else -> {
val baseString =
if (config.useRecycleBin && !config.tempSkipRecycleBin) org.fossify.commons.R.plurals.moving_items_into_bin else org.fossify.commons.R.plurals.delete_items
val deletingItems = resources.getQuantityString(baseString, fileDirItems.size, fileDirItems.size)
toast(deletingItems)
val baseString = if (config.useRecycleBin && !config.tempSkipRecycleBin) {
org.fossify.commons.R.plurals.moving_items_into_bin
} else {
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 {
val files = File(it.path).listFiles()
files?.filter {
it.absolutePath.isMediaFile() && (showHidden || !it.name.startsWith('.')) &&
((it.isImageFast() && filter and TYPE_IMAGES != 0) ||
(it.isVideoFast() && filter and TYPE_VIDEOS != 0) ||
(it.isGif() && filter and TYPE_GIFS != 0) ||
(it.isRawFast() && filter and TYPE_RAWS != 0) ||
(it.isSvg() && filter and TYPE_SVGS != 0))
it.absolutePath.isMediaFile()
&& (showHidden || !it.name.startsWith('.'))
&& ((it.isImageFast() && filter and TYPE_IMAGES != 0)
|| (it.isVideoFast() && filter and TYPE_VIDEOS != 0)
|| (it.isGif() && filter and TYPE_GIFS != 0)
|| (it.isRawFast() && filter and TYPE_RAWS != 0)
|| (it.isSvg() && filter and TYPE_SVGS != 0))
}?.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
deleteFiles(fileDirItems) {
runOnUiThread {
@ -771,7 +821,11 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
}
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 {
tryDeleteFileDirItem(it.toFileDirItem(this), true, true)
}
@ -787,7 +841,8 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
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() {
@ -795,11 +850,17 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
if (config.scrollHorizontally) {
layoutManager.orientation = RecyclerView.HORIZONTAL
binding.directoriesRefreshLayout.layoutParams =
RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT)
RelativeLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
} else {
layoutManager.orientation = RecyclerView.VERTICAL
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
@ -809,7 +870,10 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
val layoutManager = binding.directoriesGrid.layoutManager as MyGridLayoutManager
layoutManager.spanCount = 1
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
}
@ -850,10 +914,18 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
private fun changeColumnCount() {
val items = ArrayList<RadioItem>()
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) {
val newColumnCount = it as Int
if (currentColumnCount != newColumnCount) {
@ -874,40 +946,69 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
}
private fun columnCountChanged() {
(binding.directoriesGrid.layoutManager as MyGridLayoutManager).spanCount = config.dirColumnCnt
(binding.directoriesGrid.layoutManager as MyGridLayoutManager).spanCount =
config.dirColumnCnt
refreshMenuItems()
getRecyclerAdapter()?.apply {
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) &&
(intent.type!!.startsWith("image/") || intent.type == Images.Media.CONTENT_TYPE)
private fun isGetImageContentIntent(intent: Intent): Boolean {
return isGetContentIntent(intent)
&& (intent.type!!.startsWith("image/")
|| intent.type == Images.Media.CONTENT_TYPE)
}
private fun isGetVideoContentIntent(intent: Intent) = isGetContentIntent(intent) &&
(intent.type!!.startsWith("video/") || intent.type == Video.Media.CONTENT_TYPE)
private fun isGetVideoContentIntent(intent: Intent): Boolean {
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 ||
intent.data == Images.Media.INTERNAL_CONTENT_URI)
private fun hasImageContentData(intent: Intent): Boolean {
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 ||
intent.data == Video.Media.INTERNAL_CONTENT_URI)
private fun hasVideoContentData(intent: Intent): Boolean {
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? {
val file = File(resultData.data!!.path!!)
@ -932,8 +1033,13 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
private fun fillPickedPaths(resultData: Intent, resultIntent: Intent) {
val paths = resultData.extras!!.getStringArrayList(PICKED_PATHS)
val uris = paths!!.map { getFilePublicUri(File(it), BuildConfig.APPLICATION_ID) } as ArrayList
val clipData = ClipData("Attachment", arrayOf("image/*", "video/*"), ClipData.Item(uris.removeAt(0)))
val uris = paths!!
.map { getFilePublicUri(File(it), BuildConfig.APPLICATION_ID) } as ArrayList
val clipData = ClipData(
"Attachment",
arrayOf("image/*", "video/*"),
ClipData.Item(uris.removeAt(0))
)
uris.forEach {
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 (!config.shouldShowHidden) {
val favoritesFolder = newDirs.firstOrNull { it.areFavorites() }
if (favoritesFolder != null && favoritesFolder.tmb.getFilenameFromPath().startsWith('.')) {
if (
favoritesFolder != null
&& favoritesFolder.tmb.getFilenameFromPath().startsWith('.')
) {
newDirs.remove(favoritesFolder)
}
}
@ -1020,7 +1129,11 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
val lastModifieds = mLastMediaFetcher!!.getLastModifieds()
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 {
if (mediaDB.getDeletedMediaCount() > 0) {
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+
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 {
for (directory in dirs) {
if (mShouldStopFetching || isDestroyed || isFinishing) {
@ -1057,19 +1177,29 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
val sorting = config.getFolderSorting(directory.path)
val grouping = config.getFolderGrouping(directory.path)
val getProperDateTaken = config.directorySorting 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_MONTHLY != 0
val getProperDateTaken = config.directorySorting 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_MONTHLY != 0
val getProperLastModified = config.directorySorting 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_MONTHLY != 0
val getProperLastModified =
config.directorySorting 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_MONTHLY != 0
val curMedia = mLastMediaFetcher!!.getFilesFrom(
directory.path, getImagesOnly, getVideosOnly, getProperDateTaken, getProperLastModified,
getProperFileSize, favoritePaths, false, lastModifieds, dateTakens, android11Files
curPath = directory.path,
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()) {
@ -1078,7 +1208,15 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
}
directory
} 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
@ -1164,19 +1302,28 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
val sorting = config.getFolderSorting(folder)
val grouping = config.getFolderGrouping(folder)
val getProperDateTaken = config.directorySorting 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_MONTHLY != 0
val getProperDateTaken = config.directorySorting 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_MONTHLY != 0
val getProperLastModified = config.directorySorting 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_MONTHLY != 0
val getProperLastModified = config.directorySorting 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_MONTHLY != 0
val newMedia = mLastMediaFetcher!!.getFilesFrom(
folder, getImagesOnly, getVideosOnly, getProperDateTaken, getProperLastModified,
getProperFileSize, favoritePaths, false, lastModifieds, dateTakens, android11Files
curPath = folder,
isPickImage = getImagesOnly,
isPickVideo = getVideosOnly,
getProperDateTaken = getProperDateTaken,
getProperLastModified = getProperLastModified,
getProperFileSize = getProperFileSize,
favoritePaths = favoritePaths,
getVideoDurations = false,
lastModifieds = lastModifieds,
dateTakens = dateTakens,
android11Files = android11Files
)
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)
setupAdapter(dirs)
@ -1274,11 +1429,13 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
binding.directoriesEmptyPlaceholder2.beVisibleIf(dirs.isEmpty() && mLoadedInitialPhotos)
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()
} else if (dirs.isEmpty() && config.filterMedia == getDefaultFileFilter()) {
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()
} else {
binding.directoriesEmptyPlaceholder.text = getString(R.string.no_media_add_included)
@ -1292,7 +1449,8 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
}
} else {
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 {
showFilterMediaDialog()
@ -1303,11 +1461,22 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
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 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)
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) {
mDirsIgnoringSearch = dirs
@ -1345,7 +1514,9 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
} else {
runOnUiThread {
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
}
checkPlaceholderVisibility(dirsToShow)
@ -1361,7 +1532,8 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
}
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)
}
@ -1380,8 +1552,12 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
}
val hasMediaFile = children?.any {
it != null && (it.isMediaFile() || (it.startsWith("img_", true) && File(it).isDirectory))
} ?: false
it != null && (
it.isMediaFile()
|| (it.startsWith("img_", true)
&& File(it).isDirectory)
)
} == true
if (!hasMediaFile) {
invalidDirs.add(it)
@ -1458,7 +1634,9 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
Handler().postDelayed({
ensureBackgroundThread {
try {
val filesToDelete = mediaDB.getOldRecycleBinItems(System.currentTimeMillis() - MONTH_MILLISECONDS)
val filesToDelete = mediaDB.getOldRecycleBinItems(
System.currentTimeMillis() - MONTH_MILLISECONDS
)
filesToDelete.forEach {
if (File(it.path.replaceFirst(RECYCLE_BIN, recycleBinPath)).delete()) {
mediaDB.deleteMediumPath(it.path)
@ -1480,7 +1658,9 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
val internalPath = internalStoragePath
val checkedPaths = 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 {
val parts = it.split("/")
var currentString = ""

View file

@ -17,8 +17,41 @@ import com.bumptech.glide.request.target.SimpleTarget
import com.bumptech.glide.request.transition.Transition
import org.fossify.commons.dialogs.CreateNewFolderDialog
import org.fossify.commons.dialogs.RadioGroupDialog
import org.fossify.commons.extensions.*
import org.fossify.commons.helpers.*
import org.fossify.commons.extensions.appLockManager
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.RadioItem
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.databases.GalleryDatabase
import org.fossify.gallery.databinding.ActivityMediaBinding
import org.fossify.gallery.dialogs.*
import org.fossify.gallery.extensions.*
import org.fossify.gallery.helpers.*
import org.fossify.gallery.dialogs.ChangeGroupingDialog
import org.fossify.gallery.dialogs.ChangeSortingDialog
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.models.Medium
import org.fossify.gallery.models.ThumbnailItem
@ -99,7 +172,12 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
setupOptionsMenu()
refreshMenuItems()
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) {
registerFileUpdateListener()
@ -249,7 +327,8 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
}
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 {
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.open_camera).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.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.unset_as_default_folder).isVisible = isDefaultFolder
@ -352,12 +433,16 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
private fun searchQueryChanged(text: String) {
ensureBackgroundThread {
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) }
val grouped = MediaFetcher(applicationContext).groupMedia(filtered as ArrayList<Medium>, mPath)
val grouped = MediaFetcher(applicationContext).groupMedia(
media = filtered as ArrayList<Medium>, path = mPath
)
runOnUiThread {
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.mediaFastscroller.beGone()
} else {
@ -417,8 +502,13 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
if (currAdapter == null) {
initZoomListener()
MediaAdapter(
this, mMedia.clone() as ArrayList<ThumbnailItem>, this, mIsGetImageIntent || mIsGetVideoIntent || mIsGetAnyIntent,
mAllowPickingMultiple, mPath, binding.mediaGrid
activity = this,
media = mMedia.clone() as ArrayList<ThumbnailItem>,
listener = this,
isAGetIntent = mIsGetImageIntent || mIsGetVideoIntent || mIsGetAnyIntent,
allowMultiplePicks = mAllowPickingMultiple,
path = mPath,
recyclerView = binding.mediaGrid
) {
if (it is Medium && !isFinishing) {
itemClicked(it.path)
@ -585,7 +675,13 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
private fun startAsyncTask() {
mCurrAsyncTask?.stopFetching()
mCurrAsyncTask = GetMediaAsynctask(applicationContext, mPath, mIsGetImageIntent, mIsGetVideoIntent, mShowAll) {
mCurrAsyncTask = GetMediaAsynctask(
context = applicationContext,
mPath = mPath,
isPickImage = mIsGetImageIntent,
isPickVideo = mIsGetVideoIntent,
showAll = mShowAll
) {
ensureBackgroundThread {
val oldMedia = mMedia.clone() as ArrayList<ThumbnailItem>
val newMedia = it
@ -594,7 +690,10 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
// remove cached files that are no longer valid for whatever reason
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)) {
favoritesDB.deleteFavoritePath(it.path)
mediaDB.updateFavorite(it.path, false)
@ -611,7 +710,7 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
}
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) {
deleteDirectoryIfEmpty()
deleteDBDirectory()
@ -686,10 +785,16 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
val layoutManager = binding.mediaGrid.layoutManager as MyGridLayoutManager
if (config.scrollHorizontally) {
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 {
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
@ -709,7 +814,10 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
val layoutManager = binding.mediaGrid.layoutManager as MyGridLayoutManager
layoutManager.spanCount = 1
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
}
@ -722,11 +830,19 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
var currentGridDecoration: GridSpacingItemDecoration? = null
if (binding.mediaGrid.itemDecorationCount > 0) {
currentGridDecoration = binding.mediaGrid.getItemDecorationAt(0) as GridSpacingItemDecoration
currentGridDecoration =
binding.mediaGrid.getItemDecorationAt(0) as GridSpacingItemDecoration
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 != null) {
binding.mediaGrid.removeItemDecoration(currentGridDecoration)
@ -763,7 +879,14 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
private fun changeColumnCount() {
val items = ArrayList<RadioItem>()
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
@ -815,7 +938,10 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
.load(File(path))
.apply(options)
.into(object : SimpleTarget<Bitmap>() {
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
override fun onResourceReady(
resource: Bitmap,
transition: Transition<in Bitmap>?
) {
try {
WallpaperManager.getInstance(applicationContext).setBitmap(resource)
setResult(Activity.RESULT_OK)
@ -880,7 +1006,8 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
mLatestMediaId = getLatestMediaId()
mLatestMediaDateId = getLatestMediaByDateId()
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 {
try {
mediaDB.insertAll(mediaToInsert)
@ -891,13 +1018,22 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
}
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()) {
return
}
if (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)
if (
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)
movePathsInRecycleBin(filtered.map { it.path } as ArrayList<String>) {
@ -908,13 +1044,19 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
}
}
} 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)
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>) {
deleteFiles(filtered) {
@ -965,7 +1107,8 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
}
if (binding.mediaGrid.itemDecorationCount > 0) {
val currentGridDecoration = binding.mediaGrid.getItemDecorationAt(0) as GridSpacingItemDecoration
val currentGridDecoration =
binding.mediaGrid.getItemDecorationAt(0) as GridSpacingItemDecoration
currentGridDecoration.items = media
}
}

View file

@ -2,16 +2,32 @@ package org.fossify.gallery.dialogs
import android.content.DialogInterface
import org.fossify.commons.activities.BaseSimpleActivity
import org.fossify.commons.extensions.*
import org.fossify.commons.helpers.*
import org.fossify.commons.extensions.beGoneIf
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.databinding.DialogChangeSortingBinding
import org.fossify.gallery.extensions.config
import org.fossify.gallery.helpers.SHOW_ALL
class ChangeSortingDialog(
val activity: BaseSimpleActivity, val isDirectorySorting: Boolean, val showFolderCheckbox: Boolean,
val path: String = "", val callback: () -> Unit
val activity: BaseSimpleActivity,
val isDirectorySorting: Boolean,
val showFolderCheckbox: Boolean,
val path: String = "",
val callback: () -> Unit
) :
DialogInterface.OnClickListener {
private var currSorting = 0
@ -20,12 +36,24 @@ class ChangeSortingDialog(
private val binding: DialogChangeSortingBinding
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 {
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
sortingDialogUseForThisFolder.beVisibleIf(showFolderCheckbox)
@ -48,11 +76,20 @@ class ChangeSortingDialog(
private fun setupSortRadio() {
val sortingRadio = binding.sortingDialogRadioSorting
sortingRadio.setOnCheckedChangeListener { _, checkedId ->
val isSortingByNameOrPath = checkedId == binding.sortingDialogRadioName.id || checkedId == binding.sortingDialogRadioPath.id
binding.sortingDialogNumericSorting.beVisibleIf(isSortingByNameOrPath)
binding.sortingDialogOrderDivider.beVisibleIf(binding.sortingDialogNumericSorting.isVisible() || binding.sortingDialogUseForThisFolder.isVisible())
val isSortingByNameOrPath =
checkedId == binding.sortingDialogRadioName.id
|| 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.sortingDialogSortingDivider.beGoneIf(hideSortOrder)
}

View file

@ -117,6 +117,7 @@ import java.nio.ByteBuffer
import java.nio.channels.FileChannel
import java.util.Locale
import kotlin.math.max
import kotlin.math.min
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.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.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
@ -207,11 +212,12 @@ fun Context.getSortedDirectories(source: ArrayList<Directory>): ArrayList<Direct
if (sorting and SORT_USE_NUMERIC_VALUE != 0) {
AlphanumericComparator().compare(
o1.sortValue.normalizeString().lowercase(Locale.getDefault()),
o2.sortValue.normalizeString().lowercase(Locale.getDefault())
string1 = o1.sortValue.normalizeString().lowercase(Locale.getDefault()),
string2 = o2.sortValue.normalizeString().lowercase(Locale.getDefault())
)
} 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) {
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 {
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)
}
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) {
dirs.forEach {
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
if (currentPathPrefix.isNotEmpty()) {
val currentFolder =
allDirs.firstOrNull { parentDirs.firstOrNull { it.path.equals(currentPathPrefix, true) } == null && it.path.equals(currentPathPrefix, true) }
val currentFolder = allDirs.firstOrNull {
parentDirs.firstOrNull {
it.path.equals(currentPathPrefix, true)
} == null && it.path.equals(currentPathPrefix, true)
}
currentFolder?.apply {
subfoldersCount = 1
parentDirs.add(this)
@ -295,17 +313,17 @@ private fun Context.addParentWithoutMediaFiles(into: ArrayList<Directory>, path:
}
val directory = Directory(
newDirId + 1,
path,
subDirs.first().tmb,
getFolderNameFromPath(path),
subDirs.sumOf { it.mediaCnt },
lastModified,
dateTaken,
subDirs.sumByLong { it.size },
getPathLocation(path),
mediaTypes,
""
id = newDirId + 1,
path = path,
tmb = subDirs.first().tmb,
name = getFolderNameFromPath(path),
mediaCnt = subDirs.sumOf { it.mediaCnt },
modified = lastModified,
taken = dateTaken,
size = subDirs.sumByLong { it.size },
location = getPathLocation(path),
types = mediaTypes,
sortValue = ""
)
directory.containsMediaFilesDirectly = false
@ -335,7 +353,10 @@ fun Context.fillWithSharedDirectParents(dirs: ArrayList<Directory>): ArrayList<D
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 currentPaths = LinkedHashSet<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)
} 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
// /storage/emulated/0/Pictures/Images and
// /storage/emulated/0/Pictures/Screenshots,
// but /storage/emulated/0/Pictures is empty, still Pictures with the first folders thumbnails and proper other info
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)
if (addParentWithoutMediaFiles(dirs, parent)) {
foldersWithoutMediaFiles.add(parent)
@ -378,7 +412,11 @@ fun Context.getDirectParentSubfolders(dirs: ArrayList<Directory>, currentPathPre
currentPaths.forEach {
val path = it
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
}
}
@ -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) {
var longestSharedPath = ""
for (parentDir in parentDirs) {
@ -416,14 +457,21 @@ fun Context.updateSubfolderCounts(children: ArrayList<Directory>, parentDirs: Ar
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
}
}
// make sure we count only the proper direct subfolders, grouped the same way as on the main screen
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) {
subfoldersCount++
}
@ -459,7 +507,10 @@ fun Context.getNoMediaFoldersSync(): ArrayList<String> {
do {
val path = cursor.getStringValue(Files.FileColumns.DATA) ?: continue
val noMediaFile = File(path)
if (getDoesFilePathExist(noMediaFile.absolutePath, OTGPath) && noMediaFile.name == NOMEDIA) {
if (
getDoesFilePathExist(noMediaFile.absolutePath, OTGPath)
&& noMediaFile.name == NOMEDIA
) {
folders.add(noMediaFile.parent)
}
} while (cursor.moveToNext())
@ -480,7 +531,13 @@ fun Context.rescanFolderMedia(path: String) {
fun Context.rescanFolderMediaSync(path: String) {
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 {
val media = newMedia.filterIsInstance<Medium>() as ArrayList<Medium>
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 folderNoMediaStatuses = HashMap<String, Boolean>()
noMediaFolders.forEach { folder ->
folderNoMediaStatuses["$folder/$NOMEDIA"] = true
}
return if (path.doesThisOrParentHaveNoMedia(folderNoMediaStatuses, null) && !path.isThisOrParentIncluded(includedFolders)) {
return if (
path.doesThisOrParentHaveNoMedia(folderNoMediaStatuses, null)
&& !path.isThisOrParentIncluded(includedFolders)
) {
"$dirName $hidden"
} else {
dirName
@ -572,7 +637,19 @@ fun Context.addTempFolderIfNeeded(dirs: ArrayList<Directory>): ArrayList<Directo
val tempFolderPath = config.tempFolderPath
return if (tempFolderPath.isNotEmpty()) {
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.addAll(dirs)
directories
@ -611,7 +688,10 @@ fun Context.loadImageBase(
if (cropThumbnails) {
options.optionalTransform(CenterCrop())
options.optionalTransform(WebpDrawable::class.java, WebpDrawableTransformation(CenterCrop()))
options.optionalTransform(
WebpDrawable::class.java,
WebpDrawableTransformation(CenterCrop())
)
} else {
options.optionalTransform(FitCenter())
options.optionalTransform(WebpDrawable::class.java, WebpDrawableTransformation(FitCenter()))
@ -636,7 +716,10 @@ fun Context.loadImageBase(
options.optionalTransform(MultiTransformation(CenterCrop(), roundedCornersTransform))
options.optionalTransform(
WebpDrawable::class.java,
MultiTransformation(WebpDrawableTransformation(CenterCrop()), WebpDrawableTransformation(roundedCornersTransform))
MultiTransformation(
WebpDrawableTransformation(CenterCrop()),
WebpDrawableTransformation(roundedCornersTransform)
)
)
}
@ -648,7 +731,12 @@ fun Context.loadImageBase(
.transition(getOptionalCrossFadeTransition(crossFadeDuration))
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) {
tryLoadingWithPicasso(path, target, cropThumbnails, roundCorners, signature)
} else {
@ -678,7 +766,11 @@ fun Context.loadSVG(
signature: ObjectKey,
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)
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
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"
pathToLoad = pathToLoad.replace("%", "%25").replace("#", "%23")
@ -768,22 +866,27 @@ fun Context.getCachedDirectories(
}
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
}
} as ArrayList<Directory>
val filterMedia = config.filterMedia
val filterMedia = config.filterMedia
filteredDirectories = (when {
getVideosOnly -> filteredDirectories.filter { it.types and TYPE_VIDEOS != 0 }
getImagesOnly -> filteredDirectories.filter { it.types and TYPE_IMAGES != 0 }
else -> filteredDirectories.filter {
(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_GIFS != 0 && it.types and TYPE_GIFS != 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_PORTRAITS != 0 && it.types and TYPE_PORTRAITS != 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_GIFS != 0 && it.types and TYPE_GIFS != 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_PORTRAITS != 0 && it.types and TYPE_PORTRAITS != 0)
}
}) 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 {
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>()
if (path == FAVORITES) {
media.addAll(mediaDB.getFavorites())
@ -856,12 +969,12 @@ fun Context.getCachedMedia(path: String, getVideosOnly: Boolean = false, getImag
getVideosOnly -> media.filter { it.type == TYPE_VIDEOS }
getImagesOnly -> media.filter { it.type == TYPE_IMAGES }
else -> media.filter {
(filterMedia and TYPE_IMAGES != 0 && it.type == TYPE_IMAGES) ||
(filterMedia and TYPE_VIDEOS != 0 && it.type == TYPE_VIDEOS) ||
(filterMedia and TYPE_GIFS != 0 && it.type == TYPE_GIFS) ||
(filterMedia and TYPE_RAWS != 0 && it.type == TYPE_RAWS) ||
(filterMedia and TYPE_SVGS != 0 && it.type == TYPE_SVGS) ||
(filterMedia and TYPE_PORTRAITS != 0 && it.type == TYPE_PORTRAITS)
(filterMedia and TYPE_IMAGES != 0 && it.type == TYPE_IMAGES)
|| (filterMedia and TYPE_VIDEOS != 0 && it.type == TYPE_VIDEOS)
|| (filterMedia and TYPE_GIFS != 0 && it.type == TYPE_GIFS)
|| (filterMedia and TYPE_RAWS != 0 && it.type == TYPE_RAWS)
|| (filterMedia and TYPE_SVGS != 0 && it.type == TYPE_SVGS)
|| (filterMedia and TYPE_PORTRAITS != 0 && it.type == TYPE_PORTRAITS)
}
}) as ArrayList<Medium>
@ -902,7 +1015,12 @@ fun Context.getCachedMedia(path: String, getVideosOnly: Boolean = false, getImag
fun Context.removeInvalidDBDirectories(dirs: ArrayList<Directory>? = null) {
val dirsToCheck = dirs ?: directoryDB.getAll()
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 {
directoryDB.deleteDirPath(it.path)
} catch (ignored: Exception) {
@ -923,14 +1041,14 @@ fun Context.updateDBMediaPath(oldPath: String, newPath: String) {
fun Context.updateDBDirectory(directory: Directory) {
try {
directoryDB.updateDirectory(
directory.path,
directory.tmb,
directory.mediaCnt,
directory.modified,
directory.taken,
directory.size,
directory.types,
directory.sortValue
path = directory.path,
thumbnail = directory.tmb,
mediaCnt = directory.mediaCnt,
lastModified = directory.modified,
dateTaken = directory.taken,
size = directory.size,
mediaTypes = directory.types,
sortValue = directory.sortValue
)
} catch (ignored: Exception) {
}
@ -938,7 +1056,9 @@ fun Context.updateDBDirectory(directory: Directory) {
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> {
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) {
try {
@ -988,8 +1110,10 @@ fun Context.deleteMediumWithPath(path: String) {
}
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
if (widgetIDs.isNotEmpty()) {
Intent(applicationContext, MyWidgetProvider::class.java).apply {
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
fun Context.parseFileChannel(path: String, fc: FileChannel, level: Int, start: Long, end: Long, callback: () -> Unit) {
val FILE_CHANNEL_CONTAINERS = arrayListOf("moov", "trak", "mdia", "minf", "udta", "stbl")
fun Context.parseFileChannel(
path: String,
fc: FileChannel,
level: Int,
start: Long,
end: Long,
callback: () -> Unit
) {
val fileChannelContainers = arrayListOf("moov", "trak", "mdia", "minf", "udta", "stbl")
try {
var iteration = 0
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())
if (xmlString.contains("gspherical:projectiontype>equirectangular") || xmlString.contains("gspherical:projectiontype=\"equirectangular\"")) {
if (
xmlString.contains("gspherical:projectiontype>equirectangular")
|| xmlString.contains("gspherical:projectiontype=\"equirectangular\"")
) {
callback.invoke()
}
return
}
if (FILE_CHANNEL_CONTAINERS.contains(type)) {
if (fileChannelContainers.contains(type)) {
parseFileChannel(path, fc, level + 1, begin + 8, newEnd, callback)
}
@ -1075,8 +1209,18 @@ fun Context.addPathToDB(path: String) {
val isFavorite = favoritesDB.isFavorite(path)
val videoDuration = if (type == TYPE_VIDEOS) getDuration(path) ?: 0 else 0
val medium = Medium(
null, path.getFilenameFromPath(), path, path.getParentPath(), System.currentTimeMillis(), System.currentTimeMillis(),
File(path).length(), type, videoDuration, isFavorite, 0L, 0L
id = null,
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)
@ -1118,16 +1262,44 @@ fun Context.createDirectoryFromMedia(
val firstItem = curMedia.firstOrNull() ?: defaultMedium
val lastItem = curMedia.lastOrNull() ?: defaultMedium
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 dateTaken = if (isSortingAscending) Math.min(firstItem.taken, lastItem.taken) else Math.max(firstItem.taken, lastItem.taken)
val lastModified = if (isSortingAscending) {
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 mediaTypes = curMedia.getDirMediaTypes()
val count = curMedia.size
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 sorted = when {
sorting and SORT_BY_NAME != 0 -> return name
@ -1165,26 +1337,48 @@ fun Context.updateDirectoryPath(path: String) {
val sorting = config.getFolderSorting(path)
val grouping = config.getFolderGrouping(path)
val getProperDateTaken = config.directorySorting 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_MONTHLY != 0
val getProperDateTaken = config.directorySorting 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_MONTHLY != 0
val getProperLastModified = config.directorySorting 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_MONTHLY != 0
val getProperLastModified = config.directorySorting 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_MONTHLY != 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 favoritePaths = getFavoritePaths()
val curMedia = mediaFetcher.getFilesFrom(
path, getImagesOnly, getVideosOnly, getProperDateTaken, getProperLastModified, getProperFileSize,
favoritePaths, false, lastModifieds, dateTakens, null
curPath = path,
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)
}