mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2024-11-25 02:45:53 +03:00
PR Review
Cleanup and Add command line to run the UI tests
This commit is contained in:
parent
f79784bc8c
commit
b14d22550b
10 changed files with 75 additions and 50 deletions
|
@ -20,7 +20,7 @@ Build 🧱:
|
||||||
-
|
-
|
||||||
|
|
||||||
Other changes:
|
Other changes:
|
||||||
-
|
- Added registration/verification automated UI tests
|
||||||
|
|
||||||
Changes in Element 1.0.8 (2020-09-25)
|
Changes in Element 1.0.8 (2020-09-25)
|
||||||
===================================================
|
===================================================
|
||||||
|
@ -49,7 +49,6 @@ SDK API changes ⚠️:
|
||||||
|
|
||||||
Other changes:
|
Other changes:
|
||||||
- Add an advanced action to reset an account data entry
|
- Add an advanced action to reset an account data entry
|
||||||
- Added registration/verification automated UI tests
|
|
||||||
|
|
||||||
Changes in Element 1.0.7 (2020-09-17)
|
Changes in Element 1.0.7 (2020-09-17)
|
||||||
===================================================
|
===================================================
|
||||||
|
|
|
@ -16,20 +16,20 @@ Out of the box, the tests use one of the homeservers (located at http://localhos
|
||||||
|
|
||||||
You first need to follow instructions to set up Synapse in development mode at https://github.com/matrix-org/synapse#synapse-development. If you have already installed all dependencies, the steps are:
|
You first need to follow instructions to set up Synapse in development mode at https://github.com/matrix-org/synapse#synapse-development. If you have already installed all dependencies, the steps are:
|
||||||
|
|
||||||
```
|
```shell script
|
||||||
$ git clone https://github.com/matrix-org/synapse.git
|
$ git clone https://github.com/matrix-org/synapse.git
|
||||||
$ cd synapse
|
$ cd synapse
|
||||||
$ virtualenv -p python3 env
|
$ virtualenv -p python3 env
|
||||||
$ source env/bin/activate
|
$ source env/bin/activate
|
||||||
(env) $ python -m pip install --no-use-pep517 -e .`
|
(env) $ python -m pip install --no-use-pep517 -e .
|
||||||
```
|
```
|
||||||
|
|
||||||
Every time you want to launch these test homeservers, type:
|
Every time you want to launch these test homeservers, type:
|
||||||
|
|
||||||
```
|
```shell script
|
||||||
$ virtualenv -p python3 env
|
$ virtualenv -p python3 env
|
||||||
$ source env/bin/activate
|
$ source env/bin/activate
|
||||||
(env) $ demo/start.sh --no-rate-limit`
|
(env) $ demo/start.sh --no-rate-limit
|
||||||
```
|
```
|
||||||
|
|
||||||
**Emulator/Device set up**
|
**Emulator/Device set up**
|
||||||
|
@ -50,33 +50,53 @@ On your device, under **Settings > Developer options**, disable the following 3
|
||||||
- Transition animation scale
|
- Transition animation scale
|
||||||
- Animator duration scale
|
- Animator duration scale
|
||||||
|
|
||||||
|
## Run the tests
|
||||||
|
|
||||||
|
Once Synapse is running, and an emulator is running, you can run the UI tests.
|
||||||
|
|
||||||
|
### From the source code
|
||||||
|
|
||||||
|
Click on the green arrow in front of each test. Clicking on the arrow in front of the test class, or from the package directory does not always work (Tests not found issue).
|
||||||
|
|
||||||
|
### From command line
|
||||||
|
|
||||||
|
````shell script
|
||||||
|
./gradlew vector:connectedGplayDebugAndroidTest
|
||||||
|
````
|
||||||
|
|
||||||
|
To run all the tests from the `vector` module.
|
||||||
|
|
||||||
|
In case of trouble, you can try to uninstall the previous installed test APK first with this command:
|
||||||
|
|
||||||
|
```shell script
|
||||||
|
adb uninstall im.vector.app.debug.test
|
||||||
|
```
|
||||||
## Recipes
|
## Recipes
|
||||||
|
|
||||||
We added some specific Espresso IdlingResources, and other utilities for matrix related tests
|
We added some specific Espresso IdlingResources, and other utilities for matrix related tests
|
||||||
|
|
||||||
### Wait for initial sync
|
### Wait for initial sync
|
||||||
|
|
||||||
````
|
```kotlin
|
||||||
// Wait for initial sync and check room list is there
|
// Wait for initial sync and check room list is there
|
||||||
withIdlingResource(initialSyncIdlingResource(uiSession)) {
|
withIdlingResource(initialSyncIdlingResource(uiSession)) {
|
||||||
onView(withId(R.id.roomListContainer))
|
onView(withId(R.id.roomListContainer))
|
||||||
.check(matches(isDisplayed()))
|
.check(matches(isDisplayed()))
|
||||||
}
|
}
|
||||||
````
|
```
|
||||||
|
|
||||||
### Accessing current activity
|
### Accessing current activity
|
||||||
|
|
||||||
````
|
```kotlin
|
||||||
val activity = EspressoHelper.getCurrentActivity()!!
|
val activity = EspressoHelper.getCurrentActivity()!!
|
||||||
val uiSession = (activity as HomeActivity).activeSessionHolder.getActiveSession()
|
val uiSession = (activity as HomeActivity).activeSessionHolder.getActiveSession()
|
||||||
````
|
```
|
||||||
|
|
||||||
### Interact with other session
|
### Interact with other session
|
||||||
|
|
||||||
It's possible to create a session via the SDK, and then use this session to interact with the one that the emulator is using (to check verifications for example)
|
It's possible to create a session via the SDK, and then use this session to interact with the one that the emulator is using (to check verifications for example)
|
||||||
|
|
||||||
````
|
```kotlin
|
||||||
@Before
|
@Before
|
||||||
fun initAccount() {
|
fun initAccount() {
|
||||||
val context = InstrumentationRegistry.getInstrumentation().targetContext
|
val context = InstrumentationRegistry.getInstrumentation().targetContext
|
||||||
|
@ -84,4 +104,4 @@ fun initAccount() {
|
||||||
val userName = "foobar_${System.currentTimeMillis()}"
|
val userName = "foobar_${System.currentTimeMillis()}"
|
||||||
existingSession = createAccountAndSync(matrix, userName, password, true)
|
existingSession = createAccountAndSync(matrix, userName, password, true)
|
||||||
}
|
}
|
||||||
`````
|
```
|
||||||
|
|
|
@ -218,7 +218,7 @@ class CommonTestHelper(context: Context) {
|
||||||
.createAccount(userName, password, null, it)
|
.createAccount(userName, password, null, it)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Preform dummy step
|
// Perform dummy step
|
||||||
val registrationResult = doSync<RegistrationResult> {
|
val registrationResult = doSync<RegistrationResult> {
|
||||||
matrix.authenticationService
|
matrix.authenticationService
|
||||||
.getRegistrationWizard()
|
.getRegistrationWizard()
|
||||||
|
|
|
@ -372,7 +372,7 @@ internal class RealmCryptoStore @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun storePrivateKeysInfo(msk: String?, usk: String?, ssk: String?) {
|
override fun storePrivateKeysInfo(msk: String?, usk: String?, ssk: String?) {
|
||||||
Timber.v("## CRYPTO | *** storePrivateKeysInfo ${msk != null} ")
|
Timber.v("## CRYPTO | *** storePrivateKeysInfo ${msk != null}, ${usk != null}, ${ssk != null}")
|
||||||
doRealmTransaction(realmConfiguration) { realm ->
|
doRealmTransaction(realmConfiguration) { realm ->
|
||||||
realm.where<CryptoMetadataEntity>().findFirst()?.apply {
|
realm.where<CryptoMetadataEntity>().findFirst()?.apply {
|
||||||
xSignMasterPrivateKey = msk
|
xSignMasterPrivateKey = msk
|
||||||
|
|
|
@ -173,15 +173,12 @@ android {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// The following argument makes the Android Test Orchestrator run its
|
// The following argument makes the Android Test Orchestrator run its
|
||||||
// "pm clear" command after each test invocation. This command ensures
|
// "pm clear" command after each test invocation. This command ensures
|
||||||
// that the app's state is completely cleared between tests.
|
// that the app's state is completely cleared between tests.
|
||||||
testInstrumentationRunnerArguments clearPackageData: 'true'
|
testInstrumentationRunnerArguments clearPackageData: 'true'
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
testOptions {
|
testOptions {
|
||||||
// Disables animations during instrumented tests you run from the command line…
|
// Disables animations during instrumented tests you run from the command line…
|
||||||
// This property does not affect tests that you run using Android Studio.”
|
// This property does not affect tests that you run using Android Studio.”
|
||||||
|
@ -297,6 +294,11 @@ dependencies {
|
||||||
def arch_version = '2.1.0'
|
def arch_version = '2.1.0'
|
||||||
def lifecycle_version = '2.2.0'
|
def lifecycle_version = '2.2.0'
|
||||||
|
|
||||||
|
// Tests
|
||||||
|
def kluent_version = '1.44'
|
||||||
|
def androidxTest_version = '1.3.0'
|
||||||
|
def espresso_version = '3.3.0'
|
||||||
|
|
||||||
implementation project(":matrix-sdk-android")
|
implementation project(":matrix-sdk-android")
|
||||||
implementation project(":matrix-sdk-android-rx")
|
implementation project(":matrix-sdk-android-rx")
|
||||||
implementation project(":diff-match-patch")
|
implementation project(":diff-match-patch")
|
||||||
|
@ -437,20 +439,20 @@ dependencies {
|
||||||
|
|
||||||
// TESTS
|
// TESTS
|
||||||
testImplementation 'junit:junit:4.12'
|
testImplementation 'junit:junit:4.12'
|
||||||
testImplementation 'org.amshove.kluent:kluent-android:1.44'
|
testImplementation "org.amshove.kluent:kluent-android:$kluent_version"
|
||||||
// Plant Timber tree for test
|
// Plant Timber tree for test
|
||||||
testImplementation 'net.lachlanmckee:timber-junit-rule:1.0.1'
|
testImplementation 'net.lachlanmckee:timber-junit-rule:1.0.1'
|
||||||
|
|
||||||
// Activate when you want to check for leaks, from time to time.
|
// Activate when you want to check for leaks, from time to time.
|
||||||
//debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.3'
|
//debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.3'
|
||||||
|
|
||||||
androidTestImplementation 'androidx.test:core:1.3.0'
|
androidTestImplementation "androidx.test:core:$androidxTest_version"
|
||||||
androidTestImplementation 'androidx.test:runner:1.3.0'
|
androidTestImplementation "androidx.test:runner:$androidxTest_version"
|
||||||
androidTestImplementation 'androidx.test:rules:1.3.0'
|
androidTestImplementation "androidx.test:rules:$androidxTest_version"
|
||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
|
androidTestImplementation "androidx.test.espresso:espresso-core:$espresso_version"
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.3.0'
|
androidTestImplementation "androidx.test.espresso:espresso-contrib:$espresso_version"
|
||||||
androidTestImplementation 'org.amshove.kluent:kluent-android:1.44'
|
androidTestImplementation "org.amshove.kluent:kluent-android:$kluent_version"
|
||||||
androidTestImplementation "androidx.arch.core:core-testing:$arch_version"
|
androidTestImplementation "androidx.arch.core:core-testing:$arch_version"
|
||||||
// Plant Timber tree for test
|
// Plant Timber tree for test
|
||||||
androidTestImplementation 'net.lachlanmckee:timber-junit-rule:1.0.1'
|
androidTestImplementation 'net.lachlanmckee:timber-junit-rule:1.0.1'
|
||||||
|
|
|
@ -44,12 +44,14 @@ import java.util.concurrent.TimeoutException
|
||||||
object EspressoHelper {
|
object EspressoHelper {
|
||||||
fun getCurrentActivity(): Activity? {
|
fun getCurrentActivity(): Activity? {
|
||||||
var currentActivity: Activity? = null
|
var currentActivity: Activity? = null
|
||||||
getInstrumentation().runOnMainSync { run { currentActivity = ActivityLifecycleMonitorRegistry.getInstance().getActivitiesInStage(Stage.RESUMED).elementAtOrNull(0) } }
|
getInstrumentation().runOnMainSync {
|
||||||
|
currentActivity = ActivityLifecycleMonitorRegistry.getInstance().getActivitiesInStage(Stage.RESUMED).elementAtOrNull(0)
|
||||||
|
}
|
||||||
return currentActivity
|
return currentActivity
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun waitForView(viewMatcher: Matcher<View>, timeout: Long = 10000, waitForDisplayed: Boolean = true): ViewAction {
|
fun waitForView(viewMatcher: Matcher<View>, timeout: Long = 10_000, waitForDisplayed: Boolean = true): ViewAction {
|
||||||
return object : ViewAction {
|
return object : ViewAction {
|
||||||
override fun getConstraints(): Matcher<View> {
|
override fun getConstraints(): Matcher<View> {
|
||||||
return Matchers.any(View::class.java)
|
return Matchers.any(View::class.java)
|
||||||
|
@ -62,25 +64,25 @@ fun waitForView(viewMatcher: Matcher<View>, timeout: Long = 10000, waitForDispla
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun perform(uiController: UiController, view: View) {
|
override fun perform(uiController: UiController, view: View) {
|
||||||
System.out.println("*** waitForView 1 $view")
|
println("*** waitForView 1 $view")
|
||||||
uiController.loopMainThreadUntilIdle()
|
uiController.loopMainThreadUntilIdle()
|
||||||
val startTime = System.currentTimeMillis()
|
val startTime = System.currentTimeMillis()
|
||||||
val endTime = startTime + timeout
|
val endTime = startTime + timeout
|
||||||
val visibleMatcher = isDisplayed()
|
val visibleMatcher = isDisplayed()
|
||||||
|
|
||||||
do {
|
do {
|
||||||
System.out.println("*** waitForView loop $view end:$endTime currrent:${System.currentTimeMillis()}")
|
println("*** waitForView loop $view end:$endTime current:${System.currentTimeMillis()}")
|
||||||
val viewVisible = TreeIterables.breadthFirstViewTraversal(view)
|
val viewVisible = TreeIterables.breadthFirstViewTraversal(view)
|
||||||
.any { viewMatcher.matches(it) && visibleMatcher.matches(it) }
|
.any { viewMatcher.matches(it) && visibleMatcher.matches(it) }
|
||||||
|
|
||||||
System.out.println("*** waitForView loop viewVisible:$viewVisible")
|
println("*** waitForView loop viewVisible:$viewVisible")
|
||||||
if (viewVisible == waitForDisplayed) return
|
if (viewVisible == waitForDisplayed) return
|
||||||
System.out.println("*** waitForView loop loopMainThreadForAtLeast...")
|
println("*** waitForView loop loopMainThreadForAtLeast...")
|
||||||
uiController.loopMainThreadForAtLeast(50)
|
uiController.loopMainThreadForAtLeast(50)
|
||||||
System.out.println("*** waitForView loop ...loopMainThreadForAtLeast")
|
println("*** waitForView loop ...loopMainThreadForAtLeast")
|
||||||
} while (System.currentTimeMillis() < endTime)
|
} while (System.currentTimeMillis() < endTime)
|
||||||
|
|
||||||
System.out.println("*** waitForView timeout $view")
|
println("*** waitForView timeout $view")
|
||||||
// Timeout happens.
|
// Timeout happens.
|
||||||
throw PerformException.Builder()
|
throw PerformException.Builder()
|
||||||
.withActionDescription(this.description)
|
.withActionDescription(this.description)
|
||||||
|
@ -136,24 +138,24 @@ fun activityIdlingResource(activityClass: Class<*>): IdlingResource {
|
||||||
val currentActivity = currentActivity ?: ActivityLifecycleMonitorRegistry.getInstance().getActivitiesInStage(Stage.RESUMED).elementAtOrNull(0)
|
val currentActivity = currentActivity ?: ActivityLifecycleMonitorRegistry.getInstance().getActivitiesInStage(Stage.RESUMED).elementAtOrNull(0)
|
||||||
|
|
||||||
val isIdle = hasResumed || currentActivity?.javaClass?.let { activityClass.isAssignableFrom(it) } ?: false
|
val isIdle = hasResumed || currentActivity?.javaClass?.let { activityClass.isAssignableFrom(it) } ?: false
|
||||||
System.out.println("*** [$name] isIdleNow activityIdlingResource $currentActivity isIdle:$isIdle")
|
println("*** [$name] isIdleNow activityIdlingResource $currentActivity isIdle:$isIdle")
|
||||||
return isIdle
|
return isIdle
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun registerIdleTransitionCallback(callback: IdlingResource.ResourceCallback?) {
|
override fun registerIdleTransitionCallback(callback: IdlingResource.ResourceCallback?) {
|
||||||
System.out.println("*** [$name] registerIdleTransitionCallback $callback")
|
println("*** [$name] registerIdleTransitionCallback $callback")
|
||||||
this.callback = callback
|
this.callback = callback
|
||||||
// if (hasResumed) callback?.onTransitionToIdle()
|
// if (hasResumed) callback?.onTransitionToIdle()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onActivityLifecycleChanged(activity: Activity?, stage: Stage?) {
|
override fun onActivityLifecycleChanged(activity: Activity?, stage: Stage?) {
|
||||||
System.out.println("*** [$name] onActivityLifecycleChanged $activity $stage")
|
println("*** [$name] onActivityLifecycleChanged $activity $stage")
|
||||||
currentActivity = ActivityLifecycleMonitorRegistry.getInstance().getActivitiesInStage(Stage.RESUMED).elementAtOrNull(0)
|
currentActivity = ActivityLifecycleMonitorRegistry.getInstance().getActivitiesInStage(Stage.RESUMED).elementAtOrNull(0)
|
||||||
val isIdle = currentActivity?.javaClass?.let { activityClass.isAssignableFrom(it) } ?: false
|
val isIdle = currentActivity?.javaClass?.let { activityClass.isAssignableFrom(it) } ?: false
|
||||||
System.out.println("*** [$name] onActivityLifecycleChanged $currentActivity isIdle:$isIdle")
|
println("*** [$name] onActivityLifecycleChanged $currentActivity isIdle:$isIdle")
|
||||||
if (isIdle) {
|
if (isIdle) {
|
||||||
hasResumed = true
|
hasResumed = true
|
||||||
System.out.println("*** [$name] onActivityLifecycleChanged callback: $callback")
|
println("*** [$name] onActivityLifecycleChanged callback: $callback")
|
||||||
callback?.onTransitionToIdle()
|
callback?.onTransitionToIdle()
|
||||||
ActivityLifecycleMonitorRegistry.getInstance().removeLifecycleCallback(this)
|
ActivityLifecycleMonitorRegistry.getInstance().removeLifecycleCallback(this)
|
||||||
}
|
}
|
||||||
|
@ -164,10 +166,10 @@ fun activityIdlingResource(activityClass: Class<*>): IdlingResource {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun withIdlingResource(idlingResource: IdlingResource, block: (() -> Unit)) {
|
fun withIdlingResource(idlingResource: IdlingResource, block: (() -> Unit)) {
|
||||||
System.out.println("*** withIdlingResource register")
|
println("*** withIdlingResource register")
|
||||||
IdlingRegistry.getInstance().register(idlingResource)
|
IdlingRegistry.getInstance().register(idlingResource)
|
||||||
block.invoke()
|
block.invoke()
|
||||||
System.out.println("*** withIdlingResource unregister")
|
println("*** withIdlingResource unregister")
|
||||||
IdlingRegistry.getInstance().unregister(idlingResource)
|
IdlingRegistry.getInstance().unregister(idlingResource)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,7 +181,7 @@ fun allSecretsKnownIdling(session: Session): IdlingResource {
|
||||||
override fun getName() = "AllSecretsKnownIdling_${session.myUserId}"
|
override fun getName() = "AllSecretsKnownIdling_${session.myUserId}"
|
||||||
|
|
||||||
override fun isIdleNow(): Boolean {
|
override fun isIdleNow(): Boolean {
|
||||||
System.out.println("*** [$name]/isIdleNow allSecretsKnownIdling ${privateKeysInfo?.allKnown()}")
|
println("*** [$name]/isIdleNow allSecretsKnownIdling ${privateKeysInfo?.allKnown()}")
|
||||||
return privateKeysInfo?.allKnown() == true
|
return privateKeysInfo?.allKnown() == true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,7 +190,7 @@ fun allSecretsKnownIdling(session: Session): IdlingResource {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onChanged(t: Optional<PrivateKeysInfo>?) {
|
override fun onChanged(t: Optional<PrivateKeysInfo>?) {
|
||||||
System.out.println("*** [$name] allSecretsKnownIdling ${t?.getOrNull()}")
|
println("*** [$name] allSecretsKnownIdling ${t?.getOrNull()}")
|
||||||
privateKeysInfo = t?.getOrNull()
|
privateKeysInfo = t?.getOrNull()
|
||||||
if (t?.getOrNull()?.allKnown() == true) {
|
if (t?.getOrNull()?.allKnown() == true) {
|
||||||
session.cryptoService().crossSigningService().getLiveCrossSigningPrivateKeys().removeObserver(this)
|
session.cryptoService().crossSigningService().getLiveCrossSigningPrivateKeys().removeObserver(this)
|
|
@ -48,7 +48,7 @@ class RegistrationTest {
|
||||||
val password: String = "password"
|
val password: String = "password"
|
||||||
val homeServerUrl: String = "http://10.0.2.2:8080"
|
val homeServerUrl: String = "http://10.0.2.2:8080"
|
||||||
|
|
||||||
// Check splashcreen is there
|
// Check splashscreen is there
|
||||||
onView(withId(R.id.loginSplashSubmit))
|
onView(withId(R.id.loginSplashSubmit))
|
||||||
.check(matches(isDisplayed()))
|
.check(matches(isDisplayed()))
|
||||||
.check(matches(withText(R.string.login_splash_submit)))
|
.check(matches(withText(R.string.login_splash_submit)))
|
||||||
|
@ -57,7 +57,7 @@ class RegistrationTest {
|
||||||
onView(withId(R.id.loginSplashSubmit))
|
onView(withId(R.id.loginSplashSubmit))
|
||||||
.perform(click())
|
.perform(click())
|
||||||
|
|
||||||
// Check that home server options are showned
|
// Check that home server options are shown
|
||||||
onView(withId(R.id.loginServerTitle))
|
onView(withId(R.id.loginServerTitle))
|
||||||
.check(matches(isDisplayed()))
|
.check(matches(isDisplayed()))
|
||||||
.check(matches(withText(R.string.login_server_title)))
|
.check(matches(withText(R.string.login_server_title)))
|
||||||
|
|
|
@ -158,7 +158,7 @@ abstract class VerificationTestBase {
|
||||||
.createAccount(userName, password, null, it)
|
.createAccount(userName, password, null, it)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Preform dummy step
|
// Perform dummy step
|
||||||
val registrationResult = doSync<RegistrationResult> {
|
val registrationResult = doSync<RegistrationResult> {
|
||||||
matrix.authenticationService()
|
matrix.authenticationService()
|
||||||
.getRegistrationWizard()
|
.getRegistrationWizard()
|
||||||
|
|
|
@ -55,6 +55,10 @@ fun isAirplaneModeOn(context: Context): Boolean {
|
||||||
return Settings.Global.getInt(context.contentResolver, Settings.Global.AIRPLANE_MODE_ON, 0) != 0
|
return Settings.Global.getInt(context.contentResolver, Settings.Global.AIRPLANE_MODE_ON, 0) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun isAnimationDisabled(context: Context): Boolean {
|
||||||
|
return Settings.Global.getFloat(context.contentResolver, Settings.Global.ANIMATOR_DURATION_SCALE, 1f) == 0f
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* display the system dialog for granting this permission. If previously granted, the
|
* display the system dialog for granting this permission. If previously granted, the
|
||||||
* system will not show it (so you should call this method).
|
* system will not show it (so you should call this method).
|
||||||
|
|
|
@ -20,7 +20,6 @@ import android.app.Activity
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.provider.Settings
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import com.tapadoo.alerter.Alerter
|
import com.tapadoo.alerter.Alerter
|
||||||
|
@ -28,6 +27,7 @@ import com.tapadoo.alerter.OnHideAlertListener
|
||||||
import dagger.Lazy
|
import dagger.Lazy
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.platform.VectorBaseActivity
|
import im.vector.app.core.platform.VectorBaseActivity
|
||||||
|
import im.vector.app.core.utils.isAnimationDisabled
|
||||||
import im.vector.app.features.home.AvatarRenderer
|
import im.vector.app.features.home.AvatarRenderer
|
||||||
import im.vector.app.features.pin.PinActivity
|
import im.vector.app.features.pin.PinActivity
|
||||||
import im.vector.app.features.themes.ThemeUtils
|
import im.vector.app.features.themes.ThemeUtils
|
||||||
|
@ -173,9 +173,7 @@ class PopupAlertManager @Inject constructor(private val avatarRenderer: Lazy<Ava
|
||||||
private fun showAlert(alert: VectorAlert, activity: Activity, animate: Boolean = true) {
|
private fun showAlert(alert: VectorAlert, activity: Activity, animate: Boolean = true) {
|
||||||
clearLightStatusBar()
|
clearLightStatusBar()
|
||||||
|
|
||||||
val systemAnimationDurationDisabled = Settings.Global.getFloat(
|
val noAnimation = !animate || isAnimationDisabled(activity)
|
||||||
activity.contentResolver,
|
|
||||||
Settings.Global.ANIMATOR_DURATION_SCALE, 1f) == 0f
|
|
||||||
|
|
||||||
alert.weakCurrentActivity = WeakReference(activity)
|
alert.weakCurrentActivity = WeakReference(activity)
|
||||||
val alerter = if (alert is VerificationVectorAlert) Alerter.create(activity, R.layout.alerter_verification_layout)
|
val alerter = if (alert is VerificationVectorAlert) Alerter.create(activity, R.layout.alerter_verification_layout)
|
||||||
|
@ -192,7 +190,7 @@ class PopupAlertManager @Inject constructor(private val avatarRenderer: Lazy<Ava
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.apply {
|
.apply {
|
||||||
if (systemAnimationDurationDisabled || !animate) {
|
if (noAnimation) {
|
||||||
setEnterAnimation(R.anim.anim_alerter_no_anim)
|
setEnterAnimation(R.anim.anim_alerter_no_anim)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,7 +240,7 @@ class PopupAlertManager @Inject constructor(private val avatarRenderer: Lazy<Ava
|
||||||
setBackgroundColorRes(alert.colorRes ?: R.color.notification_accent_color)
|
setBackgroundColorRes(alert.colorRes ?: R.color.notification_accent_color)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.enableIconPulse(!systemAnimationDurationDisabled)
|
.enableIconPulse(!noAnimation)
|
||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue