From bc5dd79cecb5f0f7d6c6154421a4a9797d5a75c3 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 23 Nov 2023 17:55:50 +0100 Subject: [PATCH 1/2] Remove unused code to increase code coverage. --- .../androidutils/system/SystemUtils.kt | 79 ------------------- 1 file changed, 79 deletions(-) diff --git a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/system/SystemUtils.kt b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/system/SystemUtils.kt index 1aee986d32..08155b2a34 100644 --- a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/system/SystemUtils.kt +++ b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/system/SystemUtils.kt @@ -16,48 +16,22 @@ package io.element.android.libraries.androidutils.system -import android.annotation.SuppressLint import android.annotation.TargetApi import android.app.Activity -import android.app.NotificationManager import android.content.ActivityNotFoundException import android.content.Context import android.content.Intent import android.content.pm.PackageManager import android.net.Uri import android.os.Build -import android.os.PowerManager import android.provider.Settings import android.widget.Toast import androidx.activity.result.ActivityResultLauncher import androidx.annotation.ChecksSdkIntAtLeast import androidx.annotation.RequiresApi -import androidx.core.content.getSystemService import io.element.android.libraries.androidutils.R import io.element.android.libraries.androidutils.compat.getApplicationInfoCompat -/** - * Tells if the application ignores battery optimizations. - * - * Ignoring them allows the app to run in background to make background sync with the homeserver. - * This user option appears on Android M but Android O enforces its usage and kills apps not - * authorised by the user to run in background. - * - * @return true if battery optimisations are ignored - */ -fun Context.isIgnoringBatteryOptimizations(): Boolean { - // no issue before Android M, battery optimisations did not exist - return getSystemService()?.isIgnoringBatteryOptimizations(packageName) == true -} - -fun Context.isAirplaneModeOn(): Boolean { - return Settings.Global.getInt(contentResolver, Settings.Global.AIRPLANE_MODE_ON, 0) != 0 -} - -fun Context.isAnimationEnabled(): Boolean { - return Settings.Global.getFloat(contentResolver, Settings.Global.ANIMATOR_DURATION_SCALE, 1f) != 0f -} - @ChecksSdkIntAtLeast(api = Build.VERSION_CODES.O) fun supportNotificationChannels() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O @@ -73,32 +47,6 @@ fun Context.getApplicationLabel(packageName: String): String { } } -/** - * Return true it the user has enabled the do not disturb mode. - */ -fun Context.isDoNotDisturbModeOn(): Boolean { - // We cannot use NotificationManagerCompat here. - val setting = getSystemService()!!.currentInterruptionFilter - - return setting == NotificationManager.INTERRUPTION_FILTER_NONE || - setting == NotificationManager.INTERRUPTION_FILTER_ALARMS -} - -/** - * display the system dialog for granting this permission. If previously granted, the - * system will not show it (so you should call this method). - * - * Note: If the user finally does not grant the permission, PushManager.isBackgroundSyncAllowed() - * will return false and the notification privacy will fallback to "LOW_DETAIL". - */ -@SuppressLint("BatteryLife") -fun Context.requestDisablingBatteryOptimization(activityResultLauncher: ActivityResultLauncher) { - val intent = Intent() - intent.action = Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS - intent.data = Uri.parse("package:$packageName") - activityResultLauncher.launch(intent) -} - // ============================================================================================================== // Clipboard helper // ============================================================================================================== @@ -169,19 +117,6 @@ fun Activity.startNotificationChannelSettingsIntent(channelID: String) { startActivity(intent) } -fun Context.startAddGoogleAccountIntent( - activityResultLauncher: ActivityResultLauncher, - noActivityFoundMessage: String = getString(R.string.error_no_compatible_app_found), -) { - val intent = Intent(Settings.ACTION_ADD_ACCOUNT) - intent.putExtra(Settings.EXTRA_ACCOUNT_TYPES, arrayOf("com.google")) - try { - activityResultLauncher.launch(intent) - } catch (activityNotFoundException: ActivityNotFoundException) { - toast(noActivityFoundMessage) - } -} - @RequiresApi(Build.VERSION_CODES.O) fun Context.startInstallFromSourceIntent( activityResultLauncher: ActivityResultLauncher, @@ -227,20 +162,6 @@ fun Context.startSharePlainTextIntent( } } -fun Context.startImportTextFromFileIntent( - activityResultLauncher: ActivityResultLauncher, - noActivityFoundMessage: String = getString(R.string.error_no_compatible_app_found), -) { - val intent = Intent(Intent.ACTION_GET_CONTENT).apply { - type = "text/plain" - } - try { - activityResultLauncher.launch(intent) - } catch (activityNotFoundException: ActivityNotFoundException) { - toast(noActivityFoundMessage) - } -} - @Suppress("SwallowedException") fun Context.openUrlInExternalApp( url: String, From cd0d0574b7d451e49864cd20a59fcf8b98d93cec Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 23 Nov 2023 22:18:28 +0100 Subject: [PATCH 2/2] More removal of dead code. --- .../androidutils/clipboard/ClipboardHelper.kt | 1 - .../libraries/androidutils/compat/Compat.kt | 15 +--- .../androidutils/extensions/isEmail.kt | 24 ------ .../libraries/androidutils/file/File.kt | 83 ------------------- .../androidutils/network/WifiDetector.kt | 38 --------- .../androidutils/ui/DimensionConverter.kt | 45 ---------- .../android/libraries/androidutils/ui/View.kt | 9 -- .../androidutils/uri/UriExtensions.kt | 6 -- 8 files changed, 2 insertions(+), 219 deletions(-) delete mode 100644 libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/extensions/isEmail.kt delete mode 100644 libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/network/WifiDetector.kt delete mode 100644 libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/ui/DimensionConverter.kt diff --git a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/clipboard/ClipboardHelper.kt b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/clipboard/ClipboardHelper.kt index 39cb719d48..3ebfeb811a 100644 --- a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/clipboard/ClipboardHelper.kt +++ b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/clipboard/ClipboardHelper.kt @@ -21,5 +21,4 @@ package io.element.android.libraries.androidutils.clipboard */ interface ClipboardHelper { fun copyPlainText(text: String) - } diff --git a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/compat/Compat.kt b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/compat/Compat.kt index 69761ccbc2..ca00f72fb7 100644 --- a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/compat/Compat.kt +++ b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/compat/Compat.kt @@ -17,26 +17,15 @@ package io.element.android.libraries.androidutils.compat import android.content.pm.ApplicationInfo -import android.content.pm.PackageInfo import android.content.pm.PackageManager import android.os.Build fun PackageManager.getApplicationInfoCompat(packageName: String, flags: Int): ApplicationInfo { return when { Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU -> getApplicationInfo( - packageName, - PackageManager.ApplicationInfoFlags.of(flags.toLong()) + packageName, + PackageManager.ApplicationInfoFlags.of(flags.toLong()) ) else -> @Suppress("DEPRECATION") getApplicationInfo(packageName, flags) } } - -fun PackageManager.getPackageInfoCompat(packageName: String, flags: Int): PackageInfo { - return when { - Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU -> getPackageInfo( - packageName, - PackageManager.PackageInfoFlags.of(flags.toLong()) - ) - else -> @Suppress("DEPRECATION") getPackageInfo(packageName, flags) - } -} diff --git a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/extensions/isEmail.kt b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/extensions/isEmail.kt deleted file mode 100644 index b47033286d..0000000000 --- a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/extensions/isEmail.kt +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) 2023 New Vector Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.element.android.libraries.androidutils.extensions - -import android.util.Patterns - -/** - * Check if a CharSequence is an email. - */ -fun CharSequence.isEmail() = Patterns.EMAIL_ADDRESS.matcher(this).matches() diff --git a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/file/File.kt b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/file/File.kt index d7628202c0..f8d4053feb 100644 --- a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/file/File.kt +++ b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/file/File.kt @@ -21,7 +21,6 @@ import androidx.annotation.WorkerThread import io.element.android.libraries.core.data.tryOrNull import timber.log.Timber import java.io.File -import java.util.Locale import java.util.UUID fun File.safeDelete() { @@ -56,88 +55,6 @@ fun Context.createTmpFile(baseDir: File = cacheDir, extension: String? = null): return File.createTempFile(UUID.randomUUID().toString(), suffix, baseDir).apply { mkdirs() } } -// Implementation should return true in case of success -typealias ActionOnFile = (file: File) -> Boolean - -/* ========================================================================================== - * Log - * ========================================================================================== */ - -fun lsFiles(context: Context) { - Timber.v("Content of cache dir:") - recursiveActionOnFile(context.cacheDir, ::logAction) - - Timber.v("Content of files dir:") - recursiveActionOnFile(context.filesDir, ::logAction) -} - -private fun logAction(file: File): Boolean { - if (file.isDirectory) { - Timber.v(file.toString()) - } else { - Timber.v("$file ${file.length()} bytes") - } - return true -} - -/* ========================================================================================== - * Private - * ========================================================================================== */ - -/** - * Return true in case of success. - */ -private fun recursiveActionOnFile(file: File, action: ActionOnFile): Boolean { - if (file.isDirectory) { - file.list()?.forEach { - val result = recursiveActionOnFile(File(file, it), action) - - if (!result) { - // Break the loop - return false - } - } - } - - return action.invoke(file) -} - -/** - * Get the file extension of a fileUri or a filename. - * - * @param fileUri the fileUri (can be a simple filename) - * @return the file extension, in lower case, or null is extension is not available or empty - */ -fun getFileExtension(fileUri: String): String? { - var reducedStr = fileUri - - if (reducedStr.isNotEmpty()) { - // Remove fragment - reducedStr = reducedStr.substringBeforeLast('#') - - // Remove query - reducedStr = reducedStr.substringBeforeLast('?') - - // Remove path - val filename = reducedStr.substringAfterLast('/') - - // Contrary to method MimeTypeMap.getFileExtensionFromUrl, we do not check the pattern - // See https://stackoverflow.com/questions/14320527/android-should-i-use-mimetypemap-getfileextensionfromurl-bugs - if (filename.isNotEmpty()) { - val dotPos = filename.lastIndexOf('.') - if (0 <= dotPos) { - val ext = filename.substring(dotPos + 1) - - if (ext.isNotBlank()) { - return ext.lowercase(Locale.ROOT) - } - } - } - } - - return null -} - /* ========================================================================================== * Size * ========================================================================================== */ diff --git a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/network/WifiDetector.kt b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/network/WifiDetector.kt deleted file mode 100644 index 85b17c6ff8..0000000000 --- a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/network/WifiDetector.kt +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2021 New Vector Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.element.android.libraries.androidutils.network - -import android.content.Context -import android.net.ConnectivityManager -import android.net.NetworkCapabilities -import androidx.core.content.getSystemService -import io.element.android.libraries.core.bool.orFalse -import timber.log.Timber - -class WifiDetector( - context: Context -) { - private val connectivityManager = context.getSystemService()!! - - fun isConnectedToWifi(): Boolean { - return connectivityManager.activeNetwork - ?.let { connectivityManager.getNetworkCapabilities(it) } - ?.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) - .orFalse() - .also { Timber.d("isConnected to WiFi: $it") } - } -} diff --git a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/ui/DimensionConverter.kt b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/ui/DimensionConverter.kt deleted file mode 100644 index beead850b3..0000000000 --- a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/ui/DimensionConverter.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2022 New Vector Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.element.android.libraries.androidutils.ui - -import android.content.res.Resources -import android.util.TypedValue -import androidx.annotation.Px - -class DimensionConverter(private val resources: Resources) { - - @Px - fun dpToPx(dp: Int): Int { - return TypedValue.applyDimension( - TypedValue.COMPLEX_UNIT_DIP, - dp.toFloat(), - resources.displayMetrics - ).toInt() - } - - @Px - fun spToPx(sp: Int): Int { - return TypedValue.applyDimension( - TypedValue.COMPLEX_UNIT_SP, - sp.toFloat(), - resources.displayMetrics - ).toInt() - } - - fun pxToDp(@Px px: Int): Int { - return (px.toFloat() / resources.displayMetrics.density).toInt() - } -} diff --git a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/ui/View.kt b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/ui/View.kt index 8bbaf1e5c3..8546bfa66c 100644 --- a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/ui/View.kt +++ b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/ui/View.kt @@ -36,15 +36,6 @@ fun View.showKeyboard(andRequestFocus: Boolean = false) { imm?.showSoftInput(this, InputMethodManager.SHOW_IMPLICIT) } -fun View.setHorizontalPadding(padding: Int) { - setPadding( - padding, - paddingTop, - padding, - paddingBottom - ) -} - suspend fun View.awaitWindowFocus() = suspendCancellableCoroutine { continuation -> if (hasWindowFocus()) { continuation.resume(Unit) diff --git a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/uri/UriExtensions.kt b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/uri/UriExtensions.kt index 1375104b79..4a2f48457e 100644 --- a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/uri/UriExtensions.kt +++ b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/uri/UriExtensions.kt @@ -18,12 +18,6 @@ package io.element.android.libraries.androidutils.uri import android.net.Uri -const val ASSET_FILE_PATH_ROOT = "android_asset" const val IGNORED_SCHEMA = "ignored" -fun Uri.isIgnored() = scheme == IGNORED_SCHEMA - fun createIgnoredUri(path: String): Uri = Uri.parse("$IGNORED_SCHEMA://$path") - -val Uri.firstPathSegment: String? - get() = pathSegments.firstOrNull()