package ani.dantotsu.util import android.Manifest import android.content.Context import android.content.Intent import android.content.pm.PackageManager import android.net.Uri import android.os.Build import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat import ani.dantotsu.R import ani.dantotsu.settings.saving.PrefManager import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.toast class StoragePermissions { companion object { fun downloadsPermission(activity: AppCompatActivity): Boolean { if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) return true val permissions = arrayOf( Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE ) val requiredPermissions = permissions.filter { ContextCompat.checkSelfPermission(activity, it) != PackageManager.PERMISSION_GRANTED }.toTypedArray() return if (requiredPermissions.isNotEmpty()) { ActivityCompat.requestPermissions( activity, requiredPermissions, DOWNLOADS_PERMISSION_REQUEST_CODE ) false } else { true } } fun hasDirAccess(context: Context, path: String): Boolean { val uri = pathToUri(path) return context.contentResolver.persistedUriPermissions.any { it.uri == uri && it.isReadPermission && it.isWritePermission } } fun hasDirAccess(context: Context, uri: Uri): Boolean { return context.contentResolver.persistedUriPermissions.any { it.uri == uri && it.isReadPermission && it.isWritePermission } } fun hasDirAccess(context: Context): Boolean { val path = PrefManager.getVal(PrefName.DownloadsDir) return hasDirAccess(context, path) } fun AppCompatActivity.accessAlertDialog(launcher: LauncherWrapper, force: Boolean = false, complete: (Boolean) -> Unit ) { if ((PrefManager.getVal(PrefName.DownloadsDir).isNotEmpty() || hasDirAccess(this)) && !force) { complete(true) return } val builder = AlertDialog.Builder(this, R.style.MyPopup) builder.setTitle(getString(R.string.dir_access)) builder.setMessage(getString(R.string.dir_access_msg)) builder.setPositiveButton(getString(R.string.ok)) { dialog, _ -> launcher.registerForCallback(complete) launcher.launch() dialog.dismiss() } builder.setNegativeButton(getString(R.string.cancel)) { dialog, _ -> dialog.dismiss() complete(false) } val dialog = builder.show() dialog.window?.setDimAmount(0.8f) } private fun pathToUri(path: String): Uri { return Uri.parse(path) } private const val DOWNLOADS_PERMISSION_REQUEST_CODE = 100 } } class LauncherWrapper( activity: AppCompatActivity, contract: ActivityResultContracts.OpenDocumentTree) { private var launcher: ActivityResultLauncher var complete: (Boolean) -> Unit = {} init{ launcher = activity.registerForActivityResult(contract) { uri -> if (uri != null) { activity.contentResolver.takePersistableUriPermission( uri, Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION ) if (StoragePermissions.hasDirAccess(activity, uri)) { PrefManager.setVal(PrefName.DownloadsDir, uri.toString()) complete(true) } else { toast(activity.getString(R.string.dir_error)) complete(false) } } else { toast(activity.getString(R.string.dir_error)) complete(false) } } } fun registerForCallback(callback: (Boolean) -> Unit) { complete = callback } fun launch() { launcher.launch(null) } }