mirror of
https://github.com/vector-im/element-android.git
synced 2024-11-15 01:35:07 +08:00
Merge pull request #2367 from vector-im/feature/bma/sanity_test
Feature/bma/sanity test
This commit is contained in:
commit
41f46d0810
@ -31,6 +31,9 @@ SDK API changes ⚠️:
|
||||
Build 🧱:
|
||||
-
|
||||
|
||||
Test:
|
||||
- Add `allScreensTest` to cover all screens of the app
|
||||
|
||||
Other changes:
|
||||
- Upgrade Realm dependency to 10.0.0
|
||||
|
||||
@ -1044,5 +1047,8 @@ SDK API changes ⚠️:
|
||||
Build 🧱:
|
||||
-
|
||||
|
||||
Test:
|
||||
-
|
||||
|
||||
Other changes:
|
||||
-
|
||||
|
@ -1679,27 +1679,24 @@ internal class RealmCryptoStore @Inject constructor(
|
||||
// Only keep one week history
|
||||
realm.where<IncomingGossipingRequestEntity>()
|
||||
.lessThan(IncomingGossipingRequestEntityFields.LOCAL_CREATION_TIMESTAMP, prevWeekTs)
|
||||
.findAll().let {
|
||||
Timber.i("## Crypto Clean up ${it.size} IncomingGossipingRequestEntity")
|
||||
it.deleteAllFromRealm()
|
||||
}
|
||||
.findAll()
|
||||
.also { Timber.i("## Crypto Clean up ${it.size} IncomingGossipingRequestEntity") }
|
||||
.deleteAllFromRealm()
|
||||
|
||||
// Clean the cancelled ones?
|
||||
realm.where<OutgoingGossipingRequestEntity>()
|
||||
.equalTo(OutgoingGossipingRequestEntityFields.REQUEST_STATE_STR, OutgoingGossipingRequestState.CANCELLED.name)
|
||||
.equalTo(OutgoingGossipingRequestEntityFields.TYPE_STR, GossipRequestType.KEY.name)
|
||||
.findAll().let {
|
||||
Timber.i("## Crypto Clean up ${it.size} OutgoingGossipingRequestEntity")
|
||||
it.deleteAllFromRealm()
|
||||
}
|
||||
.findAll()
|
||||
.also { Timber.i("## Crypto Clean up ${it.size} OutgoingGossipingRequestEntity") }
|
||||
.deleteAllFromRealm()
|
||||
|
||||
// Only keep one week history
|
||||
realm.where<GossipingEventEntity>()
|
||||
.lessThan(GossipingEventEntityFields.AGE_LOCAL_TS, prevWeekTs)
|
||||
.findAll().let {
|
||||
Timber.i("## Crypto Clean up ${it.size} GossipingEventEntityFields")
|
||||
it.deleteAllFromRealm()
|
||||
}
|
||||
.findAll()
|
||||
.also { Timber.i("## Crypto Clean up ${it.size} GossipingEventEntityFields") }
|
||||
.deleteAllFromRealm()
|
||||
|
||||
// Can we do something for WithHeldSessionEntity?
|
||||
}
|
||||
|
@ -461,6 +461,10 @@ dependencies {
|
||||
androidTestImplementation "androidx.arch.core:core-testing:$arch_version"
|
||||
// Plant Timber tree for test
|
||||
androidTestImplementation 'net.lachlanmckee:timber-junit-rule:1.0.1'
|
||||
// "The one who serves a great Espresso"
|
||||
androidTestImplementation('com.schibsted.spain:barista:3.7.0') {
|
||||
exclude group: 'org.jetbrains.kotlin'
|
||||
}
|
||||
}
|
||||
|
||||
if (getGradle().getStartParameter().getTaskRequests().toString().contains("Gplay")) {
|
||||
|
@ -67,7 +67,7 @@ class RegistrationTest {
|
||||
.perform(click())
|
||||
|
||||
// Enter local synapse
|
||||
onView((withId(R.id.loginServerUrlFormHomeServerUrl)))
|
||||
onView(withId(R.id.loginServerUrlFormHomeServerUrl))
|
||||
.perform(typeText(homeServerUrl))
|
||||
|
||||
// Click on continue
|
||||
@ -87,7 +87,7 @@ class RegistrationTest {
|
||||
.check(matches(isDisplayed()))
|
||||
|
||||
// Ensure user id
|
||||
onView((withId(R.id.loginField)))
|
||||
onView(withId(R.id.loginField))
|
||||
.perform(typeText(userId))
|
||||
|
||||
// Ensure login button not yet enabled
|
||||
@ -95,7 +95,7 @@ class RegistrationTest {
|
||||
.check(matches(not(isEnabled())))
|
||||
|
||||
// Ensure password
|
||||
onView((withId(R.id.passwordField)))
|
||||
onView(withId(R.id.passwordField))
|
||||
.perform(closeSoftKeyboard(), typeText(password))
|
||||
|
||||
// Submit
|
||||
|
@ -79,7 +79,7 @@ class SecurityBootstrapTest : VerificationTestBase() {
|
||||
fun testBasicBootstrap() {
|
||||
val userId: String = existingSession!!.myUserId
|
||||
|
||||
doLogin(homeServerUrl, userId, password)
|
||||
uiTestBase.login(userId = userId, password = password, homeServerUrl = homeServerUrl)
|
||||
|
||||
// Thread.sleep(6000)
|
||||
withIdlingResource(activityIdlingResource(HomeActivity::class.java)) {
|
||||
|
@ -18,15 +18,11 @@ package im.vector.app
|
||||
|
||||
import android.net.Uri
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.test.espresso.Espresso
|
||||
import androidx.test.espresso.action.ViewActions
|
||||
import androidx.test.espresso.assertion.ViewAssertions
|
||||
import androidx.test.espresso.matcher.ViewMatchers
|
||||
import im.vector.app.ui.UiTestBase
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.hamcrest.CoreMatchers
|
||||
import org.junit.Assert
|
||||
import org.matrix.android.sdk.api.Matrix
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
@ -43,108 +39,12 @@ abstract class VerificationTestBase {
|
||||
val password = "password"
|
||||
val homeServerUrl: String = "http://10.0.2.2:8080"
|
||||
|
||||
fun doLogin(homeServerUrl: String, userId: String, password: String) {
|
||||
Espresso.onView(ViewMatchers.withId(R.id.loginSplashSubmit))
|
||||
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
|
||||
.check(ViewAssertions.matches(ViewMatchers.withText(R.string.login_splash_submit)))
|
||||
protected val uiTestBase = UiTestBase()
|
||||
|
||||
Espresso.onView(ViewMatchers.withId(R.id.loginSplashSubmit))
|
||||
.perform(ViewActions.click())
|
||||
|
||||
Espresso.onView(ViewMatchers.withId(R.id.loginServerTitle))
|
||||
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
|
||||
.check(ViewAssertions.matches(ViewMatchers.withText(R.string.login_server_title)))
|
||||
|
||||
// Chose custom server
|
||||
Espresso.onView(ViewMatchers.withId(R.id.loginServerChoiceOther))
|
||||
.perform(ViewActions.click())
|
||||
|
||||
// Enter local synapse
|
||||
Espresso.onView((ViewMatchers.withId(R.id.loginServerUrlFormHomeServerUrl)))
|
||||
.perform(ViewActions.typeText(homeServerUrl))
|
||||
|
||||
Espresso.onView(ViewMatchers.withId(R.id.loginServerUrlFormSubmit))
|
||||
.check(ViewAssertions.matches(ViewMatchers.isEnabled()))
|
||||
.perform(ViewActions.closeSoftKeyboard(), ViewActions.click())
|
||||
|
||||
// Click on the signin button
|
||||
Espresso.onView(ViewMatchers.withId(R.id.loginSignupSigninSignIn))
|
||||
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
|
||||
.perform(ViewActions.click())
|
||||
|
||||
// Ensure password flow supported
|
||||
Espresso.onView(ViewMatchers.withId(R.id.loginField))
|
||||
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
|
||||
Espresso.onView(ViewMatchers.withId(R.id.passwordField))
|
||||
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
|
||||
|
||||
Espresso.onView((ViewMatchers.withId(R.id.loginField)))
|
||||
.perform(ViewActions.typeText(userId))
|
||||
Espresso.onView(ViewMatchers.withId(R.id.loginSubmit))
|
||||
.check(ViewAssertions.matches(CoreMatchers.not(ViewMatchers.isEnabled())))
|
||||
|
||||
Espresso.onView((ViewMatchers.withId(R.id.passwordField)))
|
||||
.perform(ViewActions.closeSoftKeyboard(), ViewActions.typeText(password))
|
||||
|
||||
Espresso.onView(ViewMatchers.withId(R.id.loginSubmit))
|
||||
.check(ViewAssertions.matches(ViewMatchers.isEnabled()))
|
||||
.perform(ViewActions.closeSoftKeyboard(), ViewActions.click())
|
||||
}
|
||||
|
||||
private fun createAccount(userId: String = "UiAutoTest", password: String = "password", homeServerUrl: String = "http://10.0.2.2:8080") {
|
||||
Espresso.onView(ViewMatchers.withId(R.id.loginSplashSubmit))
|
||||
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
|
||||
.check(ViewAssertions.matches(ViewMatchers.withText(R.string.login_splash_submit)))
|
||||
|
||||
Espresso.onView(ViewMatchers.withId(R.id.loginSplashSubmit))
|
||||
.perform(ViewActions.click())
|
||||
|
||||
Espresso.onView(ViewMatchers.withId(R.id.loginServerTitle))
|
||||
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
|
||||
.check(ViewAssertions.matches(ViewMatchers.withText(R.string.login_server_title)))
|
||||
|
||||
// Chose custom server
|
||||
Espresso.onView(ViewMatchers.withId(R.id.loginServerChoiceOther))
|
||||
.perform(ViewActions.click())
|
||||
|
||||
// Enter local synapse
|
||||
Espresso.onView((ViewMatchers.withId(R.id.loginServerUrlFormHomeServerUrl)))
|
||||
.perform(ViewActions.typeText(homeServerUrl))
|
||||
|
||||
Espresso.onView(ViewMatchers.withId(R.id.loginServerUrlFormSubmit))
|
||||
.check(ViewAssertions.matches(ViewMatchers.isEnabled()))
|
||||
.perform(ViewActions.closeSoftKeyboard(), ViewActions.click())
|
||||
|
||||
// Click on the signup button
|
||||
Espresso.onView(ViewMatchers.withId(R.id.loginSignupSigninSubmit))
|
||||
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
|
||||
.perform(ViewActions.click())
|
||||
|
||||
// Ensure password flow supported
|
||||
Espresso.onView(ViewMatchers.withId(R.id.loginField))
|
||||
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
|
||||
Espresso.onView(ViewMatchers.withId(R.id.passwordField))
|
||||
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
|
||||
|
||||
Espresso.onView((ViewMatchers.withId(R.id.loginField)))
|
||||
.perform(ViewActions.typeText(userId))
|
||||
Espresso.onView(ViewMatchers.withId(R.id.loginSubmit))
|
||||
.check(ViewAssertions.matches(CoreMatchers.not(ViewMatchers.isEnabled())))
|
||||
|
||||
Espresso.onView((ViewMatchers.withId(R.id.passwordField)))
|
||||
.perform(ViewActions.typeText(password))
|
||||
|
||||
Espresso.onView(ViewMatchers.withId(R.id.loginSubmit))
|
||||
.check(ViewAssertions.matches(ViewMatchers.isEnabled()))
|
||||
.perform(ViewActions.closeSoftKeyboard(), ViewActions.click())
|
||||
|
||||
Espresso.onView(ViewMatchers.withId(R.id.homeDrawerFragmentContainer))
|
||||
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
|
||||
}
|
||||
|
||||
fun createAccountAndSync(matrix: Matrix, userName: String,
|
||||
password: String,
|
||||
withInitialSync: Boolean): Session {
|
||||
fun createAccountAndSync(matrix: Matrix,
|
||||
userName: String,
|
||||
password: String,
|
||||
withInitialSync: Boolean): Session {
|
||||
val hs = createHomeServerConfig()
|
||||
|
||||
doSync<LoginFlowResult> {
|
||||
@ -174,7 +74,7 @@ abstract class VerificationTestBase {
|
||||
return session
|
||||
}
|
||||
|
||||
fun createHomeServerConfig(): HomeServerConnectionConfig {
|
||||
private fun createHomeServerConfig(): HomeServerConnectionConfig {
|
||||
return HomeServerConnectionConfig.Builder()
|
||||
.withHomeServerUri(Uri.parse(homeServerUrl))
|
||||
.build()
|
||||
@ -200,7 +100,7 @@ abstract class VerificationTestBase {
|
||||
return result!!
|
||||
}
|
||||
|
||||
fun syncSession(session: Session) {
|
||||
private fun syncSession(session: Session) {
|
||||
val lock = CountDownLatch(1)
|
||||
|
||||
GlobalScope.launch(Dispatchers.Main) { session.open() }
|
||||
|
@ -78,7 +78,7 @@ class VerifySessionInteractiveTest : VerificationTestBase() {
|
||||
fun checkVerifyPopup() {
|
||||
val userId: String = existingSession!!.myUserId
|
||||
|
||||
doLogin(homeServerUrl, userId, password)
|
||||
uiTestBase.login(userId = userId, password = password, homeServerUrl = homeServerUrl)
|
||||
|
||||
// Thread.sleep(6000)
|
||||
withIdlingResource(activityIdlingResource(HomeActivity::class.java)) {
|
||||
@ -215,10 +215,10 @@ class VerifySessionInteractiveTest : VerificationTestBase() {
|
||||
}
|
||||
|
||||
fun signout() {
|
||||
onView((withId(R.id.groupToolbarAvatarImageView)))
|
||||
onView(withId(R.id.groupToolbarAvatarImageView))
|
||||
.perform(click())
|
||||
|
||||
onView((withId(R.id.homeDrawerHeaderSettingsView)))
|
||||
onView(withId(R.id.homeDrawerHeaderSettingsView))
|
||||
.perform(click())
|
||||
|
||||
onView(withText("General"))
|
||||
|
@ -88,7 +88,7 @@ class VerifySessionPassphraseTest : VerificationTestBase() {
|
||||
fun checkVerifyWithPassphrase() {
|
||||
val userId: String = existingSession!!.myUserId
|
||||
|
||||
doLogin(homeServerUrl, userId, password)
|
||||
uiTestBase.login(userId = userId, password = password, homeServerUrl = homeServerUrl)
|
||||
|
||||
// Thread.sleep(6000)
|
||||
withIdlingResource(activityIdlingResource(HomeActivity::class.java)) {
|
||||
@ -137,10 +137,10 @@ class VerifySessionPassphraseTest : VerificationTestBase() {
|
||||
onView(withId(R.id.ssss__root)).check(matches(isDisplayed()))
|
||||
}
|
||||
|
||||
onView((withId(R.id.ssss_passphrase_enter_edittext)))
|
||||
onView(withId(R.id.ssss_passphrase_enter_edittext))
|
||||
.perform(typeText(passphrase))
|
||||
|
||||
onView((withId(R.id.ssss_passphrase_submit)))
|
||||
onView(withId(R.id.ssss_passphrase_submit))
|
||||
.perform(click())
|
||||
|
||||
System.out.println("*** passphrase 1")
|
||||
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2020 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 im.vector.app.espresso.tools
|
||||
|
||||
import android.widget.Switch
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.preference.Preference
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.test.espresso.Espresso.onData
|
||||
import androidx.test.espresso.Espresso.onView
|
||||
import androidx.test.espresso.action.ViewActions.click
|
||||
import androidx.test.espresso.contrib.RecyclerViewActions.actionOnItem
|
||||
import androidx.test.espresso.matcher.PreferenceMatchers.withKey
|
||||
import androidx.test.espresso.matcher.ViewMatchers.hasDescendant
|
||||
import androidx.test.espresso.matcher.ViewMatchers.withClassName
|
||||
import androidx.test.espresso.matcher.ViewMatchers.withId
|
||||
import androidx.test.espresso.matcher.ViewMatchers.withText
|
||||
import im.vector.app.R
|
||||
import org.hamcrest.Matchers.`is`
|
||||
import org.hamcrest.Matchers.allOf
|
||||
import org.hamcrest.Matchers.instanceOf
|
||||
|
||||
fun clickOnPreference(@StringRes textResId: Int) {
|
||||
onView(withId(R.id.recycler_view))
|
||||
.perform(actionOnItem<RecyclerView.ViewHolder>(
|
||||
hasDescendant(withText(textResId)), click()))
|
||||
}
|
||||
|
||||
fun clickOnSwitchPreference(preferenceKey: String) {
|
||||
onData(allOf(`is`(instanceOf(Preference::class.java)), withKey(preferenceKey)))
|
||||
.onChildView(withClassName(`is`(Switch::class.java.name))).perform(click())
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (c) 2020 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 im.vector.app.espresso.tools
|
||||
|
||||
import android.app.Activity
|
||||
import im.vector.app.activityIdlingResource
|
||||
import im.vector.app.withIdlingResource
|
||||
|
||||
inline fun <reified T : Activity> waitUntilActivityVisible(noinline block: (() -> Unit)) {
|
||||
withIdlingResource(activityIdlingResource(T::class.java), block)
|
||||
}
|
@ -0,0 +1,460 @@
|
||||
/*
|
||||
* Copyright (c) 2020 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 im.vector.app.ui
|
||||
|
||||
import android.view.View
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.test.espresso.Espresso.onView
|
||||
import androidx.test.espresso.Espresso.pressBack
|
||||
import androidx.test.espresso.action.ViewActions.closeSoftKeyboard
|
||||
import androidx.test.espresso.action.ViewActions.longClick
|
||||
import androidx.test.espresso.contrib.RecyclerViewActions.actionOnItem
|
||||
import androidx.test.espresso.matcher.ViewMatchers
|
||||
import androidx.test.espresso.matcher.ViewMatchers.hasDescendant
|
||||
import androidx.test.espresso.matcher.ViewMatchers.isRoot
|
||||
import androidx.test.espresso.matcher.ViewMatchers.withId
|
||||
import androidx.test.espresso.matcher.ViewMatchers.withText
|
||||
import androidx.test.ext.junit.rules.ActivityScenarioRule
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.filters.LargeTest
|
||||
import com.schibsted.spain.barista.assertion.BaristaListAssertions.assertListItemCount
|
||||
import com.schibsted.spain.barista.assertion.BaristaVisibilityAssertions.assertDisplayed
|
||||
import com.schibsted.spain.barista.interaction.BaristaClickInteractions.clickBack
|
||||
import com.schibsted.spain.barista.interaction.BaristaClickInteractions.clickOn
|
||||
import com.schibsted.spain.barista.interaction.BaristaClickInteractions.longClickOn
|
||||
import com.schibsted.spain.barista.interaction.BaristaDialogInteractions.clickDialogNegativeButton
|
||||
import com.schibsted.spain.barista.interaction.BaristaDialogInteractions.clickDialogPositiveButton
|
||||
import com.schibsted.spain.barista.interaction.BaristaEditTextInteractions.writeTo
|
||||
import com.schibsted.spain.barista.interaction.BaristaListInteractions.clickListItem
|
||||
import com.schibsted.spain.barista.interaction.BaristaListInteractions.clickListItemChild
|
||||
import com.schibsted.spain.barista.interaction.BaristaMenuClickInteractions.clickMenu
|
||||
import com.schibsted.spain.barista.interaction.BaristaMenuClickInteractions.openMenu
|
||||
import im.vector.app.EspressoHelper
|
||||
import im.vector.app.R
|
||||
import im.vector.app.SleepViewAction
|
||||
import im.vector.app.activityIdlingResource
|
||||
import im.vector.app.espresso.tools.clickOnPreference
|
||||
import im.vector.app.espresso.tools.waitUntilActivityVisible
|
||||
import im.vector.app.features.MainActivity
|
||||
import im.vector.app.features.createdirect.CreateDirectRoomActivity
|
||||
import im.vector.app.features.home.HomeActivity
|
||||
import im.vector.app.features.home.room.detail.RoomDetailActivity
|
||||
import im.vector.app.features.login.LoginActivity
|
||||
import im.vector.app.features.roomdirectory.RoomDirectoryActivity
|
||||
import im.vector.app.initialSyncIdlingResource
|
||||
import im.vector.app.waitForView
|
||||
import im.vector.app.withIdlingResource
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import java.lang.Thread.sleep
|
||||
import java.util.UUID
|
||||
|
||||
/**
|
||||
* This test aim to open every possible screen of the application
|
||||
*/
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
@LargeTest
|
||||
class UiAllScreensSanityTest {
|
||||
|
||||
@get:Rule
|
||||
val activityRule = ActivityScenarioRule(MainActivity::class.java)
|
||||
|
||||
private val uiTestBase = UiTestBase()
|
||||
|
||||
// Last passing: 2020-11-09
|
||||
@Test
|
||||
fun allScreensTest() {
|
||||
// Create an account
|
||||
val userId = "UiTest_" + UUID.randomUUID().toString()
|
||||
uiTestBase.createAccount(userId = userId)
|
||||
|
||||
withIdlingResource(activityIdlingResource(HomeActivity::class.java)) {
|
||||
assertDisplayed(R.id.roomListContainer)
|
||||
closeSoftKeyboard()
|
||||
}
|
||||
|
||||
val activity = EspressoHelper.getCurrentActivity()!!
|
||||
val uiSession = (activity as HomeActivity).activeSessionHolder.getActiveSession()
|
||||
|
||||
withIdlingResource(initialSyncIdlingResource(uiSession)) {
|
||||
assertDisplayed(R.id.roomListContainer)
|
||||
}
|
||||
|
||||
assertDisplayed(R.id.bottomNavigationView)
|
||||
|
||||
// Settings
|
||||
navigateToSettings()
|
||||
|
||||
// Create DM
|
||||
clickOn(R.id.bottom_action_people)
|
||||
createDm()
|
||||
|
||||
// Create Room
|
||||
// First navigate to the other tab
|
||||
clickOn(R.id.bottom_action_rooms)
|
||||
createRoom()
|
||||
|
||||
assertDisplayed(R.id.bottomNavigationView)
|
||||
|
||||
// Long click on the room
|
||||
onView(withId(R.id.roomListView))
|
||||
.perform(
|
||||
actionOnItem<RecyclerView.ViewHolder>(
|
||||
hasDescendant(withText(R.string.room_displayname_empty_room)),
|
||||
longClick()
|
||||
)
|
||||
)
|
||||
pressBack()
|
||||
|
||||
uiTestBase.signout()
|
||||
|
||||
// We have sent a message in a e2e room, accept to loose it
|
||||
clickOn(R.id.exitAnywayButton)
|
||||
// Dark pattern
|
||||
clickDialogNegativeButton()
|
||||
|
||||
// Login again on the same account
|
||||
waitUntilActivityVisible<LoginActivity> {
|
||||
assertDisplayed(R.id.loginSplashLogo)
|
||||
}
|
||||
|
||||
uiTestBase.login(userId)
|
||||
ignoreVerification()
|
||||
|
||||
uiTestBase.signout()
|
||||
clickDialogPositiveButton()
|
||||
|
||||
// TODO Deactivate account instead of logout?
|
||||
}
|
||||
|
||||
private fun ignoreVerification() {
|
||||
Thread.sleep(6000)
|
||||
val activity = EspressoHelper.getCurrentActivity()!!
|
||||
|
||||
val popup = activity.findViewById<View>(com.tapadoo.alerter.R.id.llAlertBackground)
|
||||
activity.runOnUiThread {
|
||||
popup.performClick()
|
||||
}
|
||||
|
||||
assertDisplayed(R.id.bottomSheetFragmentContainer)
|
||||
|
||||
onView(ViewMatchers.isRoot()).perform(SleepViewAction.sleep(2000))
|
||||
|
||||
clickOn(R.string.skip)
|
||||
assertDisplayed(R.string.are_you_sure)
|
||||
clickOn(R.string.skip)
|
||||
}
|
||||
|
||||
private fun createRoom() {
|
||||
clickOn(R.id.createGroupRoomButton)
|
||||
waitUntilActivityVisible<RoomDirectoryActivity> {
|
||||
assertDisplayed(R.id.publicRoomsList)
|
||||
}
|
||||
clickOn(R.string.create_new_room)
|
||||
|
||||
// Create
|
||||
assertListItemCount(R.id.createRoomForm, 10)
|
||||
clickListItemChild(R.id.createRoomForm, 9, R.id.form_submit_button)
|
||||
|
||||
waitUntilActivityVisible<RoomDetailActivity> {
|
||||
assertDisplayed(R.id.roomDetailContainer)
|
||||
}
|
||||
|
||||
clickOn(R.id.attachmentButton)
|
||||
clickBack()
|
||||
|
||||
// Send a message
|
||||
writeTo(R.id.composerEditText, "Hello world!")
|
||||
clickOn(R.id.sendButton)
|
||||
|
||||
navigateToRoomSettings()
|
||||
|
||||
// Long click on the message
|
||||
longClickOnMessageTest()
|
||||
|
||||
// Menu
|
||||
openMenu()
|
||||
pressBack()
|
||||
clickMenu(R.id.voice_call)
|
||||
pressBack()
|
||||
clickMenu(R.id.video_call)
|
||||
pressBack()
|
||||
|
||||
pressBack()
|
||||
}
|
||||
|
||||
private fun longClickOnMessageTest() {
|
||||
// Test quick reaction
|
||||
longClickOnMessage()
|
||||
// Add quick reaction
|
||||
clickOn("👍")
|
||||
|
||||
sleep(1000)
|
||||
|
||||
// Open reactions
|
||||
longClickOn("👍")
|
||||
pressBack()
|
||||
|
||||
// Test add reaction
|
||||
longClickOnMessage()
|
||||
clickOn(R.string.message_add_reaction)
|
||||
// Filter
|
||||
// TODO clickMenu(R.id.search)
|
||||
clickListItem(R.id.emojiRecyclerView, 4)
|
||||
|
||||
// Test Edit mode
|
||||
longClickOnMessage()
|
||||
clickOn(R.string.edit)
|
||||
// TODO Cancel action
|
||||
writeTo(R.id.composerEditText, "Hello universe!")
|
||||
clickOn(R.id.sendButton)
|
||||
// Open edit history
|
||||
longClickOnMessage("Hello universe! (edited)")
|
||||
clickOn(R.string.message_view_edit_history)
|
||||
pressBack()
|
||||
}
|
||||
|
||||
private fun longClickOnMessage(text: String = "Hello world!") {
|
||||
onView(withId(R.id.timelineRecyclerView))
|
||||
.perform(
|
||||
actionOnItem<RecyclerView.ViewHolder>(
|
||||
hasDescendant(withText(text)),
|
||||
longClick()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private fun navigateToRoomSettings() {
|
||||
clickOn(R.id.roomToolbarTitleView)
|
||||
assertDisplayed(R.id.roomProfileAvatarView)
|
||||
|
||||
// Room settings
|
||||
clickListItem(R.id.matrixProfileRecyclerView, 3)
|
||||
pressBack()
|
||||
|
||||
// Notifications
|
||||
clickListItem(R.id.matrixProfileRecyclerView, 5)
|
||||
pressBack()
|
||||
|
||||
assertDisplayed(R.id.roomProfileAvatarView)
|
||||
|
||||
// People
|
||||
clickListItem(R.id.matrixProfileRecyclerView, 7)
|
||||
assertDisplayed(R.id.inviteUsersButton)
|
||||
navigateToRoomPeople()
|
||||
// Fab
|
||||
navigateToInvite()
|
||||
pressBack()
|
||||
pressBack()
|
||||
|
||||
assertDisplayed(R.id.roomProfileAvatarView)
|
||||
|
||||
// Uploads
|
||||
clickListItem(R.id.matrixProfileRecyclerView, 9)
|
||||
// File tab
|
||||
clickOn(R.string.uploads_files_title)
|
||||
pressBack()
|
||||
|
||||
assertDisplayed(R.id.roomProfileAvatarView)
|
||||
|
||||
// Leave
|
||||
clickListItem(R.id.matrixProfileRecyclerView, 13)
|
||||
clickDialogNegativeButton()
|
||||
|
||||
// Menu share
|
||||
// clickMenu(R.id.roomProfileShareAction)
|
||||
// pressBack()
|
||||
|
||||
pressBack()
|
||||
}
|
||||
|
||||
private fun navigateToInvite() {
|
||||
assertDisplayed(R.id.inviteUsersButton)
|
||||
clickOn(R.id.inviteUsersButton)
|
||||
closeSoftKeyboard()
|
||||
pressBack()
|
||||
}
|
||||
|
||||
private fun navigateToRoomPeople() {
|
||||
// Open first user
|
||||
clickListItem(R.id.roomSettingsRecyclerView, 1)
|
||||
assertDisplayed(R.id.memberProfilePowerLevelView)
|
||||
|
||||
// Verification
|
||||
clickListItem(R.id.matrixProfileRecyclerView, 1)
|
||||
clickBack()
|
||||
|
||||
// Role
|
||||
clickListItem(R.id.matrixProfileRecyclerView, 3)
|
||||
clickDialogNegativeButton()
|
||||
|
||||
clickBack()
|
||||
}
|
||||
|
||||
private fun createDm() {
|
||||
clickOn(R.id.createChatRoomButton)
|
||||
|
||||
withIdlingResource(activityIdlingResource(CreateDirectRoomActivity::class.java)) {
|
||||
assertDisplayed(R.id.addByMatrixId)
|
||||
}
|
||||
|
||||
closeSoftKeyboard()
|
||||
pressBack()
|
||||
pressBack()
|
||||
}
|
||||
|
||||
private fun navigateToSettings() {
|
||||
clickOn(R.id.groupToolbarAvatarImageView)
|
||||
clickOn(R.id.homeDrawerHeaderSettingsView)
|
||||
|
||||
clickOn(R.string.settings_general_title)
|
||||
navigateToSettingsGeneral()
|
||||
pressBack()
|
||||
|
||||
clickOn(R.string.settings_notifications)
|
||||
navigateToSettingsNotifications()
|
||||
pressBack()
|
||||
|
||||
clickOn(R.string.settings_preferences)
|
||||
navigateToSettingsPreferences()
|
||||
pressBack()
|
||||
|
||||
clickOn(R.string.preference_voice_and_video)
|
||||
pressBack()
|
||||
|
||||
clickOn(R.string.settings_ignored_users)
|
||||
pressBack()
|
||||
|
||||
clickOn(R.string.settings_security_and_privacy)
|
||||
navigateToSettingsSecurity()
|
||||
pressBack()
|
||||
|
||||
clickOn(R.string.room_settings_labs_pref_title)
|
||||
pressBack()
|
||||
|
||||
clickOn(R.string.settings_advanced_settings)
|
||||
navigateToSettingsAdvanced()
|
||||
pressBack()
|
||||
|
||||
clickOn(R.string.preference_root_help_about)
|
||||
navigateToSettingsHelp()
|
||||
pressBack()
|
||||
|
||||
pressBack()
|
||||
}
|
||||
|
||||
private fun navigateToSettingsHelp() {
|
||||
/*
|
||||
clickOn(R.string.settings_app_info_link_title)
|
||||
Cannot go back...
|
||||
pressBack()
|
||||
clickOn(R.string.settings_copyright)
|
||||
pressBack()
|
||||
clickOn(R.string.settings_app_term_conditions)
|
||||
pressBack()
|
||||
clickOn(R.string.settings_privacy_policy)
|
||||
pressBack()
|
||||
*/
|
||||
clickOn(R.string.settings_third_party_notices)
|
||||
clickDialogPositiveButton()
|
||||
}
|
||||
|
||||
private fun navigateToSettingsAdvanced() {
|
||||
clickOnPreference(R.string.settings_notifications_targets)
|
||||
pressBack()
|
||||
|
||||
clickOnPreference(R.string.settings_push_rules)
|
||||
pressBack()
|
||||
|
||||
/* TODO P2 test developer screens
|
||||
// Enable developer mode
|
||||
clickOnSwitchPreference("SETTINGS_DEVELOPER_MODE_PREFERENCE_KEY")
|
||||
|
||||
clickOnPreference(R.string.settings_account_data)
|
||||
clickOn("m.push_rules")
|
||||
pressBack()
|
||||
pressBack()
|
||||
clickOnPreference(R.string.settings_key_requests)
|
||||
pressBack()
|
||||
|
||||
// Disable developer mode
|
||||
clickOnSwitchPreference("SETTINGS_DEVELOPER_MODE_PREFERENCE_KEY")
|
||||
*/
|
||||
}
|
||||
|
||||
private fun navigateToSettingsSecurity() {
|
||||
clickOnPreference(R.string.settings_active_sessions_show_all)
|
||||
pressBack()
|
||||
|
||||
clickOnPreference(R.string.encryption_message_recovery)
|
||||
// TODO go deeper here
|
||||
pressBack()
|
||||
/* Cannot exit
|
||||
clickOnPreference(R.string.encryption_export_e2e_room_keys)
|
||||
pressBack()
|
||||
*/
|
||||
}
|
||||
|
||||
private fun navigateToSettingsPreferences() {
|
||||
clickOn(R.string.settings_interface_language)
|
||||
onView(isRoot())
|
||||
.perform(waitForView(withText("Dansk (Danmark)")))
|
||||
pressBack()
|
||||
clickOn(R.string.settings_theme)
|
||||
clickDialogNegativeButton()
|
||||
clickOn(R.string.font_size)
|
||||
clickDialogNegativeButton()
|
||||
}
|
||||
|
||||
private fun navigateToSettingsNotifications() {
|
||||
clickOn(R.string.settings_notification_advanced)
|
||||
pressBack()
|
||||
/*
|
||||
clickOn(R.string.settings_noisy_notifications_preferences)
|
||||
TODO Cannot go back
|
||||
pressBack()
|
||||
clickOn(R.string.settings_silent_notifications_preferences)
|
||||
pressBack()
|
||||
clickOn(R.string.settings_call_notifications_preferences)
|
||||
pressBack()
|
||||
*/
|
||||
clickOnPreference(R.string.settings_notification_troubleshoot)
|
||||
pressBack()
|
||||
}
|
||||
|
||||
private fun navigateToSettingsGeneral() {
|
||||
clickOn(R.string.settings_profile_picture)
|
||||
clickDialogPositiveButton()
|
||||
clickOn(R.string.settings_display_name)
|
||||
clickDialogNegativeButton()
|
||||
clickOn(R.string.settings_password)
|
||||
clickDialogNegativeButton()
|
||||
clickOn(R.string.settings_emails_and_phone_numbers_title)
|
||||
pressBack()
|
||||
clickOn(R.string.settings_discovery_manage)
|
||||
clickOn(R.string.add_identity_server)
|
||||
pressBack()
|
||||
pressBack()
|
||||
// Identity server
|
||||
clickOnPreference(R.string.settings_identity_server)
|
||||
pressBack()
|
||||
// Deactivate account
|
||||
clickOnPreference(R.string.settings_deactivate_my_account)
|
||||
pressBack()
|
||||
}
|
||||
}
|
90
vector/src/androidTest/java/im/vector/app/ui/UiTestBase.kt
Normal file
90
vector/src/androidTest/java/im/vector/app/ui/UiTestBase.kt
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (c) 2020 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 im.vector.app.ui
|
||||
|
||||
import androidx.test.espresso.Espresso.closeSoftKeyboard
|
||||
import androidx.test.espresso.Espresso.onView
|
||||
import androidx.test.espresso.matcher.ViewMatchers.isRoot
|
||||
import androidx.test.espresso.matcher.ViewMatchers.withId
|
||||
import com.schibsted.spain.barista.assertion.BaristaEnabledAssertions.assertDisabled
|
||||
import com.schibsted.spain.barista.assertion.BaristaEnabledAssertions.assertEnabled
|
||||
import com.schibsted.spain.barista.assertion.BaristaVisibilityAssertions.assertDisplayed
|
||||
import com.schibsted.spain.barista.interaction.BaristaClickInteractions.clickOn
|
||||
import com.schibsted.spain.barista.interaction.BaristaEditTextInteractions.writeTo
|
||||
import im.vector.app.R
|
||||
import im.vector.app.espresso.tools.waitUntilActivityVisible
|
||||
import im.vector.app.features.home.HomeActivity
|
||||
import im.vector.app.waitForView
|
||||
|
||||
class UiTestBase {
|
||||
fun createAccount(userId: String, password: String = "password", homeServerUrl: String = "http://10.0.2.2:8080") {
|
||||
initSession(true, userId, password, homeServerUrl)
|
||||
}
|
||||
|
||||
fun login(userId: String, password: String = "password", homeServerUrl: String = "http://10.0.2.2:8080") {
|
||||
initSession(false, userId, password, homeServerUrl)
|
||||
}
|
||||
|
||||
private fun initSession(createAccount: Boolean,
|
||||
userId: String,
|
||||
password: String,
|
||||
homeServerUrl: String) {
|
||||
assertDisplayed(R.id.loginSplashSubmit, R.string.login_splash_submit)
|
||||
clickOn(R.id.loginSplashSubmit)
|
||||
assertDisplayed(R.id.loginServerTitle, R.string.login_server_title)
|
||||
// Chose custom server
|
||||
clickOn(R.id.loginServerChoiceOther)
|
||||
// Enter local synapse
|
||||
writeTo(R.id.loginServerUrlFormHomeServerUrl, homeServerUrl)
|
||||
assertEnabled(R.id.loginServerUrlFormSubmit)
|
||||
closeSoftKeyboard()
|
||||
clickOn(R.id.loginServerUrlFormSubmit)
|
||||
onView(isRoot()).perform(waitForView(withId(R.id.loginSignupSigninSubmit)))
|
||||
|
||||
if (createAccount) {
|
||||
// Click on the signup button
|
||||
assertDisplayed(R.id.loginSignupSigninSubmit)
|
||||
clickOn(R.id.loginSignupSigninSubmit)
|
||||
} else {
|
||||
// Click on the signin button
|
||||
assertDisplayed(R.id.loginSignupSigninSignIn)
|
||||
clickOn(R.id.loginSignupSigninSignIn)
|
||||
}
|
||||
|
||||
// Ensure password flow supported
|
||||
assertDisplayed(R.id.loginField)
|
||||
assertDisplayed(R.id.passwordField)
|
||||
|
||||
writeTo(R.id.loginField, userId)
|
||||
assertDisabled(R.id.loginSubmit)
|
||||
writeTo(R.id.passwordField, password)
|
||||
assertEnabled(R.id.loginSubmit)
|
||||
|
||||
closeSoftKeyboard()
|
||||
clickOn(R.id.loginSubmit)
|
||||
|
||||
// Wait
|
||||
waitUntilActivityVisible<HomeActivity> {
|
||||
assertDisplayed(R.id.homeDetailFragmentContainer)
|
||||
}
|
||||
}
|
||||
|
||||
fun signout() {
|
||||
clickOn(R.id.groupToolbarAvatarImageView)
|
||||
clickOn(R.id.homeDrawerHeaderSignoutView)
|
||||
}
|
||||
}
|
@ -30,12 +30,12 @@ class DebugSasEmojiActivity : AppCompatActivity() {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.fragment_generic_recycler)
|
||||
val controller = SasEmojiController()
|
||||
recyclerView.configureWith(controller)
|
||||
genericRecyclerView.configureWith(controller)
|
||||
controller.setData(SasState(getAllVerificationEmojis()))
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
recyclerView.cleanup()
|
||||
genericRecyclerView.cleanup()
|
||||
super.onDestroy()
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ import im.vector.app.features.settings.VectorSettingsUrls
|
||||
// Increase this value to show again the disclaimer dialog after an upgrade of the application
|
||||
private const val CURRENT_DISCLAIMER_VALUE = 2
|
||||
|
||||
private const val SHARED_PREF_KEY = "LAST_DISCLAIMER_VERSION_VALUE"
|
||||
const val SHARED_PREF_KEY = "LAST_DISCLAIMER_VERSION_VALUE"
|
||||
|
||||
fun showDisclaimerDialog(activity: Activity) {
|
||||
val sharedPrefs = DefaultSharedPreferences.getInstance(activity)
|
||||
|
@ -55,7 +55,7 @@ class DiscoverySettingsFragment @Inject constructor(
|
||||
sharedViewModel = activityViewModelProvider.get(DiscoverySharedViewModel::class.java)
|
||||
|
||||
controller.listener = this
|
||||
recyclerView.configureWith(controller)
|
||||
genericRecyclerView.configureWith(controller)
|
||||
|
||||
sharedViewModel.navigateEvent.observeEvent(this) {
|
||||
when (it) {
|
||||
@ -74,7 +74,7 @@ class DiscoverySettingsFragment @Inject constructor(
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
recyclerView.cleanup()
|
||||
genericRecyclerView.cleanup()
|
||||
controller.listener = null
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
@ -22,6 +22,6 @@ import org.matrix.android.sdk.api.util.MatrixItem
|
||||
sealed class HomeActivityViewEvents : VectorViewEvents {
|
||||
data class AskPasswordToInitCrossSigning(val userItem: MatrixItem.UserItem?) : HomeActivityViewEvents()
|
||||
data class OnNewSession(val userItem: MatrixItem.UserItem?, val waitForIncomingRequest: Boolean = true) : HomeActivityViewEvents()
|
||||
data class OnCrossSignedInvalidated(val userItem: MatrixItem.UserItem?) : HomeActivityViewEvents()
|
||||
data class OnCrossSignedInvalidated(val userItem: MatrixItem.UserItem) : HomeActivityViewEvents()
|
||||
object PromptToEnableSessionPush : HomeActivityViewEvents()
|
||||
}
|
||||
|
@ -78,29 +78,30 @@ class HomeActivityViewModel @AssistedInject constructor(
|
||||
}
|
||||
|
||||
private fun observeCrossSigningReset() {
|
||||
val safeActiveSession = activeSessionHolder.getSafeActiveSession()
|
||||
val crossSigningService = safeActiveSession
|
||||
?.cryptoService()
|
||||
?.crossSigningService()
|
||||
onceTrusted = crossSigningService
|
||||
?.allPrivateKeysKnown() ?: false
|
||||
val safeActiveSession = activeSessionHolder.getSafeActiveSession() ?: return
|
||||
|
||||
onceTrusted = safeActiveSession
|
||||
.cryptoService()
|
||||
.crossSigningService().allPrivateKeysKnown()
|
||||
|
||||
safeActiveSession
|
||||
?.rx()
|
||||
?.liveCrossSigningInfo(safeActiveSession.myUserId)
|
||||
?.subscribe {
|
||||
.rx()
|
||||
.liveCrossSigningInfo(safeActiveSession.myUserId)
|
||||
.subscribe {
|
||||
val isVerified = it.getOrNull()?.isTrusted() ?: false
|
||||
if (!isVerified && onceTrusted) {
|
||||
// cross signing keys have been reset
|
||||
// Tigger a popup to re-verify
|
||||
_viewEvents.post(
|
||||
HomeActivityViewEvents.OnCrossSignedInvalidated(
|
||||
safeActiveSession.getUser(safeActiveSession.myUserId)?.toMatrixItem()
|
||||
)
|
||||
)
|
||||
// Note: user can be null in case of logout
|
||||
safeActiveSession.getUser(safeActiveSession.myUserId)
|
||||
?.toMatrixItem()
|
||||
?.let { user ->
|
||||
_viewEvents.post(HomeActivityViewEvents.OnCrossSignedInvalidated(user))
|
||||
}
|
||||
}
|
||||
onceTrusted = isVerified
|
||||
}?.disposeOnClear()
|
||||
}
|
||||
.disposeOnClear()
|
||||
}
|
||||
|
||||
private fun observeInitialSync() {
|
||||
|
@ -543,7 +543,7 @@ class RoomDetailFragment @Inject constructor(
|
||||
modelBuildListener = null
|
||||
autoCompleter.clear()
|
||||
debouncer.cancelAll()
|
||||
recyclerView.cleanup()
|
||||
timelineRecyclerView.cleanup()
|
||||
|
||||
super.onDestroyView()
|
||||
}
|
||||
@ -570,7 +570,7 @@ class RoomDetailFragment @Inject constructor(
|
||||
jumpToBottomViewVisibilityManager = JumpToBottomViewVisibilityManager(
|
||||
jumpToBottomView,
|
||||
debouncer,
|
||||
recyclerView,
|
||||
timelineRecyclerView,
|
||||
layoutManager
|
||||
)
|
||||
}
|
||||
@ -593,7 +593,7 @@ class RoomDetailFragment @Inject constructor(
|
||||
if (scrollPosition == null) {
|
||||
scrollOnHighlightedEventCallback.scheduleScrollTo(action.eventId)
|
||||
} else {
|
||||
recyclerView.stopScroll()
|
||||
timelineRecyclerView.stopScroll()
|
||||
layoutManager.scrollToPosition(scrollPosition)
|
||||
}
|
||||
}
|
||||
@ -1004,14 +1004,14 @@ class RoomDetailFragment @Inject constructor(
|
||||
timelineEventController.callback = this
|
||||
timelineEventController.timeline = roomDetailViewModel.timeline
|
||||
|
||||
recyclerView.trackItemsVisibilityChange()
|
||||
timelineRecyclerView.trackItemsVisibilityChange()
|
||||
layoutManager = LinearLayoutManager(context, RecyclerView.VERTICAL, true)
|
||||
val stateRestorer = LayoutManagerStateRestorer(layoutManager).register()
|
||||
scrollOnNewMessageCallback = ScrollOnNewMessageCallback(layoutManager, timelineEventController)
|
||||
scrollOnHighlightedEventCallback = ScrollOnHighlightedEventCallback(recyclerView, layoutManager, timelineEventController)
|
||||
recyclerView.layoutManager = layoutManager
|
||||
recyclerView.itemAnimator = null
|
||||
recyclerView.setHasFixedSize(true)
|
||||
scrollOnHighlightedEventCallback = ScrollOnHighlightedEventCallback(timelineRecyclerView, layoutManager, timelineEventController)
|
||||
timelineRecyclerView.layoutManager = layoutManager
|
||||
timelineRecyclerView.itemAnimator = null
|
||||
timelineRecyclerView.setHasFixedSize(true)
|
||||
modelBuildListener = OnModelBuildFinishedListener {
|
||||
it.dispatchTo(stateRestorer)
|
||||
it.dispatchTo(scrollOnNewMessageCallback)
|
||||
@ -1020,7 +1020,7 @@ class RoomDetailFragment @Inject constructor(
|
||||
jumpToBottomViewVisibilityManager.maybeShowJumpToBottomViewVisibilityWithDelay()
|
||||
}
|
||||
timelineEventController.addModelBuildListener(modelBuildListener)
|
||||
recyclerView.adapter = timelineEventController.adapter
|
||||
timelineRecyclerView.adapter = timelineEventController.adapter
|
||||
|
||||
if (vectorPreferences.swipeToReplyIsEnabled()) {
|
||||
val quickReplyHandler = object : RoomMessageTouchHelperCallback.QuickReplayHandler {
|
||||
@ -1050,9 +1050,9 @@ class RoomDetailFragment @Inject constructor(
|
||||
}
|
||||
val swipeCallback = RoomMessageTouchHelperCallback(requireContext(), R.drawable.ic_reply, quickReplyHandler)
|
||||
val touchHelper = ItemTouchHelper(swipeCallback)
|
||||
touchHelper.attachToRecyclerView(recyclerView)
|
||||
touchHelper.attachToRecyclerView(timelineRecyclerView)
|
||||
}
|
||||
recyclerView.addGlidePreloader(
|
||||
timelineRecyclerView.addGlidePreloader(
|
||||
epoxyController = timelineEventController,
|
||||
requestManager = GlideApp.with(this),
|
||||
preloader = glidePreloader { requestManager, epoxyModel: MessageImageVideoItem, _ ->
|
||||
|
@ -46,7 +46,7 @@ class PopupAlertManager @Inject constructor(private val avatarRenderer: Lazy<Ava
|
||||
private var weakCurrentActivity: WeakReference<Activity>? = null
|
||||
private var currentAlerter: VectorAlert? = null
|
||||
|
||||
private val alertFiFo = ArrayList<VectorAlert>()
|
||||
private val alertFiFo = mutableListOf<VectorAlert>()
|
||||
|
||||
fun postVectorAlert(alert: VectorAlert) {
|
||||
synchronized(alertFiFo) {
|
||||
|
@ -41,12 +41,12 @@ class EmojiSearchResultFragment @Inject constructor(
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
sharedViewModel = activityViewModelProvider.get(EmojiChooserViewModel::class.java)
|
||||
epoxyController.listener = this
|
||||
recyclerView.configureWith(epoxyController, showDivider = true)
|
||||
genericRecyclerView.configureWith(epoxyController, showDivider = true)
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
epoxyController.listener = null
|
||||
recyclerView.cleanup()
|
||||
genericRecyclerView.cleanup()
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
|
@ -56,7 +56,7 @@ class RoomBannedMemberListFragment @Inject constructor(
|
||||
roomMemberListController.callback = this
|
||||
setupToolbar(roomSettingsToolbar)
|
||||
setupSearchView()
|
||||
recyclerView.configureWith(roomMemberListController, hasFixedSize = true)
|
||||
roomSettingsRecyclerView.configureWith(roomMemberListController, hasFixedSize = true)
|
||||
|
||||
viewModel.observeViewEvents {
|
||||
when (it) {
|
||||
@ -83,7 +83,7 @@ class RoomBannedMemberListFragment @Inject constructor(
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
recyclerView.cleanup()
|
||||
roomSettingsRecyclerView.cleanup()
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ class RoomMemberListFragment @Inject constructor(
|
||||
setupToolbar(roomSettingsToolbar)
|
||||
setupSearchView()
|
||||
setupInviteUsersButton()
|
||||
recyclerView.configureWith(roomMemberListController, hasFixedSize = true)
|
||||
roomSettingsRecyclerView.configureWith(roomMemberListController, hasFixedSize = true)
|
||||
}
|
||||
|
||||
private fun setupInviteUsersButton() {
|
||||
@ -65,7 +65,7 @@ class RoomMemberListFragment @Inject constructor(
|
||||
navigator.openInviteUsersToRoom(requireContext(), roomProfileArgs.roomId)
|
||||
}
|
||||
// Hide FAB when list is scrolling
|
||||
recyclerView.addOnScrollListener(
|
||||
roomSettingsRecyclerView.addOnScrollListener(
|
||||
object : RecyclerView.OnScrollListener() {
|
||||
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
|
||||
when (newState) {
|
||||
@ -99,7 +99,7 @@ class RoomMemberListFragment @Inject constructor(
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
recyclerView.cleanup()
|
||||
roomSettingsRecyclerView.cleanup()
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
|
@ -72,7 +72,7 @@ class RoomSettingsFragment @Inject constructor(
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
controller.callback = this
|
||||
setupToolbar(roomSettingsToolbar)
|
||||
recyclerView.configureWith(controller, hasFixedSize = true)
|
||||
roomSettingsRecyclerView.configureWith(controller, hasFixedSize = true)
|
||||
waiting_view_status_text.setText(R.string.please_wait)
|
||||
waiting_view_status_text.isVisible = true
|
||||
|
||||
@ -93,7 +93,8 @@ class RoomSettingsFragment @Inject constructor(
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
recyclerView.cleanup()
|
||||
controller.callback = null
|
||||
roomSettingsRecyclerView.cleanup()
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@ import com.squareup.seismic.ShakeDetector
|
||||
import im.vector.app.BuildConfig
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.di.DefaultSharedPreferences
|
||||
import im.vector.app.features.disclaimer.SHARED_PREF_KEY
|
||||
import im.vector.app.features.homeserver.ServerUrlsRepository
|
||||
import im.vector.app.features.themes.ThemeUtils
|
||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||
@ -248,6 +249,9 @@ class VectorPreferences @Inject constructor(private val context: Context) {
|
||||
// theme
|
||||
keysToKeep.add(ThemeUtils.APPLICATION_THEME_KEY)
|
||||
|
||||
// Disclaimer dialog
|
||||
keysToKeep.add(SHARED_PREF_KEY)
|
||||
|
||||
// get all the existing keys
|
||||
val keys = defaultPrefs.all.keys
|
||||
|
||||
|
@ -68,12 +68,12 @@ class CrossSigningSettingsFragment @Inject constructor(
|
||||
}
|
||||
|
||||
private fun setupRecyclerView() {
|
||||
recyclerView.configureWith(controller, hasFixedSize = false, disableItemAnimation = true)
|
||||
genericRecyclerView.configureWith(controller, hasFixedSize = false, disableItemAnimation = true)
|
||||
controller.interactionListener = this
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
recyclerView.cleanup()
|
||||
genericRecyclerView.cleanup()
|
||||
controller.interactionListener = null
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ class VectorSettingsDevicesFragment @Inject constructor(
|
||||
waiting_view_status_text.setText(R.string.please_wait)
|
||||
waiting_view_status_text.isVisible = true
|
||||
devicesController.callback = this
|
||||
recyclerView.configureWith(devicesController, showDivider = true)
|
||||
genericRecyclerView.configureWith(devicesController, showDivider = true)
|
||||
viewModel.observeViewEvents {
|
||||
when (it) {
|
||||
is DevicesViewEvents.Loading -> showLoading(it.message)
|
||||
@ -97,7 +97,7 @@ class VectorSettingsDevicesFragment @Inject constructor(
|
||||
|
||||
override fun onDestroyView() {
|
||||
devicesController.callback = null
|
||||
recyclerView.cleanup()
|
||||
genericRecyclerView.cleanup()
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
|
@ -57,13 +57,13 @@ class AccountDataFragment @Inject constructor(
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
recyclerView.configureWith(epoxyController, showDivider = true)
|
||||
genericRecyclerView.configureWith(epoxyController, showDivider = true)
|
||||
epoxyController.interactionListener = this
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
recyclerView.cleanup()
|
||||
genericRecyclerView.cleanup()
|
||||
epoxyController.interactionListener = null
|
||||
}
|
||||
|
||||
|
@ -50,13 +50,13 @@ class GossipingEventsPaperTrailFragment @Inject constructor(
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
recyclerView.configureWith(epoxyController, showDivider = true)
|
||||
genericRecyclerView.configureWith(epoxyController, showDivider = true)
|
||||
epoxyController.interactionListener = this
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
recyclerView.cleanup()
|
||||
genericRecyclerView.cleanup()
|
||||
epoxyController.interactionListener = null
|
||||
}
|
||||
|
||||
|
@ -45,11 +45,11 @@ class IncomingKeyRequestListFragment @Inject constructor(
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
recyclerView.configureWith(epoxyController, showDivider = true)
|
||||
genericRecyclerView.configureWith(epoxyController, showDivider = true)
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
recyclerView.cleanup()
|
||||
genericRecyclerView.cleanup()
|
||||
}
|
||||
}
|
||||
|
@ -41,13 +41,13 @@ class OutgoingKeyRequestListFragment @Inject constructor(
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
recyclerView.configureWith(epoxyController, showDivider = true)
|
||||
genericRecyclerView.configureWith(epoxyController, showDivider = true)
|
||||
// epoxyController.interactionListener = this
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
recyclerView.cleanup()
|
||||
genericRecyclerView.cleanup()
|
||||
// epoxyController.interactionListener = null
|
||||
}
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ class VectorSettingsIgnoredUsersFragment @Inject constructor(
|
||||
waiting_view_status_text.setText(R.string.please_wait)
|
||||
waiting_view_status_text.isVisible = true
|
||||
ignoredUsersController.callback = this
|
||||
recyclerView.configureWith(ignoredUsersController)
|
||||
genericRecyclerView.configureWith(ignoredUsersController)
|
||||
viewModel.observeViewEvents {
|
||||
when (it) {
|
||||
is IgnoredUsersViewEvents.Loading -> showLoading(it.message)
|
||||
@ -60,7 +60,7 @@ class VectorSettingsIgnoredUsersFragment @Inject constructor(
|
||||
|
||||
override fun onDestroyView() {
|
||||
ignoredUsersController.callback = null
|
||||
recyclerView.cleanup()
|
||||
genericRecyclerView.cleanup()
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
|
@ -59,11 +59,11 @@ class PushGatewaysFragment @Inject constructor(
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
recyclerView.configureWith(epoxyController, showDivider = true)
|
||||
genericRecyclerView.configureWith(epoxyController, showDivider = true)
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
recyclerView.cleanup()
|
||||
genericRecyclerView.cleanup()
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
|
@ -43,11 +43,11 @@ class PushRulesFragment @Inject constructor(
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
recyclerView.configureWith(epoxyController, showDivider = true)
|
||||
genericRecyclerView.configureWith(epoxyController, showDivider = true)
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
recyclerView.cleanup()
|
||||
genericRecyclerView.cleanup()
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,7 @@ class ThreePidsSettingsFragment @Inject constructor(
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
recyclerView.configureWith(epoxyController)
|
||||
genericRecyclerView.configureWith(epoxyController)
|
||||
epoxyController.interactionListener = this
|
||||
|
||||
viewModel.observeViewEvents {
|
||||
@ -73,7 +73,7 @@ class ThreePidsSettingsFragment @Inject constructor(
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
recyclerView.cleanup()
|
||||
genericRecyclerView.cleanup()
|
||||
epoxyController.interactionListener = null
|
||||
}
|
||||
|
||||
|
@ -70,12 +70,12 @@ class SoftLogoutFragment @Inject constructor(
|
||||
}
|
||||
|
||||
private fun setupRecyclerView() {
|
||||
recyclerView.configureWith(softLogoutController)
|
||||
genericRecyclerView.configureWith(softLogoutController)
|
||||
softLogoutController.listener = this
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
recyclerView.cleanup()
|
||||
genericRecyclerView.cleanup()
|
||||
softLogoutController.listener = null
|
||||
super.onDestroyView()
|
||||
}
|
||||
@ -121,7 +121,7 @@ class SoftLogoutFragment @Inject constructor(
|
||||
}
|
||||
|
||||
private fun cleanupUi() {
|
||||
recyclerView.hideKeyboard()
|
||||
genericRecyclerView.hideKeyboard()
|
||||
}
|
||||
|
||||
override fun forgetPasswordClicked() {
|
||||
|
@ -82,7 +82,7 @@ class KnownUsersFragment @Inject constructor(
|
||||
|
||||
override fun onDestroyView() {
|
||||
knownUsersController.callback = null
|
||||
recyclerView.cleanup()
|
||||
knownUsersRecyclerView.cleanup()
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
@ -124,7 +124,7 @@ class KnownUsersFragment @Inject constructor(
|
||||
private fun setupRecyclerView() {
|
||||
knownUsersController.callback = this
|
||||
// Don't activate animation as we might have way to much item animation when filtering
|
||||
recyclerView.configureWith(knownUsersController, disableItemAnimation = true)
|
||||
knownUsersRecyclerView.configureWith(knownUsersController, disableItemAnimation = true)
|
||||
}
|
||||
|
||||
private fun setupFilterView() {
|
||||
|
@ -28,7 +28,6 @@ import im.vector.app.core.extensions.hideKeyboard
|
||||
import im.vector.app.core.extensions.setupAsSearch
|
||||
import im.vector.app.core.extensions.showKeyboard
|
||||
import im.vector.app.core.platform.VectorBaseFragment
|
||||
import kotlinx.android.synthetic.main.fragment_create_direct_room_directory_users.recyclerView
|
||||
import kotlinx.android.synthetic.main.fragment_user_directory.*
|
||||
import org.matrix.android.sdk.api.session.user.model.User
|
||||
import javax.inject.Inject
|
||||
@ -51,14 +50,14 @@ class UserDirectoryFragment @Inject constructor(
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
recyclerView.cleanup()
|
||||
userDirectoryRecyclerView.cleanup()
|
||||
directRoomController.callback = null
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
private fun setupRecyclerView() {
|
||||
directRoomController.callback = this
|
||||
recyclerView.configureWith(directRoomController)
|
||||
userDirectoryRecyclerView.configureWith(directRoomController)
|
||||
}
|
||||
|
||||
private fun setupSearchByMatrixIdView() {
|
||||
|
@ -1,143 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/createDirectRoomToolbar"
|
||||
style="@style/VectorToolbarStyle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="?actionBarSize"
|
||||
android:elevation="4dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/createDirectRoomClose"
|
||||
android:layout_width="@dimen/layout_touch_size"
|
||||
android:layout_height="@dimen/layout_touch_size"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:foreground="?attr/selectableItemBackground"
|
||||
android:scaleType="center"
|
||||
android:src="@drawable/ic_x_18dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/createDirectRoomTitle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="@string/fab_menu_create_chat"
|
||||
android:textColor="?riotx_text_primary"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toEndOf="@+id/createDirectRoomClose"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.appcompat.widget.Toolbar>
|
||||
|
||||
<im.vector.app.core.platform.MaxHeightScrollView
|
||||
android:id="@+id/chipGroupScrollView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/layout_horizontal_margin"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="@dimen/layout_horizontal_margin"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/createDirectRoomToolbar"
|
||||
app:maxHeight="64dp">
|
||||
|
||||
<com.google.android.material.chip.ChipGroup
|
||||
android:id="@+id/chipGroup"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:lineSpacing="2dp" />
|
||||
|
||||
</im.vector.app.core.platform.MaxHeightScrollView>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/createDirectRoomFilter"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/layout_horizontal_margin"
|
||||
android:layout_marginEnd="@dimen/layout_horizontal_margin"
|
||||
android:background="@null"
|
||||
android:drawablePadding="8dp"
|
||||
android:gravity="center_vertical"
|
||||
android:hint="@string/direct_room_filter_hint"
|
||||
android:importantForAutofill="no"
|
||||
android:inputType="text"
|
||||
android:maxHeight="80dp"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingBottom="16dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/chipGroupScrollView" />
|
||||
|
||||
<View
|
||||
android:id="@+id/createDirectRoomFilterDivider"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="1dp"
|
||||
android:background="?attr/vctr_list_divider_color"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/createDirectRoomFilter" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/addByMatrixId"
|
||||
style="@style/VectorButtonStyleText"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:minHeight="@dimen/layout_touch_size"
|
||||
android:text="@string/add_by_matrix_id"
|
||||
android:visibility="visible"
|
||||
app:icon="@drawable/ic_plus_circle"
|
||||
app:iconPadding="13dp"
|
||||
app:iconTint="@color/riotx_accent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/createDirectRoomFilterDivider" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recyclerView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:fastScrollEnabled="true"
|
||||
android:overScrollMode="always"
|
||||
android:scrollbars="vertical"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/addByMatrixId"
|
||||
tools:listitem="@layout/item_create_direct_room_user" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
@ -90,7 +90,7 @@
|
||||
app:layout_constraintTop_toBottomOf="@+id/createDirectRoomSearchByIdContainer" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recyclerView"
|
||||
android:id="@+id/createDirectRoomRecyclerView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginTop="16dp"
|
||||
|
@ -7,7 +7,7 @@
|
||||
android:background="?riotx_background">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recyclerView"
|
||||
android:id="@+id/genericRecyclerView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:itemSpacing="1dp"
|
||||
|
@ -105,7 +105,7 @@
|
||||
<com.google.android.material.bottomnavigation.BottomNavigationView
|
||||
android:id="@+id/bottomNavigationView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?riotx_background"
|
||||
app:itemIconSize="20dp"
|
||||
app:itemIconTint="@color/bottom_navigation_icon_tint_selector"
|
||||
|
@ -156,7 +156,7 @@
|
||||
app:layout_constraintTop_toBottomOf="@id/addByMatrixId" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recyclerView"
|
||||
android:id="@+id/knownUsersRecyclerView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:fastScrollEnabled="true"
|
||||
|
@ -82,7 +82,7 @@
|
||||
</androidx.appcompat.widget.Toolbar>
|
||||
|
||||
<androidx.constraintlayout.widget.Barrier
|
||||
android:id="@+id/recyclerViewBarrier"
|
||||
android:id="@+id/timelineRecyclerViewBarrier"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:barrierDirection="top"
|
||||
@ -113,11 +113,11 @@
|
||||
tools:visibility="visible" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recyclerView"
|
||||
android:id="@+id/timelineRecyclerView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:overScrollMode="always"
|
||||
app:layout_constraintBottom_toTopOf="@+id/recyclerViewBarrier"
|
||||
app:layout_constraintBottom_toTopOf="@+id/timelineRecyclerViewBarrier"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/activeConferenceView"
|
||||
|
@ -11,7 +11,8 @@
|
||||
android:id="@+id/roomListView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:overScrollMode="always" />
|
||||
android:overScrollMode="always"
|
||||
tools:listitem="@layout/item_room" />
|
||||
|
||||
<im.vector.app.features.home.room.list.widget.FabMenuView
|
||||
android:id="@+id/createChatFabMenu"
|
||||
|
@ -62,7 +62,7 @@
|
||||
app:layout_constraintTop_toBottomOf="@+id/roomSettingsToolbar">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recyclerView"
|
||||
android:id="@+id/roomSettingsRecyclerView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:overScrollMode="always"
|
||||
|
@ -90,7 +90,7 @@
|
||||
app:layout_constraintTop_toBottomOf="@+id/userDirectorySearchByIdContainer" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recyclerView"
|
||||
android:id="@+id/userDirectoryRecyclerView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginTop="16dp"
|
||||
|
Loading…
Reference in New Issue
Block a user