adding some OTG file related improvements
This commit is contained in:
parent
b744701a70
commit
556a775848
|
@ -62,7 +62,7 @@ android {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'com.simplemobiletools:commons:5.18.14'
|
implementation 'com.simplemobiletools:commons:5.18.26'
|
||||||
implementation 'com.theartofdev.edmodo:android-image-cropper:2.8.0'
|
implementation 'com.theartofdev.edmodo:android-image-cropper:2.8.0'
|
||||||
implementation 'androidx.multidex:multidex:2.0.1'
|
implementation 'androidx.multidex:multidex:2.0.1'
|
||||||
implementation 'it.sephiroth.android.exif:library:1.0.1'
|
implementation 'it.sephiroth.android.exif:library:1.0.1'
|
||||||
|
|
|
@ -389,10 +389,10 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
|
||||||
private fun removeTempFolder() {
|
private fun removeTempFolder() {
|
||||||
if (config.tempFolderPath.isNotEmpty()) {
|
if (config.tempFolderPath.isNotEmpty()) {
|
||||||
val newFolder = File(config.tempFolderPath)
|
val newFolder = File(config.tempFolderPath)
|
||||||
if (newFolder.exists() && newFolder.isDirectory) {
|
if (getDoesFilePathExist(newFolder.absolutePath) && newFolder.isDirectory) {
|
||||||
if (newFolder.list()?.isEmpty() == true && newFolder.getProperSize(true) == 0L && newFolder.getFileCount(true) == 0) {
|
if (newFolder.list()?.isEmpty() == true && newFolder.getProperSize(true) == 0L && newFolder.getFileCount(true) == 0) {
|
||||||
toast(String.format(getString(R.string.deleting_folder), config.tempFolderPath), Toast.LENGTH_LONG)
|
toast(String.format(getString(R.string.deleting_folder), config.tempFolderPath), Toast.LENGTH_LONG)
|
||||||
tryDeleteFileDirItem(newFolder.toFileDirItem(), true, true)
|
tryDeleteFileDirItem(newFolder.toFileDirItem(applicationContext), true, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
config.tempFolderPath = ""
|
config.tempFolderPath = ""
|
||||||
|
@ -408,16 +408,6 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
|
||||||
config.OTGPath = otgPath
|
config.OTGPath = otgPath
|
||||||
config.addIncludedFolder(otgPath)
|
config.addIncludedFolder(otgPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
// OTG handling has been changed again in SDK version 28, the old method no longer works
|
|
||||||
/*if (config.OTGPath.isEmpty()) {
|
|
||||||
runOnUiThread {
|
|
||||||
ConfirmationDialog(this, getString(R.string.usb_detected), positive = R.string.ok, negative = 0) {
|
|
||||||
config.wasOTGHandled = true
|
|
||||||
showOTGPermissionDialog()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -428,8 +418,9 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
|
||||||
"/storage/emulated/0/Android/data/com.facebook.orca/files/stickers"
|
"/storage/emulated/0/Android/data/com.facebook.orca/files/stickers"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val OTGPath = config.OTGPath
|
||||||
spamFolders.forEach {
|
spamFolders.forEach {
|
||||||
if (File(it).exists()) {
|
if (getDoesFilePathExist(it, OTGPath)) {
|
||||||
config.addExcludedFolder(it)
|
config.addExcludedFolder(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -570,7 +561,7 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
|
||||||
(it.isGif() && filter and TYPE_GIFS != 0) ||
|
(it.isGif() && filter and TYPE_GIFS != 0) ||
|
||||||
(it.isRawFast() && filter and TYPE_RAWS != 0) ||
|
(it.isRawFast() && filter and TYPE_RAWS != 0) ||
|
||||||
(it.isSvg() && filter and TYPE_SVGS != 0))
|
(it.isSvg() && filter and TYPE_SVGS != 0))
|
||||||
}?.mapTo(itemsToDelete) { it.toFileDirItem() }
|
}?.mapTo(itemsToDelete) { it.toFileDirItem(applicationContext) }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.useRecycleBin) {
|
if (config.useRecycleBin) {
|
||||||
|
@ -590,13 +581,14 @@ 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) {
|
deleteFiles(fileDirItems) {
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
refreshItems()
|
refreshItems()
|
||||||
}
|
}
|
||||||
|
|
||||||
ensureBackgroundThread {
|
ensureBackgroundThread {
|
||||||
folders.filter { !it.exists() }.forEach {
|
folders.filter { !getDoesFilePathExist(it.absolutePath, OTGPath) }.forEach {
|
||||||
mDirectoryDao.deleteDirPath(it.absolutePath)
|
mDirectoryDao.deleteDirPath(it.absolutePath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1115,13 +1107,14 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
|
||||||
|
|
||||||
private fun checkInvalidDirectories(dirs: ArrayList<Directory>) {
|
private fun checkInvalidDirectories(dirs: ArrayList<Directory>) {
|
||||||
val invalidDirs = ArrayList<Directory>()
|
val invalidDirs = ArrayList<Directory>()
|
||||||
|
val OTGPath = config.OTGPath
|
||||||
dirs.filter { !it.areFavorites() && !it.isRecycleBin() }.forEach {
|
dirs.filter { !it.areFavorites() && !it.isRecycleBin() }.forEach {
|
||||||
if (!File(it.path).exists()) {
|
if (!getDoesFilePathExist(it.path, OTGPath)) {
|
||||||
invalidDirs.add(it)
|
invalidDirs.add(it)
|
||||||
} else if (it.path != config.tempFolderPath) {
|
} else if (it.path != config.tempFolderPath) {
|
||||||
val children = File(it.path).listFiles()?.asList()
|
val children = if (isPathOnOTG(it.path)) getOTGFolderChildrenNames(it.path) else File(it.path).list()?.asList()
|
||||||
val hasMediaFile = children?.any {
|
val hasMediaFile = children?.any {
|
||||||
it?.isMediaFile() == true || (it.isDirectory && it.name.startsWith("img_", true))
|
it?.isMediaFile() == true || (File(it).isDirectory && it?.startsWith("img_", true) == true)
|
||||||
} ?: false
|
} ?: false
|
||||||
|
|
||||||
if (!hasMediaFile) {
|
if (!hasMediaFile) {
|
||||||
|
@ -1151,6 +1144,7 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
|
||||||
dirs.removeAll(invalidDirs)
|
dirs.removeAll(invalidDirs)
|
||||||
setupAdapter(dirs)
|
setupAdapter(dirs)
|
||||||
invalidDirs.forEach {
|
invalidDirs.forEach {
|
||||||
|
toast("invalid ${it.path}", Toast.LENGTH_LONG)
|
||||||
try {
|
try {
|
||||||
mDirectoryDao.deleteDirPath(it.path)
|
mDirectoryDao.deleteDirPath(it.path)
|
||||||
} catch (ignored: Exception) {
|
} catch (ignored: Exception) {
|
||||||
|
@ -1243,9 +1237,10 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
oftenRepeatedPaths.removeAll(substringToRemove)
|
oftenRepeatedPaths.removeAll(substringToRemove)
|
||||||
|
val OTGPath = config.OTGPath
|
||||||
oftenRepeatedPaths.forEach {
|
oftenRepeatedPaths.forEach {
|
||||||
val file = File("$internalPath/$it")
|
val file = File("$internalPath/$it")
|
||||||
if (file.exists()) {
|
if (getDoesFilePathExist(file.absolutePath, OTGPath)) {
|
||||||
config.addExcludedFolder(file.absolutePath)
|
config.addExcludedFolder(file.absolutePath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -569,7 +569,7 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
|
||||||
|
|
||||||
private fun deleteDirectoryIfEmpty() {
|
private fun deleteDirectoryIfEmpty() {
|
||||||
val fileDirItem = FileDirItem(mPath, mPath.getFilenameFromPath(), true)
|
val fileDirItem = FileDirItem(mPath, mPath.getFilenameFromPath(), true)
|
||||||
if (config.deleteEmptyFolders && !fileDirItem.isDownloadsFolder() && fileDirItem.isDirectory && fileDirItem.getProperFileCount(true) == 0) {
|
if (config.deleteEmptyFolders && !fileDirItem.isDownloadsFolder() && fileDirItem.isDirectory && fileDirItem.getProperFileCount(this, true) == 0) {
|
||||||
tryDeleteFileDirItem(fileDirItem, true, true)
|
tryDeleteFileDirItem(fileDirItem, true, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -606,7 +606,7 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
|
||||||
val newMedia = it
|
val newMedia = it
|
||||||
try {
|
try {
|
||||||
gotMedia(newMedia, false)
|
gotMedia(newMedia, false)
|
||||||
oldMedia.filter { !newMedia.contains(it) }.mapNotNull { it as? Medium }.filter { !File(it.path).exists() }.forEach {
|
oldMedia.filter { !newMedia.contains(it) }.mapNotNull { it as? Medium }.filter { !getDoesFilePathExist(it.path) }.forEach {
|
||||||
mMediumDao.deleteMediumPath(it.path)
|
mMediumDao.deleteMediumPath(it.path)
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
|
|
@ -75,7 +75,7 @@ open class PhotoVideoActivity : SimpleActivity(), ViewPagerFragment.FragmentList
|
||||||
val uri = mUri.toString()
|
val uri = mUri.toString()
|
||||||
if (uri.startsWith("content:/") && uri.contains("/storage/")) {
|
if (uri.startsWith("content:/") && uri.contains("/storage/")) {
|
||||||
val guessedPath = uri.substring(uri.indexOf("/storage/"))
|
val guessedPath = uri.substring(uri.indexOf("/storage/"))
|
||||||
if (File(guessedPath).exists()) {
|
if (getDoesFilePathExist(guessedPath)) {
|
||||||
val extras = intent.extras ?: Bundle()
|
val extras = intent.extras ?: Bundle()
|
||||||
extras.apply {
|
extras.apply {
|
||||||
putString(REAL_FILE_PATH, guessedPath)
|
putString(REAL_FILE_PATH, guessedPath)
|
||||||
|
@ -93,7 +93,7 @@ open class PhotoVideoActivity : SimpleActivity(), ViewPagerFragment.FragmentList
|
||||||
|
|
||||||
if (intent.extras?.containsKey(REAL_FILE_PATH) == true) {
|
if (intent.extras?.containsKey(REAL_FILE_PATH) == true) {
|
||||||
val realPath = intent.extras!!.getString(REAL_FILE_PATH)
|
val realPath = intent.extras!!.getString(REAL_FILE_PATH)
|
||||||
if (realPath != null && File(realPath).exists()) {
|
if (realPath != null && getDoesFilePathExist(realPath)) {
|
||||||
if (realPath.getFilenameFromPath().contains('.') || filename.contains('.')) {
|
if (realPath.getFilenameFromPath().contains('.') || filename.contains('.')) {
|
||||||
if (isFileTypeVisible(realPath)) {
|
if (isFileTypeVisible(realPath)) {
|
||||||
bottom_actions.beGone()
|
bottom_actions.beGone()
|
||||||
|
@ -125,7 +125,7 @@ open class PhotoVideoActivity : SimpleActivity(), ViewPagerFragment.FragmentList
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
val path = applicationContext.getRealPathFromURI(mUri!!) ?: ""
|
val path = applicationContext.getRealPathFromURI(mUri!!) ?: ""
|
||||||
if (path != mUri.toString() && path.isNotEmpty() && mUri!!.authority != "mms" && filename.contains('.') && File(path).exists()) {
|
if (path != mUri.toString() && path.isNotEmpty() && mUri!!.authority != "mms" && filename.contains('.') && getDoesFilePathExist(path)) {
|
||||||
if (isFileTypeVisible(path)) {
|
if (isFileTypeVisible(path)) {
|
||||||
bottom_actions.beGone()
|
bottom_actions.beGone()
|
||||||
handleLockedFolderOpening(path.getParentPath()) { success ->
|
handleLockedFolderOpening(path.getParentPath()) { success ->
|
||||||
|
|
|
@ -278,7 +278,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!File(mPath).exists() && getPortraitPath() == "") {
|
if (!getDoesFilePathExist(mPath) && getPortraitPath() == "") {
|
||||||
finish()
|
finish()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -1066,7 +1066,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
||||||
|
|
||||||
private fun deleteDirectoryIfEmpty() {
|
private fun deleteDirectoryIfEmpty() {
|
||||||
val fileDirItem = FileDirItem(mDirectory, mDirectory.getFilenameFromPath(), File(mDirectory).isDirectory)
|
val fileDirItem = FileDirItem(mDirectory, mDirectory.getFilenameFromPath(), File(mDirectory).isDirectory)
|
||||||
if (config.deleteEmptyFolders && !fileDirItem.isDownloadsFolder() && fileDirItem.isDirectory && fileDirItem.getProperFileCount(true) == 0) {
|
if (config.deleteEmptyFolders && !fileDirItem.isDownloadsFolder() && fileDirItem.isDirectory && fileDirItem.getProperFileCount(this, true) == 0) {
|
||||||
tryDeleteFileDirItem(fileDirItem, true, true)
|
tryDeleteFileDirItem(fileDirItem, true, true)
|
||||||
scanPathRecursively(mDirectory)
|
scanPathRecursively(mDirectory)
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,7 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Thumbnai
|
||||||
private var loadImageInstantly = false
|
private var loadImageInstantly = false
|
||||||
private var delayHandler = Handler(Looper.getMainLooper())
|
private var delayHandler = Handler(Looper.getMainLooper())
|
||||||
private var currentMediaHash = media.hashCode()
|
private var currentMediaHash = media.hashCode()
|
||||||
|
private val hasOTGConnected = activity.hasOTGConnected()
|
||||||
|
|
||||||
private var scrollHorizontally = config.scrollHorizontally
|
private var scrollHorizontally = config.scrollHorizontally
|
||||||
private var animateGifs = config.animateGifs
|
private var animateGifs = config.animateGifs
|
||||||
|
@ -492,7 +493,11 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Thumbnai
|
||||||
medium_check?.background?.applyColorFilter(primaryColor)
|
medium_check?.background?.applyColorFilter(primaryColor)
|
||||||
}
|
}
|
||||||
|
|
||||||
val path = medium.path
|
var path = medium.path
|
||||||
|
if (hasOTGConnected && context.isPathOnOTG(path)) {
|
||||||
|
path = path.getOTGPublicPath(context)
|
||||||
|
}
|
||||||
|
|
||||||
if (loadImageInstantly) {
|
if (loadImageInstantly) {
|
||||||
activity.loadImage(medium.type, path, medium_thumbnail, scrollHorizontally, animateGifs, cropThumbnails, rotatedImagePaths)
|
activity.loadImage(medium.type, path, medium_thumbnail, scrollHorizontally, animateGifs, cropThumbnails, rotatedImagePaths)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -7,7 +7,6 @@ import com.simplemobiletools.commons.dialogs.FilePickerDialog
|
||||||
import com.simplemobiletools.commons.extensions.*
|
import com.simplemobiletools.commons.extensions.*
|
||||||
import com.simplemobiletools.gallery.pro.R
|
import com.simplemobiletools.gallery.pro.R
|
||||||
import kotlinx.android.synthetic.main.dialog_save_as.view.*
|
import kotlinx.android.synthetic.main.dialog_save_as.view.*
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
class SaveAsDialog(val activity: BaseSimpleActivity, val path: String, val appendFilename: Boolean, val callback: (savePath: String) -> Unit) {
|
class SaveAsDialog(val activity: BaseSimpleActivity, val path: String, val appendFilename: Boolean, val callback: (savePath: String) -> Unit) {
|
||||||
|
|
||||||
|
@ -67,7 +66,7 @@ class SaveAsDialog(val activity: BaseSimpleActivity, val path: String, val appen
|
||||||
return@setOnClickListener
|
return@setOnClickListener
|
||||||
}
|
}
|
||||||
|
|
||||||
if (File(newPath).exists()) {
|
if (activity.getDoesFilePathExist(newPath)) {
|
||||||
val title = String.format(activity.getString(R.string.file_already_exists_overwrite), newFilename)
|
val title = String.format(activity.getString(R.string.file_already_exists_overwrite), newFilename)
|
||||||
ConfirmationDialog(activity, title) {
|
ConfirmationDialog(activity, title) {
|
||||||
callback(newPath)
|
callback(newPath)
|
||||||
|
|
|
@ -131,7 +131,7 @@ fun AppCompatActivity.hideSystemUI(toggleActionBarVisibility: Boolean) {
|
||||||
|
|
||||||
fun BaseSimpleActivity.addNoMedia(path: String, callback: () -> Unit) {
|
fun BaseSimpleActivity.addNoMedia(path: String, callback: () -> Unit) {
|
||||||
val file = File(path, NOMEDIA)
|
val file = File(path, NOMEDIA)
|
||||||
if (file.exists()) {
|
if (getDoesFilePathExist(file.absolutePath)) {
|
||||||
callback()
|
callback()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -164,12 +164,12 @@ fun BaseSimpleActivity.addNoMedia(path: String, callback: () -> Unit) {
|
||||||
|
|
||||||
fun BaseSimpleActivity.removeNoMedia(path: String, callback: (() -> Unit)? = null) {
|
fun BaseSimpleActivity.removeNoMedia(path: String, callback: (() -> Unit)? = null) {
|
||||||
val file = File(path, NOMEDIA)
|
val file = File(path, NOMEDIA)
|
||||||
if (!file.exists()) {
|
if (!getDoesFilePathExist(file.absolutePath)) {
|
||||||
callback?.invoke()
|
callback?.invoke()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
tryDeleteFileDirItem(file.toFileDirItem(), false, false) {
|
tryDeleteFileDirItem(file.toFileDirItem(applicationContext), false, false) {
|
||||||
callback?.invoke()
|
callback?.invoke()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -271,7 +271,7 @@ fun BaseSimpleActivity.restoreRecycleBinPaths(paths: ArrayList<String>, mediumDa
|
||||||
try {
|
try {
|
||||||
out = getFileOutputStreamSync(destination, source.getMimeType())
|
out = getFileOutputStreamSync(destination, source.getMimeType())
|
||||||
inputStream = getFileInputStreamSync(source)
|
inputStream = getFileInputStreamSync(source)
|
||||||
inputStream.copyTo(out!!)
|
inputStream!!.copyTo(out!!)
|
||||||
if (File(source).length() == File(destination).length()) {
|
if (File(source).length() == File(destination).length()) {
|
||||||
mediumDao.updateDeleted(destination.removePrefix(recycleBinPath), 0, "$RECYCLE_BIN$destination")
|
mediumDao.updateDeleted(destination.removePrefix(recycleBinPath), 0, "$RECYCLE_BIN$destination")
|
||||||
}
|
}
|
||||||
|
@ -519,7 +519,9 @@ fun BaseSimpleActivity.copyFile(source: String, destination: String) {
|
||||||
try {
|
try {
|
||||||
out = getFileOutputStreamSync(destination, source.getMimeType())
|
out = getFileOutputStreamSync(destination, source.getMimeType())
|
||||||
inputStream = getFileInputStreamSync(source)
|
inputStream = getFileInputStreamSync(source)
|
||||||
inputStream.copyTo(out!!)
|
inputStream!!.copyTo(out!!)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
showErrorToast(e)
|
||||||
} finally {
|
} finally {
|
||||||
inputStream?.close()
|
inputStream?.close()
|
||||||
out?.close()
|
out?.close()
|
||||||
|
|
|
@ -366,6 +366,7 @@ fun Context.getNoMediaFolders(callback: (folders: ArrayList<String>) -> Unit) {
|
||||||
val selection = "${MediaStore.Files.FileColumns.MEDIA_TYPE} = ? AND ${MediaStore.Files.FileColumns.TITLE} LIKE ?"
|
val selection = "${MediaStore.Files.FileColumns.MEDIA_TYPE} = ? AND ${MediaStore.Files.FileColumns.TITLE} LIKE ?"
|
||||||
val selectionArgs = arrayOf(MediaStore.Files.FileColumns.MEDIA_TYPE_NONE.toString(), "%$NOMEDIA%")
|
val selectionArgs = arrayOf(MediaStore.Files.FileColumns.MEDIA_TYPE_NONE.toString(), "%$NOMEDIA%")
|
||||||
val sortOrder = "${MediaStore.Files.FileColumns.DATE_MODIFIED} DESC"
|
val sortOrder = "${MediaStore.Files.FileColumns.DATE_MODIFIED} DESC"
|
||||||
|
val OTGPath = config.OTGPath
|
||||||
|
|
||||||
var cursor: Cursor? = null
|
var cursor: Cursor? = null
|
||||||
try {
|
try {
|
||||||
|
@ -374,7 +375,7 @@ fun Context.getNoMediaFolders(callback: (folders: ArrayList<String>) -> Unit) {
|
||||||
do {
|
do {
|
||||||
val path = cursor.getStringValue(MediaStore.Files.FileColumns.DATA) ?: continue
|
val path = cursor.getStringValue(MediaStore.Files.FileColumns.DATA) ?: continue
|
||||||
val noMediaFile = File(path)
|
val noMediaFile = File(path)
|
||||||
if (noMediaFile.exists() && noMediaFile.name == NOMEDIA) {
|
if (getDoesFilePathExist(noMediaFile.absolutePath, OTGPath) && noMediaFile.name == NOMEDIA) {
|
||||||
folders.add("${noMediaFile.parent}/")
|
folders.add("${noMediaFile.parent}/")
|
||||||
}
|
}
|
||||||
} while (cursor.moveToNext())
|
} while (cursor.moveToNext())
|
||||||
|
@ -661,9 +662,10 @@ fun Context.getCachedMedia(path: String, getVideosOnly: Boolean = false, getImag
|
||||||
mediaFetcher.sortMedia(media, config.getFileSorting(pathToUse))
|
mediaFetcher.sortMedia(media, config.getFileSorting(pathToUse))
|
||||||
val grouped = mediaFetcher.groupMedia(media, pathToUse)
|
val grouped = mediaFetcher.groupMedia(media, pathToUse)
|
||||||
callback(grouped.clone() as ArrayList<ThumbnailItem>)
|
callback(grouped.clone() as ArrayList<ThumbnailItem>)
|
||||||
|
val OTGPath = config.OTGPath
|
||||||
|
|
||||||
val mediaToDelete = ArrayList<Medium>()
|
val mediaToDelete = ArrayList<Medium>()
|
||||||
media.filter { !File(it.path).exists() }.forEach {
|
media.filter { !getDoesFilePathExist(it.path, OTGPath) }.forEach {
|
||||||
if (it.path.startsWith(recycleBinPath)) {
|
if (it.path.startsWith(recycleBinPath)) {
|
||||||
deleteDBPath(mediumDao, it.path)
|
deleteDBPath(mediumDao, it.path)
|
||||||
} else {
|
} else {
|
||||||
|
@ -682,7 +684,8 @@ fun Context.getCachedMedia(path: String, getVideosOnly: Boolean = false, getImag
|
||||||
|
|
||||||
fun Context.removeInvalidDBDirectories(dirs: ArrayList<Directory>? = null, directoryDao: DirectoryDao = galleryDB.DirectoryDao()) {
|
fun Context.removeInvalidDBDirectories(dirs: ArrayList<Directory>? = null, directoryDao: DirectoryDao = galleryDB.DirectoryDao()) {
|
||||||
val dirsToCheck = dirs ?: directoryDao.getAll()
|
val dirsToCheck = dirs ?: directoryDao.getAll()
|
||||||
dirsToCheck.filter { !it.areFavorites() && !it.isRecycleBin() && !File(it.path).exists() && it.path != config.tempFolderPath }.forEach {
|
val OTGPath = config.OTGPath
|
||||||
|
dirsToCheck.filter { !it.areFavorites() && !it.isRecycleBin() && !getDoesFilePathExist(it.path, OTGPath) && it.path != config.tempFolderPath }.forEach {
|
||||||
try {
|
try {
|
||||||
directoryDao.deleteDirPath(it.path)
|
directoryDao.deleteDirPath(it.path)
|
||||||
} catch (ignored: Exception) {
|
} catch (ignored: Exception) {
|
||||||
|
@ -706,6 +709,10 @@ fun Context.updateDBDirectory(directory: Directory, directoryDao: DirectoryDao)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Context.getOTGFolderChildren(path: String) = getDocumentFile(path)?.listFiles()
|
||||||
|
|
||||||
|
fun Context.getOTGFolderChildrenNames(path: String) = getOTGFolderChildren(path)?.map { it.name }?.toMutableList()
|
||||||
|
|
||||||
fun Context.getFavoritePaths(): ArrayList<String> {
|
fun Context.getFavoritePaths(): ArrayList<String> {
|
||||||
return try {
|
return try {
|
||||||
galleryDB.MediumDao().getFavoritePaths() as ArrayList<String>
|
galleryDB.MediumDao().getFavoritePaths() as ArrayList<String>
|
||||||
|
@ -805,7 +812,7 @@ fun Context.parseFileChannel(path: String, fc: FileChannel, level: Int, start: L
|
||||||
|
|
||||||
fun Context.addPathToDB(path: String) {
|
fun Context.addPathToDB(path: String) {
|
||||||
ensureBackgroundThread {
|
ensureBackgroundThread {
|
||||||
if (!File(path).exists()) {
|
if (!getDoesFilePathExist(path)) {
|
||||||
return@ensureBackgroundThread
|
return@ensureBackgroundThread
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -833,13 +840,18 @@ fun Context.addPathToDB(path: String) {
|
||||||
|
|
||||||
fun Context.createDirectoryFromMedia(path: String, curMedia: ArrayList<Medium>, albumCovers: ArrayList<AlbumCover>, hiddenString: String,
|
fun Context.createDirectoryFromMedia(path: String, curMedia: ArrayList<Medium>, albumCovers: ArrayList<AlbumCover>, hiddenString: String,
|
||||||
includedFolders: MutableSet<String>, isSortingAscending: Boolean, getProperFileSize: Boolean): Directory {
|
includedFolders: MutableSet<String>, isSortingAscending: Boolean, getProperFileSize: Boolean): Directory {
|
||||||
var thumbnail = curMedia.firstOrNull { File(it.path).exists() }?.path ?: ""
|
val OTGPath = config.OTGPath
|
||||||
|
var thumbnail = curMedia.firstOrNull { getDoesFilePathExist(it.path, OTGPath) }?.path ?: ""
|
||||||
albumCovers.forEach {
|
albumCovers.forEach {
|
||||||
if (it.path == path && File(it.tmb).exists()) {
|
if (it.path == path && getDoesFilePathExist(it.tmb, OTGPath)) {
|
||||||
thumbnail = it.tmb
|
thumbnail = it.tmb
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (config.OTGPath.isNotEmpty() && thumbnail.startsWith(config.OTGPath)) {
|
||||||
|
thumbnail = thumbnail.getOTGPublicPath(applicationContext)
|
||||||
|
}
|
||||||
|
|
||||||
val defaultMedium = Medium(0, "", "", "", 0L, 0L, 0L, 0, 0, false, 0L)
|
val defaultMedium = Medium(0, "", "", "", 0L, 0L, 0L, 0, 0, false, 0L)
|
||||||
val firstItem = curMedia.firstOrNull() ?: defaultMedium
|
val firstItem = curMedia.firstOrNull() ?: defaultMedium
|
||||||
val lastItem = curMedia.lastOrNull() ?: defaultMedium
|
val lastItem = curMedia.lastOrNull() ?: defaultMedium
|
||||||
|
|
|
@ -357,11 +357,11 @@ class PhotoFragment : ViewPagerFragment() {
|
||||||
|
|
||||||
private fun loadGif() {
|
private fun loadGif() {
|
||||||
try {
|
try {
|
||||||
val path = mMedium.path
|
val pathToLoad = getPathToLoad(mMedium)
|
||||||
val source = if (path.startsWith("content://") || path.startsWith("file://")) {
|
val source = if (pathToLoad.startsWith("content://") || pathToLoad.startsWith("file://")) {
|
||||||
InputSource.UriSource(context!!.contentResolver, Uri.parse(path))
|
InputSource.UriSource(context!!.contentResolver, Uri.parse(pathToLoad))
|
||||||
} else {
|
} else {
|
||||||
InputSource.FileSource(path)
|
InputSource.FileSource(pathToLoad)
|
||||||
}
|
}
|
||||||
|
|
||||||
mView.apply {
|
mView.apply {
|
||||||
|
@ -559,7 +559,7 @@ class PhotoFragment : ViewPagerFragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getFilePathToShow() = if (mMedium.isPortrait()) mCurrentPortraitPhotoPath else mMedium.path
|
private fun getFilePathToShow() = if (mMedium.isPortrait()) mCurrentPortraitPhotoPath else getPathToLoad(mMedium)
|
||||||
|
|
||||||
private fun openPanorama() {
|
private fun openPanorama() {
|
||||||
Intent(context, PanoramaPhotoActivity::class.java).apply {
|
Intent(context, PanoramaPhotoActivity::class.java).apply {
|
||||||
|
|
|
@ -35,7 +35,7 @@ abstract class ViewPagerFragment : Fragment() {
|
||||||
|
|
||||||
fun getMediumExtendedDetails(medium: Medium): String {
|
fun getMediumExtendedDetails(medium: Medium): String {
|
||||||
val file = File(medium.path)
|
val file = File(medium.path)
|
||||||
if (!file.exists()) {
|
if (context?.getDoesFilePathExist(file.absolutePath) == false) {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,6 +81,8 @@ abstract class ViewPagerFragment : Fragment() {
|
||||||
return details.toString().trim()
|
return details.toString().trim()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getPathToLoad(medium: Medium) = if (context!!.isPathOnOTG(medium.path)) medium.path.getOTGPublicPath(context!!) else medium.path
|
||||||
|
|
||||||
private fun getFileLastModified(file: File): String {
|
private fun getFileLastModified(file: File): String {
|
||||||
val projection = arrayOf(MediaStore.Images.Media.DATE_MODIFIED)
|
val projection = arrayOf(MediaStore.Images.Media.DATE_MODIFIED)
|
||||||
val uri = MediaStore.Files.getContentUri("external")
|
val uri = MediaStore.Files.getContentUri("external")
|
||||||
|
|
|
@ -2,6 +2,7 @@ package com.simplemobiletools.gallery.pro.helpers
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.database.Cursor
|
import android.database.Cursor
|
||||||
|
import android.net.Uri
|
||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
import android.provider.BaseColumns
|
import android.provider.BaseColumns
|
||||||
import android.provider.MediaStore
|
import android.provider.MediaStore
|
||||||
|
@ -27,8 +28,15 @@ class MediaFetcher(val context: Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
val curMedia = ArrayList<Medium>()
|
val curMedia = ArrayList<Medium>()
|
||||||
val newMedia = getMediaInFolder(curPath, isPickImage, isPickVideo, filterMedia, getProperDateTaken, getProperFileSize, favoritePaths, getVideoDurations)
|
if (context.isPathOnOTG(curPath)) {
|
||||||
curMedia.addAll(newMedia)
|
if (context.hasOTGConnected()) {
|
||||||
|
val newMedia = getMediaOnOTG(curPath, isPickImage, isPickVideo, filterMedia, favoritePaths, getVideoDurations)
|
||||||
|
curMedia.addAll(newMedia)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val newMedia = getMediaInFolder(curPath, isPickImage, isPickVideo, filterMedia, getProperDateTaken, getProperFileSize, favoritePaths, getVideoDurations)
|
||||||
|
curMedia.addAll(newMedia)
|
||||||
|
}
|
||||||
|
|
||||||
if (sortMedia) {
|
if (sortMedia) {
|
||||||
sortMedia(curMedia, context.config.getFileSorting(curPath))
|
sortMedia(curMedia, context.config.getFileSorting(curPath))
|
||||||
|
@ -39,12 +47,13 @@ class MediaFetcher(val context: Context) {
|
||||||
|
|
||||||
fun getFoldersToScan(): ArrayList<String> {
|
fun getFoldersToScan(): ArrayList<String> {
|
||||||
return try {
|
return try {
|
||||||
|
val OTGPath = context.config.OTGPath
|
||||||
val folders = getLatestFileFolders()
|
val folders = getLatestFileFolders()
|
||||||
folders.addAll(arrayListOf(
|
folders.addAll(arrayListOf(
|
||||||
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).toString(),
|
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).toString(),
|
||||||
"${Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)}/Camera",
|
"${Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)}/Camera",
|
||||||
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString()
|
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString()
|
||||||
).filter { File(it).exists() })
|
).filter { context.getDoesFilePathExist(it, OTGPath) })
|
||||||
|
|
||||||
val filterMedia = context.config.filterMedia
|
val filterMedia = context.config.filterMedia
|
||||||
val uri = MediaStore.Files.getContentUri("external")
|
val uri = MediaStore.Files.getContentUri("external")
|
||||||
|
@ -167,7 +176,8 @@ class MediaFetcher(val context: Context) {
|
||||||
val foldersToIgnore = arrayListOf("/storage/emulated/legacy")
|
val foldersToIgnore = arrayListOf("/storage/emulated/legacy")
|
||||||
val config = context.config
|
val config = context.config
|
||||||
val includedFolders = config.includedFolders
|
val includedFolders = config.includedFolders
|
||||||
var foldersToScan = config.everShownFolders.filter { it == FAVORITES || it == RECYCLE_BIN || File(it).exists() }.toMutableList() as ArrayList
|
val OTGPath = config.OTGPath
|
||||||
|
var foldersToScan = config.everShownFolders.filter { it == FAVORITES || it == RECYCLE_BIN || context.getDoesFilePathExist(it, OTGPath) }.toMutableList() as ArrayList
|
||||||
|
|
||||||
cursor.use {
|
cursor.use {
|
||||||
if (cursor.moveToFirst()) {
|
if (cursor.moveToFirst()) {
|
||||||
|
@ -327,6 +337,72 @@ class MediaFetcher(val context: Context) {
|
||||||
return media
|
return media
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getMediaOnOTG(folder: String, isPickImage: Boolean, isPickVideo: Boolean, filterMedia: Int, favoritePaths: ArrayList<String>,
|
||||||
|
getVideoDurations: Boolean): ArrayList<Medium> {
|
||||||
|
val media = ArrayList<Medium>()
|
||||||
|
val files = context.getDocumentFile(folder)?.listFiles() ?: return media
|
||||||
|
val checkFileExistence = context.config.fileLoadingPriority == PRIORITY_VALIDITY
|
||||||
|
val showHidden = context.config.shouldShowHidden
|
||||||
|
val OTGPath = context.config.OTGPath
|
||||||
|
|
||||||
|
for (file in files) {
|
||||||
|
if (shouldStop) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
val filename = file.name ?: continue
|
||||||
|
val isImage = filename.isImageFast()
|
||||||
|
val isVideo = if (isImage) false else filename.isVideoFast()
|
||||||
|
val isGif = if (isImage || isVideo) false else filename.isGif()
|
||||||
|
val isRaw = if (isImage || isVideo || isGif) false else filename.isRawFast()
|
||||||
|
val isSvg = if (isImage || isVideo || isGif || isRaw) false else filename.isSvg()
|
||||||
|
|
||||||
|
if (!isImage && !isVideo && !isGif && !isRaw && !isSvg)
|
||||||
|
continue
|
||||||
|
|
||||||
|
if (isVideo && (isPickImage || filterMedia and TYPE_VIDEOS == 0))
|
||||||
|
continue
|
||||||
|
|
||||||
|
if (isImage && (isPickVideo || filterMedia and TYPE_IMAGES == 0))
|
||||||
|
continue
|
||||||
|
|
||||||
|
if (isGif && filterMedia and TYPE_GIFS == 0)
|
||||||
|
continue
|
||||||
|
|
||||||
|
if (isRaw && filterMedia and TYPE_RAWS == 0)
|
||||||
|
continue
|
||||||
|
|
||||||
|
if (isSvg && filterMedia and TYPE_SVGS == 0)
|
||||||
|
continue
|
||||||
|
|
||||||
|
if (!showHidden && filename.startsWith('.'))
|
||||||
|
continue
|
||||||
|
|
||||||
|
val size = file.length()
|
||||||
|
if (size <= 0L || (checkFileExistence && !context.getDoesFilePathExist(file.uri.toString(), OTGPath)))
|
||||||
|
continue
|
||||||
|
|
||||||
|
val dateTaken = file.lastModified()
|
||||||
|
val dateModified = file.lastModified()
|
||||||
|
|
||||||
|
val type = when {
|
||||||
|
isVideo -> TYPE_VIDEOS
|
||||||
|
isGif -> TYPE_GIFS
|
||||||
|
isRaw -> TYPE_RAWS
|
||||||
|
isSvg -> TYPE_SVGS
|
||||||
|
else -> TYPE_IMAGES
|
||||||
|
}
|
||||||
|
|
||||||
|
val path = Uri.decode(file.uri.toString().replaceFirst("${context.config.OTGTreeUri}/document/${context.config.OTGPartition}%3A", "${context.config.OTGPath}/"))
|
||||||
|
val videoDuration = if (getVideoDurations) path.getVideoDuration() else 0
|
||||||
|
val isFavorite = favoritePaths.contains(path)
|
||||||
|
val medium = Medium(null, filename, path, folder, dateModified, dateTaken, size, type, videoDuration, isFavorite, 0L)
|
||||||
|
media.add(medium)
|
||||||
|
}
|
||||||
|
|
||||||
|
return media
|
||||||
|
}
|
||||||
|
|
||||||
private fun getFolderDateTakens(folder: String): HashMap<String, Long> {
|
private fun getFolderDateTakens(folder: String): HashMap<String, Long> {
|
||||||
val projection = arrayOf(
|
val projection = arrayOf(
|
||||||
MediaStore.Images.Media.DISPLAY_NAME,
|
MediaStore.Images.Media.DISPLAY_NAME,
|
||||||
|
|
Loading…
Reference in New Issue