commit
25b360427d
61 changed files with 287 additions and 268 deletions
|
@ -7,7 +7,7 @@ buildscript {
|
|||
propMinSdkVersion = 21
|
||||
propTargetSdkVersion = propCompileSdkVersion
|
||||
propVersionCode = 1
|
||||
propVersionName = '5.18.12'
|
||||
propVersionName = '5.19.2'
|
||||
kotlin_version = '1.3.50'
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@ buildscript {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.5.1'
|
||||
classpath 'com.android.tools.build:gradle:3.5.2'
|
||||
classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'
|
||||
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
|
|
|
@ -75,7 +75,8 @@ class AboutActivity : BaseSimpleActivity() {
|
|||
baseConfig.wasBeforeAskingShown = true
|
||||
about_email.movementMethod = LinkMovementMethod.getInstance()
|
||||
about_email.setOnClickListener(null)
|
||||
ConfirmationDialog(this, "", R.string.before_asking_question_read_faq, R.string.read_it, R.string.skip) {
|
||||
val msg = "${getString(R.string.before_asking_question_read_faq)}\n\n${getString(R.string.make_sure_latest)}"
|
||||
ConfirmationDialog(this, msg, 0, R.string.read_it, R.string.skip) {
|
||||
about_faq_label.performClick()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ import com.simplemobiletools.commons.asynctasks.CopyMoveTask
|
|||
import com.simplemobiletools.commons.dialogs.ConfirmationDialog
|
||||
import com.simplemobiletools.commons.dialogs.ExportSettingsDialog
|
||||
import com.simplemobiletools.commons.dialogs.FileConflictDialog
|
||||
import com.simplemobiletools.commons.dialogs.WritePermissionDialog
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import com.simplemobiletools.commons.helpers.*
|
||||
import com.simplemobiletools.commons.interfaces.CopyMoveListener
|
||||
|
@ -285,6 +286,28 @@ abstract class BaseSimpleActivity : AppCompatActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
fun handleOTGPermission(callback: (success: Boolean) -> Unit) {
|
||||
if (baseConfig.OTGTreeUri.isNotEmpty()) {
|
||||
callback(true)
|
||||
return
|
||||
}
|
||||
|
||||
funAfterSAFPermission = callback
|
||||
WritePermissionDialog(this, true) {
|
||||
Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).apply {
|
||||
if (resolveActivity(packageManager) == null) {
|
||||
type = "*/*"
|
||||
}
|
||||
|
||||
if (resolveActivity(packageManager) != null) {
|
||||
startActivityForResult(this, OPEN_DOCUMENT_TREE_OTG)
|
||||
} else {
|
||||
toast(R.string.unknown_error_occurred)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun copyMoveFilesTo(fileDirItems: ArrayList<FileDirItem>, source: String, destination: String, isCopyOperation: Boolean, copyPhotoVideoOnly: Boolean,
|
||||
copyHidden: Boolean, callback: (destinationPath: String) -> Unit) {
|
||||
if (source == destination) {
|
||||
|
@ -292,7 +315,7 @@ abstract class BaseSimpleActivity : AppCompatActivity() {
|
|||
return
|
||||
}
|
||||
|
||||
if (!File(destination).exists()) {
|
||||
if (!getDoesFilePathExist(destination)) {
|
||||
toast(R.string.invalid_destination)
|
||||
return
|
||||
}
|
||||
|
@ -359,14 +382,14 @@ abstract class BaseSimpleActivity : AppCompatActivity() {
|
|||
val newName = String.format("%s(%d).%s", file.nameWithoutExtension, fileIndex, file.extension)
|
||||
newFile = File(file.parent, newName)
|
||||
fileIndex++
|
||||
} while (File(newFile!!.absolutePath).exists())
|
||||
} while (getDoesFilePathExist(newFile!!.absolutePath))
|
||||
return newFile
|
||||
}
|
||||
|
||||
private fun startCopyMove(files: ArrayList<FileDirItem>, destinationPath: String, isCopyOperation: Boolean, copyPhotoVideoOnly: Boolean, copyHidden: Boolean) {
|
||||
val availableSpace = destinationPath.getAvailableStorageB()
|
||||
val sumToCopy = files.sumByLong { it.getProperSize(copyHidden) }
|
||||
if (sumToCopy < availableSpace) {
|
||||
val sumToCopy = files.sumByLong { it.getProperSize(applicationContext, copyHidden) }
|
||||
if (availableSpace == -1L || sumToCopy < availableSpace) {
|
||||
checkConflicts(files, destinationPath, 0, LinkedHashMap()) {
|
||||
toast(if (isCopyOperation) R.string.copying else R.string.moving)
|
||||
val pair = Pair(files, destinationPath)
|
||||
|
@ -387,7 +410,7 @@ abstract class BaseSimpleActivity : AppCompatActivity() {
|
|||
|
||||
val file = files[index]
|
||||
val newFileDirItem = FileDirItem("$destinationPath/${file.name}", file.name, file.isDirectory)
|
||||
if (File(newFileDirItem.path).exists()) {
|
||||
if (getDoesFilePathExist(newFileDirItem.path)) {
|
||||
FileConflictDialog(this, newFileDirItem, files.size > 1) { resolution, applyForAll ->
|
||||
if (applyForAll) {
|
||||
conflictResolutions.clear()
|
||||
|
|
|
@ -9,9 +9,7 @@ import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions.withC
|
|||
import com.bumptech.glide.request.RequestOptions
|
||||
import com.simplemobiletools.commons.R
|
||||
import com.simplemobiletools.commons.activities.BaseSimpleActivity
|
||||
import com.simplemobiletools.commons.extensions.formatSize
|
||||
import com.simplemobiletools.commons.extensions.getColoredDrawableWithColor
|
||||
import com.simplemobiletools.commons.extensions.isGif
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import com.simplemobiletools.commons.models.FileDirItem
|
||||
import com.simplemobiletools.commons.views.MyRecyclerView
|
||||
import kotlinx.android.synthetic.main.filepicker_list_item.view.*
|
||||
|
@ -21,6 +19,7 @@ class FilepickerItemsAdapter(activity: BaseSimpleActivity, val fileDirItems: Lis
|
|||
|
||||
private val folderDrawable = activity.resources.getColoredDrawableWithColor(R.drawable.ic_folder_vector, textColor)
|
||||
private val fileDrawable = activity.resources.getColoredDrawableWithColor(R.drawable.ic_file_vector, textColor)
|
||||
private val hasOTGConnected = activity.hasOTGConnected()
|
||||
|
||||
init {
|
||||
folderDrawable.alpha = 180
|
||||
|
@ -76,7 +75,7 @@ class FilepickerItemsAdapter(activity: BaseSimpleActivity, val fileDirItems: Lis
|
|||
.centerCrop()
|
||||
.error(fileDrawable)
|
||||
|
||||
val itemToLoad = if (fileDirItem.name.endsWith(".apk", true)) {
|
||||
var itemToLoad = if (fileDirItem.name.endsWith(".apk", true)) {
|
||||
val packageInfo = context.packageManager.getPackageArchiveInfo(path, PackageManager.GET_ACTIVITIES)
|
||||
if (packageInfo != null) {
|
||||
val appInfo = packageInfo.applicationInfo
|
||||
|
@ -94,6 +93,10 @@ class FilepickerItemsAdapter(activity: BaseSimpleActivity, val fileDirItems: Lis
|
|||
if (itemToLoad.toString().isGif()) {
|
||||
Glide.with(activity).asBitmap().load(itemToLoad).apply(options).into(list_item_icon)
|
||||
} else {
|
||||
if (hasOTGConnected && itemToLoad is String && activity.isPathOnOTG(itemToLoad)) {
|
||||
itemToLoad = itemToLoad.getOTGPublicPath(activity)
|
||||
}
|
||||
|
||||
Glide.with(activity).load(itemToLoad).transition(withCrossFade()).apply(options).into(list_item_icon)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,10 +63,10 @@ class CopyMoveTask(val activity: BaseSimpleActivity, val copyOnly: Boolean = fal
|
|||
mMaxSize = 0
|
||||
for (file in mFiles) {
|
||||
if (file.size == 0L) {
|
||||
file.size = file.getProperSize(copyHidden)
|
||||
file.size = file.getProperSize(activity, copyHidden)
|
||||
}
|
||||
val newPath = "$mDestinationPath/${file.name}"
|
||||
val fileExists = File(newPath).exists()
|
||||
val fileExists = activity.getDoesFilePathExist(newPath)
|
||||
if (getConflictResolution(conflictResolutions, newPath) != CONFLICT_SKIP || !fileExists) {
|
||||
mMaxSize += (file.size / 1000).toInt()
|
||||
}
|
||||
|
@ -81,13 +81,13 @@ class CopyMoveTask(val activity: BaseSimpleActivity, val copyOnly: Boolean = fal
|
|||
try {
|
||||
val newPath = "$mDestinationPath/${file.name}"
|
||||
var newFileDirItem = FileDirItem(newPath, newPath.getFilenameFromPath(), file.isDirectory)
|
||||
if (File(newPath).exists()) {
|
||||
if (activity.getDoesFilePathExist(newPath)) {
|
||||
val resolution = getConflictResolution(conflictResolutions, newPath)
|
||||
if (resolution == CONFLICT_SKIP) {
|
||||
mFileCountToCopy--
|
||||
continue
|
||||
} else if (resolution == CONFLICT_OVERWRITE) {
|
||||
newFileDirItem.isDirectory = if (File(newPath).exists()) File(newPath).isDirectory else activity.getSomeDocumentFile(newPath)!!.isDirectory
|
||||
newFileDirItem.isDirectory = if (activity.getDoesFilePathExist(newPath)) File(newPath).isDirectory else activity.getSomeDocumentFile(newPath)!!.isDirectory
|
||||
activity.deleteFileBg(newFileDirItem, true)
|
||||
} else if (resolution == CONFLICT_KEEP_BOTH) {
|
||||
val newFile = activity.getAlternativeFile(File(newFileDirItem.path))
|
||||
|
@ -180,19 +180,35 @@ class CopyMoveTask(val activity: BaseSimpleActivity, val copyOnly: Boolean = fal
|
|||
return
|
||||
}
|
||||
|
||||
val children = File(source.path).list()
|
||||
for (child in children) {
|
||||
val newPath = "$destinationPath/$child"
|
||||
if (File(newPath).exists()) {
|
||||
continue
|
||||
}
|
||||
if (activity.isPathOnOTG(source.path)) {
|
||||
val children = activity.getDocumentFile(source.path)?.listFiles() ?: return
|
||||
for (child in children) {
|
||||
val newPath = "$destinationPath/${child.name}"
|
||||
if (File(newPath).exists()) {
|
||||
continue
|
||||
}
|
||||
|
||||
val oldFile = File(source.path, child)
|
||||
val oldFileDirItem = oldFile.toFileDirItem()
|
||||
val newFileDirItem = FileDirItem(newPath, newPath.getFilenameFromPath(), oldFile.isDirectory)
|
||||
copy(oldFileDirItem, newFileDirItem)
|
||||
val oldPath = "${source.path}/${child.name}"
|
||||
val oldFileDirItem = FileDirItem(oldPath, child.name!!, child.isDirectory, 0, child.length())
|
||||
val newFileDirItem = FileDirItem(newPath, child.name!!, child.isDirectory)
|
||||
copy(oldFileDirItem, newFileDirItem)
|
||||
}
|
||||
mTransferredFiles.add(source)
|
||||
} else {
|
||||
val children = File(source.path).list()
|
||||
for (child in children) {
|
||||
val newPath = "$destinationPath/$child"
|
||||
if (activity.getDoesFilePathExist(newPath)) {
|
||||
continue
|
||||
}
|
||||
|
||||
val oldFile = File(source.path, child)
|
||||
val oldFileDirItem = oldFile.toFileDirItem(activity)
|
||||
val newFileDirItem = FileDirItem(newPath, newPath.getFilenameFromPath(), oldFile.isDirectory)
|
||||
copy(oldFileDirItem, newFileDirItem)
|
||||
}
|
||||
mTransferredFiles.add(source)
|
||||
}
|
||||
mTransferredFiles.add(source)
|
||||
}
|
||||
|
||||
private fun copyFile(source: FileDirItem, destination: FileDirItem) {
|
||||
|
@ -217,7 +233,7 @@ class CopyMoveTask(val activity: BaseSimpleActivity, val copyOnly: Boolean = fal
|
|||
mDocuments[directory] = activity.getDocumentFile(directory)
|
||||
}
|
||||
out = activity.getFileOutputStreamSync(destination.path, source.path.getMimeType(), mDocuments[directory])
|
||||
inputStream = activity.getFileInputStreamSync(source.path)
|
||||
inputStream = activity.getFileInputStreamSync(source.path)!!
|
||||
|
||||
var copiedSize = 0L
|
||||
val buffer = ByteArray(DEFAULT_BUFFER_SIZE)
|
||||
|
@ -231,7 +247,7 @@ class CopyMoveTask(val activity: BaseSimpleActivity, val copyOnly: Boolean = fal
|
|||
|
||||
out?.flush()
|
||||
|
||||
if (source.size == copiedSize && File(destination.path).exists()) {
|
||||
if (source.size == copiedSize && activity.getDoesFilePathExist(destination.path)) {
|
||||
mTransferredFiles.add(source)
|
||||
if (activity.baseConfig.keepLastModified) {
|
||||
copyOldLastModified(source.path, destination.path)
|
||||
|
|
|
@ -5,7 +5,6 @@ import com.simplemobiletools.commons.R
|
|||
import com.simplemobiletools.commons.activities.BaseSimpleActivity
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import kotlinx.android.synthetic.main.dialog_export_settings.view.*
|
||||
import java.io.File
|
||||
|
||||
class ExportSettingsDialog(val activity: BaseSimpleActivity, val defaultFilename: String, callback: (path: String) -> Unit) {
|
||||
init {
|
||||
|
@ -39,7 +38,7 @@ class ExportSettingsDialog(val activity: BaseSimpleActivity, val defaultFilename
|
|||
return@setOnClickListener
|
||||
}
|
||||
|
||||
if (File(newPath).exists()) {
|
||||
if (activity.getDoesFilePathExist(newPath)) {
|
||||
val title = String.format(activity.getString(R.string.file_already_exists_overwrite), newPath.getFilenameFromPath())
|
||||
ConfirmationDialog(activity, title) {
|
||||
callback(newPath)
|
||||
|
|
|
@ -44,11 +44,11 @@ class FilePickerDialog(val activity: BaseSimpleActivity,
|
|||
private var mDialogView = activity.layoutInflater.inflate(R.layout.dialog_filepicker, null)
|
||||
|
||||
init {
|
||||
if (!File(currPath).exists()) {
|
||||
if (!activity.getDoesFilePathExist(currPath)) {
|
||||
currPath = activity.internalStoragePath
|
||||
}
|
||||
|
||||
if (!File(currPath).isDirectory) {
|
||||
if (!activity.getIsPathDirectory(currPath)) {
|
||||
currPath = currPath.getParentPath()
|
||||
}
|
||||
|
||||
|
@ -174,9 +174,16 @@ class FilePickerDialog(val activity: BaseSimpleActivity,
|
|||
}
|
||||
|
||||
private fun verifyPath() {
|
||||
val file = File(currPath)
|
||||
if ((pickFile && file.isFile) || (!pickFile && file.isDirectory)) {
|
||||
sendSuccess()
|
||||
if (activity.isPathOnOTG(currPath)) {
|
||||
val fileDocument = activity.getSomeDocumentFile(currPath) ?: return
|
||||
if ((pickFile && fileDocument.isFile) || (!pickFile && fileDocument.isDirectory)) {
|
||||
sendSuccess()
|
||||
}
|
||||
} else {
|
||||
val file = File(currPath)
|
||||
if ((pickFile && file.isFile) || (!pickFile && file.isDirectory)) {
|
||||
sendSuccess()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -191,6 +198,14 @@ class FilePickerDialog(val activity: BaseSimpleActivity,
|
|||
}
|
||||
|
||||
private fun getItems(path: String, getProperFileSize: Boolean, callback: (List<FileDirItem>) -> Unit) {
|
||||
if (activity.isPathOnOTG(path)) {
|
||||
activity.getOTGItems(path, showHidden, getProperFileSize, callback)
|
||||
} else {
|
||||
getRegularItems(path, getProperFileSize, callback)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getRegularItems(path: String, getProperFileSize: Boolean, callback: (List<FileDirItem>) -> Unit) {
|
||||
val items = ArrayList<FileDirItem>()
|
||||
val base = File(path)
|
||||
val files = base.listFiles()
|
||||
|
|
|
@ -10,15 +10,15 @@ import android.view.ViewGroup
|
|||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.simplemobiletools.commons.R
|
||||
import com.simplemobiletools.commons.activities.BaseSimpleActivity
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
|
||||
import com.simplemobiletools.commons.helpers.isNougatPlus
|
||||
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.*
|
||||
|
||||
class PropertiesDialog() {
|
||||
|
@ -35,7 +35,7 @@ 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 (!File(path).exists()) {
|
||||
if (!activity.getDoesFilePathExist(path)) {
|
||||
activity.toast(String.format(activity.getString(R.string.source_file_doesnt_exist), path))
|
||||
return
|
||||
}
|
||||
|
@ -44,16 +44,16 @@ class PropertiesDialog() {
|
|||
mInflater = LayoutInflater.from(activity)
|
||||
mResources = activity.resources
|
||||
val view = mInflater.inflate(R.layout.dialog_properties, null)
|
||||
mPropertyView = view.properties_holder
|
||||
mPropertyView = view.properties_holder!!
|
||||
|
||||
val fileDirItem = FileDirItem(path, path.getFilenameFromPath(), File(path).isDirectory, 0, 0, File(path).lastModified())
|
||||
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)
|
||||
|
||||
ensureBackgroundThread {
|
||||
val fileCount = fileDirItem.getProperFileCount(countHiddenItems)
|
||||
val size = fileDirItem.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
|
||||
|
||||
|
@ -73,11 +73,16 @@ class PropertiesDialog() {
|
|||
val dateModified = cursor.getLongValue(MediaStore.Images.Media.DATE_MODIFIED) * 1000L
|
||||
updateLastModified(activity, view, dateModified)
|
||||
} else {
|
||||
updateLastModified(activity, view, fileDirItem.modified)
|
||||
updateLastModified(activity, view, fileDirItem.getLastModified(activity))
|
||||
}
|
||||
}
|
||||
|
||||
val exif = ExifInterface(fileDirItem.path)
|
||||
val exif = if (isNougatPlus() && activity.isPathOnOTG(fileDirItem.path)) {
|
||||
ExifInterface((activity as BaseSimpleActivity).getFileInputStreamSync(fileDirItem.path))
|
||||
} else {
|
||||
ExifInterface(fileDirItem.path)
|
||||
}
|
||||
|
||||
val latLon = FloatArray(2)
|
||||
if (exif.getLatLong(latLon)) {
|
||||
activity.runOnUiThread {
|
||||
|
@ -96,7 +101,7 @@ class PropertiesDialog() {
|
|||
|
||||
when {
|
||||
fileDirItem.isDirectory -> {
|
||||
addProperty(R.string.direct_children_count, fileDirItem.getDirectChildrenCount(countHiddenItems).toString())
|
||||
addProperty(R.string.direct_children_count, fileDirItem.getDirectChildrenCount(activity, countHiddenItems).toString())
|
||||
addProperty(R.string.files_count, "…", R.id.properties_file_count)
|
||||
}
|
||||
fileDirItem.path.isImageSlow() -> {
|
||||
|
@ -117,13 +122,13 @@ class PropertiesDialog() {
|
|||
}
|
||||
|
||||
if (fileDirItem.isDirectory) {
|
||||
addProperty(R.string.last_modified, fileDirItem.modified.formatDate(activity))
|
||||
addProperty(R.string.last_modified, fileDirItem.getLastModified(activity).formatDate(activity))
|
||||
} else {
|
||||
addProperty(R.string.last_modified, "…", R.id.properties_last_modified)
|
||||
try {
|
||||
addExifProperties(path, activity)
|
||||
} catch (e: FileNotFoundException) {
|
||||
activity.toast(R.string.unknown_error_occurred)
|
||||
} catch (e: Exception) {
|
||||
activity.showErrorToast(e)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -157,7 +162,7 @@ class PropertiesDialog() {
|
|||
|
||||
val fileDirItems = ArrayList<FileDirItem>(paths.size)
|
||||
paths.forEach {
|
||||
val fileDirItem = FileDirItem(it, it.getFilenameFromPath(), File(it).isDirectory, 0, 0, File(it).lastModified())
|
||||
val fileDirItem = FileDirItem(it, it.getFilenameFromPath(), activity.getIsPathDirectory(it))
|
||||
fileDirItems.add(fileDirItem)
|
||||
}
|
||||
|
||||
|
@ -172,8 +177,8 @@ class PropertiesDialog() {
|
|||
addProperty(R.string.files_count, "…", R.id.properties_file_count)
|
||||
|
||||
ensureBackgroundThread {
|
||||
val fileCount = fileDirItems.sumByInt { it.getProperFileCount(countHiddenItems) }
|
||||
val size = fileDirItems.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()
|
||||
|
@ -188,7 +193,12 @@ class PropertiesDialog() {
|
|||
}
|
||||
|
||||
private fun addExifProperties(path: String, activity: Activity) {
|
||||
val exif = ExifInterface(path)
|
||||
val exif = if (isNougatPlus() && activity.isPathOnOTG(path)) {
|
||||
ExifInterface((activity as BaseSimpleActivity).getFileInputStreamSync(path))
|
||||
} else {
|
||||
ExifInterface(path)
|
||||
}
|
||||
|
||||
val dateTaken = exif.getExifDateTaken(activity)
|
||||
if (dateTaken.isNotEmpty()) {
|
||||
addProperty(R.string.date_taken, dateTaken)
|
||||
|
|
|
@ -5,7 +5,6 @@ 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) {
|
||||
|
@ -16,7 +15,7 @@ class RenameItemDialog(val activity: BaseSimpleActivity, val path: String, val c
|
|||
var name = fullName
|
||||
|
||||
val view = activity.layoutInflater.inflate(R.layout.dialog_rename_item, null).apply {
|
||||
if (dotAt > 0 && !File(path).isDirectory) {
|
||||
if (dotAt > 0 && !activity.getIsPathDirectory(path)) {
|
||||
name = fullName.substring(0, dotAt)
|
||||
val extension = fullName.substring(dotAt + 1)
|
||||
rename_item_extension.setText(extension)
|
||||
|
@ -59,13 +58,13 @@ class RenameItemDialog(val activity: BaseSimpleActivity, val path: String, val c
|
|||
newName += ".$newExtension"
|
||||
}
|
||||
|
||||
if (!File(path).exists()) {
|
||||
if (!activity.getDoesFilePathExist(path)) {
|
||||
activity.toast(String.format(activity.getString(R.string.source_file_doesnt_exist), path))
|
||||
return@setOnClickListener
|
||||
}
|
||||
|
||||
val newPath = "${path.getParentPath()}/$newName"
|
||||
if (File(newPath).exists()) {
|
||||
if (activity.getDoesFilePathExist(newPath)) {
|
||||
activity.toast(R.string.name_taken)
|
||||
return@setOnClickListener
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ import com.simplemobiletools.commons.activities.BaseSimpleActivity
|
|||
import com.simplemobiletools.commons.extensions.*
|
||||
import kotlinx.android.synthetic.main.dialog_rename_items.*
|
||||
import kotlinx.android.synthetic.main.dialog_rename_items.view.*
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
class RenameItemsDialog(val activity: BaseSimpleActivity, val paths: ArrayList<String>, val callback: () -> Unit) {
|
||||
|
@ -39,7 +38,7 @@ class RenameItemsDialog(val activity: BaseSimpleActivity, val paths: ArrayList<S
|
|||
return@setOnClickListener
|
||||
}
|
||||
|
||||
val validPaths = paths.filter { File(it).exists() }
|
||||
val validPaths = paths.filter { activity.getDoesFilePathExist(it) }
|
||||
val sdFilePath = validPaths.firstOrNull { activity.isPathOnSD(it) } ?: validPaths.firstOrNull()
|
||||
if (sdFilePath == null) {
|
||||
activity.toast(R.string.unknown_error_occurred)
|
||||
|
@ -68,7 +67,7 @@ class RenameItemsDialog(val activity: BaseSimpleActivity, val paths: ArrayList<S
|
|||
|
||||
val newPath = "${path.getParentPath()}/$newName"
|
||||
|
||||
if (File(newPath).exists()) {
|
||||
if (activity.getDoesFilePathExist(newPath)) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
|
|
@ -1,121 +0,0 @@
|
|||
package com.simplemobiletools.commons.dialogs
|
||||
|
||||
import android.media.ExifInterface
|
||||
import android.text.format.DateFormat
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.simplemobiletools.commons.R
|
||||
import com.simplemobiletools.commons.activities.BaseSimpleActivity
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import com.simplemobiletools.commons.helpers.isNougatPlus
|
||||
import kotlinx.android.synthetic.main.dialog_rename_items_pattern.view.*
|
||||
import java.io.File
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
class RenameItemsPatternDialog(val activity: BaseSimpleActivity, val paths: ArrayList<String>, val callback: () -> Unit) {
|
||||
init {
|
||||
var ignoreClicks = false
|
||||
val view = activity.layoutInflater.inflate(R.layout.dialog_rename_items_pattern, null)
|
||||
|
||||
AlertDialog.Builder(activity)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.create().apply {
|
||||
activity.setupDialogStuff(view, this, R.string.rename) {
|
||||
showKeyboard(view.rename_items_value)
|
||||
getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
|
||||
if (ignoreClicks) {
|
||||
return@setOnClickListener
|
||||
}
|
||||
|
||||
val validPaths = paths.filter { File(it).exists() }
|
||||
val sdFilePath = validPaths.firstOrNull { activity.isPathOnSD(it) } ?: validPaths.firstOrNull()
|
||||
if (sdFilePath == null) {
|
||||
activity.toast(R.string.unknown_error_occurred)
|
||||
dismiss()
|
||||
return@setOnClickListener
|
||||
}
|
||||
|
||||
activity.handleSAFDialog(sdFilePath) {
|
||||
ignoreClicks = true
|
||||
var pathsCnt = validPaths.size
|
||||
for (path in validPaths) {
|
||||
val exif = ExifInterface(path)
|
||||
var dateTime = if (isNougatPlus()) {
|
||||
exif.getAttribute(ExifInterface.TAG_DATETIME_ORIGINAL)
|
||||
?: exif.getAttribute(ExifInterface.TAG_DATETIME)
|
||||
} else {
|
||||
exif.getAttribute(ExifInterface.TAG_DATETIME)
|
||||
}
|
||||
|
||||
if (dateTime == null) {
|
||||
val calendar = Calendar.getInstance(Locale.ENGLISH)
|
||||
calendar.timeInMillis = File(path).lastModified()
|
||||
dateTime = DateFormat.format("yyyy:MM:dd kk:mm:ss", calendar).toString()
|
||||
}
|
||||
|
||||
var newName = view.rename_items_value.value
|
||||
val simpleDateFormat = SimpleDateFormat("yyyy:MM:dd kk:mm:ss", Locale.ENGLISH)
|
||||
val dt = simpleDateFormat.parse(dateTime)
|
||||
val cal = Calendar.getInstance()
|
||||
cal.time = dt
|
||||
val year = cal.get(Calendar.YEAR).toString()
|
||||
val month = (cal.get(Calendar.MONTH) + 1).ensureTwoDigits()
|
||||
val day = (cal.get(Calendar.DAY_OF_MONTH)).ensureTwoDigits()
|
||||
val hours = (cal.get(Calendar.HOUR_OF_DAY)).ensureTwoDigits()
|
||||
val minutes = (cal.get(Calendar.MINUTE)).ensureTwoDigits()
|
||||
val seconds = (cal.get(Calendar.SECOND)).ensureTwoDigits()
|
||||
|
||||
newName = newName
|
||||
.replace("%Y", year, false)
|
||||
.replace("%M", month, false)
|
||||
.replace("%D", day, false)
|
||||
.replace("%h", hours, false)
|
||||
.replace("%m", minutes, false)
|
||||
.replace("%s", seconds, false)
|
||||
|
||||
if (newName.isEmpty()) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (!newName.contains(".") && path.contains(".")) {
|
||||
val extension = path.substringAfterLast(".")
|
||||
newName += ".$extension"
|
||||
}
|
||||
|
||||
var newPath = "${path.getParentPath()}/$newName"
|
||||
|
||||
var currentIndex = 0
|
||||
while (File(newPath).exists()) {
|
||||
currentIndex++
|
||||
var extension = ""
|
||||
val name = if (newName.contains(".")) {
|
||||
extension = ".${newName.substringAfterLast(".")}"
|
||||
newName.substringBeforeLast(".")
|
||||
} else {
|
||||
newName
|
||||
}
|
||||
|
||||
newPath = "${path.getParentPath()}/$name~$currentIndex$extension"
|
||||
}
|
||||
|
||||
activity.renameFile(path, newPath) {
|
||||
if (it) {
|
||||
pathsCnt--
|
||||
if (pathsCnt == 0) {
|
||||
callback()
|
||||
dismiss()
|
||||
}
|
||||
} else {
|
||||
ignoreClicks = false
|
||||
activity.toast(R.string.unknown_error_occurred)
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -105,14 +105,14 @@ class StoragePickerDialog(val activity: BaseSimpleActivity, currPath: String, va
|
|||
}
|
||||
|
||||
private fun otgPicked() {
|
||||
if (activity.baseConfig.OTGPath.isEmpty()) {
|
||||
activity.getStorageDirectories().firstOrNull { it.trimEnd('/') != activity.internalStoragePath && it.trimEnd('/') != activity.sdCardPath }?.apply {
|
||||
activity.baseConfig.OTGPath = trimEnd('/')
|
||||
activity.handleOTGPermission {
|
||||
if (it) {
|
||||
callback(activity.otgPath)
|
||||
mDialog.dismiss()
|
||||
} else {
|
||||
radioGroup.check(defaultSelectedId)
|
||||
}
|
||||
}
|
||||
|
||||
mDialog.dismiss()
|
||||
callback(activity.otgPath)
|
||||
}
|
||||
|
||||
private fun rootPicked() {
|
||||
|
|
|
@ -70,12 +70,12 @@ fun Activity.appLaunched(appId: String) {
|
|||
showDonateOrUpgradeDialog()
|
||||
}
|
||||
|
||||
if (baseConfig.appRunCount > 203 && !baseConfig.wasRateUsPromptShown) {
|
||||
if (baseConfig.appRunCount > 175 && !baseConfig.wasRateUsPromptShown) {
|
||||
baseConfig.wasRateUsPromptShown = true
|
||||
RateUsDialog(this)
|
||||
}
|
||||
|
||||
if (baseConfig.navigationBarColor == INVALID_NAVIGATION_BAR_COLOR) {
|
||||
if (baseConfig.navigationBarColor == INVALID_NAVIGATION_BAR_COLOR && (window.attributes.flags and WindowManager.LayoutParams.FLAG_FULLSCREEN == 0)) {
|
||||
baseConfig.defaultNavigationBarColor = window.navigationBarColor
|
||||
baseConfig.navigationBarColor = window.navigationBarColor
|
||||
}
|
||||
|
@ -426,7 +426,7 @@ fun BaseSimpleActivity.deleteFolderBg(fileDirItem: FileDirItem, deleteMediaOnly:
|
|||
|
||||
val files = filesArr.toMutableList().filter { !deleteMediaOnly || it.isMediaFile() }
|
||||
for (file in files) {
|
||||
deleteFileBg(file.toFileDirItem(), false) { }
|
||||
deleteFileBg(file.toFileDirItem(applicationContext), false) { }
|
||||
}
|
||||
|
||||
if (folder.listFiles()?.isEmpty() == true) {
|
||||
|
@ -491,7 +491,7 @@ fun BaseSimpleActivity.deleteFileBg(fileDirItem: FileDirItem, allowDeleteFolder:
|
|||
callback?.invoke(true)
|
||||
}
|
||||
} else {
|
||||
if (file.isDirectory && allowDeleteFolder) {
|
||||
if (getIsPathDirectory(file.absolutePath) && allowDeleteFolder) {
|
||||
fileDeleted = deleteRecursively(file)
|
||||
}
|
||||
|
||||
|
@ -629,7 +629,7 @@ fun BaseSimpleActivity.getFileOutputStream(fileDirItem: FileDirItem, allowCreati
|
|||
return@handleSAFDialog
|
||||
}
|
||||
|
||||
if (!File(fileDirItem.path).exists()) {
|
||||
if (!getDoesFilePathExist(fileDirItem.path)) {
|
||||
document = document.createFile("", fileDirItem.name)
|
||||
}
|
||||
|
||||
|
@ -671,7 +671,7 @@ fun BaseSimpleActivity.getFileOutputStreamSync(path: String, mimeType: String, p
|
|||
return if (needsStupidWritePermissions(path)) {
|
||||
var documentFile = parentDocumentFile
|
||||
if (documentFile == null) {
|
||||
if (targetFile.parentFile?.exists() == true) {
|
||||
if (getDoesFilePathExist(targetFile.parentFile.absolutePath)) {
|
||||
documentFile = getDocumentFile(targetFile.parent)
|
||||
} else {
|
||||
documentFile = getDocumentFile(targetFile.parentFile.parent)
|
||||
|
@ -700,7 +700,14 @@ fun BaseSimpleActivity.getFileOutputStreamSync(path: String, mimeType: String, p
|
|||
}
|
||||
}
|
||||
|
||||
fun BaseSimpleActivity.getFileInputStreamSync(path: String) = FileInputStream(File(path))
|
||||
fun BaseSimpleActivity.getFileInputStreamSync(path: String): InputStream? {
|
||||
return if (isPathOnOTG(path)) {
|
||||
val fileDocument = getSomeDocumentFile(path)
|
||||
applicationContext.contentResolver.openInputStream(fileDocument?.uri)
|
||||
} else {
|
||||
FileInputStream(File(path))
|
||||
}
|
||||
}
|
||||
|
||||
fun Activity.handleHiddenFolderPasswordProtection(callback: () -> Unit) {
|
||||
if (baseConfig.isHiddenPasswordProtectionOn) {
|
||||
|
@ -747,7 +754,7 @@ fun Activity.handleLockedFolderOpening(path: String, callback: (success: Boolean
|
|||
}
|
||||
|
||||
fun BaseSimpleActivity.createDirectorySync(directory: String): Boolean {
|
||||
if (File(directory).exists()) {
|
||||
if (getDoesFilePathExist(directory)) {
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
|
@ -191,17 +191,18 @@ fun Context.getFastDocumentFile(path: String): DocumentFile? {
|
|||
return DocumentFile.fromSingleUri(this, Uri.parse(fullUri))
|
||||
}
|
||||
|
||||
fun Context.getOTGFastDocumentFile(path: String): DocumentFile? {
|
||||
fun Context.getOTGFastDocumentFile(path: String, otgPathToUse: String? = null): DocumentFile? {
|
||||
if (baseConfig.OTGTreeUri.isEmpty()) {
|
||||
return null
|
||||
}
|
||||
|
||||
val otgPath = otgPathToUse ?: baseConfig.OTGPath
|
||||
if (baseConfig.OTGPartition.isEmpty()) {
|
||||
baseConfig.OTGPartition = baseConfig.OTGTreeUri.removeSuffix("%3A").substringAfterLast('/').trimEnd('/')
|
||||
updateOTGPathFromPartition()
|
||||
}
|
||||
|
||||
val relativePath = Uri.encode(path.substring(baseConfig.OTGPath.length).trim('/'))
|
||||
val relativePath = Uri.encode(path.substring(otgPath.length).trim('/'))
|
||||
val fullUri = "${baseConfig.OTGTreeUri}/document/${baseConfig.OTGPartition}%3A$relativePath"
|
||||
return DocumentFile.fromSingleUri(this, Uri.parse(fullUri))
|
||||
}
|
||||
|
@ -285,7 +286,7 @@ fun Context.getFileUri(path: String) = when {
|
|||
|
||||
// these functions update the mediastore instantly, MediaScannerConnection.scanFileRecursively takes some time to really get applied
|
||||
fun Context.deleteFromMediaStore(path: String) {
|
||||
if (File(path).isDirectory) {
|
||||
if (getDoesFilePathExist(path) || getIsPathDirectory(path)) {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -335,7 +336,12 @@ fun Context.updateLastModified(path: String, lastModified: Long) {
|
|||
fun Context.getOTGItems(path: String, shouldShowHidden: Boolean, getProperFileSize: Boolean, callback: (ArrayList<FileDirItem>) -> Unit) {
|
||||
val items = ArrayList<FileDirItem>()
|
||||
val OTGTreeUri = baseConfig.OTGTreeUri
|
||||
var rootUri = DocumentFile.fromTreeUri(applicationContext, Uri.parse(OTGTreeUri))
|
||||
var rootUri = try {
|
||||
DocumentFile.fromTreeUri(applicationContext, Uri.parse(OTGTreeUri))
|
||||
} catch (ignored: Exception) {
|
||||
null
|
||||
}
|
||||
|
||||
if (rootUri == null) {
|
||||
callback(items)
|
||||
return
|
||||
|
@ -409,13 +415,31 @@ fun Context.trySAFFileDelete(fileDirItem: FileDirItem, allowDeleteFolder: Boolea
|
|||
}
|
||||
|
||||
fun Context.updateOTGPathFromPartition() {
|
||||
baseConfig.OTGPath = if (File("/storage/${baseConfig.OTGPartition}").exists()) {
|
||||
val otgPath = "/storage/${baseConfig.OTGPartition}"
|
||||
baseConfig.OTGPath = if (getOTGFastDocumentFile(otgPath, otgPath)?.exists() == true) {
|
||||
"/storage/${baseConfig.OTGPartition}"
|
||||
} else {
|
||||
"/mnt/media_rw/${baseConfig.OTGPartition}"
|
||||
}
|
||||
}
|
||||
|
||||
fun Context.getDoesFilePathExist(path: String, otgPathToUse: String? = null): Boolean {
|
||||
val otgPath = otgPathToUse ?: baseConfig.OTGPath
|
||||
return if (otgPath.isNotEmpty() && path.startsWith(otgPath)) {
|
||||
getOTGFastDocumentFile(path)?.exists() ?: false
|
||||
} else {
|
||||
File(path).exists()
|
||||
}
|
||||
}
|
||||
|
||||
fun Context.getIsPathDirectory(path: String): Boolean {
|
||||
return if (isPathOnOTG(path)) {
|
||||
getOTGFastDocumentFile(path)?.isDirectory ?: false
|
||||
} else {
|
||||
File(path).isDirectory
|
||||
}
|
||||
}
|
||||
|
||||
// avoid these being set as SD card paths
|
||||
private val physicalPaths = arrayListOf(
|
||||
"/storage/sdcard1", // Motorola Xoom
|
||||
|
|
|
@ -319,11 +319,13 @@ fun Context.getMimeTypeFromUri(uri: Uri): String {
|
|||
}
|
||||
|
||||
fun Context.ensurePublicUri(path: String, applicationId: String): Uri? {
|
||||
val uri = Uri.parse(path)
|
||||
return when {
|
||||
isPathOnOTG(path) && baseConfig.OTGPartition.isNotEmpty() && baseConfig.OTGTreeUri.isNotEmpty() -> getDocumentFile(path)?.uri
|
||||
uri.scheme == "content" -> uri
|
||||
else -> {
|
||||
return if (isPathOnOTG(path)) {
|
||||
getDocumentFile(path)?.uri
|
||||
} else {
|
||||
val uri = Uri.parse(path)
|
||||
if (uri.scheme == "content") {
|
||||
uri
|
||||
} else {
|
||||
val newPath = if (uri.toString().startsWith("/")) uri.toString() else uri.path
|
||||
val file = File(newPath)
|
||||
getFilePublicUri(file, applicationId)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.simplemobiletools.commons.extensions
|
||||
|
||||
import android.content.Context
|
||||
import com.simplemobiletools.commons.helpers.*
|
||||
import com.simplemobiletools.commons.models.FileDirItem
|
||||
import java.io.File
|
||||
|
@ -74,7 +75,7 @@ private fun getDirectoryFileCount(dir: File, countHiddenItems: Boolean): Int {
|
|||
|
||||
fun File.getDirectChildrenCount(countHiddenItems: Boolean) = listFiles()?.filter { if (countHiddenItems) true else !it.isHidden }?.size ?: 0
|
||||
|
||||
fun File.toFileDirItem() = FileDirItem(absolutePath, name, File(absolutePath).isDirectory, 0, length(), lastModified())
|
||||
fun File.toFileDirItem(context: Context) = FileDirItem(absolutePath, name, context.getIsPathDirectory(absolutePath), 0, length(), lastModified())
|
||||
|
||||
fun File.containsNoMedia() = isDirectory && File(this, NOMEDIA).exists()
|
||||
|
||||
|
|
|
@ -39,6 +39,8 @@ fun String.isAValidFilename(): Boolean {
|
|||
return true
|
||||
}
|
||||
|
||||
fun String.getOTGPublicPath(context: Context) = "${context.baseConfig.OTGTreeUri}/document/${context.baseConfig.OTGPartition}%3A${substring(context.baseConfig.OTGPath.length).replace("/", "%2F")}"
|
||||
|
||||
fun String.isMediaFile() = isImageFast() || isVideoFast() || isGif() || isRawFast() || isSvg() || isPortrait()
|
||||
|
||||
fun String.isGif() = endsWith(".gif", true)
|
||||
|
@ -204,9 +206,13 @@ fun String.getFileKey(): String {
|
|||
}
|
||||
|
||||
fun String.getAvailableStorageB(): Long {
|
||||
val stat = StatFs(this)
|
||||
val bytesAvailable = stat.blockSizeLong * stat.availableBlocksLong
|
||||
return bytesAvailable
|
||||
return try {
|
||||
val stat = StatFs(this)
|
||||
val bytesAvailable = stat.blockSizeLong * stat.availableBlocksLong
|
||||
bytesAvailable
|
||||
} catch (e: Exception) {
|
||||
-1L
|
||||
}
|
||||
}
|
||||
|
||||
// remove diacritics, for example č -> c
|
||||
|
|
|
@ -355,4 +355,8 @@ open class BaseConfig(val context: Context) {
|
|||
var lastRenameUsed: Int
|
||||
get() = prefs.getInt(LAST_RENAME_USED, RENAME_SIMPLE)
|
||||
set(lastRenameUsed) = prefs.edit().putInt(LAST_RENAME_USED, lastRenameUsed).apply()
|
||||
|
||||
var lastRenamePatternUsed: String
|
||||
get() = prefs.getString(LAST_RENAME_PATTERN_USED, "")!!
|
||||
set(lastRenamePatternUsed) = prefs.edit().putString(LAST_RENAME_PATTERN_USED, lastRenamePatternUsed).apply()
|
||||
}
|
||||
|
|
|
@ -119,6 +119,7 @@ const val WAS_RATE_US_PROMPT_SHOWN = "was_rate_us_prompt_shown"
|
|||
const val WAS_SORTING_BY_NUMERIC_VALUE_ADDED = "was_sorting_by_numeric_value_added"
|
||||
const val WAS_FOLDER_LOCKING_NOTICE_SHOWN = "was_folder_locking_notice_shown"
|
||||
const val LAST_RENAME_USED = "last_rename_used"
|
||||
const val LAST_RENAME_PATTERN_USED = "last_rename_pattern_used"
|
||||
|
||||
// licenses
|
||||
internal const val LICENSE_KOTLIN = 1
|
||||
|
|
|
@ -55,11 +55,37 @@ open class FileDirItem(val path: String, val name: String = "", var isDirectory:
|
|||
else -> name
|
||||
}
|
||||
|
||||
fun getProperSize(countHidden: Boolean) = File(path).getProperSize(countHidden)
|
||||
fun getProperSize(context: Context, countHidden: Boolean): Long {
|
||||
return if (context.isPathOnOTG(path)) {
|
||||
context.getDocumentFile(path)?.getItemSize(countHidden) ?: 0
|
||||
} else {
|
||||
File(path).getProperSize(countHidden)
|
||||
}
|
||||
}
|
||||
|
||||
fun getProperFileCount(countHidden: Boolean) = File(path).getFileCount(countHidden)
|
||||
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(countHiddenItems: Boolean) = File(path).getDirectChildrenCount(countHiddenItems)
|
||||
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).getDirectChildrenCount(countHiddenItems)
|
||||
}
|
||||
}
|
||||
|
||||
fun getLastModified(context: Context): Long {
|
||||
return if (context.isPathOnOTG(path)) {
|
||||
context.getFastDocumentFile(path)?.lastModified() ?: 0L
|
||||
} else {
|
||||
File(path).lastModified()
|
||||
}
|
||||
}
|
||||
|
||||
fun getParentPath() = path.getParentPath()
|
||||
|
||||
|
@ -78,4 +104,6 @@ open class FileDirItem(val path: String, val name: String = "", var isDirectory:
|
|||
fun getVideoResolution(context: Context) = context.getVideoResolution(path)
|
||||
|
||||
fun getImageResolution() = path.getImageResolution()
|
||||
|
||||
fun getPublicUri(context: Context) = context.getDocumentFile(path)?.uri ?: ""
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ class RenamePatternTab(context: Context, attrs: AttributeSet) : RelativeLayout(c
|
|||
override fun initTab(activity: BaseSimpleActivity, paths: ArrayList<String>) {
|
||||
this.activity = activity
|
||||
this.paths = paths
|
||||
rename_items_value.setText(activity.baseConfig.lastRenamePatternUsed)
|
||||
}
|
||||
|
||||
override fun dialogConfirmed(callback: (success: Boolean) -> Unit) {
|
||||
|
@ -42,13 +43,14 @@ class RenamePatternTab(context: Context, attrs: AttributeSet) : RelativeLayout(c
|
|||
return
|
||||
}
|
||||
|
||||
val validPaths = paths.filter { File(it).exists() }
|
||||
val validPaths = paths.filter { activity?.getDoesFilePathExist(it) == true }
|
||||
val sdFilePath = validPaths.firstOrNull { activity?.isPathOnSD(it) == true } ?: validPaths.firstOrNull()
|
||||
if (sdFilePath == null) {
|
||||
activity?.toast(R.string.unknown_error_occurred)
|
||||
return
|
||||
}
|
||||
|
||||
activity?.baseConfig?.lastRenamePatternUsed = rename_items_value.value
|
||||
activity?.handleSAFDialog(sdFilePath) {
|
||||
ignoreClicks = true
|
||||
var pathsCnt = validPaths.size
|
||||
|
@ -67,7 +69,8 @@ class RenamePatternTab(context: Context, attrs: AttributeSet) : RelativeLayout(c
|
|||
dateTime = DateFormat.format("yyyy:MM:dd kk:mm:ss", calendar).toString()
|
||||
}
|
||||
|
||||
val simpleDateFormat = SimpleDateFormat("yyyy:MM:dd kk:mm:ss", Locale.ENGLISH)
|
||||
val pattern = if (dateTime.substring(4, 5) == "-") "yyyy-MM-dd kk:mm:ss" else "yyyy:MM:dd kk:mm:ss"
|
||||
val simpleDateFormat = SimpleDateFormat(pattern, Locale.ENGLISH)
|
||||
val dt = simpleDateFormat.parse(dateTime)
|
||||
val cal = Calendar.getInstance()
|
||||
cal.time = dt
|
||||
|
@ -98,7 +101,7 @@ class RenamePatternTab(context: Context, attrs: AttributeSet) : RelativeLayout(c
|
|||
var newPath = "${path.getParentPath()}/$newName"
|
||||
|
||||
var currentIndex = 0
|
||||
while (File(newPath).exists()) {
|
||||
while (activity?.getDoesFilePathExist(newPath) == true) {
|
||||
currentIndex++
|
||||
var extension = ""
|
||||
val name = if (newName.contains(".")) {
|
||||
|
|
|
@ -8,7 +8,6 @@ import com.simplemobiletools.commons.activities.BaseSimpleActivity
|
|||
import com.simplemobiletools.commons.extensions.*
|
||||
import com.simplemobiletools.commons.interfaces.RenameTab
|
||||
import kotlinx.android.synthetic.main.tab_rename_simple.view.*
|
||||
import java.io.File
|
||||
|
||||
class RenameSimpleTab(context: Context, attrs: AttributeSet) : RelativeLayout(context, attrs), RenameTab {
|
||||
var ignoreClicks = false
|
||||
|
@ -39,7 +38,7 @@ class RenameSimpleTab(context: Context, attrs: AttributeSet) : RelativeLayout(co
|
|||
return
|
||||
}
|
||||
|
||||
val validPaths = paths.filter { File(it).exists() }
|
||||
val validPaths = paths.filter { activity?.getDoesFilePathExist(it) == true }
|
||||
val sdFilePath = validPaths.firstOrNull { activity?.isPathOnSD(it) == true } ?: validPaths.firstOrNull()
|
||||
if (sdFilePath == null) {
|
||||
activity?.toast(R.string.unknown_error_occurred)
|
||||
|
@ -67,7 +66,7 @@ class RenameSimpleTab(context: Context, attrs: AttributeSet) : RelativeLayout(co
|
|||
|
||||
val newPath = "${path.getParentPath()}/$newName"
|
||||
|
||||
if (File(newPath).exists()) {
|
||||
if (activity?.getDoesFilePathExist(newPath) == true) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
<string name="simple_renaming">Simple renaming</string>
|
||||
<string name="pattern_renaming">Pattern</string>
|
||||
<string name="string_to_add">String to add</string>
|
||||
<string name="rename_date_time_pattern">%Y - year\n%M - month\n%D - day\n%h - hour\n%m - minute\n%s - second</string>
|
||||
<string name="rename_date_time_pattern">%Y - year\n%M - month\n%D - day\n%h - hour\n%m - minute\n%s - second\n%i - number increasing from 1</string>
|
||||
|
||||
<!-- Copy / Move -->
|
||||
<string name="copy">نسخ</string>
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
<string name="simple_renaming">Simple renaming</string>
|
||||
<string name="pattern_renaming">Pattern</string>
|
||||
<string name="string_to_add">String to add</string>
|
||||
<string name="rename_date_time_pattern">%Y - year\n%M - month\n%D - day\n%h - hour\n%m - minute\n%s - second</string>
|
||||
<string name="rename_date_time_pattern">%Y - year\n%M - month\n%D - day\n%h - hour\n%m - minute\n%s - second\n%i - number increasing from 1</string>
|
||||
|
||||
<!-- Copy / Move -->
|
||||
<string name="copy">Kopyala</string>
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
<string name="simple_renaming">Simple renaming</string>
|
||||
<string name="pattern_renaming">Pattern</string>
|
||||
<string name="string_to_add">String to add</string>
|
||||
<string name="rename_date_time_pattern">%Y - year\n%M - month\n%D - day\n%h - hour\n%m - minute\n%s - second</string>
|
||||
<string name="rename_date_time_pattern">%Y - year\n%M - month\n%D - day\n%h - hour\n%m - minute\n%s - second\n%i - number increasing from 1</string>
|
||||
|
||||
<!-- Copy / Move -->
|
||||
<string name="copy">Copy</string>
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
<string name="simple_renaming">Reanomenat simple</string>
|
||||
<string name="pattern_renaming">Patró</string>
|
||||
<string name="string_to_add">Cadena per afegir</string>
|
||||
<string name="rename_date_time_pattern">%Y - any\n%M - mes\n%D - dia\n%h - hora\n%m - minut\n%s - segon</string>
|
||||
<string name="rename_date_time_pattern">%Y - any\n%M - mes\n%D - dia\n%h - hora\n%m - minut\n%s - segon\n%i - number increasing from 1</string>
|
||||
|
||||
<!-- Copy / Move -->
|
||||
<string name="copy">Copiar</string>
|
||||
|
@ -646,8 +646,8 @@
|
|||
Un cop llançat, simplement configureu la icona de taronja per defecte # F57C00. És possible que hàgiu de tornar a instal·lar l\'aplicació en el pitjor dels casos.</string>
|
||||
<string name="faq_7_title_commons">Els diners han estat deduïts del meu compte bancari, però no puc descarregar l\'aplicació. Què puc fer?</string>
|
||||
<string name="faq_7_text_commons">Google fa que els pagaments siguin completament gestionats i alguns cops això genera problemes de sistema. Només cal que esborris la memòria cau de l\’aplicació Google Play i reiniciis el dispositiu. A continuació prova a baixar-la de nou.</string>
|
||||
<string name="faq_8_title_commons">Per què he d'actualitzar a la versió Pro?</string>
|
||||
<string name="faq_8_text_commons">Com que la versió de l\'aplicació ja no s'actualitza, els errors que heu vist, no seran corregits. Tampoc s\’hi afegiran noves funcions. Podeu comprar la versió Pro a Google Play per una petita quantitat de diners.
|
||||
<string name="faq_8_title_commons">Per què he d\'actualitzar a la versió Pro?</string>
|
||||
<string name="faq_8_text_commons">Com que la versió de l\'aplicació ja no s\'actualitza, els errors que heu vist, no seran corregits. Tampoc s\’hi afegiran noves funcions. Podeu comprar la versió Pro a Google Play per una petita quantitat de diners.
|
||||
Es tracta d\’un pagament únic, cosa que significa que un cop l\’adquireixis, no hauràs de tornar a pagar mai més. Ni tan sols després de canviar de dispositiu. Si no us agrada la versió Pro, podeu desinstal·lar-la en poques hores i automàticament obtindreu els diners.
|
||||
Si voleu un reemborsament en qualsevol moment més tard, només cal que contacteu amb nosaltres a l\'adreça hello@simplemobiletools.com i ho aconseguireu.</string>
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
<string name="simple_renaming">Simple renaming</string>
|
||||
<string name="pattern_renaming">Pattern</string>
|
||||
<string name="string_to_add">String to add</string>
|
||||
<string name="rename_date_time_pattern">%Y - year\n%M - month\n%D - day\n%h - hour\n%m - minute\n%s - second</string>
|
||||
<string name="rename_date_time_pattern">%Y - year\n%M - month\n%D - day\n%h - hour\n%m - minute\n%s - second\n%i - number increasing from 1</string>
|
||||
|
||||
<!-- Copy / Move -->
|
||||
<string name="copy">Kopírovat</string>
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
<string name="simple_renaming">Simple renaming</string>
|
||||
<string name="pattern_renaming">Pattern</string>
|
||||
<string name="string_to_add">String to add</string>
|
||||
<string name="rename_date_time_pattern">%Y - year\n%M - month\n%D - day\n%h - hour\n%m - minute\n%s - second</string>
|
||||
<string name="rename_date_time_pattern">%Y - year\n%M - month\n%D - day\n%h - hour\n%m - minute\n%s - second\n%i - number increasing from 1</string>
|
||||
|
||||
<!-- Copy / Move -->
|
||||
<string name="copy">Copïo</string>
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
<string name="simple_renaming">Simple omdøbning</string>
|
||||
<string name="pattern_renaming">Mønster</string>
|
||||
<string name="string_to_add">Tekststreng der skal tilføjes</string>
|
||||
<string name="rename_date_time_pattern">%Y - år\n%M - måned\n%D - dag\n%h - time\n%m - minut\n%s - sekund</string>
|
||||
<string name="rename_date_time_pattern">%Y - år\n%M - måned\n%D - dag\n%h - time\n%m - minut\n%s - sekund\n%i - number increasing from 1</string>
|
||||
|
||||
<!-- Copy / Move -->
|
||||
<string name="copy">Kopier</string>
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
<string name="simple_renaming">Simple renaming</string>
|
||||
<string name="pattern_renaming">Pattern</string>
|
||||
<string name="string_to_add">String to add</string>
|
||||
<string name="rename_date_time_pattern">%Y - year\n%M - month\n%D - day\n%h - hour\n%m - minute\n%s - second</string>
|
||||
<string name="rename_date_time_pattern">%Y - year\n%M - month\n%D - day\n%h - hour\n%m - minute\n%s - second\n%i - number increasing from 1</string>
|
||||
|
||||
<!-- Copy / Move -->
|
||||
<string name="copy">Kopieren</string>
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
<string name="simple_renaming">Απλή μετονομασία</string>
|
||||
<string name="pattern_renaming">Μοτίβο</string>
|
||||
<string name="string_to_add">Συμβολοσειρά για προσθήκη</string>
|
||||
<string name="rename_date_time_pattern">%Y - έτος\n%M - μήνας\n%D - ημέρα\n%h - ώρα\n%m - λεπτό\n%s - δευτ/το</string>
|
||||
<string name="rename_date_time_pattern">%Y - έτος\n%M - μήνας\n%D - ημέρα\n%h - ώρα\n%m - λεπτό\n%s - δευτ/το\n%i - number increasing from 1</string>
|
||||
|
||||
<!-- Copy / Move -->
|
||||
<string name="copy">Αντιγραφή</string>
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
<string name="simple_renaming">Renombrado simple</string>
|
||||
<string name="pattern_renaming">Modelo</string>
|
||||
<string name="string_to_add">Cadena para agregar</string>
|
||||
<string name="rename_date_time_pattern">%Y - year\n%M - month\n%D - day\n%h - hour\n%m - minute\n%s - second</string>
|
||||
<string name="rename_date_time_pattern">%Y - year\n%M - month\n%D - day\n%h - hour\n%m - minute\n%s - second\n%i - number increasing from 1</string>
|
||||
|
||||
<!-- Copy / Move -->
|
||||
<string name="copy">Copiar</string>
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
<string name="simple_renaming">Simple renaming</string>
|
||||
<string name="pattern_renaming">Pattern</string>
|
||||
<string name="string_to_add">String to add</string>
|
||||
<string name="rename_date_time_pattern">%Y - year\n%M - month\n%D - day\n%h - hour\n%m - minute\n%s - second</string>
|
||||
<string name="rename_date_time_pattern">%Y - year\n%M - month\n%D - day\n%h - hour\n%m - minute\n%s - second\n%i - number increasing from 1</string>
|
||||
|
||||
<!-- Copy / Move -->
|
||||
<string name="copy">Kopioi</string>
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
<string name="simple_renaming">Simple</string>
|
||||
<string name="pattern_renaming">Modèle</string>
|
||||
<string name="string_to_add">Caractères à ajouter</string>
|
||||
<string name="rename_date_time_pattern">%Y - année\n%M - mois\n%D - jour\n%h - heure\n%m - minute\n%s - seconde</string>
|
||||
<string name="rename_date_time_pattern">%Y - année\n%M - mois\n%D - jour\n%h - heure\n%m - minute\n%s - seconde\n%i - number increasing from 1</string>
|
||||
|
||||
<!-- Copy / Move -->
|
||||
<string name="copy">Copier</string>
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
<string name="simple_renaming">Simple renaming</string>
|
||||
<string name="pattern_renaming">Pattern</string>
|
||||
<string name="string_to_add">String to add</string>
|
||||
<string name="rename_date_time_pattern">%Y - year\n%M - month\n%D - day\n%h - hour\n%m - minute\n%s - second</string>
|
||||
<string name="rename_date_time_pattern">%Y - year\n%M - month\n%D - day\n%h - hour\n%m - minute\n%s - second\n%i - number increasing from 1</string>
|
||||
|
||||
<!-- Copy / Move -->
|
||||
<string name="copy">Copiar</string>
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
<string name="simple_renaming">Simple renaming</string>
|
||||
<string name="pattern_renaming">Pattern</string>
|
||||
<string name="string_to_add">String to add</string>
|
||||
<string name="rename_date_time_pattern">%Y - year\n%M - month\n%D - day\n%h - hour\n%m - minute\n%s - second</string>
|
||||
<string name="rename_date_time_pattern">%Y - year\n%M - month\n%D - day\n%h - hour\n%m - minute\n%s - second\n%i - number increasing from 1</string>
|
||||
|
||||
<!-- Copy / Move -->
|
||||
<string name="copy">Copy</string>
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
<string name="simple_renaming">Simple renaming</string>
|
||||
<string name="pattern_renaming">Pattern</string>
|
||||
<string name="string_to_add">String to add</string>
|
||||
<string name="rename_date_time_pattern">%Y - year\n%M - month\n%D - day\n%h - hour\n%m - minute\n%s - second</string>
|
||||
<string name="rename_date_time_pattern">%Y - year\n%M - month\n%D - day\n%h - hour\n%m - minute\n%s - second\n%i - number increasing from 1</string>
|
||||
|
||||
<!-- Copy / Move -->
|
||||
<string name="copy">Kopiraj</string>
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
<string name="simple_renaming">Simple renaming</string>
|
||||
<string name="pattern_renaming">Pattern</string>
|
||||
<string name="string_to_add">String to add</string>
|
||||
<string name="rename_date_time_pattern">%É - év\\n%H - hónap\\n%N - nap\\n%ó - óra\\n%p - perc\\n%mp - másodperc</string>
|
||||
<string name="rename_date_time_pattern">%É - év\\n%H - hónap\\n%N - nap\\n%ó - óra\\n%p - perc\\n%mp - másodperc\n%i - number increasing from 1</string>
|
||||
|
||||
<!-- Copy / Move -->
|
||||
<string name="copy">Másolás</string>
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
<string name="simple_renaming">Ubah nama</string>
|
||||
<string name="pattern_renaming">Pola</string>
|
||||
<string name="string_to_add">Kata untuk ditambahkan</string>
|
||||
<string name="rename_date_time_pattern">%Y - tahun\n%M - bulan\n%D - hari\n%h - jam\n%m - menit\n%s - detik</string>
|
||||
<string name="rename_date_time_pattern">%Y - tahun\n%M - bulan\n%D - hari\n%h - jam\n%m - menit\n%s - detik\n%i - number increasing from 1</string>
|
||||
|
||||
<!-- Copy / Move -->
|
||||
<string name="copy">Salin</string>
|
||||
|
@ -572,7 +572,7 @@
|
|||
<string name="purchase">Beli</string>
|
||||
<string name="update_thank_you">Silakan perbarui Simple Thank You ke versi terbaru</string>
|
||||
<string name="before_asking_question_read_faq">Sebelum anda bertanya, silakan periksa pengaturan aplikasi dan baca Pertanyaan yang Paling Sering Ditanyakan terlebih dahulu. Mungkin solusi yang anda cari ada di sana.</string>
|
||||
<string name="make_sure_latest">Also make sure that you are using the latest app version.</string>
|
||||
<string name="make_sure_latest">Pastikan juga anda menggunakan versi aplikasi terbaru.</string>
|
||||
<string name="read_it">Baca</string>
|
||||
<string name="rate_us_prompt">Halo,\n\nsepertinya anda sudah menggunakan aplikasi ini cukup lama, dan kami sangat menghargainya.\n\nJika anda tidak keberatan, silakan nilai kami di Google Play. Itu akan sangat membantu kami.\n\nApapun keputusan anda, anda tidak akan melihat pesan ini lagi.\n\nTerima kasih!</string>
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
<string name="simple_renaming">Ubah nama</string>
|
||||
<string name="pattern_renaming">Pola</string>
|
||||
<string name="string_to_add">Kata untuk ditambahkan</string>
|
||||
<string name="rename_date_time_pattern">%Y - tahun\n%M - bulan\n%D - hari\n%h - jam\n%m - menit\n%s - detik</string>
|
||||
<string name="rename_date_time_pattern">%Y - tahun\n%M - bulan\n%D - hari\n%h - jam\n%m - menit\n%s - detik\n%i - number increasing from 1</string>
|
||||
|
||||
<!-- Copy / Move -->
|
||||
<string name="copy">Salin</string>
|
||||
|
@ -572,7 +572,7 @@
|
|||
<string name="purchase">Beli</string>
|
||||
<string name="update_thank_you">Silakan perbarui Simple Thank You ke versi terbaru</string>
|
||||
<string name="before_asking_question_read_faq">Sebelum anda bertanya, silakan periksa pengaturan aplikasi dan baca Pertanyaan yang Paling Sering Ditanyakan terlebih dahulu. Mungkin solusi yang anda cari ada di sana.</string>
|
||||
<string name="make_sure_latest">Also make sure that you are using the latest app version.</string>
|
||||
<string name="make_sure_latest">Pastikan juga anda menggunakan versi aplikasi terbaru.</string>
|
||||
<string name="read_it">Baca</string>
|
||||
<string name="rate_us_prompt">Halo,\n\nsepertinya anda sudah menggunakan aplikasi ini cukup lama, dan kami sangat menghargainya.\n\nJika anda tidak keberatan, silakan nilai kami di Google Play. Itu akan sangat membantu kami.\n\nApapun keputusan anda, anda tidak akan melihat pesan ini lagi.\n\nTerima kasih!</string>
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
<string name="simple_renaming">Rinominazione semplice</string>
|
||||
<string name="pattern_renaming">Modello</string>
|
||||
<string name="string_to_add">Stringa da aggiungere</string>
|
||||
<string name="rename_date_time_pattern">%Y - anno\n%M - mese\n%D - giorno\n%h - ora\n%m - minuto\n%s - secondo</string>
|
||||
<string name="rename_date_time_pattern">%Y - anno\n%M - mese\n%D - giorno\n%h - ora\n%m - minuto\n%s - secondo\n%i - number increasing from 1</string>
|
||||
|
||||
<!-- Copy / Move -->
|
||||
<string name="copy">Copia</string>
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
<string name="simple_renaming">Simple renaming</string>
|
||||
<string name="pattern_renaming">Pattern</string>
|
||||
<string name="string_to_add">String to add</string>
|
||||
<string name="rename_date_time_pattern">%Y - year\n%M - month\n%D - day\n%h - hour\n%m - minute\n%s - second</string>
|
||||
<string name="rename_date_time_pattern">%Y - year\n%M - month\n%D - day\n%h - hour\n%m - minute\n%s - second\n%i - number increasing from 1</string>
|
||||
|
||||
<!-- Copy / Move -->
|
||||
<string name="copy">Copy</string>
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
<string name="simple_renaming">Simple renaming</string>
|
||||
<string name="pattern_renaming">Pattern</string>
|
||||
<string name="string_to_add">String to add</string>
|
||||
<string name="rename_date_time_pattern">%Y - year\n%M - month\n%D - day\n%h - hour\n%m - minute\n%s - second</string>
|
||||
<string name="rename_date_time_pattern">%Y - year\n%M - month\n%D - day\n%h - hour\n%m - minute\n%s - second\n%i - number increasing from 1</string>
|
||||
|
||||
<!-- Copy / Move -->
|
||||
<string name="copy">コピー</string>
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
<string name="simple_renaming">심플 이름 바꾸기</string>
|
||||
<string name="pattern_renaming">패턴</string>
|
||||
<string name="string_to_add">추가할 문장</string>
|
||||
<string name="rename_date_time_pattern">%Y - 년\n%M - 월\n%D - 일\n%h - 시\n%m - 분\n%s - 초</string>
|
||||
<string name="rename_date_time_pattern">%Y - 년\n%M - 월\n%D - 일\n%h - 시\n%m - 분\n%s - 초\n%i - number increasing from 1</string>
|
||||
|
||||
<!-- Copy / Move -->
|
||||
<string name="copy">복사</string>
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
<string name="simple_renaming">Simple renaming</string>
|
||||
<string name="pattern_renaming">Pattern</string>
|
||||
<string name="string_to_add">String to add</string>
|
||||
<string name="rename_date_time_pattern">%Y - year\n%M - month\n%D - day\n%h - hour\n%m - minute\n%s - second</string>
|
||||
<string name="rename_date_time_pattern">%Y - year\n%M - month\n%D - day\n%h - hour\n%m - minute\n%s - second\n%i - number increasing from 1</string>
|
||||
|
||||
<!-- Copy / Move -->
|
||||
<string name="copy">Kopijuoti</string>
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
<string name="simple_renaming">Simple renaming</string>
|
||||
<string name="pattern_renaming">Pattern</string>
|
||||
<string name="string_to_add">String to add</string>
|
||||
<string name="rename_date_time_pattern">%Y - year\n%M - month\n%D - day\n%h - hour\n%m - minute\n%s - second</string>
|
||||
<string name="rename_date_time_pattern">%Y - year\n%M - month\n%D - day\n%h - hour\n%m - minute\n%s - second\n%i - number increasing from 1</string>
|
||||
|
||||
<!-- Copy / Move -->
|
||||
<string name="copy">Kopier</string>
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
<string name="simple_renaming">Eenvoudig hernoemen</string>
|
||||
<string name="pattern_renaming">Patroon</string>
|
||||
<string name="string_to_add">Tekens toevoegen</string>
|
||||
<string name="rename_date_time_pattern">%Y - jaar\n%M - maand\n%D - dag\n%h - uur\n%m - minuut\n%s - seconde</string>
|
||||
<string name="rename_date_time_pattern">%Y - jaar\n%M - maand\n%D - dag\n%h - uur\n%m - minuut\n%s - seconde\n%i - number increasing from 1</string>
|
||||
|
||||
<!-- Copy / Move -->
|
||||
<string name="copy">Kopiëren</string>
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
<string name="simple_renaming">Simple renaming</string>
|
||||
<string name="pattern_renaming">Pattern</string>
|
||||
<string name="string_to_add">String to add</string>
|
||||
<string name="rename_date_time_pattern">%Y - year\n%M - month\n%D - day\n%h - hour\n%m - minute\n%s - second</string>
|
||||
<string name="rename_date_time_pattern">%Y - year\n%M - month\n%D - day\n%h - hour\n%m - minute\n%s - second\n%i - number increasing from 1</string>
|
||||
|
||||
<!-- Copy / Move -->
|
||||
<string name="copy">Kopier</string>
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
<string name="simple_renaming">Simple renaming</string>
|
||||
<string name="pattern_renaming">Pattern</string>
|
||||
<string name="string_to_add">String to add</string>
|
||||
<string name="rename_date_time_pattern">%Y - year\n%M - month\n%D - day\n%h - hour\n%m - minute\n%s - second</string>
|
||||
<string name="rename_date_time_pattern">%Y - year\n%M - month\n%D - day\n%h - hour\n%m - minute\n%s - second\n%i - number increasing from 1</string>
|
||||
|
||||
<!-- Copy / Move -->
|
||||
<string name="copy">Kopiuj</string>
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
<string name="simple_renaming">Simple renaming</string>
|
||||
<string name="pattern_renaming">Pattern</string>
|
||||
<string name="string_to_add">String to add</string>
|
||||
<string name="rename_date_time_pattern">%Y - ano\n%M - mês\n%D - dia\n%h - hora\n%m - minuto\n%s - segundo</string>
|
||||
<string name="rename_date_time_pattern">%Y - ano\n%M - mês\n%D - dia\n%h - hora\n%m - minuto\n%s - segundo\n%i - number increasing from 1</string>
|
||||
|
||||
<!-- Copy / Move -->
|
||||
<string name="copy">Copiar</string>
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
<string name="simple_renaming">Mudar nome</string>
|
||||
<string name="pattern_renaming">Padrão</string>
|
||||
<string name="string_to_add">Texto a adicionar</string>
|
||||
<string name="rename_date_time_pattern">%Y - ano\n%M - mês\n%D - dia\n%h - horas\n%m - minutos\n%s - segundos</string>
|
||||
<string name="rename_date_time_pattern">%Y - ano\n%M - mês\n%D - dia\n%h - horas\n%m - minutos\n%s - segundos\n%i - number increasing from 1</string>
|
||||
|
||||
<!-- Copy / Move -->
|
||||
<string name="copy">Copiar</string>
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
<string name="simple_renaming">Простое переименование</string>
|
||||
<string name="pattern_renaming">Шаблон</string>
|
||||
<string name="string_to_add">Строка для добавления</string>
|
||||
<string name="rename_date_time_pattern">%Y - год\n%M - месяц\n%D - день\n%h - час\n%m - минута\n%s - секунда</string>
|
||||
<string name="rename_date_time_pattern">%Y - год\n%M - месяц\n%D - день\n%h - час\n%m - минута\n%s - секунда\n%i - number increasing from 1</string>
|
||||
|
||||
<!-- Copy / Move -->
|
||||
<string name="copy">Копировать</string>
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
<string name="simple_renaming">Jednoduché premenovanie</string>
|
||||
<string name="pattern_renaming">Vzor</string>
|
||||
<string name="string_to_add">Reťazec na pridanie</string>
|
||||
<string name="rename_date_time_pattern">%Y - rok\n%M - mesiac\n%D - deň\n%h - hodina\n%m - minúta\n%s - sekunda</string>
|
||||
<string name="rename_date_time_pattern">%Y - rok\n%M - mesiac\n%D - deň\n%h - hodina\n%m - minúta\n%s - sekunda\n%i - číslo narastajúce od 1</string>
|
||||
|
||||
<!-- Copy / Move -->
|
||||
<string name="copy">Kopírovať</string>
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
<string name="simple_renaming">Simple renaming</string>
|
||||
<string name="pattern_renaming">Pattern</string>
|
||||
<string name="string_to_add">String to add</string>
|
||||
<string name="rename_date_time_pattern">%Y - year\n%M - month\n%D - day\n%h - hour\n%m - minute\n%s - second</string>
|
||||
<string name="rename_date_time_pattern">%Y - year\n%M - month\n%D - day\n%h - hour\n%m - minute\n%s - second\n%i - number increasing from 1</string>
|
||||
|
||||
<!-- Copy / Move -->
|
||||
<string name="copy">Kopiraj</string>
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
<string name="simple_renaming">Simple renaming</string>
|
||||
<string name="pattern_renaming">Pattern</string>
|
||||
<string name="string_to_add">String to add</string>
|
||||
<string name="rename_date_time_pattern">%Y - year\n%M - month\n%D - day\n%h - hour\n%m - minute\n%s - second</string>
|
||||
<string name="rename_date_time_pattern">%Y - year\n%M - month\n%D - day\n%h - hour\n%m - minute\n%s - second\n%i - number increasing from 1</string>
|
||||
|
||||
<!-- Copy / Move -->
|
||||
<string name="copy">Копирај</string>
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
<string name="simple_renaming">Simple renaming</string>
|
||||
<string name="pattern_renaming">Pattern</string>
|
||||
<string name="string_to_add">String to add</string>
|
||||
<string name="rename_date_time_pattern">%Y - år\n%M - månad\n%D - dag\n%h - timme\n%m - minut\n%s - sekund</string>
|
||||
<string name="rename_date_time_pattern">%Y - år\n%M - månad\n%D - dag\n%h - timme\n%m - minut\n%s - sekund\n%i - number increasing from 1</string>
|
||||
|
||||
<!-- Copy / Move -->
|
||||
<string name="copy">Kopiera</string>
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
<string name="simple_renaming">Basit yeniden adlandırma</string>
|
||||
<string name="pattern_renaming">Desen</string>
|
||||
<string name="string_to_add">Eklenecek dize</string>
|
||||
<string name="rename_date_time_pattern">%Y - yıl\n%M - ay\n%D - gün\n%h - saat\n%m - dakika\n%s - saniye</string>
|
||||
<string name="rename_date_time_pattern">%Y - yıl\n%M - ay\n%D - gün\n%h - saat\n%m - dakika\n%s - saniye\n%i - number increasing from 1</string>
|
||||
|
||||
<!-- Copy / Move -->
|
||||
<string name="copy">Kopyala</string>
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
<string name="simple_renaming">Simple renaming</string>
|
||||
<string name="pattern_renaming">Pattern</string>
|
||||
<string name="string_to_add">String to add</string>
|
||||
<string name="rename_date_time_pattern">%Y - рік\n%M - місяць\n%D - день\n%h - година\n%m - хвилина\n%s - секунда</string>
|
||||
<string name="rename_date_time_pattern">%Y - рік\n%M - місяць\n%D - день\n%h - година\n%m - хвилина\n%s - секунда\n%i - number increasing from 1</string>
|
||||
|
||||
<!-- Copy / Move -->
|
||||
<string name="copy">Копіювати</string>
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
<string name="simple_renaming">简单重命名</string>
|
||||
<string name="pattern_renaming">图案</string>
|
||||
<string name="string_to_add">要添加的字符串</string>
|
||||
<string name="rename_date_time_pattern">%Y - 年\n%M - 月\n%D - 日\n%h - 时\n%m - 分\n%s - 秒</string>
|
||||
<string name="rename_date_time_pattern">%Y - 年\n%M - 月\n%D - 日\n%h - 时\n%m - 分\n%s - 秒\n%i - number increasing from 1</string>
|
||||
|
||||
<!-- Copy / Move -->
|
||||
<string name="copy">复制</string>
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
<string name="simple_renaming">簡易重新命名</string>
|
||||
<string name="pattern_renaming">格式重新命名</string>
|
||||
<string name="string_to_add">添加文字</string>
|
||||
<string name="rename_date_time_pattern">%Y - 年\n%M - 月\n%D - 日\n%h - 小時\n%m - 分鐘\n%s - 秒鐘</string>
|
||||
<string name="rename_date_time_pattern">%Y - 年\n%M - 月\n%D - 日\n%h - 小時\n%m - 分鐘\n%s - 秒鐘\n%i - number increasing from 1</string>
|
||||
|
||||
<!-- Copy / Move -->
|
||||
<string name="copy">複製</string>
|
||||
|
@ -536,8 +536,8 @@
|
|||
<string name="sunday_short">週日</string>
|
||||
|
||||
<!-- Pro version -->
|
||||
<string name="upgrade_to_pro_long">Your app version will not be updated anymore. Please upgrade to the Pro version to receive new fixes and other improvements.</string>
|
||||
<string name="upgrade_to_pro_long_click">Your app version will not be updated anymore. Please upgrade to the Pro version to receive new fixes and other improvements by clicking here.</string>
|
||||
<string name="upgrade_to_pro_long">你的應用程式版本將不再更新。請更新到專業版以獲得新的修復和其他改善。</string>
|
||||
<string name="upgrade_to_pro_long_click">你的應用程式版本將不再更新。請點擊這裡,更新到專業版以獲得新的修復和其他改善。</string>
|
||||
<string name="it_is_free">它在此日期前免費:%s。如果您在到期前下載,將能夠永久免費使用。</string>
|
||||
<string name="more_info">更多資訊</string>
|
||||
<string name="upgrade">升級</string>
|
||||
|
@ -572,7 +572,7 @@
|
|||
<string name="purchase">購買</string>
|
||||
<string name="update_thank_you">請更新[Simple Thank You]至最新版本</string>
|
||||
<string name="before_asking_question_read_faq">在您發問前,請先檢查程式設定及閱讀[常見問題]。或許解決方法就在那裡。</string>
|
||||
<string name="make_sure_latest">Also make sure that you are using the latest app version.</string>
|
||||
<string name="make_sure_latest">並且確保您正使用最新的應用程式版本。</string>
|
||||
<string name="read_it">讀它</string>
|
||||
<string name="rate_us_prompt">哈囉\n\n您似乎已經使用這應用程式一段時間了,我們相當感激。\n\n如果我們能請您幫個忙,請在Google Play上為我們評分。這對我們很有幫助。\n\n無論您的決定如何,都不會再看到這則訊息。\n\n感謝!</string>
|
||||
|
||||
|
@ -613,10 +613,10 @@
|
|||
一旦啟動,只要設回預設的橘色圖標 #F57C00 即可。最糟的情況,你可能必須重新安裝應用程式。</string>
|
||||
<string name="faq_7_title_commons">錢已經從我的銀行帳戶扣除,但我無法下載這應用程式。我能怎麼做?</string>
|
||||
<string name="faq_7_text_commons">支付完全交由Google處理,他們的系統偶爾會發生故障。只要清除您的Google Play應用程式快取並重新啟動裝置,然後再次嘗試下載。</string>
|
||||
<string name="faq_8_title_commons">Why should I upgrade to the Pro version?</string>
|
||||
<string name="faq_8_text_commons">As your app version is no longer updated, the bugs you have maybe spotted will never be fixed. There will also be no new functions added. You can purchase the Pro version on Google Play for a small sum of money.
|
||||
It is a one time payment, which means that once you purchase it, you will never have to pay again. Not even after getting a new device. If you won\'t like the Pro version, you can just uninstall it within a few hours and you will automatically get your money back.
|
||||
If you want a refund anytime later, just contact us at hello@simplemobiletools.com and you will get it.</string>
|
||||
<string name="faq_8_title_commons">為什麼我應該升級到專業版?</string>
|
||||
<string name="faq_8_text_commons">由於你的程式版本不再更新,將永遠不會修復可能遇到的錯誤,也不會再添加新功能。你可以在Google Play上用一小筆錢購買專業版。
|
||||
這是一次性付款。也就是說,一旦你購買了將不必再次付費,即使之後有新裝置也不用。如果你不喜歡專業版,則可以在幾個小時內解除安裝,將自動拿回你的錢。
|
||||
之後如果何時想退款,只要你以 hello@simplemobiletools.com 聯絡我們然後就能獲得退款了。</string>
|
||||
|
||||
<!-- License -->
|
||||
<string name="notice">這程式使用了下列的第三方函式庫來讓我工作簡化。感謝。</string>
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
<string name="simple_renaming">Simple renaming</string>
|
||||
<string name="pattern_renaming">Pattern</string>
|
||||
<string name="string_to_add">String to add</string>
|
||||
<string name="rename_date_time_pattern">%Y - year\n%M - month\n%D - day\n%h - hour\n%m - minute\n%s - second</string>
|
||||
<string name="rename_date_time_pattern">%Y - year\n%M - month\n%D - day\n%h - hour\n%m - minute\n%s - second\n%i - number increasing from 1</string>
|
||||
|
||||
<!-- Copy / Move -->
|
||||
<string name="copy">Copy</string>
|
||||
|
|
Loading…
Reference in a new issue