Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ android {
}

buildTypes {
debug {
isMinifyEnabled = false
versionNameSuffix = " | Debug"
applicationIdSuffix = ".debug"
}
release {
isMinifyEnabled = true
proguardFiles(
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@

<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.raival.compose.file.explorer.provider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.raival.compose.file.explorer.common

import android.content.Context
import android.media.MediaScannerConnection
import java.io.File

object MediaStoreUtils {
/**
* Notifies the MediaStore that one or more files have changed.
*
* @param context Context to use (applicationContext recommended)
* @param files List of files to notify
* @param mimeTypes Optional MIME types (should be same length as files array, or null)
*/
@JvmOverloads
fun notifyFileChanged(
context: Context,
files: List<File>,
mimeTypes: List<String?>? = null
) {
MediaScannerConnection.scanFile(
context,
files.map { it.absolutePath }.toTypedArray(),
mimeTypes?.toTypedArray(),
null
)
}

/**
* Notifies the MediaStore that a single file has changed.
*
* @param context Context to use (applicationContext recommended)
* @param file The file that has changed.
* @param mimeType Optional MIME type of the file.
*/
@JvmOverloads
fun notifyFileChanged(
context: Context,
file: File,
mimeType: String? = null
) {
notifyFileChanged(context, listOf(file), mimeTypes = mimeType?.let { listOf(it) })
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.raival.compose.file.explorer.screen.main.tab.files.task
import com.raival.compose.file.explorer.App.Companion.globalClass
import com.raival.compose.file.explorer.App.Companion.logger
import com.raival.compose.file.explorer.R
import com.raival.compose.file.explorer.common.MediaStoreUtils
import com.raival.compose.file.explorer.common.emptyString
import com.raival.compose.file.explorer.common.isNot
import com.raival.compose.file.explorer.common.listFilesAndEmptyDirs
Expand All @@ -27,10 +28,15 @@ class CopyTask(
val sourceFiles: List<ContentHolder>,
val deleteSourceFiles: Boolean
) : Task() {
private val context = globalClass.applicationContext

private var parameters: CopyTaskParameters? = null
private val pendingFiles: ArrayList<TaskContentItem> = arrayListOf()
private var canPerformAtomicFileMove = true

private val modifiedFiles = mutableListOf<File>()
private val deletedFiles = mutableListOf<File>()

override val metadata = createTaskMetadata()
override val progressMonitor = TaskProgressMonitor(
status = TaskStatus.PENDING,
Expand Down Expand Up @@ -220,6 +226,8 @@ class CopyTask(
append("\n")
}
}

notifyMediaStoreChanges()
}
}

Expand Down Expand Up @@ -313,7 +321,9 @@ class CopyTask(
progress = (index + 1f) / successfulItems.size
}

(item.content as LocalFileHolder).file.deleteRecursively()
val file = (item.content as LocalFileHolder).file
trackFileDeletion(file)
file.deleteRecursively()
}

// Clean up empty directories
Expand Down Expand Up @@ -464,6 +474,7 @@ class CopyTask(
} else {
source.copyTo(destination, overwrite)
}
trackFileModification(destination)
} else {
destination.mkdirs() || destination.exists()
}
Expand Down Expand Up @@ -649,6 +660,7 @@ class CopyTask(
input.copyTo(output)
}
}
trackFileModification(destinationFile)
} else {
destinationFile.mkdirs()
}
Expand Down Expand Up @@ -816,4 +828,17 @@ class CopyTask(
else -> emptyList()
}
}

private fun trackFileModification(file: File) {
if (!modifiedFiles.contains(file)) modifiedFiles.add(file)
}

private fun trackFileDeletion(file: File) {
if (!deletedFiles.contains(file)) deletedFiles.add(file)
}

