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 propMinSdkVersion = 16
propTargetSdkVersion = propCompileSdkVersion propTargetSdkVersion = propCompileSdkVersion
propVersionCode = 1 propVersionCode = 1
propVersionName = '3.11.47' propVersionName = '3.11.48'
kotlin_version = '1.2.21' kotlin_version = '1.2.21'
support_libs = '27.0.2' support_libs = '27.0.2'
} }

View file

@ -183,8 +183,7 @@ open class BaseSimpleActivity : AppCompatActivity() {
return return
} }
val destinationFolder = File(destination) if (!doesFilePathExist(destination)) {
if (!destinationFolder.exists() && getSomeDocumentFile(destination) == null) {
toast(R.string.invalid_destination) toast(R.string.invalid_destination)
return return
} }
@ -203,6 +202,7 @@ open class BaseSimpleActivity : AppCompatActivity() {
val updatedFiles = ArrayList<FileDirItem>(fileDirItems.size * 2) val updatedFiles = ArrayList<FileDirItem>(fileDirItems.size * 2)
updatedFiles.addAll(fileDirItems) updatedFiles.addAll(fileDirItems)
try { try {
val destinationFolder = File(destination)
for (oldFileDirItem in fileDirItems) { for (oldFileDirItem in fileDirItems) {
val newFile = File(destinationFolder, oldFileDirItem.name) val newFile = File(destinationFolder, oldFileDirItem.name)
if (!newFile.exists() && File(oldFileDirItem.path).renameTo(newFile)) { if (!newFile.exists() && File(oldFileDirItem.path).renameTo(newFile)) {
@ -244,15 +244,15 @@ open class BaseSimpleActivity : AppCompatActivity() {
} }
val file = files[index] val file = files[index]
val newFile = File(destinationFileDirItem.path, file.name) val newFileDirItem = FileDirItem("${destinationFileDirItem.path}/${file.name}", file.name, file.isDirectory)
if (newFile.exists()) { if (doesFilePathExist(newFileDirItem.path)) {
FileConflictDialog(this, newFile) { resolution, applyForAll -> FileConflictDialog(this, newFileDirItem) { resolution, applyForAll ->
if (applyForAll) { if (applyForAll) {
conflictResolutions.clear() conflictResolutions.clear()
conflictResolutions[""] = resolution conflictResolutions[""] = resolution
checkConflict(files, destinationFileDirItem, files.size, conflictResolutions, callback) checkConflict(files, destinationFileDirItem, files.size, conflictResolutions, callback)
} else { } else {
conflictResolutions[newFile.absolutePath] = resolution conflictResolutions[newFileDirItem.path] = resolution
checkConflict(files, destinationFileDirItem, index + 1, conflictResolutions, callback) 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) { while (bytes >= 0) {
out!!.write(buffer, 0, bytes) out!!.write(buffer, 0, bytes)
copiedSize += bytes copiedSize += bytes
mCurrentProgress += bytes
bytes = inputStream.read(buffer) bytes = inputStream.read(buffer)
} }
mCurrentProgress += copiedSize
if (source.size == copiedSize) { if (source.size == copiedSize) {
mTransferredFiles.add(source) 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) { class CreateNewFolderDialog(val activity: BaseSimpleActivity, val path: String, val callback: (path: String) -> Unit) {
init { init {
val view = activity.layoutInflater.inflate(R.layout.dialog_create_new_folder, null) 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) AlertDialog.Builder(activity)
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)
@ -45,9 +45,12 @@ class CreateNewFolderDialog(val activity: BaseSimpleActivity, val path: String,
when { when {
activity.needsStupidWritePermissions(path) -> activity.handleSAFDialog(path) { activity.needsStupidWritePermissions(path) -> activity.handleSAFDialog(path) {
try { try {
val documentFile = activity.getDocumentFile(path) val documentFile = activity.getDocumentFile(path.getParentPath())
documentFile?.createDirectory(path.getFilenameFromPath()) if (documentFile?.createDirectory(path.getFilenameFromPath()) != null) {
sendSuccess(alertDialog, path) sendSuccess(alertDialog, path)
} else {
activity.toast(R.string.unknown_error_occurred)
}
} catch (e: SecurityException) { } catch (e: SecurityException) {
activity.showErrorToast(e) 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_MERGE
import com.simplemobiletools.commons.helpers.CONFLICT_OVERWRITE import com.simplemobiletools.commons.helpers.CONFLICT_OVERWRITE
import com.simplemobiletools.commons.helpers.CONFLICT_SKIP import com.simplemobiletools.commons.helpers.CONFLICT_SKIP
import com.simplemobiletools.commons.models.FileDirItem
import kotlinx.android.synthetic.main.dialog_file_conflict.view.* 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)!! val view = activity.layoutInflater.inflate(R.layout.dialog_file_conflict, null)!!
init { init {
view.apply { view.apply {
val stringBase = if (file.isDirectory) R.string.folder_already_exists else R.string.file_already_exists 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), file.name) conflict_dialog_title.text = String.format(activity.getString(stringBase), fileDirItem.name)
conflict_dialog_apply_to_all.isChecked = activity.baseConfig.lastConflictApplyToAll 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) { val resolutionButton = when (activity.baseConfig.lastConflictResolution) {
CONFLICT_OVERWRITE -> conflict_dialog_radio_overwrite CONFLICT_OVERWRITE -> conflict_dialog_radio_overwrite

View file

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

View file

@ -6,15 +6,16 @@ import android.media.ExifInterface
import android.provider.MediaStore import android.provider.MediaStore
import android.support.v7.app.AlertDialog import android.support.v7.app.AlertDialog
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.TextView import android.widget.TextView
import com.simplemobiletools.commons.R import com.simplemobiletools.commons.R
import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.sumByInt import com.simplemobiletools.commons.helpers.sumByInt
import com.simplemobiletools.commons.helpers.sumByLong 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.dialog_properties.view.*
import kotlinx.android.synthetic.main.property_item.view.* import kotlinx.android.synthetic.main.property_item.view.*
import java.io.File
import java.io.FileNotFoundException import java.io.FileNotFoundException
import java.util.* 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) * @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() { 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) mInflater = LayoutInflater.from(activity)
mResources = activity.resources mResources = activity.resources
val view = mInflater.inflate(R.layout.dialog_properties, null) val view = mInflater.inflate(R.layout.dialog_properties, null)
mPropertyView = view.properties_holder mPropertyView = view.properties_holder
val file = File(path) val fileDirItem = FileDirItem(path, path.getFilenameFromPath(), activity.getIsPathDirectory(path))
addProperty(R.string.name, file.name) addProperty(R.string.name, fileDirItem.name)
addProperty(R.string.path, file.parent) addProperty(R.string.path, fileDirItem.getParentPath())
addProperty(R.string.size, "", R.id.properties_size) addProperty(R.string.size, "", R.id.properties_size)
Thread { Thread {
val fileCount = file.getFileCount(countHiddenItems) val fileCount = fileDirItem.getProperFileCount(activity, countHiddenItems)
val size = file.getProperSize(countHiddenItems).formatSize() val size = fileDirItem.getProperSize(activity, countHiddenItems).formatSize()
activity.runOnUiThread { activity.runOnUiThread {
view.findViewById<TextView>(R.id.properties_size).property_value.text = size 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() 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 projection = arrayOf(MediaStore.Images.Media.DATE_MODIFIED)
val uri = MediaStore.Files.getContentUri("external") val uri = MediaStore.Files.getContentUri("external")
val selection = "${MediaStore.MediaColumns.DATA} = ?" val selection = "${MediaStore.MediaColumns.DATA} = ?"
@ -60,37 +66,39 @@ class PropertiesDialog() {
val cursor = activity.contentResolver.query(uri, projection, selection, selectionArgs, null) val cursor = activity.contentResolver.query(uri, projection, selection, selectionArgs, null)
cursor?.use { cursor?.use {
if (cursor.moveToFirst()) { if (cursor.moveToFirst()) {
val dateModified = cursor.getIntValue(MediaStore.Images.Media.DATE_MODIFIED) val dateModified = cursor.getLongValue(MediaStore.Images.Media.DATE_MODIFIED)
activity.runOnUiThread { updateLastModified(activity, view, dateModified)
view.findViewById<TextView>(R.id.properties_last_modified).property_value.text = (dateModified * 1000L).formatDate() } else {
} updateLastModified(activity, view, fileDirItem.getLastModified(activity))
} }
} }
} }
}.start() }.start()
when { when {
file.isDirectory -> { fileDirItem.isDirectory -> {
addProperty(R.string.direct_children_count, getDirectChildrenCount(file, countHiddenItems)) addProperty(R.string.direct_children_count, fileDirItem.getDirectChildrenCount(activity, countHiddenItems).toString())
addProperty(R.string.files_count, "", R.id.properties_file_count) addProperty(R.string.files_count, "", R.id.properties_file_count)
} }
file.isImageSlow() -> addProperty(R.string.resolution, file.getResolution().formatAsResolution()) fileDirItem.path.isImageSlow() -> {
file.isAudioSlow() -> { fileDirItem.getResolution()?.let { addProperty(R.string.resolution, it.formatAsResolution()) }
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) }
} }
file.isVideoSlow() -> { fileDirItem.path.isAudioSlow() -> {
file.getDuration().let { addProperty(R.string.duration, it) } fileDirItem.getDuration()?.let { addProperty(R.string.duration, it) }
addProperty(R.string.resolution, file.getResolution().formatAsResolution()) fileDirItem.getSongTitle()?.let { addProperty(R.string.song_title, it) }
file.getArtist()?.let { addProperty(R.string.artist, it) } fileDirItem.getArtist()?.let { addProperty(R.string.artist, it) }
file.getAlbum()?.let { addProperty(R.string.album, 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) { if (fileDirItem.isDirectory) {
addProperty(R.string.last_modified, file.lastModified().formatDate()) addProperty(R.string.last_modified, fileDirItem.getLastModified(activity).formatDate())
} else { } else {
addProperty(R.string.last_modified, "", R.id.properties_last_modified) addProperty(R.string.last_modified, "", R.id.properties_last_modified)
try { 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 * 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) val view = mInflater.inflate(R.layout.dialog_properties, null)
mPropertyView = view.properties_holder mPropertyView = view.properties_holder
val files = ArrayList<File>(paths.size) val fileDirItems = ArrayList<FileDirItem>(paths.size)
paths.forEach { files.add(File(it)) } 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()) addProperty(R.string.items_selected, paths.size.toString())
if (isSameParent) { 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.size, "", R.id.properties_size)
addProperty(R.string.files_count, "", R.id.properties_file_count) addProperty(R.string.files_count, "", R.id.properties_file_count)
Thread { Thread {
val fileCount = files.sumByInt { it.getFileCount(countHiddenItems) } val fileCount = fileDirItems.sumByInt { it.getProperFileCount(activity, countHiddenItems) }
val size = files.sumByLong { it.getProperSize(countHiddenItems) }.formatSize() val size = fileDirItems.sumByLong { it.getProperSize(activity, countHiddenItems) }.formatSize()
activity.runOnUiThread { activity.runOnUiThread {
view.findViewById<TextView>(R.id.properties_size).property_value.text = size view.findViewById<TextView>(R.id.properties_size).property_value.text = size
view.findViewById<TextView>(R.id.properties_file_count).property_value.text = fileCount.toString() 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 { private fun isSameParent(fileDirItems: List<FileDirItem>): Boolean {
var parent = files[0].parent var parent = fileDirItems[0].getParentPath()
for (file in files) { for (file in fileDirItems) {
val curParent = file.parent val curParent = file.getParentPath()
if (curParent != parent) { if (curParent != parent) {
return false return false
} }
@ -181,14 +198,6 @@ class PropertiesDialog() {
return true 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) { private fun addProperty(labelId: Int, value: String?, viewId: Int = 0) {
if (value == null) if (value == null)
return return

View file

@ -6,18 +6,16 @@ import com.simplemobiletools.commons.R
import com.simplemobiletools.commons.activities.BaseSimpleActivity import com.simplemobiletools.commons.activities.BaseSimpleActivity
import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.extensions.*
import kotlinx.android.synthetic.main.dialog_rename_item.view.* import kotlinx.android.synthetic.main.dialog_rename_item.view.*
import java.io.File
import java.util.* import java.util.*
class RenameItemDialog(val activity: BaseSimpleActivity, val path: String, val callback: (newPath: String) -> Unit) { class RenameItemDialog(val activity: BaseSimpleActivity, val path: String, val callback: (newPath: String) -> Unit) {
init { init {
val file = File(path) val fullName = path.getFilenameFromPath()
val fullName = file.name
val dotAt = fullName.lastIndexOf(".") val dotAt = fullName.lastIndexOf(".")
var name = fullName var name = fullName
val view = activity.layoutInflater.inflate(R.layout.dialog_rename_item, null).apply { 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) name = fullName.substring(0, dotAt)
val extension = fullName.substring(dotAt + 1) val extension = fullName.substring(dotAt + 1)
rename_item_extension.setText(extension) 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_name.setText(name)
rename_item_path.text = activity.humanizePath(file.parent ?: "") + "/" rename_item_path.text = activity.humanizePath(path.getParentPath())
} }
AlertDialog.Builder(activity) AlertDialog.Builder(activity)
@ -50,22 +48,29 @@ class RenameItemDialog(val activity: BaseSimpleActivity, val path: String, val c
return@setOnClickListener return@setOnClickListener
} }
val updatedFiles = ArrayList<File>() val updatedPaths = ArrayList<String>()
updatedFiles.add(file) updatedPaths.add(path)
if (!newExtension.isEmpty()) { if (!newExtension.isEmpty()) {
newName += ".$newExtension" newName += ".$newExtension"
} }
val newFile = File(file.parent, newName) if (!activity.doesFilePathExist(path)) {
if (newFile.exists()) { 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) activity.toast(R.string.name_taken)
return@setOnClickListener return@setOnClickListener
} }
updatedFiles.add(newFile) updatedPaths.add(newPath)
activity.renameFile(path, "${file.parent}/$newName") { activity.renameFile(path, newPath) {
if (it) { if (it) {
sendSuccess(updatedFiles) activity.scanPaths(updatedPaths) {
callback(newPath)
}
dismiss() dismiss()
} else { } else {
activity.toast(R.string.unknown_error_occurred) 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 { try {
val uri = DocumentsContract.renameDocument(applicationContext.contentResolver, document.uri, newPath) val uri = DocumentsContract.renameDocument(applicationContext.contentResolver, document.uri, newPath.getFilenameFromPath())
if (document.uri != uri) { if (document.uri != uri) {
updateInMediaStore(oldPath, newPath) updateInMediaStore(oldPath, newPath)
scanPaths(arrayListOf(oldPath, newPath)) { scanPaths(arrayListOf(oldPath, newPath)) {

View file

@ -98,7 +98,7 @@ fun Context.humanizePath(path: String): String {
val basePath = path.getBasePath(this) val basePath = path.getBasePath(this)
return when (basePath) { return when (basePath) {
"/" -> "${getHumanReadablePath(basePath)}$path" "/" -> "${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)) 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.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 // avoid these being set as SD card paths
private val physicalPaths = arrayListOf( private val physicalPaths = arrayListOf(
"/storage/sdcard1", // Motorola Xoom "/storage/sdcard1", // Motorola Xoom

View file

@ -27,3 +27,29 @@ private fun getDirectorySize(dir: DocumentFile, countHiddenItems: Boolean): Long
} }
return size 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.content.Context
import android.graphics.Bitmap import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Point
import android.media.MediaMetadataRetriever
import com.simplemobiletools.commons.models.FileDirItem import com.simplemobiletools.commons.models.FileDirItem
import java.io.File import java.io.File
@ -20,80 +17,6 @@ fun File.isAudioSlow() = absolutePath.isAudioFast() || getMimeType().startsWith(
fun File.getMimeType() = absolutePath.getMimeTypeFromPath() 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()) { fun File.getCompressionFormat() = when (extension.toLowerCase()) {
"png" -> Bitmap.CompressFormat.PNG "png" -> Bitmap.CompressFormat.PNG
"webp" -> Bitmap.CompressFormat.WEBP "webp" -> Bitmap.CompressFormat.WEBP
@ -102,7 +25,7 @@ fun File.getCompressionFormat() = when (extension.toLowerCase()) {
fun File.getProperSize(countHiddenItems: Boolean): Long { fun File.getProperSize(countHiddenItems: Boolean): Long {
return if (isDirectory) { return if (isDirectory) {
getDirectorySize(File(path), countHiddenItems) getDirectorySize(this, countHiddenItems)
} else { } else {
length() length()
} }
@ -127,7 +50,7 @@ private fun getDirectorySize(dir: File, countHiddenItems: Boolean): Long {
fun File.getFileCount(countHiddenItems: Boolean): Int { fun File.getFileCount(countHiddenItems: Boolean): Int {
return if (isDirectory) { return if (isDirectory) {
getDirectoryFileCount(File(path), countHiddenItems) getDirectoryFileCount(this, countHiddenItems)
} else { } else {
1 1
} }
@ -151,4 +74,4 @@ private fun getDirectoryFileCount(dir: File, countHiddenItems: Boolean): Int {
return count 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 package com.simplemobiletools.commons.extensions
import android.content.Context import android.content.Context
import android.graphics.BitmapFactory
import android.graphics.Point
import android.media.ExifInterface import android.media.ExifInterface
import android.media.MediaMetadataRetriever
import com.simplemobiletools.commons.helpers.OTG_PATH import com.simplemobiletools.commons.helpers.OTG_PATH
import java.io.File
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.* import java.util.*
@ -126,11 +128,83 @@ fun String.getGenericMimeType(): String {
fun String.getParentPath() = substring(0, length - getFilenameFromPath().length) fun String.getParentPath() = substring(0, length - getFilenameFromPath().length)
fun String.getIsDirectory(context: Context): Boolean { fun String.getDuration() = getFileDurationSeconds()?.getFormattedDuration()
return if (context.isPathOnOTG(this)) {
context.getFastDocumentFile(this)?.isDirectory ?: false 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 { } 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 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_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="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="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 --> <!-- Copy / Move -->
<string name="copy">Copiar</string> <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_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="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="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 --> <!-- Copy / Move -->
<string name="copy">Kopírovat</string> <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_cannot_be_empty">Filen skal have et navn</string>
<string name="filename_invalid_characters">Filnavnet indeholder ugyldige tegn</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="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 --> <!-- Copy / Move -->
<string name="copy">Kopier</string> <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_cannot_be_empty">Dateiname darf nicht leer sein</string>
<string name="filename_invalid_characters">Dateiname enthält ungültige Zeichen</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="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 --> <!-- Copy / Move -->
<string name="copy">Kopieren</string> <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_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="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="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 --> <!-- Copy / Move -->
<string name="copy">Copiar</string> <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_cannot_be_empty">Filename cannot be empty</string>
<string name="filename_invalid_characters">Filename contains invalid characters</string> <string name="filename_invalid_characters">Filename contains invalid characters</string>
<string name="extension_cannot_be_empty">Extension cannot be empty</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 --> <!-- Copy / Move -->
<string name="copy">Copy</string> <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_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="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="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 --> <!-- Copy / Move -->
<string name="copy">Copier</string> <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_cannot_be_empty">Filename cannot be empty</string>
<string name="filename_invalid_characters">Filename contains invalid characters</string> <string name="filename_invalid_characters">Filename contains invalid characters</string>
<string name="extension_cannot_be_empty">Extension cannot be empty</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 --> <!-- Copy / Move -->
<string name="copy">Copy</string> <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_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="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="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 --> <!-- Copy / Move -->
<string name="copy">Kopiraj</string> <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_cannot_be_empty">Filename cannot be empty</string>
<string name="filename_invalid_characters">Filename contains invalid characters</string> <string name="filename_invalid_characters">Filename contains invalid characters</string>
<string name="extension_cannot_be_empty">Extension cannot be empty</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 --> <!-- Copy / Move -->
<string name="copy">Copy</string> <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_cannot_be_empty">Nama File Tidak Boleh Kosong</string>
<string name="filename_invalid_characters">Nama mengandung Karakter Tidak Di Dukung</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="extension_cannot_be_empty">Extension Tidak Boleh Kosong</string>
<string name="source_file_doesnt_exist">Source file %s doesn\'t exist</string>
<!-- Copy / Move --> <!-- Copy / Move -->
<string name="copy">Salin</string> <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_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="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="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 --> <!-- Copy / Move -->
<string name="copy">Copia</string> <string name="copy">Copia</string>

View file

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

View file

@ -43,6 +43,7 @@
<string name="filename_cannot_be_empty">파일명이 비어있으면 안됨</string> <string name="filename_cannot_be_empty">파일명이 비어있으면 안됨</string>
<string name="filename_invalid_characters">파일명에 사용할 수 없는 문자가 포함됨</string> <string name="filename_invalid_characters">파일명에 사용할 수 없는 문자가 포함됨</string>
<string name="extension_cannot_be_empty">확장자가 비어있으면 안됨</string> <string name="extension_cannot_be_empty">확장자가 비어있으면 안됨</string>
<string name="source_file_doesnt_exist">Source file %s doesn\'t exist</string>
<!-- Copy / Move --> <!-- Copy / Move -->
<string name="copy">복사</string> <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_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="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="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 --> <!-- Copy / Move -->
<string name="copy">Kopijuoti</string> <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_cannot_be_empty">Filename cannot be empty</string>
<string name="filename_invalid_characters">Filename contains invalid characters</string> <string name="filename_invalid_characters">Filename contains invalid characters</string>
<string name="extension_cannot_be_empty">Extension cannot be empty</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 --> <!-- Copy / Move -->
<string name="copy">Kopier</string> <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_cannot_be_empty">Bestandsnaam mag niet leeg zijn</string>
<string name="filename_invalid_characters">Bestandsnaam bevat ongeldige tekens</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="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 --> <!-- Copy / Move -->
<string name="copy">Kopiëren</string> <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_cannot_be_empty">Filename cannot be empty</string>
<string name="filename_invalid_characters">Filename contains invalid characters</string> <string name="filename_invalid_characters">Filename contains invalid characters</string>
<string name="extension_cannot_be_empty">Extension cannot be empty</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 --> <!-- Copy / Move -->
<string name="copy">Kopier</string> <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_cannot_be_empty">Nazwa pliku nie może być pusta</string>
<string name="filename_invalid_characters">Nazwa pliku zawiera niedozwolone znaki</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="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 --> <!-- Copy / Move -->
<string name="copy">Kopiuj</string> <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_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="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="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 --> <!-- Copy / Move -->
<string name="copy">Copiar</string> <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_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="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="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 --> <!-- Copy / Move -->
<string name="copy">Copiar</string> <string name="copy">Copiar</string>

View file

@ -43,6 +43,7 @@
<string name="filename_cannot_be_empty">Имя файла не может быть пустым</string> <string name="filename_cannot_be_empty">Имя файла не может быть пустым</string>
<string name="filename_invalid_characters">Имя файла содержит недопустимые символы</string> <string name="filename_invalid_characters">Имя файла содержит недопустимые символы</string>
<string name="extension_cannot_be_empty">Расширение не может быть пустым</string> <string name="extension_cannot_be_empty">Расширение не может быть пустым</string>
<string name="source_file_doesnt_exist">Source file %s doesn\'t exist</string>
<!-- Copy / Move --> <!-- Copy / Move -->
<string name="copy">Копировать</string> <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_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="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="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 --> <!-- Copy / Move -->
<string name="copy">Kopírovať</string> <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_cannot_be_empty">Du måste ange ett filnamn</string>
<string name="filename_invalid_characters">Filnamnet innehåller ogiltiga tecken</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="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 --> <!-- Copy / Move -->
<string name="copy">Kopiera</string> <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_cannot_be_empty">Dosya adı boş olamaz</string>
<string name="filename_invalid_characters">Dosya adı geçersiz karakterler içeriyor</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="extension_cannot_be_empty">Uzantı boş olamaz</string>
<string name="source_file_doesnt_exist">Source file %s doesn\'t exist</string>
<!-- Copy / Move --> <!-- Copy / Move -->
<string name="copy">Kopyala</string> <string name="copy">Kopyala</string>

View file

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

View file

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

View file

@ -43,6 +43,7 @@
<string name="filename_cannot_be_empty">Filename cannot be empty</string> <string name="filename_cannot_be_empty">Filename cannot be empty</string>
<string name="filename_invalid_characters">Filename contains invalid characters</string> <string name="filename_invalid_characters">Filename contains invalid characters</string>
<string name="extension_cannot_be_empty">Extension cannot be empty</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 --> <!-- Copy / Move -->
<string name="copy">Copy</string> <string name="copy">Copy</string>