Browse Source

Merge pull request #1872 from vector-im/feature/bma/removeDeadCode

Remove unused code to increase code coverage.
pull/1889/head
Benoit Marty 10 months ago committed by GitHub
parent
commit
524067fafe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/clipboard/ClipboardHelper.kt
  2. 15
      libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/compat/Compat.kt
  3. 24
      libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/extensions/isEmail.kt
  4. 83
      libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/file/File.kt
  5. 38
      libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/network/WifiDetector.kt
  6. 79
      libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/system/SystemUtils.kt
  7. 45
      libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/ui/DimensionConverter.kt
  8. 9
      libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/ui/View.kt
  9. 6
      libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/uri/UriExtensions.kt

1
libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/clipboard/ClipboardHelper.kt

@ -21,5 +21,4 @@ package io.element.android.libraries.androidutils.clipboard @@ -21,5 +21,4 @@ package io.element.android.libraries.androidutils.clipboard
*/
interface ClipboardHelper {
fun copyPlainText(text: String)
}

15
libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/compat/Compat.kt

@ -17,26 +17,15 @@ @@ -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)
}
}

24
libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/extensions/isEmail.kt

@ -1,24 +0,0 @@ @@ -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()

83
libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/file/File.kt

@ -21,7 +21,6 @@ import androidx.annotation.WorkerThread @@ -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): @@ -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
* ========================================================================================== */

38
libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/network/WifiDetector.kt

@ -1,38 +0,0 @@ @@ -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<ConnectivityManager>()!!
fun isConnectedToWifi(): Boolean {
return connectivityManager.activeNetwork
?.let { connectivityManager.getNetworkCapabilities(it) }
?.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
.orFalse()
.also { Timber.d("isConnected to WiFi: $it") }
}
}

79
libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/system/SystemUtils.kt

@ -16,48 +16,22 @@ @@ -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<PowerManager>()?.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 { @@ -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<NotificationManager>()!!.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<Intent>) {
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) { @@ -169,19 +117,6 @@ fun Activity.startNotificationChannelSettingsIntent(channelID: String) {
startActivity(intent)
}
fun Context.startAddGoogleAccountIntent(
activityResultLauncher: ActivityResultLauncher<Intent>,
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<Intent>,
@ -227,20 +162,6 @@ fun Context.startSharePlainTextIntent( @@ -227,20 +162,6 @@ fun Context.startSharePlainTextIntent(
}
}
fun Context.startImportTextFromFileIntent(
activityResultLauncher: ActivityResultLauncher<Intent>,
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,

45
libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/ui/DimensionConverter.kt

@ -1,45 +0,0 @@ @@ -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()
}
}

9
libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/ui/View.kt

@ -36,15 +36,6 @@ fun View.showKeyboard(andRequestFocus: Boolean = false) { @@ -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)

6
libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/uri/UriExtensions.kt

@ -18,12 +18,6 @@ package io.element.android.libraries.androidutils.uri @@ -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()

Loading…
Cancel
Save