private fun notifyMediaStoreChanges() {
if (modifiedFiles.isNotEmpty()) MediaStoreUtils.notifyFileChanged(context, modifiedFiles)
if (deletedFiles.isNotEmpty()) MediaStoreUtils.notifyFileChanged(context, deletedFiles)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.raival.compose.file.explorer.screen.main.tab.files.task
import com.raival.compose.file.explorer.App.Companion.globalClass
import com.raival.compose.file.explorer.App.Companion.logger
import com.raival.compose.file.explorer.R
import com.raival.compose.file.explorer.common.MediaStoreUtils
import com.raival.compose.file.explorer.common.emptyString
import com.raival.compose.file.explorer.common.toFormattedDate
import com.raival.compose.file.explorer.screen.main.tab.files.holder.ContentHolder
Expand All @@ -19,9 +20,13 @@ import java.util.zip.ZipOutputStream
class DeleteTask(
val sourceContent: List<ContentHolder>
) : Task() {
private val context = globalClass.applicationContext

private var parameters: DeleteTaskParameters? = null
private var pendingContent = arrayListOf<DeleteContentItem>()

private val deletedFiles = mutableListOf<File>()

override val metadata = System.currentTimeMillis().toFormattedDate().let { time ->
TaskMetadata(
id = id,
Expand Down Expand Up @@ -174,6 +179,7 @@ class DeleteTask(

try {
val localFile = itemToDelete.source as LocalFileHolder
trackFileDeletion(localFile.file)
if (localFile.file.deleteRecursively()) {
itemToDelete.status = TaskContentStatus.SUCCESS
} else {
Expand All @@ -191,6 +197,8 @@ class DeleteTask(
}
}
}

notifyMediaStoreChanges()
}

private suspend fun handleZipFileDeletion() {
Expand Down Expand Up @@ -360,4 +368,12 @@ class DeleteTask(
val source: ContentHolder,
var status: TaskContentStatus
)

private fun trackFileDeletion(file: File) {
if (!deletedFiles.contains(file)) deletedFiles.add(file)
}

private fun notifyMediaStoreChanges() {
if (deletedFiles.isNotEmpty()) MediaStoreUtils.notifyFileChanged(context, deletedFiles)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.raival.compose.file.explorer.screen.main.tab.files.task
import com.raival.compose.file.explorer.App.Companion.globalClass
import com.raival.compose.file.explorer.App.Companion.logger
import com.raival.compose.file.explorer.R
import com.raival.compose.file.explorer.common.MediaStoreUtils
import com.raival.compose.file.explorer.common.emptyString
import com.raival.compose.file.explorer.common.toFormattedDate
import com.raival.compose.file.explorer.screen.main.tab.files.holder.ContentHolder
Expand All @@ -20,9 +21,13 @@ import java.util.zip.ZipFile
import java.util.zip.ZipOutputStream

class RenameTask(val sourceContent: List<ContentHolder>) : Task() {
private val context = globalClass.applicationContext

private var parameters: RenameTaskParameters? = null
private var pendingContent = arrayListOf<RenameContentItem>()

private val modifiedFiles = mutableListOf<File>()

override val metadata = System.currentTimeMillis().toFormattedDate().let { time ->
TaskMetadata(
id = id,
Expand Down Expand Up @@ -171,6 +176,8 @@ class RenameTask(val sourceContent: List<ContentHolder>) : Task() {
}

if (progressMonitor.status == TaskStatus.RUNNING) {
if (sampleContent is LocalFileHolder) notifyMediaStoreChanges()

progressMonitor.apply {
status = TaskStatus.SUCCESS
progress = 1.0f
Expand Down Expand Up @@ -201,6 +208,7 @@ class RenameTask(val sourceContent: List<ContentHolder>) : Task() {
val newFile = File(itemToRename.newPath)

if (localFile.file.renameTo(newFile)) {
trackFileModification(localFile.file, newFile)
itemToRename.status = TaskContentStatus.SUCCESS
} else {
throw Exception(globalClass.getString(R.string.failed_to_rename_file))
Expand All @@ -217,6 +225,8 @@ class RenameTask(val sourceContent: List<ContentHolder>) : Task() {
}
}
}

notifyMediaStoreChanges()
}

private suspend fun handleZipFileRenaming() {
Expand Down Expand Up @@ -502,4 +512,13 @@ class RenameTask(val sourceContent: List<ContentHolder>) : Task() {
val newPath: String,
var status: TaskContentStatus
)

private fun trackFileModification(oldFile: File, newFile: File) {
if (!modifiedFiles.contains(oldFile)) modifiedFiles.add(oldFile)
if (!modifiedFiles.contains(newFile)) modifiedFiles.add(newFile)
}

private fun notifyMediaStoreChanges() {
if (modifiedFiles.isNotEmpty()) MediaStoreUtils.notifyFileChanged(context, modifiedFiles)
}
}