updating some dialog and documentfile related things

This commit is contained in:
tibbi 2018-02-16 16:19:10 +01:00
parent db42b53658
commit 464482bf1a
42 changed files with 278 additions and 188 deletions

View file

@ -6,7 +6,7 @@ buildscript {
propMinSdkVersion = 16
propTargetSdkVersion = propCompileSdkVersion
propVersionCode = 1
propVersionName = '3.11.47'
propVersionName = '3.11.48'
kotlin_version = '1.2.21'
support_libs = '27.0.2'
}

View file

@ -183,8 +183,7 @@ open class BaseSimpleActivity : AppCompatActivity() {
return
}
val destinationFolder = File(destination)
if (!destinationFolder.exists() && getSomeDocumentFile(destination) == null) {
if (!doesFilePathExist(destination)) {
toast(R.string.invalid_destination)
return
}
@ -203,6 +202,7 @@ open class BaseSimpleActivity : AppCompatActivity() {
val updatedFiles = ArrayList<FileDirItem>(fileDirItems.size * 2)
updatedFiles.addAll(fileDirItems)
try {
val destinationFolder = File(destination)
for (oldFileDirItem in fileDirItems) {
val newFile = File(destinationFolder, oldFileDirItem.name)
if (!newFile.exists() && File(oldFileDirItem.path).renameTo(newFile)) {
@ -244,15 +244,15 @@ open class BaseSimpleActivity : AppCompatActivity() {
}
val file = files[index]
val newFile = File(destinationFileDirItem.path, file.name)
if (newFile.exists()) {
FileConflictDialog(this, newFile) { resolution, applyForAll ->
val newFileDirItem = FileDirItem("${destinationFileDirItem.path}/${file.name}", file.name, file.isDirectory)
if (doesFilePathExist(newFileDirItem.path)) {
FileConflictDialog(this, newFileDirItem) { resolution, applyForAll ->
if (applyForAll) {
conflictResolutions.clear()
conflictResolutions[""] = resolution
checkConflict(files, destinationFileDirItem, files.size, conflictResolutions, callback)
} else {
conflictResolutions[newFile.absolutePath] = resolution
conflictResolutions[newFileDirItem.path] = resolution
checkConflict(files, destinationFileDirItem, index + 1, conflictResolutions, callback)
}
}

View file

@ -232,9 +232,9 @@ class CopyMoveTask(val activity: BaseSimpleActivity, val copyOnly: Boolean = fal
while (bytes >= 0) {
out!!.write(buffer, 0, bytes)
copiedSize += bytes
mCurrentProgress += bytes
bytes = inputStream.read(buffer)
}
mCurrentProgress += copiedSize
if (source.size == copiedSize) {
mTransferredFiles.add(source)

View file

@ -12,7 +12,7 @@ import java.io.File
class CreateNewFolderDialog(val activity: BaseSimpleActivity, val path: String, val callback: (path: String) -> Unit) {
init {
val view = activity.layoutInflater.inflate(R.layout.dialog_create_new_folder, null)
view.folder_path.text = activity.humanizePath(path).trimEnd('/') + "/"
view.folder_path.text = "${activity.humanizePath(path)}/"
AlertDialog.Builder(activity)
.setPositiveButton(R.string.ok, null)
@ -45,9 +45,12 @@ class CreateNewFolderDialog(val activity: BaseSimpleActivity, val path: String,
when {
activity.needsStupidWritePermissions(path) -> activity.handleSAFDialog(path) {
try {
val documentFile = activity.getDocumentFile(path)
documentFile?.createDirectory(path.getFilenameFromPath())
sendSuccess(alertDialog, path)
val documentFile = activity.getDocumentFile(path.getParentPath())
if (documentFile?.createDirectory(path.getFilenameFromPath()) != null) {
sendSuccess(alertDialog, path)
} else {
activity.toast(R.string.unknown_error_occurred)
}
} catch (e: SecurityException) {
activity.showErrorToast(e)
}

View file

@ -11,18 +11,18 @@ import com.simplemobiletools.commons.extensions.setupDialogStuff
import com.simplemobiletools.commons.helpers.CONFLICT_MERGE
import com.simplemobiletools.commons.helpers.CONFLICT_OVERWRITE
import com.simplemobiletools.commons.helpers.CONFLICT_SKIP
import com.simplemobiletools.commons.models.FileDirItem
import kotlinx.android.synthetic.main.dialog_file_conflict.view.*
import java.io.File
class FileConflictDialog(val activity: Activity, val file: File, val callback: (resolution: Int, applyForAll: Boolean) -> Unit) {
class FileConflictDialog(val activity: Activity, val fileDirItem: FileDirItem, val callback: (resolution: Int, applyForAll: Boolean) -> Unit) {
val view = activity.layoutInflater.inflate(R.layout.dialog_file_conflict, null)!!
init {
view.apply {
val stringBase = if (file.isDirectory) R.string.folder_already_exists else R.string.file_already_exists
conflict_dialog_title.text = String.format(activity.getString(stringBase), file.name)
val stringBase = if (fileDirItem.isDirectory) R.string.folder_already_exists else R.string.file_already_exists
conflict_dialog_title.text = String.format(activity.getString(stringBase), fileDirItem.name)
conflict_dialog_apply_to_all.isChecked = activity.baseConfig.lastConflictApplyToAll
conflict_dialog_radio_merge.beVisibleIf(file.isDirectory)
conflict_dialog_radio_merge.beVisibleIf(fileDirItem.isDirectory)
val resolutionButton = when (activity.baseConfig.lastConflictResolution) {
CONFLICT_OVERWRITE -> conflict_dialog_radio_overwrite

View file

@ -94,7 +94,7 @@ class FilePickerDialog(val activity: BaseSimpleActivity,
private fun createNewFolder() {
CreateNewFolderDialog(activity, currPath) {
callback(it.trimEnd('/'))
callback(it)
mDialog.dismiss()
}
}

View file

@ -6,15 +6,16 @@ import android.media.ExifInterface
import android.provider.MediaStore
import android.support.v7.app.AlertDialog
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import com.simplemobiletools.commons.R
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.sumByInt
import com.simplemobiletools.commons.helpers.sumByLong
import com.simplemobiletools.commons.models.FileDirItem
import kotlinx.android.synthetic.main.dialog_properties.view.*
import kotlinx.android.synthetic.main.property_item.view.*
import java.io.File
import java.io.FileNotFoundException
import java.util.*
@ -31,28 +32,33 @@ class PropertiesDialog() {
* @param countHiddenItems toggle determining if we will count hidden files themselves and their sizes (reasonable only at directory properties)
*/
constructor(activity: Activity, path: String, countHiddenItems: Boolean = false) : this() {
if (!activity.doesFilePathExist(path)) {
activity.toast(String.format(activity.getString(R.string.source_file_doesnt_exist), path))
return
}
mInflater = LayoutInflater.from(activity)
mResources = activity.resources
val view = mInflater.inflate(R.layout.dialog_properties, null)
mPropertyView = view.properties_holder
val file = File(path)
addProperty(R.string.name, file.name)
addProperty(R.string.path, file.parent)
val fileDirItem = FileDirItem(path, path.getFilenameFromPath(), activity.getIsPathDirectory(path))
addProperty(R.string.name, fileDirItem.name)
addProperty(R.string.path, fileDirItem.getParentPath())
addProperty(R.string.size, "", R.id.properties_size)
Thread {
val fileCount = file.getFileCount(countHiddenItems)
val size = file.getProperSize(countHiddenItems).formatSize()
val fileCount = fileDirItem.getProperFileCount(activity, countHiddenItems)
val size = fileDirItem.getProperSize(activity, countHiddenItems).formatSize()
activity.runOnUiThread {
view.findViewById<TextView>(R.id.properties_size).property_value.text = size
if (file.isDirectory) {
if (fileDirItem.isDirectory) {
view.findViewById<TextView>(R.id.properties_file_count).property_value.text = fileCount.toString()
}
}
if (!file.isDirectory) {
if (!fileDirItem.isDirectory) {
val projection = arrayOf(MediaStore.Images.Media.DATE_MODIFIED)
val uri = MediaStore.Files.getContentUri("external")
val selection = "${MediaStore.MediaColumns.DATA} = ?"
@ -60,37 +66,39 @@ class PropertiesDialog() {
val cursor = activity.contentResolver.query(uri, projection, selection, selectionArgs, null)
cursor?.use {
if (cursor.moveToFirst()) {
val dateModified = cursor.getIntValue(MediaStore.Images.Media.DATE_MODIFIED)
activity.runOnUiThread {
view.findViewById<TextView>(R.id.properties_last_modified).property_value.text = (dateModified * 1000L).formatDate()
}
val dateModified = cursor.getLongValue(MediaStore.Images.Media.DATE_MODIFIED)
updateLastModified(activity, view, dateModified)
} else {
updateLastModified(activity, view, fileDirItem.getLastModified(activity))
}
}
}
}.start()
when {
file.isDirectory -> {
addProperty(R.string.direct_children_count, getDirectChildrenCount(file, countHiddenItems))
fileDirItem.isDirectory -> {
addProperty(R.string.direct_children_count, fileDirItem.getDirectChildrenCount(activity, countHiddenItems).toString())
addProperty(R.string.files_count, "", R.id.properties_file_count)
}
file.isImageSlow() -> addProperty(R.string.resolution, file.getResolution().formatAsResolution())
file.isAudioSlow() -> {
file.getDuration().let { addProperty(R.string.duration, it) }
file.getSongTitle()?.let { addProperty(R.string.song_title, it) }
file.getArtist()?.let { addProperty(R.string.artist, it) }
file.getAlbum()?.let { addProperty(R.string.album, it) }
fileDirItem.path.isImageSlow() -> {
fileDirItem.getResolution()?.let { addProperty(R.string.resolution, it.formatAsResolution()) }
}
file.isVideoSlow() -> {
file.getDuration().let { addProperty(R.string.duration, it) }
addProperty(R.string.resolution, file.getResolution().formatAsResolution())
file.getArtist()?.let { addProperty(R.string.artist, it) }
file.getAlbum()?.let { addProperty(R.string.album, it) }
fileDirItem.path.isAudioSlow() -> {
fileDirItem.getDuration()?.let { addProperty(R.string.duration, it) }
fileDirItem.getSongTitle()?.let { addProperty(R.string.song_title, it) }
fileDirItem.getArtist()?.let { addProperty(R.string.artist, it) }
fileDirItem.getAlbum()?.let { addProperty(R.string.album, it) }
}
fileDirItem.path.isVideoSlow() -> {
fileDirItem.getDuration()?.let { addProperty(R.string.duration, it) }
fileDirItem.getResolution()?.let { addProperty(R.string.resolution, it.formatAsResolution()) }
fileDirItem.getArtist()?.let { addProperty(R.string.artist, it) }
fileDirItem.getAlbum()?.let { addProperty(R.string.album, it) }
}
}
if (file.isDirectory) {
addProperty(R.string.last_modified, file.lastModified().formatDate())
if (fileDirItem.isDirectory) {
addProperty(R.string.last_modified, fileDirItem.getLastModified(activity).formatDate())
} else {
addProperty(R.string.last_modified, "", R.id.properties_last_modified)
try {
@ -108,6 +116,12 @@ class PropertiesDialog() {
}
}
private fun updateLastModified(activity: Activity, view: View, timestamp: Long) {
activity.runOnUiThread {
view.findViewById<TextView>(R.id.properties_last_modified).property_value.text = timestamp.formatDate()
}
}
/**
* A File Properties dialog constructor with an optional parameter, usable at multiple items selected
*
@ -121,22 +135,25 @@ class PropertiesDialog() {
val view = mInflater.inflate(R.layout.dialog_properties, null)
mPropertyView = view.properties_holder
val files = ArrayList<File>(paths.size)
paths.forEach { files.add(File(it)) }
val fileDirItems = ArrayList<FileDirItem>(paths.size)
paths.forEach {
val fileDirItem = FileDirItem(it, it.getFilenameFromPath(), activity.getIsPathDirectory(it))
fileDirItems.add(fileDirItem)
}
val isSameParent = isSameParent(files)
val isSameParent = isSameParent(fileDirItems)
addProperty(R.string.items_selected, paths.size.toString())
if (isSameParent) {
addProperty(R.string.path, files[0].parent)
addProperty(R.string.path, fileDirItems[0].getParentPath())
}
addProperty(R.string.size, "", R.id.properties_size)
addProperty(R.string.files_count, "", R.id.properties_file_count)
Thread {
val fileCount = files.sumByInt { it.getFileCount(countHiddenItems) }
val size = files.sumByLong { it.getProperSize(countHiddenItems) }.formatSize()
val fileCount = fileDirItems.sumByInt { it.getProperFileCount(activity, countHiddenItems) }
val size = fileDirItems.sumByLong { it.getProperSize(activity, countHiddenItems) }.formatSize()
activity.runOnUiThread {
view.findViewById<TextView>(R.id.properties_size).property_value.text = size
view.findViewById<TextView>(R.id.properties_file_count).property_value.text = fileCount.toString()
@ -168,10 +185,10 @@ class PropertiesDialog() {
}
}
private fun isSameParent(files: List<File>): Boolean {
var parent = files[0].parent
for (file in files) {
val curParent = file.parent
private fun isSameParent(fileDirItems: List<FileDirItem>): Boolean {
var parent = fileDirItems[0].getParentPath()
for (file in fileDirItems) {
val curParent = file.getParentPath()
if (curParent != parent) {
return false
}
@ -181,14 +198,6 @@ class PropertiesDialog() {
return true
}
private fun getDirectChildrenCount(file: File, countHiddenItems: Boolean): String {
return if (file.listFiles() == null) {
"0"
} else {
file.listFiles().filter { it != null && (!it.isHidden || (it.isHidden && countHiddenItems)) }.size.toString()
}
}
private fun addProperty(labelId: Int, value: String?, viewId: Int = 0) {
if (value == null)
return

View file

@ -6,18 +6,16 @@ import com.simplemobiletools.commons.R
import com.simplemobiletools.commons.activities.BaseSimpleActivity
import com.simplemobiletools.commons.extensions.*
import kotlinx.android.synthetic.main.dialog_rename_item.view.*
import java.io.File
import java.util.*
class RenameItemDialog(val activity: BaseSimpleActivity, val path: String, val callback: (newPath: String) -> Unit) {
init {
val file = File(path)
val fullName = file.name
val fullName = path.getFilenameFromPath()
val dotAt = fullName.lastIndexOf(".")
var name = fullName
val view = activity.layoutInflater.inflate(R.layout.dialog_rename_item, null).apply {
if (dotAt > 0 && !file.isDirectory) {
if (dotAt > 0 && !activity.getIsPathDirectory(path)) {
name = fullName.substring(0, dotAt)
val extension = fullName.substring(dotAt + 1)
rename_item_extension.setText(extension)
@ -27,7 +25,7 @@ class RenameItemDialog(val activity: BaseSimpleActivity, val path: String, val c
}
rename_item_name.setText(name)
rename_item_path.text = activity.humanizePath(file.parent ?: "") + "/"
rename_item_path.text = activity.humanizePath(path.getParentPath())
}
AlertDialog.Builder(activity)
@ -50,22 +48,29 @@ class RenameItemDialog(val activity: BaseSimpleActivity, val path: String, val c
return@setOnClickListener
}
val updatedFiles = ArrayList<File>()
updatedFiles.add(file)
val updatedPaths = ArrayList<String>()
updatedPaths.add(path)
if (!newExtension.isEmpty()) {
newName += ".$newExtension"
}
val newFile = File(file.parent, newName)
if (newFile.exists()) {
if (!activity.doesFilePathExist(path)) {
activity.toast(String.format(activity.getString(R.string.source_file_doesnt_exist), path))
return@setOnClickListener
}
val newPath = "${path.getParentPath()}/$newName"
if (activity.doesFilePathExist(newPath)) {
activity.toast(R.string.name_taken)
return@setOnClickListener
}
updatedFiles.add(newFile)
activity.renameFile(path, "${file.parent}/$newName") {
updatedPaths.add(newPath)
activity.renameFile(path, newPath) {
if (it) {
sendSuccess(updatedFiles)
activity.scanPaths(updatedPaths) {
callback(newPath)
}
dismiss()
} else {
activity.toast(R.string.unknown_error_occurred)
@ -75,30 +80,4 @@ class RenameItemDialog(val activity: BaseSimpleActivity, val path: String, val c
}
}
}
private fun sendSuccess(updatedFiles: ArrayList<File>) {
activity.apply {
if (updatedFiles[1].isDirectory) {
val files = updatedFiles[1].listFiles()
if (files != null) {
if (files.isEmpty()) {
scanPath(updatedFiles[1].absolutePath) {
callback(updatedFiles[1].absolutePath.trimEnd('/'))
}
} else {
for (file in files) {
scanPath(file.absolutePath) {
callback(updatedFiles[1].absolutePath.trimEnd('/'))
}
break
}
}
}
} else {
scanFiles(updatedFiles) {
callback(updatedFiles[1].absolutePath.trimEnd('/'))
}
}
}
}
}

View file

@ -452,7 +452,7 @@ fun BaseSimpleActivity.renameFile(oldPath: String, newPath: String, callback: ((
}
try {
val uri = DocumentsContract.renameDocument(applicationContext.contentResolver, document.uri, newPath)
val uri = DocumentsContract.renameDocument(applicationContext.contentResolver, document.uri, newPath.getFilenameFromPath())
if (document.uri != uri) {
updateInMediaStore(oldPath, newPath)
scanPaths(arrayListOf(oldPath, newPath)) {

View file

@ -98,7 +98,7 @@ fun Context.humanizePath(path: String): String {
val basePath = path.getBasePath(this)
return when (basePath) {
"/" -> "${getHumanReadablePath(basePath)}$path"
OTG_PATH -> path.replaceFirst(basePath, "${getHumanReadablePath(basePath)}/")
OTG_PATH -> path.replaceFirst(basePath, getHumanReadablePath(basePath)).replaceFirst("otg://", OTG_PATH).trimEnd('/')
else -> path.replaceFirst(basePath, getHumanReadablePath(basePath))
}
}
@ -357,6 +357,14 @@ fun Context.trySAFFileDelete(fileDirItem: FileDirItem, allowDeleteFolder: Boolea
fun Context.doesFilePathExist(path: String) = if (isPathOnOTG(path)) getFastDocumentFile(path)?.exists() ?: false else File(path).exists()
fun Context.getIsPathDirectory(path: String): Boolean {
return if (isPathOnOTG(path)) {
getFastDocumentFile(path)?.isDirectory ?: false
} else {
File(path).isDirectory
}
}
// avoid these being set as SD card paths
private val physicalPaths = arrayListOf(
"/storage/sdcard1", // Motorola Xoom

View file

@ -27,3 +27,29 @@ private fun getDirectorySize(dir: DocumentFile, countHiddenItems: Boolean): Long
}
return size
}
fun DocumentFile.getFileCount(countHiddenItems: Boolean): Int {
return if (isDirectory) {
getDirectoryFileCount(this, countHiddenItems)
} else {
1
}
}
private fun getDirectoryFileCount(dir: DocumentFile, countHiddenItems: Boolean): Int {
var count = 0
if (dir.exists()) {
val files = dir.listFiles()
if (files != null) {
for (i in files.indices) {
val file = files[i]
if (file.isDirectory) {
count += getDirectoryFileCount(file, countHiddenItems)
} else if (!file.name.startsWith(".") || countHiddenItems) {
count++
}
}
}
}
return count
}

View file

@ -2,9 +2,6 @@ package com.simplemobiletools.commons.extensions
import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Point
import android.media.MediaMetadataRetriever
import com.simplemobiletools.commons.models.FileDirItem
import java.io.File
@ -20,80 +17,6 @@ fun File.isAudioSlow() = absolutePath.isAudioFast() || getMimeType().startsWith(
fun File.getMimeType() = absolutePath.getMimeTypeFromPath()
fun File.getDuration() = getDurationSeconds().getFormattedDuration()
fun File.getDurationSeconds(): Int {
return try {
val retriever = MediaMetadataRetriever()
retriever.setDataSource(absolutePath)
val time = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)
val timeInMs = java.lang.Long.parseLong(time)
(timeInMs / 1000).toInt()
} catch (e: Exception) {
0
}
}
fun File.getArtist(): String? {
return try {
val retriever = MediaMetadataRetriever()
retriever.setDataSource(absolutePath)
retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST)
} catch (ignored: Exception) {
null
}
}
fun File.getAlbum(): String? {
return try {
val retriever = MediaMetadataRetriever()
retriever.setDataSource(absolutePath)
retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM)
} catch (ignored: Exception) {
null
}
}
fun File.getSongTitle(): String? {
return try {
val retriever = MediaMetadataRetriever()
retriever.setDataSource(absolutePath)
retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE)
} catch (ignored: Exception) {
null
}
}
fun File.getResolution(): Point {
return if (isImageFast() || isImageSlow()) {
getImageResolution()
} else if (isVideoFast() || isVideoSlow()) {
getVideoResolution()
} else {
return Point(0, 0)
}
}
fun File.getVideoResolution(): Point {
try {
val retriever = MediaMetadataRetriever()
retriever.setDataSource(absolutePath)
val width = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH).toInt()
val height = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT).toInt()
return Point(width, height)
} catch (ignored: Exception) {
}
return Point(0, 0)
}
fun File.getImageResolution(): Point {
val options = BitmapFactory.Options()
options.inJustDecodeBounds = true
BitmapFactory.decodeFile(absolutePath, options)
return Point(options.outWidth, options.outHeight)
}
fun File.getCompressionFormat() = when (extension.toLowerCase()) {
"png" -> Bitmap.CompressFormat.PNG
"webp" -> Bitmap.CompressFormat.WEBP
@ -102,7 +25,7 @@ fun File.getCompressionFormat() = when (extension.toLowerCase()) {
fun File.getProperSize(countHiddenItems: Boolean): Long {
return if (isDirectory) {
getDirectorySize(File(path), countHiddenItems)
getDirectorySize(this, countHiddenItems)
} else {
length()
}
@ -127,7 +50,7 @@ private fun getDirectorySize(dir: File, countHiddenItems: Boolean): Long {
fun File.getFileCount(countHiddenItems: Boolean): Int {
return if (isDirectory) {
getDirectoryFileCount(File(path), countHiddenItems)
getDirectoryFileCount(this, countHiddenItems)
} else {
1
}
@ -151,4 +74,4 @@ private fun getDirectoryFileCount(dir: File, countHiddenItems: Boolean): Int {
return count
}
fun File.toFileDirItem(context: Context) = FileDirItem(absolutePath, name, absolutePath.getIsDirectory(context), 0, 0L)
fun File.toFileDirItem(context: Context) = FileDirItem(absolutePath, name, context.getIsPathDirectory(absolutePath), 0, 0L)

View file

@ -1,9 +1,11 @@
package com.simplemobiletools.commons.extensions
import android.content.Context
import android.graphics.BitmapFactory
import android.graphics.Point
import android.media.ExifInterface
import android.media.MediaMetadataRetriever
import com.simplemobiletools.commons.helpers.OTG_PATH
import java.io.File
import java.text.SimpleDateFormat
import java.util.*
@ -126,11 +128,83 @@ fun String.getGenericMimeType(): String {
fun String.getParentPath() = substring(0, length - getFilenameFromPath().length)
fun String.getIsDirectory(context: Context): Boolean {
return if (context.isPathOnOTG(this)) {
context.getFastDocumentFile(this)?.isDirectory ?: false
fun String.getDuration() = getFileDurationSeconds()?.getFormattedDuration()
fun String.getFileDurationSeconds(): Int? {
return try {
val retriever = MediaMetadataRetriever()
retriever.setDataSource(this)
val time = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)
val timeInMs = java.lang.Long.parseLong(time)
(timeInMs / 1000).toInt()
} catch (e: Exception) {
null
}
}
fun String.getFileArtist(): String? {
return try {
val retriever = MediaMetadataRetriever()
retriever.setDataSource(this)
retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST)
} catch (ignored: Exception) {
null
}
}
fun String.getFileAlbum(): String? {
return try {
val retriever = MediaMetadataRetriever()
retriever.setDataSource(this)
retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM)
} catch (ignored: Exception) {
null
}
}
fun String.getFileSongTitle(): String? {
return try {
val retriever = MediaMetadataRetriever()
retriever.setDataSource(this)
retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE)
} catch (ignored: Exception) {
null
}
}
fun String.getResolution(): Point? {
return if (isImageFast() || isImageSlow()) {
getImageResolution()
} else if (isVideoFast() || isVideoSlow()) {
getVideoResolution()
} else {
File(this).isDirectory
return null
}
}
fun String.getVideoResolution(): Point? {
try {
val retriever = MediaMetadataRetriever()
retriever.setDataSource(this)
val width = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH).toInt()
val height = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT).toInt()
return Point(width, height)
} catch (ignored: Exception) {
}
return null
}
fun String.getImageResolution(): Point? {
val options = BitmapFactory.Options()
options.inJustDecodeBounds = true
BitmapFactory.decodeFile(this, options)
val width = options.outWidth
val height = options.outHeight
return if (width > 0 && height > 0) {
Point(options.outWidth, options.outHeight)
} else {
null
}
}

View file

@ -63,5 +63,45 @@ data class FileDirItem(val path: String, val name: String = "", var isDirectory:
}
}
fun getProperFileCount(context: Context, countHidden: Boolean): Int {
return if (context.isPathOnOTG(path)) {
context.getDocumentFile(path)?.getFileCount(countHidden) ?: 0
} else {
File(path).getFileCount(countHidden)
}
}
fun getDirectChildrenCount(context: Context, countHiddenItems: Boolean): Int {
return if (context.isPathOnOTG(path)) {
context.getDocumentFile(path)?.listFiles()?.filter { if (countHiddenItems) true else !it.name.startsWith(".") }?.size ?: 0
} else {
File(path).listFiles().filter { if (countHiddenItems) true else it.isHidden }.size
}
}
fun getLastModified(context: Context): Long {
return if (context.isPathOnOTG(path)) {
context.getFastDocumentFile(path)?.lastModified() ?: 0L
} else {
File(path).lastModified()
}
}
fun getParentPath() = path.getParentPath()
fun getDuration() = path.getDuration()
fun getFileDurationSeconds() = path.getFileDurationSeconds()
fun getArtist() = path.getFileArtist()
fun getAlbum() = path.getFileAlbum()
fun getSongTitle() = path.getFileSongTitle()
fun getResolution() = path.getResolution()
fun getVideoResolution() = path.getVideoResolution()
fun getImageResolution() = path.getImageResolution()
}

View file

@ -43,6 +43,7 @@
<string name="filename_cannot_be_empty">El nom de l\'arxiu no pot ser buit</string>
<string name="filename_invalid_characters">El nom de l\'arxiu conté caràcters no vàlids</string>
<string name="extension_cannot_be_empty">La extensió no pot estar buida</string>
<string name="source_file_doesnt_exist">Source file %s doesn\'t exist</string>
<!-- Copy / Move -->
<string name="copy">Copiar</string>

View file

@ -43,6 +43,7 @@
<string name="filename_cannot_be_empty">Název souboru nemůže být prázdný</string>
<string name="filename_invalid_characters">Název souboru obsahuje neplatné znaky</string>
<string name="extension_cannot_be_empty">Přípona nemůže být prázdná</string>
<string name="source_file_doesnt_exist">Source file %s doesn\'t exist</string>
<!-- Copy / Move -->
<string name="copy">Kopírovat</string>

View file

@ -43,6 +43,7 @@
<string name="filename_cannot_be_empty">Filen skal have et navn</string>
<string name="filename_invalid_characters">Filnavnet indeholder ugyldige tegn</string>
<string name="extension_cannot_be_empty">Filtypen kan ikke stå tom</string>
<string name="source_file_doesnt_exist">Source file %s doesn\'t exist</string>
<!-- Copy / Move -->
<string name="copy">Kopier</string>

View file

@ -43,6 +43,7 @@
<string name="filename_cannot_be_empty">Dateiname darf nicht leer sein</string>
<string name="filename_invalid_characters">Dateiname enthält ungültige Zeichen</string>
<string name="extension_cannot_be_empty">Dateiendung darf nicht leer sein</string>
<string name="source_file_doesnt_exist">Source file %s doesn\'t exist</string>
<!-- Copy / Move -->
<string name="copy">Kopieren</string>

View file

@ -43,6 +43,7 @@
<string name="filename_cannot_be_empty">El nombre de archivo no puede estar vacío</string>
<string name="filename_invalid_characters">El nombre archivo contiene caracteres no válidos</string>
<string name="extension_cannot_be_empty">La extensión no puede estar vacía</string>
<string name="source_file_doesnt_exist">Source file %s doesn\'t exist</string>
<!-- Copy / Move -->
<string name="copy">Copiar</string>

View file

@ -43,6 +43,7 @@
<string name="filename_cannot_be_empty">Filename cannot be empty</string>
<string name="filename_invalid_characters">Filename contains invalid characters</string>
<string name="extension_cannot_be_empty">Extension cannot be empty</string>
<string name="source_file_doesnt_exist">Source file %s doesn\'t exist</string>
<!-- Copy / Move -->
<string name="copy">Copy</string>

View file

@ -43,6 +43,7 @@
<string name="filename_cannot_be_empty">Le nom de fichier ne peut pas rester vide</string>
<string name="filename_invalid_characters">Le nom de fichier contient des caractères invalides</string>
<string name="extension_cannot_be_empty">L\'extension ne peut pas rester vide</string>
<string name="source_file_doesnt_exist">Source file %s doesn\'t exist</string>
<!-- Copy / Move -->
<string name="copy">Copier</string>

View file

@ -43,6 +43,7 @@
<string name="filename_cannot_be_empty">Filename cannot be empty</string>
<string name="filename_invalid_characters">Filename contains invalid characters</string>
<string name="extension_cannot_be_empty">Extension cannot be empty</string>
<string name="source_file_doesnt_exist">Source file %s doesn\'t exist</string>
<!-- Copy / Move -->
<string name="copy">Copy</string>

View file

@ -43,6 +43,7 @@
<string name="filename_cannot_be_empty">Naziv datoteke ne smije biti prazan</string>
<string name="filename_invalid_characters">Naziv datoteke sadrži ne podržane znakove</string>
<string name="extension_cannot_be_empty">Ekstenzija ne smije biti prazna</string>
<string name="source_file_doesnt_exist">Source file %s doesn\'t exist</string>
<!-- Copy / Move -->
<string name="copy">Kopiraj</string>

View file

@ -43,6 +43,7 @@
<string name="filename_cannot_be_empty">Filename cannot be empty</string>
<string name="filename_invalid_characters">Filename contains invalid characters</string>
<string name="extension_cannot_be_empty">Extension cannot be empty</string>
<string name="source_file_doesnt_exist">Source file %s doesn\'t exist</string>
<!-- Copy / Move -->
<string name="copy">Copy</string>

View file

@ -43,6 +43,7 @@
<string name="filename_cannot_be_empty">Nama File Tidak Boleh Kosong</string>
<string name="filename_invalid_characters">Nama mengandung Karakter Tidak Di Dukung</string>
<string name="extension_cannot_be_empty">Extension Tidak Boleh Kosong</string>
<string name="source_file_doesnt_exist">Source file %s doesn\'t exist</string>
<!-- Copy / Move -->
<string name="copy">Salin</string>

View file

@ -43,6 +43,7 @@
<string name="filename_cannot_be_empty">Il nome del file non deve essere vuoto</string>
<string name="filename_invalid_characters">Il nome contiene caratteri non validi</string>
<string name="extension_cannot_be_empty">L\'estensione non può essere vuota</string>
<string name="source_file_doesnt_exist">Source file %s doesn\'t exist</string>
<!-- Copy / Move -->
<string name="copy">Copia</string>

View file

@ -43,6 +43,7 @@
<string name="filename_cannot_be_empty">ファイル名は空にできません</string>
<string name="filename_invalid_characters">ファイル名に無効な文字が含まれています</string>
<string name="extension_cannot_be_empty">拡張子は省略できません</string>
<string name="source_file_doesnt_exist">Source file %s doesn\'t exist</string>
<!-- Copy / Move -->
<string name="copy">コピー</string>

View file

@ -43,6 +43,7 @@
<string name="filename_cannot_be_empty">파일명이 비어있으면 안됨</string>
<string name="filename_invalid_characters">파일명에 사용할 수 없는 문자가 포함됨</string>
<string name="extension_cannot_be_empty">확장자가 비어있으면 안됨</string>
<string name="source_file_doesnt_exist">Source file %s doesn\'t exist</string>
<!-- Copy / Move -->
<string name="copy">복사</string>

View file

@ -43,6 +43,7 @@
<string name="filename_cannot_be_empty">Failo pavadinimas negali bûti paliktas tusèias</string>
<string name="filename_invalid_characters">Failo varde yra negalimø simboliø</string>
<string name="extension_cannot_be_empty">Papildinys negali bûti paliktas tuðèias</string>
<string name="source_file_doesnt_exist">Source file %s doesn\'t exist</string>
<!-- Copy / Move -->
<string name="copy">Kopijuoti</string>

View file

@ -43,6 +43,7 @@
<string name="filename_cannot_be_empty">Filename cannot be empty</string>
<string name="filename_invalid_characters">Filename contains invalid characters</string>
<string name="extension_cannot_be_empty">Extension cannot be empty</string>
<string name="source_file_doesnt_exist">Source file %s doesn\'t exist</string>
<!-- Copy / Move -->
<string name="copy">Kopier</string>

View file

@ -43,6 +43,7 @@
<string name="filename_cannot_be_empty">Bestandsnaam mag niet leeg zijn</string>
<string name="filename_invalid_characters">Bestandsnaam bevat ongeldige tekens</string>
<string name="extension_cannot_be_empty">Extensie mag niet leeg zijn</string>
<string name="source_file_doesnt_exist">Source file %s doesn\'t exist</string>
<!-- Copy / Move -->
<string name="copy">Kopiëren</string>

View file

@ -43,6 +43,7 @@
<string name="filename_cannot_be_empty">Filename cannot be empty</string>
<string name="filename_invalid_characters">Filename contains invalid characters</string>
<string name="extension_cannot_be_empty">Extension cannot be empty</string>
<string name="source_file_doesnt_exist">Source file %s doesn\'t exist</string>
<!-- Copy / Move -->
<string name="copy">Kopier</string>

View file

@ -43,6 +43,7 @@
<string name="filename_cannot_be_empty">Nazwa pliku nie może być pusta</string>
<string name="filename_invalid_characters">Nazwa pliku zawiera niedozwolone znaki</string>
<string name="extension_cannot_be_empty">Rozszerzenie pliku nie może być puste</string>
<string name="source_file_doesnt_exist">Source file %s doesn\'t exist</string>
<!-- Copy / Move -->
<string name="copy">Kopiuj</string>

View file

@ -43,6 +43,7 @@
<string name="filename_cannot_be_empty">O nome do arquivo não pode ficar em branco</string>
<string name="filename_invalid_characters">O nome do arquivo contém caracteres inválidos</string>
<string name="extension_cannot_be_empty">A extensão não pode ficar em branco</string>
<string name="source_file_doesnt_exist">Source file %s doesn\'t exist</string>
<!-- Copy / Move -->
<string name="copy">Copiar</string>

View file

@ -43,6 +43,7 @@
<string name="filename_cannot_be_empty">O nome do ficheiro não pode estar vazio</string>
<string name="filename_invalid_characters">O nome do ficheiro contém caracteres inválidos</string>
<string name="extension_cannot_be_empty">A extensão não pode estar vazia</string>
<string name="source_file_doesnt_exist">Source file %s doesn\'t exist</string>
<!-- Copy / Move -->
<string name="copy">Copiar</string>

View file

@ -43,6 +43,7 @@
<string name="filename_cannot_be_empty">Имя файла не может быть пустым</string>
<string name="filename_invalid_characters">Имя файла содержит недопустимые символы</string>
<string name="extension_cannot_be_empty">Расширение не может быть пустым</string>
<string name="source_file_doesnt_exist">Source file %s doesn\'t exist</string>
<!-- Copy / Move -->
<string name="copy">Копировать</string>

View file

@ -43,6 +43,7 @@
<string name="filename_cannot_be_empty">Názov súboru nemôže byť prázdny</string>
<string name="filename_invalid_characters">Názov súboru obsahuje neplatné znaky</string>
<string name="extension_cannot_be_empty">Prípona nesmie byť prázdna</string>
<string name="source_file_doesnt_exist">Zdrojový súbor %s neexistuje</string>
<!-- Copy / Move -->
<string name="copy">Kopírovať</string>

View file

@ -43,6 +43,7 @@
<string name="filename_cannot_be_empty">Du måste ange ett filnamn</string>
<string name="filename_invalid_characters">Filnamnet innehåller ogiltiga tecken</string>
<string name="extension_cannot_be_empty">Filändelsen får inte vara tom</string>
<string name="source_file_doesnt_exist">Source file %s doesn\'t exist</string>
<!-- Copy / Move -->
<string name="copy">Kopiera</string>

View file

@ -43,6 +43,7 @@
<string name="filename_cannot_be_empty">Dosya adı boş olamaz</string>
<string name="filename_invalid_characters">Dosya adı geçersiz karakterler içeriyor</string>
<string name="extension_cannot_be_empty">Uzantı boş olamaz</string>
<string name="source_file_doesnt_exist">Source file %s doesn\'t exist</string>
<!-- Copy / Move -->
<string name="copy">Kopyala</string>

View file

@ -43,6 +43,7 @@
<string name="filename_cannot_be_empty">文件名不能为空</string>
<string name="filename_invalid_characters">文件名包含非法字符</string>
<string name="extension_cannot_be_empty">扩展名不能为空</string>
<string name="source_file_doesnt_exist">Source file %s doesn\'t exist</string>
<!-- Copy / Move -->
<string name="copy">复制</string>

View file

@ -43,6 +43,7 @@
<string name="filename_cannot_be_empty">檔名不得空白</string>
<string name="filename_invalid_characters">檔名包含無效字符</string>
<string name="extension_cannot_be_empty">副檔名不得空白</string>
<string name="source_file_doesnt_exist">Source file %s doesn\'t exist</string>
<!-- Copy / Move -->
<string name="copy">複製</string>

View file

@ -43,6 +43,7 @@
<string name="filename_cannot_be_empty">Filename cannot be empty</string>
<string name="filename_invalid_characters">Filename contains invalid characters</string>
<string name="extension_cannot_be_empty">Extension cannot be empty</string>
<string name="source_file_doesnt_exist">Source file %s doesn\'t exist</string>
<!-- Copy / Move -->
<string name="copy">Copy</string>