✨
This commit is contained in:
@@ -59,6 +59,19 @@
|
||||
<activity
|
||||
android:name=".activities.PreviewActivity"
|
||||
android:configChanges="orientation|screenSize"/>
|
||||
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="devs.org.calculator.fileprovider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/file_paths" />
|
||||
</provider>
|
||||
|
||||
|
||||
</application>
|
||||
|
||||
|
||||
</manifest>
|
||||
@@ -73,7 +73,7 @@ class PreviewActivity : AppCompatActivity() {
|
||||
|
||||
private fun clickListeners() {
|
||||
binding.delete.setOnClickListener {
|
||||
val fileUri = FileManager.FileManager().getContentUri(this, files[binding.viewPager.currentItem], filetype)
|
||||
val fileUri = FileManager.FileManager().getContentUriImage(this, files[binding.viewPager.currentItem], filetype)
|
||||
if (fileUri != null) {
|
||||
MaterialAlertDialogBuilder(this)
|
||||
.setTitle("Delete File")
|
||||
@@ -93,7 +93,7 @@ class PreviewActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
binding.unHide.setOnClickListener {
|
||||
val fileUri = FileManager.FileManager().getContentUri(this, files[binding.viewPager.currentItem], filetype)
|
||||
val fileUri = FileManager.FileManager().getContentUriImage(this, files[binding.viewPager.currentItem], filetype)
|
||||
if (fileUri != null) {
|
||||
MaterialAlertDialogBuilder(this)
|
||||
.setTitle("Unhide File")
|
||||
|
||||
@@ -2,7 +2,6 @@ package devs.org.calculator.adapters
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
@@ -16,19 +15,21 @@ import androidx.recyclerview.widget.RecyclerView
|
||||
import com.bumptech.glide.Glide
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import devs.org.calculator.R
|
||||
import devs.org.calculator.activities.BaseGalleryActivity
|
||||
import devs.org.calculator.activities.PreviewActivity
|
||||
import devs.org.calculator.utils.DialogUtil
|
||||
import devs.org.calculator.utils.FileManager
|
||||
import kotlinx.coroutines.launch
|
||||
import java.io.File
|
||||
import kotlin.collections.remove
|
||||
|
||||
class FileAdapter(private val fileType: FileManager.FileType, var context: Context, private var lifecycleOwner: LifecycleOwner) :
|
||||
class FileAdapter(
|
||||
private val fileType: FileManager.FileType,
|
||||
var context: Context,
|
||||
private var lifecycleOwner: LifecycleOwner
|
||||
) :
|
||||
ListAdapter<File, FileAdapter.FileViewHolder>(FileDiffCallback()) {
|
||||
|
||||
private val selectedItems = mutableSetOf<Int>()
|
||||
private var isSelectionMode = false
|
||||
private var fileName = "Unknown File"
|
||||
|
||||
inner class FileViewHolder(view: View) : RecyclerView.ViewHolder(view) {
|
||||
private val imageView: ImageView = view.findViewById(R.id.imageView)
|
||||
@@ -42,6 +43,7 @@ class FileAdapter(private val fileType: FileManager.FileType, var context: Conte
|
||||
.centerCrop()
|
||||
.into(imageView)
|
||||
}
|
||||
|
||||
FileManager.FileType.VIDEO -> {
|
||||
Glide.with(imageView)
|
||||
.asBitmap()
|
||||
@@ -49,6 +51,7 @@ class FileAdapter(private val fileType: FileManager.FileType, var context: Conte
|
||||
.centerCrop()
|
||||
.into(imageView)
|
||||
}
|
||||
|
||||
else -> {
|
||||
val resourceId = when (fileType) {
|
||||
FileManager.FileType.AUDIO -> R.drawable.ic_audio
|
||||
@@ -61,17 +64,20 @@ class FileAdapter(private val fileType: FileManager.FileType, var context: Conte
|
||||
itemView.setOnClickListener {
|
||||
|
||||
|
||||
var fileTypes = when(fileType){
|
||||
var fileTypes = when (fileType) {
|
||||
|
||||
FileManager.FileType.IMAGE -> {
|
||||
"IMAGE"
|
||||
}
|
||||
|
||||
FileManager.FileType.VIDEO -> {
|
||||
"VIDEO"
|
||||
}
|
||||
|
||||
FileManager.FileType.AUDIO -> {
|
||||
"AUDIO"
|
||||
}
|
||||
|
||||
else -> "DOCUMENT"
|
||||
|
||||
}
|
||||
@@ -83,20 +89,27 @@ class FileAdapter(private val fileType: FileManager.FileType, var context: Conte
|
||||
|
||||
}
|
||||
itemView.setOnLongClickListener {
|
||||
val fileUri = FileManager.FileManager().getContentUri(context, file, fileType)
|
||||
if (fileUri == null) {
|
||||
Toast.makeText(context, "Unable to access file: $file", Toast.LENGTH_SHORT).show()
|
||||
return@setOnLongClickListener true
|
||||
}
|
||||
|
||||
val fileName = FileManager.FileName(context).getFileNameFromUri(fileUri)?.toString() ?: "Unknown File"
|
||||
val fileUri = FileManager.FileManager().getContentUriImage(context, file, fileType)
|
||||
if (fileUri == null) {
|
||||
Toast.makeText(context, "Unable to access file: $file", Toast.LENGTH_SHORT)
|
||||
.show()
|
||||
|
||||
return@setOnLongClickListener true
|
||||
|
||||
}
|
||||
fileName = FileManager.FileName(context).getFileNameFromUri(fileUri)?.toString()
|
||||
?: "Unknown File"
|
||||
|
||||
|
||||
MaterialAlertDialogBuilder(context)
|
||||
.setTitle("Details")
|
||||
.setMessage("File Name: $fileName\n\nYou can delete or unhide this file.")
|
||||
.setMessage("File Name: $fileName\n\nFile Path: $file\n\nYou can delete or unhide this file.")
|
||||
.setPositiveButton("Delete") { dialog, _ ->
|
||||
lifecycleOwner.lifecycleScope.launch {
|
||||
FileManager(context, lifecycleOwner).deletePhotoFromExternalStorage(fileUri)
|
||||
FileManager(context, lifecycleOwner).deletePhotoFromExternalStorage(
|
||||
fileUri
|
||||
)
|
||||
}
|
||||
val currentList = currentList.toMutableList()
|
||||
currentList.remove(file)
|
||||
|
||||
@@ -24,6 +24,7 @@ import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.io.File
|
||||
import android.Manifest
|
||||
import androidx.core.content.FileProvider
|
||||
|
||||
class FileManager(private val context: Context, private val lifecycleOwner: LifecycleOwner) {
|
||||
private lateinit var intentSenderLauncher: ActivityResultLauncher<IntentSenderRequest>
|
||||
@@ -224,9 +225,9 @@ class FileManager(private val context: Context, private val lifecycleOwner: Life
|
||||
|
||||
}
|
||||
class FileManager(){
|
||||
fun getContentUri(context: Context, file: File, fileType: FileType): Uri? {
|
||||
when(fileType){
|
||||
FileType.IMAGE -> {
|
||||
fun getContentUriImage(context: Context, file: File, fileType: FileType): Uri? {
|
||||
|
||||
// Query MediaStore for the file
|
||||
val projection = arrayOf(MediaStore.MediaColumns._ID)
|
||||
val selection = "${MediaStore.MediaColumns.DATA} = ?"
|
||||
val selectionArgs = arrayOf(file.absolutePath)
|
||||
@@ -238,55 +239,15 @@ class FileManager(private val context: Context, private val lifecycleOwner: Life
|
||||
return Uri.withAppendedPath(queryUri, id.toString())
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
FileType.VIDEO -> {
|
||||
val projection = arrayOf(MediaStore.Video.Media._ID)
|
||||
val selection = "${MediaStore.Video.Media.DATA} = ?"
|
||||
val selectionArgs = arrayOf(file.absolutePath)
|
||||
val queryUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI
|
||||
|
||||
context.contentResolver.query(queryUri, projection, selection, selectionArgs, null)?.use { cursor ->
|
||||
if (cursor.moveToFirst()) {
|
||||
val id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID))
|
||||
return Uri.withAppendedPath(queryUri, id.toString())
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
FileType.AUDIO -> {
|
||||
val projection = arrayOf(MediaStore.Audio.Media._ID)
|
||||
val selection = "${MediaStore.Audio.Media.DATA} = ?"
|
||||
val selectionArgs = arrayOf(file.absolutePath)
|
||||
val queryUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
|
||||
|
||||
context.contentResolver.query(queryUri, projection, selection, selectionArgs, null)?.use { cursor ->
|
||||
if (cursor.moveToFirst()) {
|
||||
val id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media._ID))
|
||||
return Uri.withAppendedPath(queryUri, id.toString())
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
FileType.DOCUMENT -> {
|
||||
val projection = arrayOf(MediaStore.Files.FileColumns._ID)
|
||||
val selection = "${MediaStore.Files.FileColumns.DATA} = ?"
|
||||
val selectionArgs = arrayOf(file.absolutePath)
|
||||
val queryUri = MediaStore.Files.getContentUri("external")
|
||||
|
||||
context.contentResolver.query(queryUri, projection, selection, selectionArgs, null)?.use { cursor ->
|
||||
if (cursor.moveToFirst()) {
|
||||
val id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns._ID))
|
||||
return Uri.withAppendedPath(queryUri, id.toString())
|
||||
// If the file is not found in MediaStore, fallback to FileProvider for hidden files
|
||||
return if (file.exists()) {
|
||||
FileProvider.getUriForFile(context, "devs.org.calculator.fileprovider", file)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
8
app/src/main/res/xml/file_paths.xml
Normal file
8
app/src/main/res/xml/file_paths.xml
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<paths xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- Allow access to external files -->
|
||||
<external-path name="external_files" path="." />
|
||||
<!-- Allow access to hidden directories -->
|
||||
<external-files-path name="hidden_files" path=".CalculatorHide/" />
|
||||
</paths>
|
||||
|
||||
Reference in New Issue
Block a user