Merge pull request #1948 from tilosp/api-21-cleanup

Remove old code that was used on devices with api level <21
This commit is contained in:
Benoit Marty 2020-08-18 10:11:15 +02:00 committed by GitHub
commit 8581d06931
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
47 changed files with 137 additions and 489 deletions

View File

@ -33,6 +33,7 @@ Other changes:
- Rename package `im.vector.riotx.attachmentviewer` to `im.vector.lib.attachmentviewer`
- Rename package `im.vector.riotx.multipicker` to `im.vector.lib.multipicker`
- Rename package `im.vector.riotx` to `im.vector.app`
- Remove old code that was used on devices with api level <21
- Add Official Gradle Wrapper Validation Action
Changes in Element 1.0.4 (2020-08-03)

View File

@ -29,5 +29,6 @@
<issue id="SetTextI18n" severity="error" />
<issue id="ViewConstructor" severity="error" />
<issue id="UseValueOf" severity="error" />
<issue id="ObsoleteSdkInt" severity="error" />
</lint>

View File

@ -18,7 +18,6 @@
package org.matrix.android.sdk.internal.crypto.store.db
import android.util.Base64
import org.matrix.android.sdk.internal.util.CompatUtil
import io.realm.Realm
import io.realm.RealmConfiguration
import io.realm.RealmObject
@ -26,6 +25,7 @@ import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.ObjectOutputStream
import java.util.zip.GZIPInputStream
import java.util.zip.GZIPOutputStream
/**
* Get realm, invoke the action, close realm, and return the result of the action
@ -78,7 +78,7 @@ fun serializeForRealm(o: Any?): String? {
}
val baos = ByteArrayOutputStream()
val gzis = CompatUtil.createGzipOutputStream(baos)
val gzis = GZIPOutputStream(baos)
val out = ObjectOutputStream(gzis)
out.use {
it.writeObject(o)

View File

@ -44,10 +44,7 @@ import javax.crypto.CipherInputStream
import javax.crypto.CipherOutputStream
import javax.crypto.KeyGenerator
import javax.crypto.SecretKey
import javax.crypto.SecretKeyFactory
import javax.crypto.spec.GCMParameterSpec
import javax.crypto.spec.IvParameterSpec
import javax.crypto.spec.PBEKeySpec
import javax.crypto.spec.SecretKeySpec
import javax.inject.Inject
import javax.security.auth.x500.X500Principal
@ -128,8 +125,7 @@ internal class SecretStoringUtils @Inject constructor(private val context: Conte
fun securelyStoreString(secret: String, keyAlias: String): ByteArray? {
return when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.M -> encryptStringM(secret, keyAlias)
Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT -> encryptStringK(secret, keyAlias)
else -> encryptForOldDevicesNotGood(secret, keyAlias)
else -> encryptString(secret, keyAlias)
}
}
@ -140,24 +136,21 @@ internal class SecretStoringUtils @Inject constructor(private val context: Conte
fun loadSecureSecret(encrypted: ByteArray, keyAlias: String): String? {
return when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.M -> decryptStringM(encrypted, keyAlias)
Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT -> decryptStringK(encrypted, keyAlias)
else -> decryptForOldDevicesNotGood(encrypted, keyAlias)
else -> decryptString(encrypted, keyAlias)
}
}
fun securelyStoreObject(any: Any, keyAlias: String, output: OutputStream) {
when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.M -> saveSecureObjectM(keyAlias, output, any)
Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT -> saveSecureObjectK(keyAlias, output, any)
else -> saveSecureObjectOldNotGood(keyAlias, output, any)
else -> saveSecureObject(keyAlias, output, any)
}
}
fun <T> loadSecureSecret(inputStream: InputStream, keyAlias: String): T? {
return when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.M -> loadSecureObjectM(keyAlias, inputStream)
Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT -> loadSecureObjectK(keyAlias, inputStream)
else -> loadSecureObjectOldNotGood(keyAlias, inputStream)
else -> loadSecureObject(keyAlias, inputStream)
}
}
@ -188,7 +181,6 @@ internal class SecretStoringUtils @Inject constructor(private val context: Conte
- Store the encrypted AES
Generate a key pair for encryption
*/
@RequiresApi(Build.VERSION_CODES.KITKAT)
fun getOrGenerateKeyPairForAlias(alias: String): KeyStore.PrivateKeyEntry {
val privateKeyEntry = (keyStore.getEntry(alias, null) as? KeyStore.PrivateKeyEntry)
@ -238,8 +230,7 @@ internal class SecretStoringUtils @Inject constructor(private val context: Conte
return String(cipher.doFinal(encryptedText), Charsets.UTF_8)
}
@RequiresApi(Build.VERSION_CODES.KITKAT)
private fun encryptStringK(text: String, keyAlias: String): ByteArray? {
private fun encryptString(text: String, keyAlias: String): ByteArray? {
// we generate a random symmetric key
val key = ByteArray(16)
secureRandom.nextBytes(key)
@ -256,47 +247,13 @@ internal class SecretStoringUtils @Inject constructor(private val context: Conte
return format1Make(encryptedKey, iv, encryptedBytes)
}
private fun encryptForOldDevicesNotGood(text: String, keyAlias: String): ByteArray {
val salt = ByteArray(8)
secureRandom.nextBytes(salt)
val factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256")
val spec = PBEKeySpec(keyAlias.toCharArray(), salt, 10000, 128)
val tmp = factory.generateSecret(spec)
val sKey = SecretKeySpec(tmp.encoded, "AES")
val cipher = Cipher.getInstance(AES_MODE)
cipher.init(Cipher.ENCRYPT_MODE, sKey)
val iv = cipher.iv
val encryptedBytes: ByteArray = cipher.doFinal(text.toByteArray(Charsets.UTF_8))
return format2Make(salt, iv, encryptedBytes)
}
private fun decryptForOldDevicesNotGood(data: ByteArray, keyAlias: String): String? {
val (salt, iv, encrypted) = format2Extract(ByteArrayInputStream(data))
val factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256")
val spec = PBEKeySpec(keyAlias.toCharArray(), salt, 10_000, 128)
val tmp = factory.generateSecret(spec)
val sKey = SecretKeySpec(tmp.encoded, "AES")
val cipher = Cipher.getInstance(AES_MODE)
// cipher.init(Cipher.ENCRYPT_MODE, sKey)
// val encryptedBytes: ByteArray = cipher.doFinal(text.toByteArray(Charsets.UTF_8))
val specIV = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) IvParameterSpec(iv) else GCMParameterSpec(128, iv)
cipher.init(Cipher.DECRYPT_MODE, sKey, specIV)
return String(cipher.doFinal(encrypted), Charsets.UTF_8)
}
@RequiresApi(Build.VERSION_CODES.KITKAT)
private fun decryptStringK(data: ByteArray, keyAlias: String): String? {
private fun decryptString(data: ByteArray, keyAlias: String): String? {
val (encryptedKey, iv, encrypted) = format1Extract(ByteArrayInputStream(data))
// we need to decrypt the key
val sKeyBytes = rsaDecrypt(keyAlias, ByteArrayInputStream(encryptedKey))
val cipher = Cipher.getInstance(AES_MODE)
val spec = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) IvParameterSpec(iv) else GCMParameterSpec(128, iv)
val spec = GCMParameterSpec(128, iv)
cipher.init(Cipher.DECRYPT_MODE, SecretKeySpec(sKeyBytes, "AES"), spec)
return String(cipher.doFinal(encrypted), Charsets.UTF_8)
@ -323,8 +280,7 @@ internal class SecretStoringUtils @Inject constructor(private val context: Conte
output.write(doFinal)
}
@RequiresApi(Build.VERSION_CODES.KITKAT)
private fun saveSecureObjectK(keyAlias: String, output: OutputStream, writeObject: Any) {
private fun saveSecureObject(keyAlias: String, output: OutputStream, writeObject: Any) {
// we generate a random symmetric key
val key = ByteArray(16)
secureRandom.nextBytes(key)
@ -352,32 +308,6 @@ internal class SecretStoringUtils @Inject constructor(private val context: Conte
output.write(bos1.toByteArray())
}
private fun saveSecureObjectOldNotGood(keyAlias: String, output: OutputStream, writeObject: Any) {
val salt = ByteArray(8)
secureRandom.nextBytes(salt)
val factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256")
val tmp = factory.generateSecret(PBEKeySpec(keyAlias.toCharArray(), salt, 10000, 128))
val secretKey = SecretKeySpec(tmp.encoded, "AES")
val cipher = Cipher.getInstance(AES_MODE)
cipher.init(Cipher.ENCRYPT_MODE, secretKey)
val iv = cipher.iv
val bos1 = ByteArrayOutputStream()
ObjectOutputStream(bos1).use {
it.writeObject(writeObject)
}
// Have to do it like that if i encapsulate the output stream, the cipher could fail saying reuse IV
val doFinal = cipher.doFinal(bos1.toByteArray())
output.write(FORMAT_2.toInt())
output.write(salt.size)
output.write(salt)
output.write(iv.size)
output.write(iv)
output.write(doFinal)
}
// @RequiresApi(Build.VERSION_CODES.M)
// @Throws(IOException::class)
// fun saveSecureObjectM(keyAlias: String, file: File, writeObject: Any) {
@ -418,15 +348,14 @@ internal class SecretStoringUtils @Inject constructor(private val context: Conte
}
}
@RequiresApi(Build.VERSION_CODES.KITKAT)
@Throws(IOException::class)
private fun <T> loadSecureObjectK(keyAlias: String, inputStream: InputStream): T? {
private fun <T> loadSecureObject(keyAlias: String, inputStream: InputStream): T? {
val (encryptedKey, iv, encrypted) = format1Extract(inputStream)
// we need to decrypt the key
val sKeyBytes = rsaDecrypt(keyAlias, ByteArrayInputStream(encryptedKey))
val cipher = Cipher.getInstance(AES_MODE)
val spec = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) IvParameterSpec(iv) else GCMParameterSpec(128, iv)
val spec = GCMParameterSpec(128, iv)
cipher.init(Cipher.DECRYPT_MODE, SecretKeySpec(sKeyBytes, "AES"), spec)
val encIS = ByteArrayInputStream(encrypted)
@ -440,31 +369,6 @@ internal class SecretStoringUtils @Inject constructor(private val context: Conte
}
}
@Throws(Exception::class)
private fun <T> loadSecureObjectOldNotGood(keyAlias: String, inputStream: InputStream): T? {
val (salt, iv, encrypted) = format2Extract(inputStream)
val factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256")
val tmp = factory.generateSecret(PBEKeySpec(keyAlias.toCharArray(), salt, 10000, 128))
val sKey = SecretKeySpec(tmp.encoded, "AES")
// we need to decrypt the key
val cipher = Cipher.getInstance(AES_MODE)
val spec = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) IvParameterSpec(iv) else GCMParameterSpec(128, iv)
cipher.init(Cipher.DECRYPT_MODE, sKey, spec)
val encIS = ByteArrayInputStream(encrypted)
CipherInputStream(encIS, cipher).use {
ObjectInputStream(it).use { ois ->
val readObject = ois.readObject()
@Suppress("UNCHECKED_CAST")
return readObject as? T
}
}
}
@RequiresApi(Build.VERSION_CODES.KITKAT)
@Throws(Exception::class)
private fun rsaEncrypt(alias: String, secret: ByteArray): ByteArray {
val privateKeyEntry = getOrGenerateKeyPairForAlias(alias)
@ -480,7 +384,6 @@ internal class SecretStoringUtils @Inject constructor(private val context: Conte
return outputStream.toByteArray()
}
@RequiresApi(Build.VERSION_CODES.KITKAT)
@Throws(Exception::class)
private fun rsaDecrypt(alias: String, encrypted: InputStream): ByteArray {
val privateKeyEntry = getOrGenerateKeyPairForAlias(alias)

View File

@ -17,7 +17,6 @@
package org.matrix.android.sdk.internal.session.widgets
import android.os.Build
import android.webkit.JavascriptInterface
import android.webkit.WebView
import com.squareup.moshi.Moshi
@ -172,11 +171,7 @@ internal class DefaultWidgetPostAPIMediator @Inject constructor(private val mosh
val functionLine = "sendResponseFromRiotAndroid('" + eventData["_id"] + "' , " + jsString + ");"
Timber.v("BRIDGE sendResponse: $functionLine")
// call the javascript method
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
webView?.loadUrl("javascript:$functionLine")
} else {
webView?.evaluateJavascript(functionLine, null)
}
} catch (e: Exception) {
Timber.e(e, "## sendResponse() failed ")
}

View File

@ -27,7 +27,6 @@ import android.security.KeyPairGeneratorSpec
import android.security.keystore.KeyGenParameterSpec
import android.security.keystore.KeyProperties
import android.util.Base64
import androidx.annotation.RequiresApi
import androidx.core.content.edit
import timber.log.Timber
import java.io.IOException
@ -48,7 +47,6 @@ import java.security.cert.CertificateException
import java.security.spec.AlgorithmParameterSpec
import java.security.spec.RSAKeyGenParameterSpec
import java.util.Calendar
import java.util.zip.GZIPOutputStream
import javax.crypto.Cipher
import javax.crypto.CipherInputStream
import javax.crypto.CipherOutputStream
@ -82,22 +80,6 @@ object CompatUtil {
*/
private val prng: SecureRandom by lazy(LazyThreadSafetyMode.NONE) { SecureRandom() }
/**
* Create a GZIPOutputStream instance
* Special treatment on KitKat device, force the syncFlush param to false
* Before Kitkat, this param does not exist and after Kitkat it is set to false by default
*
* @param outputStream the output stream
*/
@Throws(IOException::class)
fun createGzipOutputStream(outputStream: OutputStream): GZIPOutputStream {
return if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
GZIPOutputStream(outputStream, false)
} else {
GZIPOutputStream(outputStream)
}
}
/**
* Returns the AES key used for local storage encryption/decryption with AES/GCM.
* The key is created if it does not exist already in the keystore.
@ -107,7 +89,6 @@ object CompatUtil {
*
* @param context the context holding the application shared preferences
*/
@RequiresApi(Build.VERSION_CODES.KITKAT)
@Synchronized
@Throws(KeyStoreException::class,
CertificateException::class,
@ -249,10 +230,6 @@ object CompatUtil {
KeyStoreException::class,
IllegalBlockSizeException::class)
fun createCipherOutputStream(out: OutputStream, context: Context): OutputStream? {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
return out
}
val keyAndVersion = getAesGcmLocalProtectionKey(context)
val cipher = Cipher.getInstance(AES_GCM_CIPHER_TYPE)
@ -298,10 +275,6 @@ object CompatUtil {
InvalidAlgorithmParameterException::class,
IOException::class)
fun createCipherInputStream(`in`: InputStream, context: Context): InputStream? {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
return `in`
}
val iv_len = `in`.read()
if (iv_len != AES_GCM_IV_LENGTH) {
Timber.e(TAG, "Invalid IV length $iv_len")

View File

@ -37,6 +37,7 @@
<issue id="SetTextI18n" severity="error" />
<issue id="ViewConstructor" severity="error" />
<issue id="UseValueOf" severity="error" />
<issue id="ObsoleteSdkInt" severity="error" />
<issue id="Recycle" severity="error" />
<issue id="KotlinPropertyAccess" severity="error" />

View File

@ -22,7 +22,6 @@ import android.content.Context
import android.hardware.Camera
import android.hardware.camera2.CameraCharacteristics
import android.hardware.camera2.CameraManager
import android.os.Build
import androidx.core.content.getSystemService
import javax.inject.Inject
@ -33,10 +32,6 @@ class HardwareInfo @Inject constructor(
* Tell if the device has a back (or external) camera
*/
fun hasBackCamera(): Boolean {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
return Camera.getNumberOfCameras() > 0
}
val manager = context.getSystemService<CameraManager>() ?: return Camera.getNumberOfCameras() > 0
return manager.cameraIdList.any {

View File

@ -20,7 +20,6 @@ import android.content.ClipData
import android.content.ClipDescription
import android.content.Intent
import android.net.Uri
import android.os.Build
import androidx.core.util.PatternsCompat.WEB_URL
/**
@ -87,13 +86,9 @@ fun analyseIntent(intent: Intent): List<ExternalIntentData> {
}
}
var clipData: ClipData? = null
val clipData: ClipData? = intent.clipData
var mimeTypes: List<String>? = null
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
clipData = intent.clipData
}
// multiple data
if (null != clipData) {
if (null != clipData.description) {

View File

@ -19,7 +19,6 @@ package im.vector.app.core.ui.views
import android.content.Context
import android.content.res.ColorStateList
import android.graphics.drawable.Drawable
import android.os.Build
import android.util.AttributeSet
import android.view.View
import android.widget.FrameLayout
@ -105,13 +104,7 @@ class BottomSheetActionButton @JvmOverloads constructor(
var tint: Int? = null
set(value) {
field = value
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
leftIconImageView.imageTintList = value?.let { ColorStateList.valueOf(value) }
} else {
leftIcon?.let {
leftIcon = ThemeUtils.tintDrawable(context, it, value ?: ThemeUtils.getColor(context, android.R.attr.textColor))
}
}
}
init {

View File

@ -134,9 +134,7 @@ fun openFileSelection(activity: Activity,
allowMultipleSelection: Boolean,
requestCode: Int) {
val fileIntent = Intent(Intent.ACTION_GET_CONTENT)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
fileIntent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, allowMultipleSelection)
}
fileIntent.addCategory(Intent.CATEGORY_OPENABLE)
fileIntent.type = "*/*"

View File

@ -101,15 +101,10 @@ fun startNotificationSettingsIntent(activity: AppCompatActivity, requestCode: In
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
intent.action = Settings.ACTION_APP_NOTIFICATION_SETTINGS
intent.putExtra(Settings.EXTRA_APP_PACKAGE, activity.packageName)
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
} else {
intent.action = Settings.ACTION_APP_NOTIFICATION_SETTINGS
intent.putExtra("app_package", activity.packageName)
intent.putExtra("app_uid", activity.applicationInfo?.uid)
} else {
intent.action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
intent.addCategory(Intent.CATEGORY_DEFAULT)
val uri = Uri.fromParts("package", activity.packageName, null)
intent.data = uri
}
activity.startActivityForResult(intent, requestCode)
}
@ -140,11 +135,7 @@ fun startAddGoogleAccountIntent(context: AppCompatActivity, requestCode: Int) {
fun startSharePlainTextIntent(fragment: Fragment, chooserTitle: String?, text: String, subject: String? = null, requestCode: Int? = null) {
val share = Intent(Intent.ACTION_SEND)
share.type = "text/plain"
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
share.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT)
} else {
share.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK)
}
// Add data to the intent, the receiving app will decide what to do with it.
share.putExtra(Intent.EXTRA_SUBJECT, subject)
share.putExtra(Intent.EXTRA_TEXT, text)

View File

@ -18,10 +18,8 @@ package im.vector.app.features.attachments
import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.annotation.TargetApi
import android.content.Context
import android.graphics.drawable.BitmapDrawable
import android.os.Build
import android.util.Pair
import android.view.Gravity
import android.view.LayoutInflater
@ -109,13 +107,8 @@ class AttachmentTypeSelectorView(context: Context,
showAtLocation(anchor, Gravity.NO_GRAVITY, 0, anchorCoordinates[1] - contentViewHeight)
}
contentView.doOnNextLayout {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
animateWindowInCircular(anchor, contentView)
} else {
animateWindowInTranslate(contentView)
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
animateButtonIn(galleryButton, ANIMATION_DURATION / 2)
animateButtonIn(cameraButton, ANIMATION_DURATION / 2)
animateButtonIn(fileButton, ANIMATION_DURATION / 4)
@ -123,11 +116,10 @@ class AttachmentTypeSelectorView(context: Context,
animateButtonIn(contactButton, ANIMATION_DURATION / 4)
animateButtonIn(stickersButton, 0)
}
}
override fun dismiss() {
val capturedAnchor = anchor
if (capturedAnchor != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (capturedAnchor != null) {
animateWindowOutCircular(capturedAnchor, contentView)
} else {
animateWindowOutTranslate(contentView)
@ -144,7 +136,6 @@ class AttachmentTypeSelectorView(context: Context,
button.startAnimation(animation)
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private fun animateWindowInCircular(anchor: View, contentView: View) {
val coordinates = getClickCoordinates(anchor, contentView)
val animator = ViewAnimationUtils.createCircularReveal(contentView,
@ -162,7 +153,6 @@ class AttachmentTypeSelectorView(context: Context,
getContentView().startAnimation(animation)
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private fun animateWindowOutCircular(anchor: View, contentView: View) {
val coordinates = getClickCoordinates(anchor, contentView)
val animator = ViewAnimationUtils.createCircularReveal(getContentView(),

View File

@ -23,7 +23,6 @@ import android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP
import android.os.Build
import android.os.Bundle
import android.os.Parcelable
import android.view.KeyEvent
import android.view.View
import android.view.Window
import android.view.WindowManager
@ -334,20 +333,6 @@ class VectorCallActivity : VectorBaseActivity(), CallControlsView.InteractionLis
surfaceRenderersAreInitialized = true
}
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
// for newer version, it will be passed automatically to active media session
// in call service
when (keyCode) {
KeyEvent.KEYCODE_HEADSETHOOK -> {
callViewModel.handle(VectorCallViewActions.HeadSetButtonPressed)
return true
}
}
}
return super.onKeyDown(keyCode, event)
}
private fun handleViewEvents(event: VectorCallViewEvents?) {
Timber.v("## VOIP handleViewEvents $event")
when (event) {

View File

@ -18,8 +18,6 @@ package im.vector.app.features.call
import android.content.Context
import android.hardware.camera2.CameraManager
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.core.content.getSystemService
import im.vector.app.ActiveSessionDataSource
import im.vector.app.core.services.BluetoothHeadsetReceiver
@ -363,11 +361,6 @@ class WebRtcPeerConnectionManager @Inject constructor(
}
}
else -> {
// Fallback for old android, try to restart capture when attached
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP && capturerIsInError && call.mxCall.isVideoCall) {
// try to restart capture?
videoCapturer?.startCapture(currentCaptureMode.width, currentCaptureMode.height, currentCaptureMode.fps)
}
// sink existing tracks (configuration change, e.g screen rotation)
attachViewRenderersInternal()
}
@ -478,13 +471,11 @@ class WebRtcPeerConnectionManager @Inject constructor(
// We then register in order to restart capture as soon as the camera is available again
Timber.v("## VOIP onCameraClosed")
this@WebRtcPeerConnectionManager.capturerIsInError = true
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
val restarter = CameraRestarter(cameraInUse?.name ?: "", callContext.mxCall.callId)
callContext.cameraAvailabilityCallback = restarter
val cameraManager = context.getSystemService<CameraManager>()!!
cameraManager.registerAvailabilityCallback(restarter, null)
}
}
})
val videoSource = peerConnectionFactory!!.createVideoSource(videoCapturer.isScreencast)
@ -792,11 +783,9 @@ class WebRtcPeerConnectionManager @Inject constructor(
currentCall?.localVideoTrack?.setEnabled(false)
currentCall?.cameraAvailabilityCallback?.let { cameraAvailabilityCallback ->
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
val cameraManager = context.getSystemService<CameraManager>()!!
cameraManager.unregisterAvailabilityCallback(cameraAvailabilityCallback)
}
}
if (originatedByMe) {
// send hang up event
@ -1041,7 +1030,6 @@ class WebRtcPeerConnectionManager @Inject constructor(
}
}
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
inner class CameraRestarter(val cameraId: String, val callId: String) : CameraManager.AvailabilityCallback() {
override fun onCameraAvailable(cameraId: String) {

View File

@ -82,9 +82,7 @@ class VectorConfiguration @Inject constructor(private val context: Context) {
} else {
@Suppress("DEPRECATION")
configuration.locale = locale
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
configuration.setLayoutDirection(locale)
}
@Suppress("DEPRECATION")
resources.updateConfiguration(configuration, resources.displayMetrics)
return context

View File

@ -16,7 +16,6 @@
package im.vector.app.features.login
import android.os.Build
import android.os.Bundle
import android.view.View
import androidx.annotation.CallSuper
@ -48,10 +47,8 @@ abstract class AbstractLoginFragment : VectorBaseFragment(), OnBackPressed {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
sharedElementEnterTransition = TransitionInflater.from(context).inflateTransition(android.R.transition.move)
}
}
@CallSuper
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {

View File

@ -22,7 +22,6 @@ import android.annotation.SuppressLint
import android.content.DialogInterface
import android.graphics.Bitmap
import android.net.http.SslError
import android.os.Build
import android.os.Bundle
import android.view.KeyEvent
import android.view.View
@ -102,14 +101,6 @@ class LoginWebFragment @Inject constructor(
launchWebView(state)
} else {
if (!cookieManager.hasCookies()) {
launchWebView(state)
} else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
try {
cookieManager.removeAllCookie()
} catch (e: Exception) {
Timber.e(e, " cookieManager.removeAllCookie() fails")
}
launchWebView(state)
} else {
try {

View File

@ -19,12 +19,10 @@ package im.vector.app.features.media
import android.content.Context
import android.content.Intent
import android.graphics.drawable.Drawable
import android.os.Build
import android.os.Bundle
import android.view.MenuItem
import android.view.View
import android.view.ViewTreeObserver
import androidx.annotation.RequiresApi
import androidx.appcompat.widget.Toolbar
import androidx.core.net.toUri
import androidx.core.transition.addListener
@ -84,7 +82,7 @@ class ImageMediaViewerActivity : VectorBaseActivity() {
configureToolbar(imageMediaViewerToolbar, mediaData)
if (isFirstCreation() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && addTransitionListener()) {
if (isFirstCreation() && addTransitionListener()) {
// Encrypted image
imageTransitionView.isVisible = true
imageMediaViewerImageView.isVisible = false
@ -183,7 +181,6 @@ class ImageMediaViewerActivity : VectorBaseActivity() {
*
* @return true if we were successful in adding a listener to the enter transition
*/
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
private fun addTransitionListener(): Boolean {
val transition = window.sharedElementEnterTransition

View File

@ -20,6 +20,7 @@ import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Typeface
import android.os.Trace
import android.text.StaticLayout
import android.text.TextPaint
import android.util.AttributeSet
@ -43,7 +44,7 @@ class EmojiDrawView @JvmOverloads constructor(
var emoji: String? = null
override fun onDraw(canvas: Canvas?) {
EmojiRecyclerAdapter.beginTraceSession("EmojiDrawView.onDraw")
Trace.beginSection("EmojiDrawView.onDraw")
super.onDraw(canvas)
canvas?.save()
val space = abs((width - emojiSize) / 2f)
@ -52,7 +53,7 @@ class EmojiDrawView @JvmOverloads constructor(
mLayout!!.draw(canvas)
}
canvas?.restore()
EmojiRecyclerAdapter.endTraceSession()
Trace.endSection()
}
companion object {

View File

@ -125,7 +125,7 @@ class EmojiRecyclerAdapter @Inject constructor(
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
beginTraceSession("MyAdapter.onCreateViewHolder")
Trace.beginSection("MyAdapter.onCreateViewHolder")
val inflater = LayoutInflater.from(parent.context)
val itemView = inflater.inflate(viewType, parent, false)
itemView.setOnClickListener(itemClickListener)
@ -133,16 +133,16 @@ class EmojiRecyclerAdapter @Inject constructor(
R.layout.grid_section_header -> SectionViewHolder(itemView)
else -> EmojiViewHolder(itemView)
}
endTraceSession()
Trace.endSection()
return viewHolder
}
override fun getItemViewType(position: Int): Int {
beginTraceSession("MyAdapter.getItemViewType")
Trace.beginSection("MyAdapter.getItemViewType")
if (isSection(position)) {
return R.layout.grid_section_header
}
endTraceSession()
Trace.endSection()
return R.layout.grid_item_emoji
}
@ -183,7 +183,7 @@ class EmojiRecyclerAdapter @Inject constructor(
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
beginTraceSession("MyAdapter.onBindViewHolder")
Trace.beginSection("MyAdapter.onBindViewHolder")
val sectionNumber = getSectionForAbsoluteIndex(position)
if (isSection(position)) {
holder.bind(dataSource.rawData.categories[sectionNumber].name)
@ -202,7 +202,7 @@ class EmojiRecyclerAdapter @Inject constructor(
holder.bind(null)
}
}
endTraceSession()
Trace.endSection()
}
override fun onViewRecycled(holder: ViewHolder) {
@ -259,18 +259,6 @@ class EmojiRecyclerAdapter @Inject constructor(
}
companion object {
fun endTraceSession() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
Trace.endSection()
}
}
fun beginTraceSession(sectionName: String) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
Trace.beginSection(sectionName)
}
}
private val staticLayoutCache = HashMap<String, StaticLayout>()
private fun getStaticLayoutForEmoji(emoji: String): StaticLayout {

View File

@ -18,7 +18,6 @@ package im.vector.app.features.settings
import android.content.Context
import android.content.res.Configuration
import android.os.Build
import androidx.core.content.edit
import androidx.preference.PreferenceManager
import im.vector.app.BuildConfig
@ -108,7 +107,6 @@ object VectorLocale {
putString(APPLICATION_LOCALE_VARIANT_KEY, variant)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
val script = locale.script
if (script.isEmpty()) {
remove(APPLICATION_LOCALE_SCRIPT_KEY)
@ -117,7 +115,6 @@ object VectorLocale {
}
}
}
}
/**
* Get String from a locale
@ -128,40 +125,15 @@ object VectorLocale {
* @return the localized string
*/
private fun getString(context: Context, locale: Locale, resourceId: Int): String {
val result: String
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
val config = Configuration(context.resources.configuration)
config.setLocale(locale)
result = try {
return try {
context.createConfigurationContext(config).getText(resourceId).toString()
} catch (e: Exception) {
Timber.e(e, "## getString() failed")
// use the default one
context.getString(resourceId)
}
} else {
val resources = context.resources
val conf = resources.configuration
@Suppress("DEPRECATION")
val savedLocale = conf.locale
@Suppress("DEPRECATION")
conf.locale = locale
@Suppress("DEPRECATION")
resources.updateConfiguration(conf, null)
// retrieve resources from desired locale
result = resources.getString(resourceId)
// restore original locale
@Suppress("DEPRECATION")
conf.locale = savedLocale
@Suppress("DEPRECATION")
resources.updateConfiguration(conf, null)
}
return result
}
/**
@ -194,7 +166,6 @@ object VectorLocale {
}
val list = knownLocalesSet.mapNotNull { (language, country, script) ->
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
try {
Locale.Builder()
.setLanguage(language)
@ -208,9 +179,6 @@ object VectorLocale {
// Ignore this locale in production
null
}
} else {
Locale(language, country)
}
}
// sort by human display names
.sortedBy { localeToLocalisedString(it).toLowerCase(it) }
@ -229,9 +197,7 @@ object VectorLocale {
return buildString {
append(locale.getDisplayLanguage(locale))
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP
&& locale.script != ISO_15924_LATN
&& locale.getDisplayScript(locale).isNotEmpty()) {
if (locale.script != ISO_15924_LATN && locale.getDisplayScript(locale).isNotEmpty()) {
append(" - ")
append(locale.getDisplayScript(locale))
}
@ -254,7 +220,7 @@ object VectorLocale {
return buildString {
append("[")
append(locale.displayLanguage)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && locale.script != ISO_15924_LATN) {
if (locale.script != ISO_15924_LATN) {
append(" - ")
append(locale.displayScript)
}

View File

@ -15,7 +15,6 @@
*/
package im.vector.app.features.settings.troubleshoot
import android.os.Build
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@ -87,9 +86,7 @@ class NotificationTroubleshootRecyclerViewAdapter(val tests: ArrayList<Troublesh
statusIconImage.visibility = View.VISIBLE
statusIconImage.setImageResource(R.drawable.unit_test_ko)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
statusIconImage.imageTintList = null
}
descriptionText.setTextColor(ContextCompat.getColor(context, R.color.riotx_notice))
}

View File

@ -18,7 +18,6 @@ package im.vector.app.features.webview
import android.content.Context
import android.content.Intent
import android.os.Build
import android.webkit.WebChromeClient
import android.webkit.WebView
import androidx.annotation.CallSuper
@ -70,10 +69,8 @@ class VectorWebViewActivity : VectorBaseActivity() {
displayZoomControls = false
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
val cookieManager = android.webkit.CookieManager.getInstance()
cookieManager.setAcceptThirdPartyCookies(simple_webview, true)
}
val url = intent.extras?.getString(EXTRA_URL)
val title = intent.extras?.getString(EXTRA_TITLE, USE_TITLE_FROM_WEB_PAGE)

View File

@ -26,7 +26,6 @@ import android.webkit.WebResourceRequest
import android.webkit.WebResourceResponse
import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.annotation.RequiresApi
/**
* This class inherits from WebViewClient. It has to be used with a WebView.
@ -58,7 +57,6 @@ class VectorWebViewClient(private val eventListener: WebViewEventListener) : Web
}
}
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
override fun onReceivedHttpError(view: WebView, request: WebResourceRequest, errorResponse: WebResourceResponse) {
super.onReceivedHttpError(view, request, errorResponse)
eventListener.onHttpError(request.url.toString(),

View File

@ -16,7 +16,6 @@
package im.vector.app.features.widgets.permissions
import android.content.DialogInterface
import android.os.Build
import android.text.Spannable
import android.text.SpannableStringBuilder
import android.text.style.BulletSpan
@ -71,18 +70,7 @@ class RoomWidgetPermissionBottomSheet : VectorBaseBottomSheetDialogFragment() {
permissionData.permissionsList.forEach {
infoBuilder.append("\n")
val bulletPoint = getString(it)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
infoBuilder.append(bulletPoint, BulletSpan(resources.getDimension(R.dimen.quote_gap).toInt()), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
} else {
val start = infoBuilder.length
infoBuilder.append(bulletPoint)
infoBuilder.setSpan(
BulletSpan(resources.getDimension(R.dimen.quote_gap).toInt()),
start,
bulletPoint.length,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
}
}
infoBuilder.append("\n")
widgetPermissionSharedInfo.text = infoBuilder

View File

@ -17,7 +17,6 @@
package im.vector.app.features.widgets.webview
import android.annotation.SuppressLint
import android.os.Build
import android.view.ViewGroup
import android.webkit.CookieManager
import android.webkit.PermissionRequest
@ -68,11 +67,9 @@ fun WebView.setupForWidget(webViewEventListener: WebViewEventListener) {
}
webViewClient = VectorWebViewClient(webViewEventListener)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
val cookieManager = CookieManager.getInstance()
cookieManager.setAcceptThirdPartyCookies(this, false)
}
}
fun WebView.clearAfterWidget() {
// Make sure you remove the WebView from its parent view before doing anything.

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- End and Start attribute has to be set here -->
</resources>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="floating_action_button_margin">16dp</dimen>
<!-- Improve size (+20dp) to take status bar height into account -->
<dimen name="navigation_view_height">196dp</dimen>
<dimen name="navigation_avatar_top_margin">44dp</dimen>
</resources>

View File

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
</resources>

View File

@ -1,18 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme.Black.v21" parent="AppTheme.Base.Black">
<item name="android:statusBarColor">@color/riotx_header_panel_background_black</item>
<item name="android:navigationBarColor">@color/riotx_header_panel_background_black</item>
<!-- enable window content transitions -->
<item name="android:windowContentTransitions">true</item>
<!-- specify shared element enter and exit transitions -->
<item name="android:windowSharedElementEnterTransition">@transition/image_preview_transition</item>
<item name="android:windowSharedElementExitTransition">@transition/image_preview_transition</item>
</style>
<style name="AppTheme.Black" parent="AppTheme.Black.v21" />
</resources>

View File

@ -1,16 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme.Launcher.v21" parent="AppTheme.Launcher.Base">
<item name="android:statusBarColor">@color/riotx_accent</item>
<item name="android:navigationBarColor">@color/riotx_accent</item>
</style>
<style name="AppTheme.Launcher" parent="AppTheme.Launcher.v21"/>
<style name="AppTheme.AttachmentsPreview" parent="AppTheme.Base.Black">
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
</style>
</resources>

View File

@ -1,18 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme.Dark.v21" parent="AppTheme.Base.Dark">
<item name="android:statusBarColor">@color/riotx_header_panel_background_dark</item>
<item name="android:navigationBarColor">@color/riotx_header_panel_background_dark</item>
<!-- enable window content transitions -->
<item name="android:windowContentTransitions">true</item>
<!-- specify shared element enter and exit transitions -->
<item name="android:windowSharedElementEnterTransition">@transition/image_preview_transition</item>
<item name="android:windowSharedElementExitTransition">@transition/image_preview_transition</item>
</style>
<style name="AppTheme.Dark" parent="AppTheme.Dark.v21" />
</resources>

View File

@ -1,20 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme.Light.v21" parent="AppTheme.Base.Light">
<!-- Use dark color, to have enough contrast with icons color. windowLightStatusBar is only available in API 23+ -->
<item name="android:statusBarColor">@color/riotx_header_panel_background_dark</item>
<!-- Use dark color, to have enough contrast with icons color. windowLightNavigationBar is only available in API 27+ -->
<item name="android:navigationBarColor">@color/riotx_header_panel_background_dark</item>
<!-- enable window content transitions -->
<item name="android:windowContentTransitions">true</item>
<!-- specify shared element enter and exit transitions -->
<item name="android:windowSharedElementEnterTransition">@transition/image_preview_transition</item>
<item name="android:windowSharedElementExitTransition">@transition/image_preview_transition</item>
</style>
<style name="AppTheme.Light" parent="AppTheme.Light.v21"/>
</resources>

View File

@ -1,20 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme.Status.v21" parent="AppTheme.Base.Status">
<!-- Use dark color, to have enough contrast with icons color. windowLightStatusBar is only available in API 23+ -->
<item name="android:statusBarColor">@color/riotx_header_panel_background_dark</item>
<!-- Use dark color, to have enough contrast with icons color. windowLightNavigationBar is only available in API 27+ -->
<item name="android:navigationBarColor">@color/riotx_header_panel_background_dark</item>
<!-- enable window content transitions -->
<item name="android:windowContentTransitions">true</item>
<!-- specify shared element enter and exit transitions -->
<item name="android:windowSharedElementEnterTransition">@transition/image_preview_transition</item>
<item name="android:windowSharedElementExitTransition">@transition/image_preview_transition</item>
</style>
<style name="AppTheme.Status" parent="AppTheme.Status.v21" />
</resources>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme.Black.v23" parent="AppTheme.Black.v21">
<style name="AppTheme.Black.v23" parent="AppTheme.Base.Black">
<item name="android:windowLightStatusBar">false</item>
</style>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme.Dark.v23" parent="AppTheme.Dark.v21">
<style name="AppTheme.Dark.v23" parent="AppTheme.Base.Dark">
<item name="android:windowLightStatusBar">false</item>
</style>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme.Light.v23" parent="AppTheme.Light.v21">
<style name="AppTheme.Light.v23" parent="AppTheme.Base.Light">
<item name="android:statusBarColor">@color/riotx_header_panel_background_light</item>
<item name="android:windowLightStatusBar">true</item>
</style>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme.Status.v23" parent="AppTheme.Status.v21">
<style name="AppTheme.Status.v23" parent="AppTheme.Base.Status">
<item name="android:statusBarColor">@color/riotx_header_panel_background_light</item>
<item name="android:windowLightStatusBar">true</item>
</style>

View File

@ -9,9 +9,9 @@
<dimen name="layout_vertical_margin_big">32dp</dimen>
<dimen name="profile_avatar_size">50dp</dimen>
<dimen name="floating_action_button_margin">0dp</dimen>
<dimen name="navigation_view_height">172dp</dimen>
<dimen name="navigation_avatar_top_margin">20dp</dimen>
<dimen name="floating_action_button_margin">16dp</dimen>
<dimen name="navigation_view_height">196dp</dimen>
<dimen name="navigation_avatar_top_margin">44dp</dimen>
<dimen name="item_decoration_left_margin">72dp</dimen>
<dimen name="chat_avatar_size">40dp</dimen>

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- On post Lollipop use default background drawable instead of color -->
<style name="Vector.PopupMenu" parent="Vector.PopupMenuBase" />
</resources>

View File

@ -63,14 +63,6 @@
<item name="android:dropDownVerticalOffset">0dp</item>
</style>
<style name="Vector.PopupMenu" parent="Vector.PopupMenuBase">
<!--
Before Lollipop the popup background is white on dark theme, so force color here.
(v21 will revert back to default drawable)
-->
<item name="android:popupBackground">?colorBackgroundFloating</item>
</style>
<!-- actionbar icons color -->
<style name="Vector.ActionBarTheme" parent="ThemeOverlay.MaterialComponents.ActionBar">
<item name="colorControlNormal">@android:color/white</item>

View File

@ -81,6 +81,15 @@
<item name="riotx_bottom_nav_background_color">@color/riotx_bottom_nav_background_color_black</item>
<item name="riotx_bottom_nav_background_border_color">@color/riotx_bottom_nav_background_border_color_black</item>
<item name="android:statusBarColor">@color/riotx_header_panel_background_black</item>
<item name="android:navigationBarColor">@color/riotx_header_panel_background_black</item>
<!-- enable window content transitions -->
<item name="android:windowContentTransitions">true</item>
<!-- specify shared element enter and exit transitions -->
<item name="android:windowSharedElementEnterTransition">@transition/image_preview_transition</item>
<item name="android:windowSharedElementExitTransition">@transition/image_preview_transition</item>
</style>
<style name="AppTheme.Black" parent="AppTheme.Base.Black" />

View File

@ -6,11 +6,16 @@
<style name="AppTheme.Launcher.Base" parent="Theme.MaterialComponents.Light.NoActionBar">
<item name="android:windowBackground">@drawable/splash</item>
<item name="android:statusBarColor">@color/riotx_accent</item>
<item name="android:navigationBarColor">@color/riotx_accent</item>
<item name="colorPrimaryDark">@color/primary_color_dark</item>
</style>
<style name="AppTheme.AttachmentsPreview" parent="AppTheme.Base.Black"/>
<style name="AppTheme.AttachmentsPreview" parent="AppTheme.Base.Black">
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
</style>
<style name="AppTheme.Transparent" parent="AppTheme.Base.Black">
<item name="windowActionBar">false</item>

View File

@ -182,6 +182,15 @@
<item name="pf_fingerprint_button">@style/PinCodeFingerprintButtonStyle</item>
<item name="pf_next">@style/PinCodeNextButtonStyle</item>
<item name="android:statusBarColor">@color/riotx_header_panel_background_dark</item>
<item name="android:navigationBarColor">@color/riotx_header_panel_background_dark</item>
<!-- enable window content transitions -->
<item name="android:windowContentTransitions">true</item>
<!-- specify shared element enter and exit transitions -->
<item name="android:windowSharedElementEnterTransition">@transition/image_preview_transition</item>
<item name="android:windowSharedElementExitTransition">@transition/image_preview_transition</item>
</style>
<style name="AppTheme.Dark" parent="AppTheme.Base.Dark" />

View File

@ -182,6 +182,17 @@
<item name="pf_fingerprint_button">@style/PinCodeFingerprintButtonStyle</item>
<item name="pf_next">@style/PinCodeNextButtonStyle</item>
<!-- Use dark color, to have enough contrast with icons color. windowLightStatusBar is only available in API 23+ -->
<item name="android:statusBarColor">@color/riotx_header_panel_background_dark</item>
<!-- Use dark color, to have enough contrast with icons color. windowLightNavigationBar is only available in API 27+ -->
<item name="android:navigationBarColor">@color/riotx_header_panel_background_dark</item>
<!-- enable window content transitions -->
<item name="android:windowContentTransitions">true</item>
<!-- specify shared element enter and exit transitions -->
<item name="android:windowSharedElementEnterTransition">@transition/image_preview_transition</item>
<item name="android:windowSharedElementExitTransition">@transition/image_preview_transition</item>
</style>
<style name="AppTheme.Light" parent="AppTheme.Base.Light" />

View File

@ -99,6 +99,18 @@
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
<item name="bottomSheetDialogTheme">@style/Vector.BottomSheet.Status</item>
<!-- Use dark color, to have enough contrast with icons color. windowLightStatusBar is only available in API 23+ -->
<item name="android:statusBarColor">@color/riotx_header_panel_background_dark</item>
<!-- Use dark color, to have enough contrast with icons color. windowLightNavigationBar is only available in API 27+ -->
<item name="android:navigationBarColor">@color/riotx_header_panel_background_dark</item>
<!-- enable window content transitions -->
<item name="android:windowContentTransitions">true</item>
<!-- specify shared element enter and exit transitions -->
<item name="android:windowSharedElementEnterTransition">@transition/image_preview_transition</item>
<item name="android:windowSharedElementExitTransition">@transition/image_preview_transition</item>
</style>
<style name="AppTheme.Status" parent="AppTheme.Base.Status" />