diff --git a/commons/src/main/kotlin/org/fossify/commons/activities/BaseSimpleActivity.kt b/commons/src/main/kotlin/org/fossify/commons/activities/BaseSimpleActivity.kt index 53eb0b571..c1906678e 100644 --- a/commons/src/main/kotlin/org/fossify/commons/activities/BaseSimpleActivity.kt +++ b/commons/src/main/kotlin/org/fossify/commons/activities/BaseSimpleActivity.kt @@ -36,9 +36,12 @@ import androidx.appcompat.widget.Toolbar import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.core.animation.doOnEnd import androidx.core.app.ActivityCompat +import androidx.core.net.toUri import androidx.core.util.Pair import androidx.core.view.ScrollingView import androidx.core.view.WindowInsetsCompat +import androidx.core.view.get +import androidx.core.view.size import androidx.core.widget.NestedScrollView import androidx.recyclerview.widget.RecyclerView import org.fossify.commons.R @@ -104,7 +107,12 @@ abstract class BaseSimpleActivity : AppCompatActivity() { if (!packageName.startsWith("org.fossify.", true)) { if ((0..50).random() == 10 || baseConfig.appRunCount % 100 == 0) { val label = "You are using a fake version of the app. For your own safety download the original one from www.fossify.org. Thanks" - ConfirmationDialog(this, label, positive = R.string.ok, negative = 0) { + ConfirmationDialog( + activity = this, + message = label, + positive = R.string.ok, + negative = 0 + ) { launchViewIntent(DEVELOPER_PLAY_STORE_URL) } } @@ -311,9 +319,9 @@ abstract class BaseSimpleActivity : AppCompatActivity() { toolbar.overflowIcon = resources.getColoredDrawableWithColor(R.drawable.ic_three_dots_vector, contrastColor) val menu = toolbar.menu - for (i in 0 until menu.size()) { + for (i in 0 until menu.size) { try { - menu.getItem(i)?.icon?.setTint(contrastColor) + menu[i].icon?.setTint(contrastColor) } catch (ignored: Exception) { } } @@ -392,7 +400,11 @@ abstract class BaseSimpleActivity : AppCompatActivity() { } } - fun updateMenuItemColors(menu: Menu?, baseColor: Int = getProperStatusBarColor(), forceWhiteIcons: Boolean = false) { + fun updateMenuItemColors( + menu: Menu?, + baseColor: Int = getProperStatusBarColor(), + forceWhiteIcons: Boolean = false + ) { if (menu == null) { return } @@ -402,9 +414,9 @@ abstract class BaseSimpleActivity : AppCompatActivity() { color = Color.WHITE } - for (i in 0 until menu.size()) { + for (i in 0 until menu.size) { try { - menu.getItem(i)?.icon?.setTint(color) + menu[i].icon?.setTint(color) } catch (ignored: Exception) { } } @@ -639,7 +651,12 @@ abstract class BaseSimpleActivity : AppCompatActivity() { if (!packageName.contains("yfissof".reversed(), true)) { if (baseConfig.appRunCount > 100) { val label = "You are using a fake version of the app. For your own safety download the original one from www.fossify.org. Thanks" - ConfirmationDialog(this, label, positive = R.string.ok, negative = 0) { + ConfirmationDialog( + activity = this, + message = label, + positive = R.string.ok, + negative = 0 + ) { launchViewIntent(DEVELOPER_PLAY_STORE_URL) } return @@ -793,7 +810,11 @@ abstract class BaseSimpleActivity : AppCompatActivity() { } @SuppressLint("NewApi") - fun trashSDK30Uris(uris: List, toTrash: Boolean, callback: (success: Boolean) -> Unit) { + fun trashSDK30Uris( + uris: List, + toTrash: Boolean, + callback: (success: Boolean) -> Unit + ) { hideKeyboard() if (isRPlus()) { funAfterTrash30File = callback @@ -809,7 +830,10 @@ abstract class BaseSimpleActivity : AppCompatActivity() { } @SuppressLint("NewApi") - fun updateSDK30Uris(uris: List, callback: (success: Boolean) -> Unit) { + fun updateSDK30Uris( + uris: List, + callback: (success: Boolean) -> Unit + ) { hideKeyboard() if (isRPlus()) { funAfterUpdate30File = callback @@ -843,7 +867,7 @@ abstract class BaseSimpleActivity : AppCompatActivity() { @RequiresApi(Build.VERSION_CODES.S) fun launchMediaManagementIntent(callback: () -> Unit) { Intent(Settings.ACTION_REQUEST_MANAGE_MEDIA).apply { - data = Uri.parse("package:$packageName") + data = "package:$packageName".toUri() try { startActivityForResult(this, MANAGE_MEDIA_RC) } catch (e: Exception) { @@ -854,8 +878,13 @@ abstract class BaseSimpleActivity : AppCompatActivity() { } fun copyMoveFilesTo( - fileDirItems: ArrayList, source: String, destination: String, isCopyOperation: Boolean, copyPhotoVideoOnly: Boolean, - copyHidden: Boolean, callback: (destinationPath: String) -> Unit, + fileDirItems: ArrayList, + source: String, + destination: String, + isCopyOperation: Boolean, + copyPhotoVideoOnly: Boolean, + copyHidden: Boolean, + callback: (destinationPath: String) -> Unit, ) { if (source == destination) { toast(R.string.source_and_destination_same) @@ -960,6 +989,7 @@ abstract class BaseSimpleActivity : AppCompatActivity() { } } + @SuppressLint("DefaultLocale") fun getAlternativeFile(file: File): File { var fileIndex = 1 var newFile: File? @@ -986,9 +1016,19 @@ abstract class BaseSimpleActivity : AppCompatActivity() { val pair = Pair(files, destinationPath) handleNotificationPermission { granted -> if (granted) { - CopyMoveTask(this, isCopyOperation, copyPhotoVideoOnly, it, copyMoveListener, copyHidden).execute(pair) + CopyMoveTask( + activity = this, + copyOnly = isCopyOperation, + copyMediaOnly = copyPhotoVideoOnly, + conflictResolutions = it, + listener = copyMoveListener, + copyHidden = copyHidden + ).execute(pair) } else { - PermissionRequiredDialog(this, R.string.allow_notifications_files, { openNotificationSettings() }) + PermissionRequiredDialog( + activity = this, + textId = R.string.allow_notifications_files, + positiveActionCallback = { openNotificationSettings() }) } } } @@ -999,7 +1039,10 @@ abstract class BaseSimpleActivity : AppCompatActivity() { } fun checkConflicts( - files: ArrayList, destinationPath: String, index: Int, conflictResolutions: LinkedHashMap, + files: ArrayList, + destinationPath: String, + index: Int, + conflictResolutions: LinkedHashMap, callback: (resolutions: LinkedHashMap) -> Unit, ) { if (index == files.size) { @@ -1012,26 +1055,51 @@ abstract class BaseSimpleActivity : AppCompatActivity() { ensureBackgroundThread { if (getDoesFilePathExist(newFileDirItem.path)) { runOnUiThread { - FileConflictDialog(this, newFileDirItem, files.size > 1) { resolution, applyForAll -> + FileConflictDialog( + activity = this, + fileDirItem = newFileDirItem, + showApplyToAllCheckbox = files.size > 1 + ) { resolution, applyForAll -> if (applyForAll) { conflictResolutions.clear() conflictResolutions[""] = resolution - checkConflicts(files, destinationPath, files.size, conflictResolutions, callback) + checkConflicts( + files = files, + destinationPath = destinationPath, + index = files.size, + conflictResolutions = conflictResolutions, + callback = callback + ) } else { conflictResolutions[newFileDirItem.path] = resolution - checkConflicts(files, destinationPath, index + 1, conflictResolutions, callback) + checkConflicts( + files = files, + destinationPath = destinationPath, + index = index + 1, + conflictResolutions = conflictResolutions, + callback = callback + ) } } } } else { runOnUiThread { - checkConflicts(files, destinationPath, index + 1, conflictResolutions, callback) + checkConflicts( + files = files, + destinationPath = destinationPath, + index = index + 1, + conflictResolutions = conflictResolutions, + callback = callback + ) } } } } - fun handlePermission(permissionId: Int, callback: (granted: Boolean) -> Unit) { + fun handlePermission( + permissionId: Int, + callback: (granted: Boolean) -> Unit + ) { actionOnPermission = null if (hasPermission(permissionId)) { callback(true) @@ -1042,7 +1110,11 @@ abstract class BaseSimpleActivity : AppCompatActivity() { } } - fun handlePartialMediaPermissions(permissionIds: Collection, force: Boolean = false, callback: (granted: Boolean) -> Unit) { + fun handlePartialMediaPermissions( + permissionIds: Collection, + force: Boolean = false, + callback: (granted: Boolean) -> Unit + ) { actionOnPermission = null if (isUpsideDownCakePlus()) { if (hasPermission(PERMISSION_READ_MEDIA_VISUAL_USER_SELECTED) && !force) { @@ -1073,7 +1145,11 @@ abstract class BaseSimpleActivity : AppCompatActivity() { } } - override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) isAskingPermissions = false if (requestCode == GENERIC_PERM_HANDLER && grantResults.isNotEmpty()) { @@ -1082,7 +1158,12 @@ abstract class BaseSimpleActivity : AppCompatActivity() { } val copyMoveListener = object : CopyMoveListener { - override fun copySucceeded(copyOnly: Boolean, copiedAll: Boolean, destinationPath: String, wasCopyingOneFileOnly: Boolean) { + override fun copySucceeded( + copyOnly: Boolean, + copiedAll: Boolean, + destinationPath: String, + wasCopyingOneFileOnly: Boolean + ) { if (copyOnly) { toast( if (copiedAll) { @@ -1122,43 +1203,43 @@ abstract class BaseSimpleActivity : AppCompatActivity() { fun checkAppOnSDCard() { if (!baseConfig.wasAppOnSDShown && isAppInstalledOnSDCard()) { baseConfig.wasAppOnSDShown = true - ConfirmationDialog(this, "", R.string.app_on_sd_card, R.string.ok, 0) {} + ConfirmationDialog( + activity = this, + message = "", + messageId = R.string.app_on_sd_card, + positive = R.string.ok, + negative = 0 + ) {} } } fun exportSettings(configItems: LinkedHashMap) { - if (isQPlus()) { - configItemsToExport = configItems - ExportSettingsDialog(this, getExportSettingsFilename(), true) { path, filename -> - Intent(Intent.ACTION_CREATE_DOCUMENT).apply { - type = "text/plain" - putExtra(Intent.EXTRA_TITLE, filename) - addCategory(Intent.CATEGORY_OPENABLE) + configItemsToExport = configItems + ExportSettingsDialog( + activity = this, + defaultFilename = getExportSettingsFilename(), + hidePath = true + ) { path, filename -> + Intent(Intent.ACTION_CREATE_DOCUMENT).apply { + type = "text/plain" + putExtra(Intent.EXTRA_TITLE, filename) + addCategory(Intent.CATEGORY_OPENABLE) - try { - startActivityForResult(this, SELECT_EXPORT_SETTINGS_FILE_INTENT) - } catch (e: ActivityNotFoundException) { - toast(R.string.system_service_disabled, Toast.LENGTH_LONG) - } catch (e: Exception) { - showErrorToast(e) - } - } - } - } else { - handlePermission(PERMISSION_WRITE_STORAGE) { - if (it) { - ExportSettingsDialog(this, getExportSettingsFilename(), false) { path, filename -> - val file = File(path) - getFileOutputStream(file.toFileDirItem(this), true) { - exportSettingsTo(it, configItems) - } - } + try { + startActivityForResult(this, SELECT_EXPORT_SETTINGS_FILE_INTENT) + } catch (e: ActivityNotFoundException) { + toast(R.string.system_service_disabled, Toast.LENGTH_LONG) + } catch (e: Exception) { + showErrorToast(e) } } } } - private fun exportSettingsTo(outputStream: OutputStream?, configItems: LinkedHashMap) { + private fun exportSettingsTo( + outputStream: OutputStream?, + configItems: LinkedHashMap + ) { if (outputStream == null) { toast(R.string.unknown_error_occurred) return diff --git a/commons/src/main/kotlin/org/fossify/commons/activities/ManageBlockedNumbersActivity.kt b/commons/src/main/kotlin/org/fossify/commons/activities/ManageBlockedNumbersActivity.kt index 6bfa44e84..5f29f9eda 100644 --- a/commons/src/main/kotlin/org/fossify/commons/activities/ManageBlockedNumbersActivity.kt +++ b/commons/src/main/kotlin/org/fossify/commons/activities/ManageBlockedNumbersActivity.kt @@ -1,6 +1,5 @@ package org.fossify.commons.activities -import android.app.Activity import android.app.Application import android.content.ActivityNotFoundException import android.content.Intent @@ -8,6 +7,7 @@ import android.net.Uri import android.os.Bundle import android.widget.Toast import androidx.activity.compose.setContent +import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.viewModels import androidx.compose.runtime.* import androidx.compose.ui.platform.LocalContext @@ -30,7 +30,6 @@ import org.fossify.commons.compose.screens.ManageBlockedNumbersScreen import org.fossify.commons.compose.theme.AppThemeSurface import org.fossify.commons.dialogs.AddOrEditBlockedNumberAlertDialog import org.fossify.commons.dialogs.ExportBlockedNumbersDialog -import org.fossify.commons.dialogs.FilePickerDialog import org.fossify.commons.extensions.* import org.fossify.commons.helpers.* import org.fossify.commons.models.BlockedNumber @@ -39,13 +38,30 @@ import java.io.OutputStream class ManageBlockedNumbersActivity : BaseSimpleActivity() { - private val config by lazy { - baseConfig + private val config by lazy { baseConfig } + + private val blockedNumberMimeTypes = buildList { + add("text/plain") + if (!isQPlus()) { + add("application/octet-stream") + } + }.toTypedArray() + + private val openDocument = registerForActivityResult( + ActivityResultContracts.OpenDocument() + ) { uri -> + if (uri != null) { + tryImportBlockedNumbersFromFile(uri) + } } - private companion object { - private const val PICK_IMPORT_SOURCE_INTENT = 11 - private const val PICK_EXPORT_FILE_INTENT = 21 + private val createDocument = registerForActivityResult( + ActivityResultContracts.CreateDocument("text/plain") + ) { uri -> + if (uri != null) { + val outputStream = contentResolver.openOutputStream(uri) + exportBlockedNumbersTo(outputStream) + } } override fun getAppIconIDs() = intent.getIntegerArrayListExtra(APP_ICON_IDS) ?: ArrayList() @@ -147,31 +163,12 @@ class ManageBlockedNumbersActivity : BaseSimpleActivity() { } private fun tryImportBlockedNumbers() { - if (isQPlus()) { - Intent(Intent.ACTION_GET_CONTENT).apply { - addCategory(Intent.CATEGORY_OPENABLE) - type = "text/plain" - - try { - startActivityForResult(this, PICK_IMPORT_SOURCE_INTENT) - } catch (e: ActivityNotFoundException) { - toast(R.string.system_service_disabled, Toast.LENGTH_LONG) - } catch (e: Exception) { - showErrorToast(e) - } - } - } else { - handlePermission(PERMISSION_READ_STORAGE) { isAllowed -> - if (isAllowed) { - pickFileToImportBlockedNumbers() - } - } - } - } - - private fun pickFileToImportBlockedNumbers() { - FilePickerDialog(this) { - importBlockedNumbers(it) + try { + openDocument.launch(blockedNumberMimeTypes) + } catch (_: ActivityNotFoundException) { + toast(R.string.system_service_disabled, Toast.LENGTH_LONG) + } catch (e: Exception) { + showErrorToast(e) } } @@ -235,20 +232,10 @@ class ManageBlockedNumbersActivity : BaseSimpleActivity() { updateBlockedNumbers() } - requestCode == PICK_IMPORT_SOURCE_INTENT && resultCode == Activity.RESULT_OK && resultData != null && resultData.data != null -> { - tryImportBlockedNumbersFromFile(resultData.data!!) - } - - requestCode == PICK_EXPORT_FILE_INTENT && resultCode == Activity.RESULT_OK && resultData != null && resultData.data != null -> { - val outputStream = contentResolver.openOutputStream(resultData.data!!) - exportBlockedNumbersTo(outputStream) - } - - requestCode == REQUEST_CODE_SET_DEFAULT_CALLER_ID && resultCode != Activity.RESULT_OK -> { + requestCode == REQUEST_CODE_SET_DEFAULT_CALLER_ID && resultCode != RESULT_OK -> { toast(R.string.must_make_default_caller_id_app, length = Toast.LENGTH_LONG) baseConfig.blockUnknownNumbers = false baseConfig.blockHiddenNumbers = false - } } } @@ -272,31 +259,17 @@ class ManageBlockedNumbersActivity : BaseSimpleActivity() { } private fun tryExportBlockedNumbers() { - if (isQPlus()) { - ExportBlockedNumbersDialog(this, baseConfig.lastBlockedNumbersExportPath, true) { file -> - Intent(Intent.ACTION_CREATE_DOCUMENT).apply { - type = "text/plain" - putExtra(Intent.EXTRA_TITLE, file.name) - addCategory(Intent.CATEGORY_OPENABLE) - - try { - startActivityForResult(this, PICK_EXPORT_FILE_INTENT) - } catch (e: ActivityNotFoundException) { - toast(R.string.system_service_disabled, Toast.LENGTH_LONG) - } catch (e: Exception) { - showErrorToast(e) - } - } - } - } else { - handlePermission(PERMISSION_WRITE_STORAGE) { isAllowed -> - if (isAllowed) { - ExportBlockedNumbersDialog(this, baseConfig.lastBlockedNumbersExportPath, false) { file -> - getFileOutputStream(file.toFileDirItem(this), true) { out -> - exportBlockedNumbersTo(out) - } - } - } + ExportBlockedNumbersDialog( + activity = this, + path = baseConfig.lastBlockedNumbersExportPath, + hidePath = true + ) { file -> + try { + createDocument.launch(file.name) + } catch (_: ActivityNotFoundException) { + toast(R.string.system_service_disabled, Toast.LENGTH_LONG) + } catch (e: Exception) { + showErrorToast(e) } } }