Merge pull request #1872 from vector-im/feature/bma/removeDeadCode
Remove unused code to increase code coverage.
This commit is contained in:
@@ -21,5 +21,4 @@ package io.element.android.libraries.androidutils.clipboard
|
||||
*/
|
||||
interface ClipboardHelper {
|
||||
fun copyPlainText(text: String)
|
||||
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
@@ -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
|
||||
* ========================================================================================== */
|
||||
|
||||
@@ -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") }
|
||||
}
|
||||
}
|
||||
@@ -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 {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
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(
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user