mirror of
https://github.com/FossifyOrg/Gallery.git
synced 2025-03-17 17:10:04 +01:00
Merge pull request #421 from FossifyOrg/cleanup_code
Cleanup and format some code
This commit is contained in:
commit
52ca5a0a4d
4 changed files with 872 additions and 259 deletions
|
@ -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)
|
||||
}
|
||||
|
@ -392,7 +401,7 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
|
|||
if (mCurrentPathPrefix.isEmpty()) {
|
||||
super.onBackPressed()
|
||||
} else {
|
||||
mOpenedSubfolders.removeLast()
|
||||
mOpenedSubfolders.removeAt(mOpenedSubfolders.lastIndex)
|
||||
mCurrentPathPrefix = mOpenedSubfolders.last()
|
||||
setupAdapter(mDirs)
|
||||
}
|
||||
|
@ -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 = ""
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
package org.fossify.gallery.activities
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.WallpaperManager
|
||||
import android.content.Intent
|
||||
import android.graphics.Bitmap
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.view.ViewGroup
|
||||
import android.widget.RelativeLayout
|
||||
import androidx.core.net.toUri
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.bumptech.glide.Glide
|
||||
|
@ -17,8 +16,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 +60,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 +171,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()
|
||||
|
@ -240,7 +317,7 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
|
|||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) {
|
||||
if (requestCode == REQUEST_EDIT_IMAGE) {
|
||||
if (resultCode == Activity.RESULT_OK && resultData != null) {
|
||||
if (resultCode == RESULT_OK && resultData != null) {
|
||||
mMedia.clear()
|
||||
refreshItems()
|
||||
}
|
||||
|
@ -249,7 +326,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 +339,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 +432,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 +501,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 +674,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 +689,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 +709,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 +784,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 +813,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 +829,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 +878,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,10 +937,13 @@ 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)
|
||||
setResult(RESULT_OK)
|
||||
} catch (ignored: IOException) {
|
||||
}
|
||||
|
||||
|
@ -827,8 +952,8 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
|
|||
})
|
||||
} else if (mIsGetImageIntent || mIsGetVideoIntent || mIsGetAnyIntent) {
|
||||
Intent().apply {
|
||||
data = Uri.parse(path)
|
||||
setResult(Activity.RESULT_OK, this)
|
||||
data = path.toUri()
|
||||
setResult(RESULT_OK, this)
|
||||
}
|
||||
finish()
|
||||
} else {
|
||||
|
@ -880,7 +1005,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 +1017,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 +1043,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) {
|
||||
|
@ -949,7 +1090,7 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
|
|||
override fun selectedPaths(paths: ArrayList<String>) {
|
||||
Intent().apply {
|
||||
putExtra(PICKED_PATHS, paths)
|
||||
setResult(Activity.RESULT_OK, this)
|
||||
setResult(RESULT_OK, this)
|
||||
}
|
||||
finish()
|
||||
}
|
||||
|
@ -965,7 +1106,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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -33,23 +33,91 @@ import com.bumptech.glide.request.RequestOptions
|
|||
import com.bumptech.glide.request.target.Target
|
||||
import com.bumptech.glide.signature.ObjectKey
|
||||
import com.squareup.picasso.Picasso
|
||||
import org.fossify.commons.extensions.*
|
||||
import org.fossify.commons.helpers.*
|
||||
import org.fossify.commons.extensions.doesThisOrParentHaveNoMedia
|
||||
import org.fossify.commons.extensions.getDocumentFile
|
||||
import org.fossify.commons.extensions.getDoesFilePathExist
|
||||
import org.fossify.commons.extensions.getDuration
|
||||
import org.fossify.commons.extensions.getFilenameFromPath
|
||||
import org.fossify.commons.extensions.getLongValue
|
||||
import org.fossify.commons.extensions.getOTGPublicPath
|
||||
import org.fossify.commons.extensions.getParentPath
|
||||
import org.fossify.commons.extensions.getStringValue
|
||||
import org.fossify.commons.extensions.humanizePath
|
||||
import org.fossify.commons.extensions.internalStoragePath
|
||||
import org.fossify.commons.extensions.isGif
|
||||
import org.fossify.commons.extensions.isPathOnOTG
|
||||
import org.fossify.commons.extensions.isPathOnSD
|
||||
import org.fossify.commons.extensions.isPng
|
||||
import org.fossify.commons.extensions.isPortrait
|
||||
import org.fossify.commons.extensions.isRawFast
|
||||
import org.fossify.commons.extensions.isSvg
|
||||
import org.fossify.commons.extensions.isVideoFast
|
||||
import org.fossify.commons.extensions.isWebP
|
||||
import org.fossify.commons.extensions.normalizeString
|
||||
import org.fossify.commons.extensions.otgPath
|
||||
import org.fossify.commons.extensions.recycleBinPath
|
||||
import org.fossify.commons.extensions.sdCardPath
|
||||
import org.fossify.commons.extensions.toast
|
||||
import org.fossify.commons.helpers.AlphanumericComparator
|
||||
import org.fossify.commons.helpers.FAVORITES
|
||||
import org.fossify.commons.helpers.NOMEDIA
|
||||
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.commons.helpers.ensureBackgroundThread
|
||||
import org.fossify.commons.helpers.sumByLong
|
||||
import org.fossify.commons.views.MySquareImageView
|
||||
import org.fossify.gallery.R
|
||||
import org.fossify.gallery.asynctasks.GetMediaAsynctask
|
||||
import org.fossify.gallery.databases.GalleryDatabase
|
||||
import org.fossify.gallery.helpers.*
|
||||
import org.fossify.gallery.interfaces.*
|
||||
import org.fossify.gallery.models.*
|
||||
import org.fossify.gallery.helpers.Config
|
||||
import org.fossify.gallery.helpers.GROUP_BY_DATE_TAKEN_DAILY
|
||||
import org.fossify.gallery.helpers.GROUP_BY_DATE_TAKEN_MONTHLY
|
||||
import org.fossify.gallery.helpers.GROUP_BY_LAST_MODIFIED_DAILY
|
||||
import org.fossify.gallery.helpers.GROUP_BY_LAST_MODIFIED_MONTHLY
|
||||
import org.fossify.gallery.helpers.IsoTypeReader
|
||||
import org.fossify.gallery.helpers.LOCATION_INTERNAL
|
||||
import org.fossify.gallery.helpers.LOCATION_OTG
|
||||
import org.fossify.gallery.helpers.LOCATION_SD
|
||||
import org.fossify.gallery.helpers.MediaFetcher
|
||||
import org.fossify.gallery.helpers.MyWidgetProvider
|
||||
import org.fossify.gallery.helpers.PicassoRoundedCornersTransformation
|
||||
import org.fossify.gallery.helpers.RECYCLE_BIN
|
||||
import org.fossify.gallery.helpers.ROUNDED_CORNERS_NONE
|
||||
import org.fossify.gallery.helpers.ROUNDED_CORNERS_SMALL
|
||||
import org.fossify.gallery.helpers.SHOW_ALL
|
||||
import org.fossify.gallery.helpers.THUMBNAIL_FADE_DURATION_MS
|
||||
import org.fossify.gallery.helpers.TYPE_GIFS
|
||||
import org.fossify.gallery.helpers.TYPE_IMAGES
|
||||
import org.fossify.gallery.helpers.TYPE_PORTRAITS
|
||||
import org.fossify.gallery.helpers.TYPE_RAWS
|
||||
import org.fossify.gallery.helpers.TYPE_SVGS
|
||||
import org.fossify.gallery.helpers.TYPE_VIDEOS
|
||||
import org.fossify.gallery.interfaces.DateTakensDao
|
||||
import org.fossify.gallery.interfaces.DirectoryDao
|
||||
import org.fossify.gallery.interfaces.FavoritesDao
|
||||
import org.fossify.gallery.interfaces.MediumDao
|
||||
import org.fossify.gallery.interfaces.WidgetsDao
|
||||
import org.fossify.gallery.models.AlbumCover
|
||||
import org.fossify.gallery.models.Directory
|
||||
import org.fossify.gallery.models.Favorite
|
||||
import org.fossify.gallery.models.Medium
|
||||
import org.fossify.gallery.models.ThumbnailItem
|
||||
import org.fossify.gallery.svg.SvgSoftwareLayerSetter
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import java.nio.ByteBuffer
|
||||
import java.nio.channels.FileChannel
|
||||
import java.util.Locale
|
||||
import kotlin.collections.set
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
val Context.audioManager get() = getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
||||
|
||||
|
@ -60,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
|
||||
|
||||
|
@ -140,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()))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -158,20 +231,17 @@ 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()))
|
||||
} else {
|
||||
o1.sortValue.lowercase(Locale.getDefault()).compareTo(o2.sortValue.lowercase(Locale.getDefault()))
|
||||
}
|
||||
}
|
||||
|
||||
sorting and SORT_BY_PATH != 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()))
|
||||
}
|
||||
}
|
||||
|
||||
sorting and SORT_BY_SIZE != 0 -> (o1.sortValue.toLongOrNull() ?: 0).compareTo(o2.sortValue.toLongOrNull() ?: 0)
|
||||
sorting and SORT_BY_COUNT != 0 -> (o1.sortValue.toLongOrNull() ?: 0).compareTo(o2.sortValue.toLongOrNull() ?: 0)
|
||||
sorting and SORT_BY_DATE_MODIFIED != 0 -> (o1.sortValue.toLongOrNull() ?: 0).compareTo(o2.sortValue.toLongOrNull() ?: 0)
|
||||
// SORT_BY_SIZE, SORT_BY_COUNT, SORT_BY_DATE_MODIFIED are numerical
|
||||
else -> (o1.sortValue.toLongOrNull() ?: 0).compareTo(o2.sortValue.toLongOrNull() ?: 0)
|
||||
}
|
||||
|
||||
|
@ -184,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
|
||||
|
@ -197,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)
|
||||
|
@ -235,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
|
||||
|
@ -275,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>()
|
||||
|
@ -295,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)
|
||||
|
@ -318,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
|
||||
}
|
||||
}
|
||||
|
@ -347,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) {
|
||||
|
@ -356,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++
|
||||
}
|
||||
|
@ -399,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())
|
||||
|
@ -420,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 {
|
||||
|
@ -447,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
|
||||
|
@ -512,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
|
||||
|
@ -551,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()))
|
||||
|
@ -576,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)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -588,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 {
|
||||
|
@ -618,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)
|
||||
|
@ -642,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")
|
||||
|
||||
|
@ -708,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>
|
||||
|
||||
|
@ -754,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())
|
||||
|
@ -796,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>
|
||||
|
||||
|
@ -842,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) {
|
||||
|
@ -863,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) {
|
||||
}
|
||||
|
@ -878,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 {
|
||||
|
@ -888,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 {
|
||||
|
@ -928,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
|
||||
|
@ -940,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
|
||||
|
@ -980,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)
|
||||
}
|
||||
|
||||
|
@ -1015,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)
|
||||
|
@ -1058,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
|
||||
|
@ -1105,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)
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue