mirror of
https://gitlab.linphone.org/BC/public/linphone-android.git
synced 2026-04-17 12:58:28 +00:00
Trying ai generated test from gherkin
This commit is contained in:
parent
bdbdfda4b7
commit
c17b028113
23 changed files with 733 additions and 235 deletions
|
|
@ -98,10 +98,6 @@ tasks.register("linphoneSdkSource") {
|
|||
}
|
||||
project.tasks.preBuild.dependsOn("linphoneSdkSource")
|
||||
|
||||
configurations {
|
||||
implementation { isCanBeResolved = true }
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "org.linphone"
|
||||
compileSdk = 36
|
||||
|
|
@ -254,6 +250,8 @@ dependencies {
|
|||
androidTestImplementation(libs.androidx.test.runner)
|
||||
androidTestImplementation(libs.androidx.junit)
|
||||
androidTestImplementation(libs.androidx.espresso)
|
||||
androidTestImplementation(libs.androidx.espresso.intents)
|
||||
androidTestImplementation(libs.androidx.uiautomator)
|
||||
androidTestImplementation(libs.cucumber.android)
|
||||
androidTestImplementation(libs.cucumber.junit)
|
||||
|
||||
|
|
|
|||
103
app/src/androidTest/assets/features/assistant_activity.feature
Normal file
103
app/src/androidTest/assets/features/assistant_activity.feature
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
# language: fr
|
||||
Fonctionnalité: Création de compte
|
||||
|
||||
Background:
|
||||
Etant donné que l’utilisateur vient de lancer l'app pour la première fois
|
||||
|
||||
Scénario: Accorder les permissions
|
||||
Etant donné que toutes les permissions ne sont pas accordées
|
||||
Quand l’utilisateur clique sur le bouton "OK"
|
||||
Alors l'utilisateur est redirigé vers la page d'accueil
|
||||
|
||||
Scénario: Créer un compte
|
||||
Etant donné que l’utilisateur est sur la vue de login
|
||||
Quand l’utilisateur clique sur le bouton "Créer un compte"
|
||||
Alors l'utilisateur est redirigé vers le formulaire d'inscription.
|
||||
|
||||
#Tel#
|
||||
|
||||
Scénario: Bouton "Créer" inactif sans champs remplis
|
||||
Etant donné que l’utilisateur clique sur le bouton "S'inscrire"
|
||||
Quand l’utilisateur clique sur "Créer" sans remplir les champs
|
||||
Alors le bouton "Créer" est grisé et non cliquable
|
||||
|
||||
Plan du Scénario: Validation des champs lors de la création de compte par téléphone
|
||||
Etant donné que l’utilisateur clique sur le bouton "S'inscrire"
|
||||
Quand l’utilisateur saisit "<Nom utilisateur>" dans le champ Nom utilisateur
|
||||
Et saisit "<Indicatif international>" dans le champ Numéro de téléphone
|
||||
Et saisit "<Numéro de téléphone>" dans le champ Numéro de téléphone
|
||||
Et saisit "<Password>" dans le champ mot de passe
|
||||
Et clique sur "Créer"
|
||||
Alors "<expectedResult>"
|
||||
|
||||
Exemples:
|
||||
| Nom utilisateur | Numéro de téléphone | Indicatif international | Password | expectedResult |
|
||||
| TestAccount666 | 0600000000 | +33 | azertyiop123 | No uppercase letters are allowed. (and 1 more error) |
|
||||
| testaccoun/t | 0600000000 | +33 | azertyiop123 | The pseudo should be a valid SIP username |
|
||||
| testaccount | 0600000000 | +33 | azertyiop123 | Le nom d'utilisateur est déjà pris |
|
||||
| unused_account | 0600000000 | +33 | azertyiop123 | L'utilisateur est redirigé vers la validation par SMS |
|
||||
|
||||
Scénario: Validation du numéro de téléphone avec code
|
||||
Etant donné que l’utilisateur est sur la vue de validation du phone number
|
||||
Quand l’utilisateur saisit "1111" comme code
|
||||
Alors l'utilisateur n'est pas redirigé vers l'application.
|
||||
|
||||
Scénario: Création de compte validée
|
||||
Etant donné que l’utilisateur est sur la vue de validation du phone number
|
||||
Quand l’utilisateur saisit le code reçu par SMS
|
||||
Alors l'utilisateur est redirigé vers l'application sur la vue Appels
|
||||
|
||||
#MAIL#
|
||||
Scénario: Formulaire inscription par email
|
||||
Etant donné que l’utilisateur est sur la vue de login
|
||||
Quand l’utilisateur clique sur le bouton "Créer un compte"
|
||||
Quand l’utilisateur clique sur le bouton "subscribe.linphone.org"
|
||||
Alors l'utilisateur et redirigé sur son navigateur.
|
||||
|
||||
#SIP tiers
|
||||
Scénario: Connexion via un compte SIP tiers
|
||||
Etant donné que l’utilisateur est sur la vue de login
|
||||
Quand Je clique sur le bouton "J'ai un compte SIP tiers" depuis la vue login
|
||||
Alors Une vue m’informe que certaines fonctionnalités ne seront pas disponibles
|
||||
|
||||
Quand Je clique sur "je préfère créer un compte"
|
||||
Alors Je suis redirigé vers la création de compte
|
||||
|
||||
Quand Je clique sur la flèche en haut à gauche
|
||||
Et Je clique de nouveau sur "J'ai un compte SIP tiers"
|
||||
Et Je clique sur "J’ai compris"
|
||||
Alors La vue de connexion avec un compte SIP tiers est affichée
|
||||
Et Le bouton connexion est désactivé tant que tous les champs obligatoires ne sont pas remplis
|
||||
|
||||
Quand Je saisis un username "dummy_account"
|
||||
Et Je saisis un mot de passe "invalid"
|
||||
Et Je saisis un nom de domaine "sip.linphone.org"
|
||||
Et Je clique sur connexion
|
||||
Alors un dialogue apparait "opération en cours, merci de patienter..."
|
||||
Et Un message indique "Erreur durant la connexion"
|
||||
|
||||
Quand Je saisis un username "dummy_account"
|
||||
Et Je saisis un mot de passe "3V3ee@dummy!"
|
||||
Et Je saisis un nom de domaine "sip.linphone.org"
|
||||
Et Je clique sur connexion
|
||||
Alors On sort de l'assistant
|
||||
|
||||
#QRcode
|
||||
Scénario: Connexion via QR code
|
||||
Quand Je clique sur "Scanner un QR code"
|
||||
Alors La vue de scan de QR code s’ouvre
|
||||
|
||||
#compte linphone
|
||||
Scénario: Connexion via formulaire classique
|
||||
Quand Je clique sur "Connexion" sans saisir de username ni mot de passe
|
||||
Alors Le bouton "connexion" est grisé.
|
||||
|
||||
Quand Je saisis une adresse SIP "dummy_account_2"
|
||||
Et Je saisis un mot de passe "invalid"
|
||||
Et Je clique sur "Connexion"
|
||||
Alors Un toast indique "Mauvais nom d'utilisateur ou mot de passe"
|
||||
|
||||
Quand Je saisis une adresse SIP "dummy_account_2"
|
||||
Et Je saisis un mot de passe "3V3ee@dummy!"
|
||||
Et Je clique sur "Connexion"
|
||||
Alors On sort de l'assistant
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
Feature:Welcome
|
||||
When app starts the first time, it must display the welcome screens
|
||||
|
||||
Scenario Outline:Welcome screens displayed at first start
|
||||
Given I have a welcome Activity
|
||||
When I press skip
|
||||
Then I should be sent to the assistant Activity
|
||||
|
|
@ -0,0 +1,404 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2025 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-android
|
||||
* (see https://www.linphone.org).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.linphone.test
|
||||
|
||||
import android.content.Intent
|
||||
import androidx.test.espresso.Espresso.onData
|
||||
import androidx.test.espresso.Espresso.onView
|
||||
import androidx.test.espresso.action.ViewActions.*
|
||||
import androidx.test.espresso.assertion.ViewAssertions.matches
|
||||
import androidx.test.espresso.intent.Intents
|
||||
import androidx.test.espresso.intent.Intents.intended
|
||||
import androidx.test.espresso.intent.matcher.IntentMatchers.hasAction
|
||||
import androidx.test.espresso.intent.matcher.IntentMatchers.hasData
|
||||
import androidx.test.espresso.intent.matcher.UriMatchers.hasHost
|
||||
import androidx.test.espresso.matcher.ViewMatchers.*
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.filters.LargeTest
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.test.rule.ActivityTestRule
|
||||
import androidx.test.uiautomator.UiDevice
|
||||
import androidx.test.uiautomator.UiSelector
|
||||
import io.cucumber.java.After
|
||||
import io.cucumber.java.Before
|
||||
import io.cucumber.java.en.Given
|
||||
import io.cucumber.java.en.Then
|
||||
import io.cucumber.java.en.When
|
||||
import junit.framework.TestCase.assertTrue
|
||||
import org.hamcrest.Matchers.*
|
||||
import org.junit.Rule
|
||||
import org.junit.runner.RunWith
|
||||
import org.linphone.R
|
||||
import org.linphone.ui.assistant.AssistantActivity
|
||||
import kotlin.random.Random
|
||||
import kotlin.random.nextInt
|
||||
|
||||
@LargeTest
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class AssistantActivityTest {
|
||||
@JvmField
|
||||
@Rule
|
||||
var activityTestRule: ActivityTestRule<AssistantActivity> =
|
||||
ActivityTestRule(AssistantActivity::class.java, false, false)
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
Intents.init()
|
||||
activityTestRule.launchActivity(Intent())
|
||||
}
|
||||
|
||||
@After
|
||||
fun finish() {
|
||||
Intents.release()
|
||||
activityTestRule.finishActivity()
|
||||
}
|
||||
|
||||
@Given("^toutes les permissions ne sont pas accordées$")
|
||||
fun grant_all_permissions() {
|
||||
onView(withId(R.id.grant_permissions_title)).check(matches(isDisplayed()))
|
||||
}
|
||||
|
||||
@When("^l’utilisateur clique sur le bouton \"OK\"$")
|
||||
fun user_clicks_on_grant_permissions() {
|
||||
val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
|
||||
|
||||
try {
|
||||
// Check if we are on the permissions fragment
|
||||
onView(withId(R.id.grant_all_permissions)).check(matches(isDisplayed()))
|
||||
|
||||
// Click the grant all button
|
||||
onView(withId(R.id.grant_all_permissions)).perform(click())
|
||||
|
||||
// Handle system permission dialogs if they appear
|
||||
var allowButton =
|
||||
device.findObject(UiSelector().textMatches("(?i)ALLOW|AUTORISER|ACCEPTER|WHILE USING THE APP|LORSQUE VOUS UTILISEZ L'APPLI"))
|
||||
var tries = 0
|
||||
var clicks = 0
|
||||
while (allowButton.exists() && tries < 10) {
|
||||
allowButton.click()
|
||||
clicks += 1
|
||||
tries++
|
||||
// Wait a bit for the next one
|
||||
Thread.sleep(1000)
|
||||
allowButton =
|
||||
device.findObject(UiSelector().textMatches("(?i)ALLOW|AUTORISER|ACCEPTER|WHILE USING THE APP|LORSQUE VOUS UTILISEZ L'APPLI"))
|
||||
}
|
||||
assertTrue(clicks == 4)
|
||||
} catch (e: Exception) {
|
||||
// If the view is not found, permissions might already be granted
|
||||
}
|
||||
}
|
||||
|
||||
@Then("^l'utilisateur est redirigé vers la page d'accueil$")
|
||||
fun user_is_redirected_to_landing_page() {
|
||||
onView(withId(R.id.login_title)).check(matches(isDisplayed()))
|
||||
}
|
||||
|
||||
@Given("^l’utilisateur est sur la vue de login$")
|
||||
fun user_is_on_login_page() {
|
||||
onView(withId(R.id.login_title)).check(matches(isDisplayed()))
|
||||
}
|
||||
|
||||
@When("^l’utilisateur clique sur le bouton \"Créer un compte\"$")
|
||||
fun user_clicks_on_create_account() {
|
||||
onView(withId(R.id.register)).perform(click())
|
||||
|
||||
// Handle app accept conditions & terms dialog if they appear
|
||||
val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
|
||||
var allowButton = device.findObject(UiSelector().textMatches("(?i)Accept|Accepter"))
|
||||
var count = 0
|
||||
while (allowButton.exists() && count < 10) {
|
||||
allowButton.click()
|
||||
count++
|
||||
// Wait a bit for the next one
|
||||
Thread.sleep(1000)
|
||||
allowButton = device.findObject(UiSelector().textMatches("(?i)Accept|Accepter"))
|
||||
}
|
||||
}
|
||||
|
||||
@Then("^l'utilisateur est redirigé vers le formulaire d'inscription.$")
|
||||
fun user_is_redirected_to_registration_form() {
|
||||
onView(withId(R.id.register_title)).check(matches(isDisplayed()))
|
||||
}
|
||||
|
||||
@Given("^l’utilisateur clique sur le bouton \"S'inscrire\"$")
|
||||
fun user_clicks_on_signup_button() {
|
||||
// Dans LandingFragment, "Créer un compte" correspond au bouton d'inscription
|
||||
onView(withId(R.id.register)).perform(click())
|
||||
}
|
||||
|
||||
@When("^l’utilisateur clique sur \"Créer\" sans remplir les champs$")
|
||||
fun user_clicks_create_without_filling_fields() {
|
||||
// On s'assure juste que le bouton est présent
|
||||
onView(withId(R.id.create)).check(matches(isDisplayed()))
|
||||
}
|
||||
|
||||
@Then("^le bouton \"Créer\" est grisé et non cliquable$")
|
||||
fun create_button_is_disabled() {
|
||||
onView(withId(R.id.create)).check(matches(not(isEnabled())))
|
||||
}
|
||||
|
||||
@When("^l’utilisateur saisit \"([^\"]*)\" dans le champ Nom utilisateur$")
|
||||
fun user_enters_username(username: String) {
|
||||
val usernameToSet = if (username == "unused_account") {
|
||||
val randInt = Random.nextInt(0..1000000)
|
||||
"usernameToSet-$randInt"
|
||||
} else {
|
||||
username
|
||||
}
|
||||
onView(withId(R.id.username)).perform(replaceText(usernameToSet))
|
||||
}
|
||||
|
||||
@When("^saisit \"([^\"]*)\" dans le champ Numéro de téléphone$")
|
||||
fun user_enters_phone_info(value: String) {
|
||||
if (value.startsWith("+")) {
|
||||
// C'est l'indicatif (Spinner)
|
||||
onView(withId(R.id.prefix)).perform(click())
|
||||
onData(
|
||||
allOf(
|
||||
`is`(instanceOf(String::class.java)),
|
||||
containsString(value)
|
||||
)
|
||||
).perform(click())
|
||||
} else {
|
||||
// C'est le numéro
|
||||
onView(withId(R.id.phone_number)).perform(replaceText(value))
|
||||
}
|
||||
}
|
||||
|
||||
@When("^saisit \"([^\"]*)\" dans le champ mot de passe$")
|
||||
fun user_enters_password(password: String) {
|
||||
onView(withId(R.id.password)).perform(replaceText(password))
|
||||
}
|
||||
|
||||
@When("^clique sur \"Créer\"$")
|
||||
fun user_clicks_create() {
|
||||
onView(withId(R.id.create)).perform(click())
|
||||
|
||||
// Une popup de confirmation s'affiche d'abord
|
||||
onView(withText(R.string.assistant_dialog_confirm_phone_number_title)).check(
|
||||
matches(
|
||||
isDisplayed()
|
||||
)
|
||||
)
|
||||
onView(withId(R.id.confirm)).perform(click())
|
||||
}
|
||||
|
||||
@Then("^\"([^\"]*)\"$")
|
||||
fun check_expected_result(expectedResult: String) {
|
||||
Thread.sleep(1000)
|
||||
when (expectedResult) {
|
||||
"no upper case letters are allowed",
|
||||
"Special characters are not allowed" -> {
|
||||
// On vérifie que le message d'erreur contient le texte attendu
|
||||
onView(withId(R.id.username_error)).check(
|
||||
matches(
|
||||
withText(
|
||||
containsString(
|
||||
expectedResult
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
"L'utilisateur est redirigé vers la validation par SMS" -> {
|
||||
// On arrive sur la vue du code
|
||||
onView(withId(R.id.register_code_confirmation_title)).check(matches(isDisplayed()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Given("^l’utilisateur est sur la vue de validation du phone number$")
|
||||
fun user_is_on_sms_validation_view() {
|
||||
user_is_on_login_page()
|
||||
onView(withId(R.id.register)).perform(click())
|
||||
user_enters_username("testaccount")
|
||||
user_enters_phone_info("+33")
|
||||
user_enters_phone_info("0600000000")
|
||||
user_enters_password("azertyiop123")
|
||||
onView(withId(R.id.create)).perform(click())
|
||||
onView(withId(R.id.confirm)).perform(click())
|
||||
onView(withId(R.id.register_code_confirmation_title)).check(matches(isDisplayed()))
|
||||
}
|
||||
|
||||
@When("^l’utilisateur saisit \"([^\"]*)\" comme code$")
|
||||
fun user_enters_code(code: String) {
|
||||
if (code.length == 4) {
|
||||
onView(withId(R.id.code_first_digit)).perform(replaceText(code[0].toString()))
|
||||
onView(withId(R.id.code_second_digit)).perform(replaceText(code[1].toString()))
|
||||
onView(withId(R.id.code_third_digit)).perform(replaceText(code[2].toString()))
|
||||
onView(withId(R.id.code_last_digit)).perform(replaceText(code[3].toString()))
|
||||
}
|
||||
}
|
||||
|
||||
@Then("^l'utilisateur n'est pas redirigé vers l'application.$")
|
||||
fun user_is_not_redirected() {
|
||||
onView(withId(R.id.register_code_confirmation_title)).check(matches(isDisplayed()))
|
||||
}
|
||||
|
||||
@When("^l’utilisateur saisit le code reçu par SMS$")
|
||||
fun user_enters_correct_sms_code() {
|
||||
// Simulation de saisie d'un code (dépend de votre environnement de test pour le code réel)
|
||||
user_enters_code("0000")
|
||||
}
|
||||
|
||||
@Then("^l'utilisateur est redirigé vers l'application sur la vue Appels$")
|
||||
fun user_is_redirected_to_calls_view() {
|
||||
// Une fois validé, l'assistant se ferme et on arrive sur l'historique des appels
|
||||
onView(withId(R.id.history_list)).check(matches(isDisplayed()))
|
||||
}
|
||||
|
||||
@When("^l’utilisateur clique sur le bouton \"subscribe.linphone.org\"$")
|
||||
fun user_clicks_on_subscribe_link() {
|
||||
onView(withId(R.id.create_email_account)).perform(click())
|
||||
}
|
||||
|
||||
@Then("^l'utilisateur et redirigé sur son navigateur.$")
|
||||
fun user_is_redirected_to_browser() {
|
||||
intended(
|
||||
allOf(
|
||||
hasAction(Intent.ACTION_VIEW),
|
||||
hasData(hasHost("subscribe.linphone.org"))
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@When("^Je clique sur le bouton \"J'ai un compte SIP tiers\" depuis la vue login$")
|
||||
fun click_third_party_sip_account() {
|
||||
onView(withId(R.id.third_party_sip_account)).perform(click())
|
||||
}
|
||||
|
||||
@Then("^Une vue m’informe que certaines fonctionnalités ne seront pas disponibles$")
|
||||
fun check_third_party_warning_view() {
|
||||
onView(withId(R.id.third_party_warning_title)).check(matches(isDisplayed()))
|
||||
}
|
||||
|
||||
@When("^Je clique sur \"je préfère créer un compte\"$")
|
||||
fun click_prefer_create_account() {
|
||||
onView(withId(R.id.create_linphone_account)).perform(click())
|
||||
}
|
||||
|
||||
@Then("^Je suis redirigé vers la création de compte$")
|
||||
fun check_redirected_to_creation() {
|
||||
onView(withId(R.id.register_title)).check(matches(isDisplayed()))
|
||||
}
|
||||
|
||||
@When("^Je clique sur la flèche en haut à gauche$")
|
||||
fun click_back_arrow() {
|
||||
onView(withId(R.id.back)).perform(click())
|
||||
}
|
||||
|
||||
@When("^Je clique de nouveau sur \"J'ai un compte SIP tiers\"$")
|
||||
fun click_third_party_sip_account_again() {
|
||||
onView(withId(R.id.third_party_sip_account)).perform(click())
|
||||
}
|
||||
|
||||
@When("^Je clique sur \"J’ai compris\"$")
|
||||
fun click_understood() {
|
||||
onView(withId(R.id.continue_third_party_account_login)).perform(click())
|
||||
}
|
||||
|
||||
@Then("^La vue de connexion avec un compte SIP tiers est affichée$")
|
||||
fun check_third_party_login_view() {
|
||||
onView(withId(R.id.third_party_login_title)).check(matches(isDisplayed()))
|
||||
}
|
||||
|
||||
@Then("^Le bouton connexion est désactivé tant que tous les champs obligatoires ne sont pas remplis$")
|
||||
fun check_login_button_disabled() {
|
||||
onView(withId(R.id.login)).check(matches(not(isEnabled())))
|
||||
}
|
||||
|
||||
@When("^Je saisis un username \"([^\"]*)\"$")
|
||||
fun enter_valid_username(user: String) {
|
||||
onView(withId(R.id.username)).perform(replaceText(user))
|
||||
}
|
||||
|
||||
@When("^Je saisis un nom de domaine \"([^\"]*)\"$")
|
||||
fun enter_domain(user: String) {
|
||||
onView(withId(R.id.domain)).perform(replaceText(user))
|
||||
}
|
||||
|
||||
@When("^Je clique sur connexion$")
|
||||
fun click_login() {
|
||||
onView(withId(R.id.login)).perform(click())
|
||||
}
|
||||
|
||||
@Then("^un dialogue apparait \"opération en cours, merci de patienter...\"$")
|
||||
fun check_operation_in_progress() {
|
||||
onView(withText(R.string.operation_in_progress_overlay)).check(matches(isDisplayed()))
|
||||
}
|
||||
|
||||
@Then("^Un message indique \"Erreur durant la connexion\"$")
|
||||
fun check_login_error_message() {
|
||||
// TODO
|
||||
Thread.sleep(3000)
|
||||
}
|
||||
|
||||
@Then("^On sort de l'assistant$")
|
||||
fun check_call_view() {
|
||||
// This is a workaround since the MainActivity wasn't started before the Assistant one...
|
||||
// Can't check for Paused activity, have to wait for destroyed lifecycle state hence the long sleep
|
||||
Thread.sleep(3000)
|
||||
assertTrue(activityTestRule.getActivity().isDestroyed)
|
||||
}
|
||||
|
||||
@When("^Je clique sur \"Scanner un QR code\"$")
|
||||
fun click_scan_qr_code() {
|
||||
onView(withId(R.id.scan_qr_code)).perform(click())
|
||||
}
|
||||
|
||||
@Then("^La vue de scan de QR code s’ouvre$")
|
||||
fun check_qr_scanner_view() {
|
||||
onView(withId(R.id.scan_qr_code_title)).check(matches(isDisplayed()))
|
||||
}
|
||||
|
||||
@When("^Je clique sur \"Connexion\" sans saisir de username ni mot de passe$")
|
||||
fun click_login_empty() {
|
||||
onView(withId(R.id.sip_identity)).perform(replaceText(""))
|
||||
onView(withId(R.id.password)).perform(replaceText(""), closeSoftKeyboard())
|
||||
}
|
||||
|
||||
@Then("^Le bouton \"connexion\" est grisé.$")
|
||||
fun check_login_button_grayed() {
|
||||
onView(withId(R.id.login)).check(matches(not(isEnabled())))
|
||||
}
|
||||
|
||||
@When("^Je saisis un mot de passe \"([^\"]*)\"$")
|
||||
fun enter_password(pass: String) {
|
||||
onView(withId(R.id.password)).perform(replaceText(pass))
|
||||
}
|
||||
|
||||
@When("^Je clique sur \"Connexion\"$")
|
||||
fun click_login_linphone() {
|
||||
onView(withId(R.id.login)).perform(click())
|
||||
}
|
||||
|
||||
@Then("^Un toast indique \"Mauvais nom d'utilisateur ou mot de passe\"$")
|
||||
fun check_wrong_credentials_popup() {
|
||||
// TODO
|
||||
Thread.sleep(3000)
|
||||
}
|
||||
|
||||
@When("^Je saisis une adresse SIP \"([^\"]*)\"$")
|
||||
fun enter_sip_address(user: String) {
|
||||
onView(withId(R.id.sip_identity)).perform(replaceText(user))
|
||||
}
|
||||
}
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2025 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-android
|
||||
* (see https://www.linphone.org).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.linphone.test
|
||||
|
||||
import android.content.Intent
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.filters.SmallTest
|
||||
import androidx.test.rule.ActivityTestRule
|
||||
import io.cucumber.java.After
|
||||
import io.cucumber.java.Before
|
||||
import io.cucumber.java.en.Given
|
||||
import io.cucumber.java.en.Then
|
||||
import io.cucumber.java.en.When
|
||||
import junit.framework.TestCase.assertNotNull
|
||||
import org.junit.Rule
|
||||
import org.junit.runner.RunWith
|
||||
import org.linphone.ui.welcome.WelcomeActivity
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class WelcomeActivityTest {
|
||||
@JvmField
|
||||
@Rule
|
||||
var activityTestRule: ActivityTestRule<WelcomeActivity> = ActivityTestRule(WelcomeActivity::class.java)
|
||||
|
||||
@Rule
|
||||
lateinit var activity: WelcomeActivity
|
||||
|
||||
@Before()
|
||||
fun setup() {
|
||||
activityTestRule.launchActivity(Intent())
|
||||
activity = activityTestRule.activity
|
||||
}
|
||||
|
||||
@After()
|
||||
fun finish() {
|
||||
activityTestRule.finishActivity()
|
||||
}
|
||||
|
||||
@Given("^I have a welcome Activity")
|
||||
fun I_have_a_login_activity() {
|
||||
assertNotNull(activity)
|
||||
}
|
||||
|
||||
@When("^I press skip")
|
||||
fun I_press_skip() {
|
||||
|
||||
}
|
||||
|
||||
@Then("^I should be sent to the assistant Activity")
|
||||
fun I_should_be_sent_to_the_assistant_activity() {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -55,6 +55,10 @@ class AssistantActivity : GenericActivity() {
|
|||
enableEdgeToEdge()
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
while (!coreContext.isReady()) {
|
||||
Thread.sleep(50)
|
||||
}
|
||||
|
||||
binding = DataBindingUtil.setContentView(this, R.layout.assistant_activity)
|
||||
binding.lifecycleOwner = this
|
||||
setUpToastsArea(binding.toastsArea)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2023 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-android
|
||||
* (see https://www.linphone.org).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.linphone.ui.main.sso
|
||||
|
||||
import android.net.Uri
|
||||
import net.openid.appauth.connectivity.ConnectionBuilder
|
||||
import java.net.HttpURLConnection
|
||||
import java.net.URL
|
||||
import java.security.cert.X509Certificate
|
||||
import javax.net.ssl.*
|
||||
|
||||
class AppAuthConnectionBuilder(private val trustAll: Boolean) : ConnectionBuilder {
|
||||
override fun openConnection(uri: Uri): HttpURLConnection {
|
||||
val conn = URL(uri.toString()).openConnection() as HttpURLConnection
|
||||
if (trustAll && conn is HttpsURLConnection) {
|
||||
conn.sslSocketFactory = TRUSTING_CONTEXT.socketFactory
|
||||
conn.hostnameVerifier = HostnameVerifier { _, _ -> true }
|
||||
}
|
||||
return conn
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val TRUSTING_CONTEXT: SSLContext by lazy {
|
||||
val context = SSLContext.getInstance("TLS")
|
||||
context.init(
|
||||
null,
|
||||
arrayOf<TrustManager>(object : X509TrustManager {
|
||||
override fun checkClientTrusted(chain: Array<out X509Certificate>?, authType: String?) {}
|
||||
|
||||
override fun checkServerTrusted(chain: Array<out X509Certificate>?, authType: String?) {}
|
||||
|
||||
override fun getAcceptedIssuers(): Array<X509Certificate> = arrayOf()
|
||||
}),
|
||||
java.security.SecureRandom()
|
||||
)
|
||||
context
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -21,10 +21,12 @@ package org.linphone.ui.main.sso.viewmodel
|
|||
|
||||
import android.content.Intent
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.core.net.toUri
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import java.io.File
|
||||
import kotlinx.coroutines.launch
|
||||
import net.openid.appauth.AppAuthConfiguration
|
||||
import net.openid.appauth.AuthState
|
||||
import net.openid.appauth.AuthorizationException
|
||||
import net.openid.appauth.AuthorizationRequest
|
||||
|
|
@ -39,10 +41,10 @@ import org.linphone.R
|
|||
import org.linphone.core.Factory
|
||||
import org.linphone.core.tools.Log
|
||||
import org.linphone.ui.GenericViewModel
|
||||
import org.linphone.ui.main.sso.AppAuthConnectionBuilder
|
||||
import org.linphone.utils.Event
|
||||
import org.linphone.utils.FileUtils
|
||||
import org.linphone.utils.TimestampUtils
|
||||
import androidx.core.net.toUri
|
||||
|
||||
class SingleSignOnViewModel
|
||||
@UiThread
|
||||
|
|
@ -51,19 +53,7 @@ class SingleSignOnViewModel
|
|||
private const val TAG = "[Single Sign On ViewModel]"
|
||||
}
|
||||
|
||||
val operationInProgress = MutableLiveData<Boolean>()
|
||||
|
||||
val singleSignOnProcessCompletedEvent: MutableLiveData<Event<Boolean>> by lazy {
|
||||
MutableLiveData()
|
||||
}
|
||||
|
||||
val startAuthIntentEvent: MutableLiveData<Event<Intent>> by lazy {
|
||||
MutableLiveData()
|
||||
}
|
||||
|
||||
val onErrorEvent: MutableLiveData<Event<String>> by lazy {
|
||||
MutableLiveData()
|
||||
}
|
||||
val singleSignOnProcessCompletedEvent = MutableLiveData<Event<Boolean>>()
|
||||
|
||||
private var clientId: String
|
||||
private val redirectUri: String
|
||||
|
|
@ -72,6 +62,16 @@ class SingleSignOnViewModel
|
|||
|
||||
private var username: String = ""
|
||||
|
||||
val operationInProgress = MutableLiveData<Boolean>()
|
||||
|
||||
val startAuthIntentEvent: MutableLiveData<Event<Intent>> by lazy {
|
||||
MutableLiveData<Event<Intent>>()
|
||||
}
|
||||
|
||||
val onErrorEvent: MutableLiveData<Event<String>> by lazy {
|
||||
MutableLiveData<Event<String>>()
|
||||
}
|
||||
|
||||
private lateinit var authState: AuthState
|
||||
private lateinit var authService: AuthorizationService
|
||||
|
||||
|
|
@ -133,64 +133,72 @@ class SingleSignOnViewModel
|
|||
@UiThread
|
||||
private fun singleSignOn() {
|
||||
Log.i("$TAG Fetch from issuer [$singleSignOnUrl]")
|
||||
operationInProgress.postValue(true)
|
||||
val connectionBuilder = AppAuthConnectionBuilder(true)
|
||||
val callback = AuthorizationServiceConfiguration.RetrieveConfigurationCallback { serviceConfiguration, ex ->
|
||||
if (ex != null) {
|
||||
Log.e(
|
||||
"$TAG Failed to fetch configuration from issuer [$singleSignOnUrl]: ${ex.errorDescription}"
|
||||
)
|
||||
onErrorEvent.postValue(
|
||||
Event("Failed to fetch configuration from issuer $singleSignOnUrl")
|
||||
)
|
||||
operationInProgress.postValue(false)
|
||||
return@RetrieveConfigurationCallback
|
||||
}
|
||||
|
||||
if (serviceConfiguration == null) {
|
||||
Log.e("$TAG Service configuration is null!")
|
||||
onErrorEvent.postValue(Event("Service configuration is null"))
|
||||
operationInProgress.postValue(false)
|
||||
return@RetrieveConfigurationCallback
|
||||
}
|
||||
|
||||
if (!::authState.isInitialized) {
|
||||
Log.i("$TAG Initializing AuthState object")
|
||||
authState = AuthState(serviceConfiguration)
|
||||
storeAuthStateAsJsonFile()
|
||||
}
|
||||
|
||||
val authRequestBuilder = AuthorizationRequest.Builder(
|
||||
serviceConfiguration, // the authorization service configuration
|
||||
clientId, // the client ID, typically pre-registered and static
|
||||
ResponseTypeValues.CODE, // the response_type value: we want a code
|
||||
redirectUri.toUri() // the redirect URI to which the auth response is sent
|
||||
)
|
||||
|
||||
// Needed for SDK to be able to refresh the token, otherwise it will return
|
||||
// an invalid grant error with description "Session not active"
|
||||
authRequestBuilder.setScopes("offline_access")
|
||||
|
||||
if (username.isNotEmpty() && corePreferences.useUsernameAsSingleSignOnLoginHint) {
|
||||
Log.i("$TAG Using username [$username] as login hint")
|
||||
authRequestBuilder.setLoginHint(username)
|
||||
}
|
||||
|
||||
val authRequest = authRequestBuilder.build()
|
||||
val authConfig = AppAuthConfiguration.Builder()
|
||||
.setConnectionBuilder(connectionBuilder)
|
||||
.build()
|
||||
authService = AuthorizationService(coreContext.context, authConfig)
|
||||
val authIntent = authService.getAuthorizationRequestIntent(authRequest)
|
||||
startAuthIntentEvent.postValue(Event(authIntent))
|
||||
}
|
||||
|
||||
AuthorizationServiceConfiguration.fetchFromIssuer(
|
||||
singleSignOnUrl.toUri(),
|
||||
AuthorizationServiceConfiguration.RetrieveConfigurationCallback { serviceConfiguration, ex ->
|
||||
if (ex != null) {
|
||||
Log.e(
|
||||
"$TAG Failed to fetch configuration from issuer [$singleSignOnUrl]: ${ex.errorDescription}"
|
||||
)
|
||||
onErrorEvent.postValue(
|
||||
Event("Failed to fetch configuration from issuer $singleSignOnUrl")
|
||||
)
|
||||
operationInProgress.postValue(false)
|
||||
return@RetrieveConfigurationCallback
|
||||
}
|
||||
|
||||
if (serviceConfiguration == null) {
|
||||
Log.e("$TAG Service configuration is null!")
|
||||
onErrorEvent.postValue(Event("Service configuration is null"))
|
||||
operationInProgress.postValue(false)
|
||||
return@RetrieveConfigurationCallback
|
||||
}
|
||||
|
||||
if (!::authState.isInitialized) {
|
||||
Log.i("$TAG Initializing AuthState object")
|
||||
authState = AuthState(serviceConfiguration)
|
||||
storeAuthStateAsJsonFile()
|
||||
}
|
||||
|
||||
val authRequestBuilder = AuthorizationRequest.Builder(
|
||||
serviceConfiguration, // the authorization service configuration
|
||||
clientId, // the client ID, typically pre-registered and static
|
||||
ResponseTypeValues.CODE, // the response_type value: we want a code
|
||||
redirectUri.toUri() // the redirect URI to which the auth response is sent
|
||||
)
|
||||
|
||||
// Needed for SDK to be able to refresh the token, otherwise it will return
|
||||
// an invalid grant error with description "Session not active"
|
||||
authRequestBuilder.setScopes("offline_access")
|
||||
|
||||
if (username.isNotEmpty() && corePreferences.useUsernameAsSingleSignOnLoginHint) {
|
||||
Log.i("$TAG Using username [$username] as login hint")
|
||||
authRequestBuilder.setLoginHint(username)
|
||||
}
|
||||
|
||||
val authRequest = authRequestBuilder.build()
|
||||
authService = AuthorizationService(coreContext.context)
|
||||
val authIntent = authService.getAuthorizationRequestIntent(authRequest)
|
||||
startAuthIntentEvent.postValue(Event(authIntent))
|
||||
}
|
||||
callback,
|
||||
connectionBuilder
|
||||
)
|
||||
}
|
||||
|
||||
@UiThread
|
||||
private fun performRefreshToken() {
|
||||
operationInProgress.postValue(true)
|
||||
if (::authState.isInitialized) {
|
||||
if (!::authService.isInitialized) {
|
||||
authService = AuthorizationService(coreContext.context)
|
||||
val authConfig = AppAuthConfiguration.Builder()
|
||||
.setConnectionBuilder(AppAuthConnectionBuilder(true))
|
||||
.build()
|
||||
authService = AuthorizationService(coreContext.context, authConfig)
|
||||
}
|
||||
|
||||
val authStateJsonFile = File(corePreferences.ssoCacheFile)
|
||||
|
|
|
|||
|
|
@ -68,13 +68,13 @@
|
|||
android:background="@drawable/circle_transparent_button_background"
|
||||
android:visibility="@{viewModel.showBackButton ? View.VISIBLE : View.INVISIBLE, default=invisible}"
|
||||
app:tint="?attr/color_main2_500"
|
||||
app:layout_constraintTop_toTopOf="@id/title"
|
||||
app:layout_constraintTop_toTopOf="@id/login_title"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/title"/>
|
||||
app:layout_constraintEnd_toStartOf="@id/login_title"/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/assistant_page_title_style"
|
||||
android:id="@+id/title"
|
||||
android:id="@+id/login_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="@dimen/top_bar_height"
|
||||
android:layout_marginStart="10dp"
|
||||
|
|
@ -146,7 +146,7 @@
|
|||
android:labelFor="@id/sip_identity"
|
||||
android:text="@{@string/username + `*`, default=`Username*`}"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
app:layout_constraintTop_toBottomOf="@id/title"
|
||||
app:layout_constraintTop_toBottomOf="@id/login_title"
|
||||
app:layout_constraintStart_toStartOf="@id/sip_identity"
|
||||
app:layout_constraintBottom_toTopOf="@id/sip_identity"/>
|
||||
|
||||
|
|
@ -166,8 +166,8 @@
|
|||
android:inputType="text|textNoSuggestions"
|
||||
android:hint="@string/username"
|
||||
app:layout_constraintWidth_max="@dimen/text_input_max_width"
|
||||
app:layout_constraintStart_toStartOf="@id/title"
|
||||
app:layout_constraintEnd_toEndOf="@id/title"
|
||||
app:layout_constraintStart_toStartOf="@id/login_title"
|
||||
app:layout_constraintEnd_toEndOf="@id/login_title"
|
||||
app:layout_constraintTop_toBottomOf="@id/sip_identity_label"
|
||||
app:layout_constraintBottom_toTopOf="@id/password_label"/>
|
||||
|
||||
|
|
@ -201,8 +201,8 @@
|
|||
android:hint="@string/password"
|
||||
passwordInputType="@{viewModel.showPassword ? InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD : InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD, default=textPassword}"
|
||||
app:layout_constraintWidth_max="@dimen/text_input_max_width"
|
||||
app:layout_constraintStart_toStartOf="@id/title"
|
||||
app:layout_constraintEnd_toEndOf="@id/title"
|
||||
app:layout_constraintStart_toStartOf="@id/login_title"
|
||||
app:layout_constraintEnd_toEndOf="@id/login_title"
|
||||
app:layout_constraintTop_toBottomOf="@id/password_label"
|
||||
app:layout_constraintBottom_toTopOf="@id/login"/>
|
||||
|
||||
|
|
@ -233,7 +233,7 @@
|
|||
android:text="@string/assistant_account_login"
|
||||
app:layout_constraintWidth_max="@dimen/button_max_width"
|
||||
app:layout_constraintTop_toBottomOf="@id/password"
|
||||
app:layout_constraintStart_toStartOf="@id/title"
|
||||
app:layout_constraintStart_toStartOf="@id/login_title"
|
||||
app:layout_constraintBottom_toTopOf="@id/scan_qr_code"/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
|
|
@ -269,8 +269,8 @@
|
|||
android:drawablePadding="8dp"
|
||||
android:visibility="@{viewModel.hideScanQrCode ? View.GONE : View.VISIBLE}"
|
||||
app:drawableTint="@color/secondary_button_label_color"
|
||||
app:layout_constraintStart_toStartOf="@id/title"
|
||||
app:layout_constraintEnd_toEndOf="@id/title"
|
||||
app:layout_constraintStart_toStartOf="@id/login_title"
|
||||
app:layout_constraintEnd_toEndOf="@id/login_title"
|
||||
app:layout_constraintTop_toBottomOf="@id/login"
|
||||
app:layout_constraintBottom_toTopOf="@id/third_party_sip_account" />
|
||||
|
||||
|
|
@ -285,8 +285,8 @@
|
|||
android:layout_marginEnd="16dp"
|
||||
android:text="@string/assistant_login_third_party_sip_account"
|
||||
android:visibility="@{viewModel.hideThirdPartyAccount ? View.GONE : View.VISIBLE}"
|
||||
app:layout_constraintStart_toStartOf="@id/title"
|
||||
app:layout_constraintEnd_toEndOf="@id/title"
|
||||
app:layout_constraintStart_toStartOf="@id/login_title"
|
||||
app:layout_constraintEnd_toEndOf="@id/login_title"
|
||||
app:layout_constraintTop_toBottomOf="@id/scan_qr_code"
|
||||
app:layout_constraintBottom_toTopOf="@id/mountains"/>
|
||||
|
||||
|
|
|
|||
|
|
@ -49,13 +49,13 @@
|
|||
android:contentDescription="@string/content_description_go_back_icon"
|
||||
android:background="@drawable/circle_transparent_button_background"
|
||||
app:tint="?attr/color_main2_500"
|
||||
app:layout_constraintTop_toTopOf="@id/title"
|
||||
app:layout_constraintTop_toTopOf="@id/grant_permissions_title"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/title"/>
|
||||
app:layout_constraintEnd_toStartOf="@id/grant_permissions_title"/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/assistant_page_title_style"
|
||||
android:id="@+id/title"
|
||||
android:id="@+id/grant_permissions_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="@dimen/top_bar_height"
|
||||
android:layout_marginStart="10dp"
|
||||
|
|
@ -82,7 +82,7 @@
|
|||
app:layout_constraintVertical_chainStyle="packed"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/title"
|
||||
app:layout_constraintTop_toBottomOf="@id/grant_permissions_title"
|
||||
app:layout_constraintBottom_toTopOf="@id/post_notifications_icon"/>
|
||||
|
||||
<ImageView
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
app:layout_constraintStart_toEndOf="@id/message"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@id/mountains"
|
||||
app:layout_constraintTop_toBottomOf="@id/title" />
|
||||
app:layout_constraintTop_toBottomOf="@id/register_code_confirmation_title" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/back"
|
||||
|
|
@ -47,13 +47,13 @@
|
|||
android:background="@drawable/circle_transparent_button_background"
|
||||
android:visibility="invisible"
|
||||
app:tint="?attr/color_main2_500"
|
||||
app:layout_constraintTop_toTopOf="@id/title"
|
||||
app:layout_constraintTop_toTopOf="@id/register_code_confirmation_title"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/title"/>
|
||||
app:layout_constraintEnd_toStartOf="@id/register_code_confirmation_title"/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/assistant_page_title_style"
|
||||
android:id="@+id/title"
|
||||
android:id="@+id/register_code_confirmation_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="@dimen/top_bar_height"
|
||||
android:layout_marginStart="10dp"
|
||||
|
|
@ -79,10 +79,10 @@
|
|||
android:textSize="14sp"
|
||||
android:textColor="?attr/color_main2_600"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
app:layout_constraintTop_toBottomOf="@id/title"
|
||||
app:layout_constraintTop_toBottomOf="@id/register_code_confirmation_title"
|
||||
app:layout_constraintBottom_toTopOf="@id/code_first_digit"
|
||||
app:layout_constraintStart_toStartOf="@id/title"
|
||||
app:layout_constraintEnd_toEndOf="@id/title"/>
|
||||
app:layout_constraintStart_toStartOf="@id/register_code_confirmation_title"
|
||||
app:layout_constraintEnd_toEndOf="@id/register_code_confirmation_title"/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatEditText
|
||||
focusNextOnInput="@{true}"
|
||||
|
|
@ -105,7 +105,7 @@
|
|||
app:layout_constraintHorizontal_chainStyle="spread_inside"
|
||||
app:layout_constraintTop_toBottomOf="@id/message"
|
||||
app:layout_constraintBottom_toTopOf="@id/wrong_number"
|
||||
app:layout_constraintStart_toStartOf="@id/title"
|
||||
app:layout_constraintStart_toStartOf="@id/register_code_confirmation_title"
|
||||
app:layout_constraintEnd_toStartOf="@id/code_second_digit" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatEditText
|
||||
|
|
@ -171,7 +171,7 @@
|
|||
app:layout_constraintTop_toTopOf="@id/code_first_digit"
|
||||
app:layout_constraintBottom_toBottomOf="@id/code_first_digit"
|
||||
app:layout_constraintStart_toEndOf="@id/code_third_digit"
|
||||
app:layout_constraintEnd_toEndOf="@id/title" />
|
||||
app:layout_constraintEnd_toEndOf="@id/register_code_confirmation_title" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/default_text_style_600"
|
||||
|
|
@ -189,8 +189,8 @@
|
|||
android:textColor="@color/secondary_button_label_color"
|
||||
android:gravity="center"
|
||||
android:background="@drawable/secondary_button_background"
|
||||
app:layout_constraintStart_toStartOf="@id/title"
|
||||
app:layout_constraintEnd_toEndOf="@id/title"
|
||||
app:layout_constraintStart_toStartOf="@id/register_code_confirmation_title"
|
||||
app:layout_constraintEnd_toEndOf="@id/register_code_confirmation_title"
|
||||
app:layout_constraintTop_toBottomOf="@id/code_first_digit"
|
||||
app:layout_constraintBottom_toTopOf="@id/mountains"/>
|
||||
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@
|
|||
android:scaleType="centerCrop"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/assistant_logo"
|
||||
app:layout_constraintStart_toEndOf="@id/title"
|
||||
app:layout_constraintStart_toEndOf="@id/register_title"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@id/mountains"
|
||||
app:layout_constraintTop_toBottomOf="@id/login" />
|
||||
|
|
@ -73,13 +73,13 @@
|
|||
android:contentDescription="@string/content_description_go_back_icon"
|
||||
android:background="@drawable/circle_transparent_button_background"
|
||||
app:tint="?attr/color_main2_500"
|
||||
app:layout_constraintTop_toTopOf="@id/title"
|
||||
app:layout_constraintTop_toTopOf="@id/register_title"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/title"/>
|
||||
app:layout_constraintEnd_toStartOf="@id/register_title"/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/assistant_page_title_style"
|
||||
android:id="@+id/title"
|
||||
android:id="@+id/register_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="@dimen/top_bar_height"
|
||||
android:layout_marginStart="10dp"
|
||||
|
|
@ -104,9 +104,9 @@
|
|||
android:contentDescription="@null"
|
||||
app:tint="?attr/color_main2_500"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
app:layout_constraintStart_toStartOf="@id/title"
|
||||
app:layout_constraintEnd_toEndOf="@id/title"
|
||||
app:layout_constraintTop_toBottomOf="@id/title"
|
||||
app:layout_constraintStart_toStartOf="@id/register_title"
|
||||
app:layout_constraintEnd_toEndOf="@id/register_title"
|
||||
app:layout_constraintTop_toBottomOf="@id/register_title"
|
||||
app:layout_constraintBottom_toTopOf="@id/no_push_label"/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
|
|
@ -121,8 +121,8 @@
|
|||
android:text="@string/assistant_account_register_unavailable_no_push_warning"
|
||||
app:layout_constraintTop_toBottomOf="@id/no_push"
|
||||
app:layout_constraintBottom_toTopOf="@id/create_email_account_no_push"
|
||||
app:layout_constraintStart_toStartOf="@id/title"
|
||||
app:layout_constraintEnd_toEndOf="@id/title"/>
|
||||
app:layout_constraintStart_toStartOf="@id/register_title"
|
||||
app:layout_constraintEnd_toEndOf="@id/register_title"/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:onClick="@{openSubscribeWebPageClickListener}"
|
||||
|
|
@ -141,8 +141,8 @@
|
|||
android:textColor="@color/secondary_button_label_color"
|
||||
android:gravity="center"
|
||||
android:background="@drawable/secondary_button_background"
|
||||
app:layout_constraintStart_toStartOf="@id/title"
|
||||
app:layout_constraintEnd_toEndOf="@id/title"
|
||||
app:layout_constraintStart_toStartOf="@id/register_title"
|
||||
app:layout_constraintEnd_toEndOf="@id/register_title"
|
||||
app:layout_constraintTop_toBottomOf="@id/no_push_label"
|
||||
app:layout_constraintBottom_toTopOf="@id/mountains" />
|
||||
|
||||
|
|
@ -156,7 +156,7 @@
|
|||
android:labelFor="@id/username"
|
||||
android:text="@{@string/username + `*`}"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
app:layout_constraintTop_toBottomOf="@id/title"
|
||||
app:layout_constraintTop_toBottomOf="@id/register_title"
|
||||
app:layout_constraintBottom_toTopOf="@id/username"
|
||||
app:layout_constraintStart_toStartOf="@id/username"/>
|
||||
|
||||
|
|
@ -179,8 +179,8 @@
|
|||
app:layout_constraintWidth_max="@dimen/text_input_max_width"
|
||||
app:layout_constraintTop_toBottomOf="@id/username_label"
|
||||
app:layout_constraintBottom_toTopOf="@id/username_error"
|
||||
app:layout_constraintStart_toStartOf="@id/title"
|
||||
app:layout_constraintEnd_toEndOf="@id/title"/>
|
||||
app:layout_constraintStart_toStartOf="@id/register_title"
|
||||
app:layout_constraintEnd_toEndOf="@id/register_title"/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/default_text_style_600"
|
||||
|
|
@ -319,8 +319,8 @@
|
|||
app:layout_constraintWidth_max="@dimen/text_input_max_width"
|
||||
app:layout_constraintTop_toBottomOf="@id/password_label"
|
||||
app:layout_constraintBottom_toTopOf="@id/password_error"
|
||||
app:layout_constraintStart_toStartOf="@id/title"
|
||||
app:layout_constraintEnd_toEndOf="@id/title"/>
|
||||
app:layout_constraintStart_toStartOf="@id/register_title"
|
||||
app:layout_constraintEnd_toEndOf="@id/register_title"/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/default_text_style_600"
|
||||
|
|
@ -364,8 +364,8 @@
|
|||
app:layout_constraintWidth_max="@dimen/button_max_width"
|
||||
app:layout_constraintTop_toBottomOf="@id/password_error"
|
||||
app:layout_constraintBottom_toTopOf="@id/create_email_account"
|
||||
app:layout_constraintStart_toStartOf="@id/title"
|
||||
app:layout_constraintEnd_toEndOf="@id/title" />
|
||||
app:layout_constraintStart_toStartOf="@id/register_title"
|
||||
app:layout_constraintEnd_toEndOf="@id/register_title" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/default_text_style"
|
||||
|
|
@ -378,7 +378,7 @@
|
|||
android:textColor="?attr/color_main2_700"
|
||||
app:layout_constraintTop_toTopOf="@id/create_email_account"
|
||||
app:layout_constraintBottom_toBottomOf="@id/create_email_account"
|
||||
app:layout_constraintStart_toStartOf="@id/title"
|
||||
app:layout_constraintStart_toStartOf="@id/register_title"
|
||||
app:layout_constraintEnd_toStartOf="@id/create_email_account"/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
|
|
@ -427,8 +427,8 @@
|
|||
android:text="@string/assistant_account_login"
|
||||
app:layout_constraintVertical_bias="1"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/title"
|
||||
app:layout_constraintBottom_toBottomOf="@id/title"/>
|
||||
app:layout_constraintTop_toTopOf="@id/register_title"
|
||||
app:layout_constraintBottom_toBottomOf="@id/register_title"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/mountains"
|
||||
|
|
|
|||
|
|
@ -55,13 +55,13 @@
|
|||
android:contentDescription="@string/content_description_go_back_icon"
|
||||
android:background="@drawable/circle_transparent_button_background"
|
||||
app:tint="?attr/color_main2_500"
|
||||
app:layout_constraintTop_toTopOf="@id/title"
|
||||
app:layout_constraintTop_toTopOf="@id/third_party_login_title"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/title"/>
|
||||
app:layout_constraintEnd_toStartOf="@id/third_party_login_title"/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/assistant_page_title_style"
|
||||
android:id="@+id/title"
|
||||
android:id="@+id/third_party_login_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="@dimen/top_bar_height"
|
||||
android:layout_marginStart="10dp"
|
||||
|
|
@ -86,7 +86,7 @@
|
|||
android:labelFor="@id/username"
|
||||
android:text="@{@string/username + `*`}"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
app:layout_constraintTop_toBottomOf="@id/title"
|
||||
app:layout_constraintTop_toBottomOf="@id/third_party_login_title"
|
||||
app:layout_constraintBottom_toTopOf="@id/username"
|
||||
app:layout_constraintStart_toStartOf="@id/username"/>
|
||||
|
||||
|
|
@ -108,8 +108,8 @@
|
|||
app:layout_constraintWidth_max="@dimen/button_max_width"
|
||||
app:layout_constraintTop_toBottomOf="@id/username_label"
|
||||
app:layout_constraintBottom_toTopOf="@id/password_label"
|
||||
app:layout_constraintStart_toStartOf="@id/title"
|
||||
app:layout_constraintEnd_toEndOf="@id/title"/>
|
||||
app:layout_constraintStart_toStartOf="@id/third_party_login_title"
|
||||
app:layout_constraintEnd_toEndOf="@id/third_party_login_title"/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/header_style"
|
||||
|
|
@ -143,8 +143,8 @@
|
|||
app:layout_constraintWidth_max="@dimen/text_input_max_width"
|
||||
app:layout_constraintTop_toBottomOf="@id/password_label"
|
||||
app:layout_constraintBottom_toTopOf="@id/domain_label"
|
||||
app:layout_constraintStart_toStartOf="@id/title"
|
||||
app:layout_constraintEnd_toEndOf="@id/title"/>
|
||||
app:layout_constraintStart_toStartOf="@id/third_party_login_title"
|
||||
app:layout_constraintEnd_toEndOf="@id/third_party_login_title"/>
|
||||
|
||||
<ImageView
|
||||
android:onClick="@{() -> viewModel.toggleShowPassword()}"
|
||||
|
|
@ -192,8 +192,8 @@
|
|||
app:layout_constraintWidth_max="@dimen/text_input_max_width"
|
||||
app:layout_constraintTop_toBottomOf="@id/domain_label"
|
||||
app:layout_constraintBottom_toTopOf="@id/display_name_label"
|
||||
app:layout_constraintStart_toStartOf="@id/title"
|
||||
app:layout_constraintEnd_toEndOf="@id/title"/>
|
||||
app:layout_constraintStart_toStartOf="@id/third_party_login_title"
|
||||
app:layout_constraintEnd_toEndOf="@id/third_party_login_title"/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/header_style"
|
||||
|
|
@ -227,8 +227,8 @@
|
|||
app:layout_constraintWidth_max="@dimen/text_input_max_width"
|
||||
app:layout_constraintTop_toBottomOf="@id/display_name_label"
|
||||
app:layout_constraintBottom_toTopOf="@id/transport_label"
|
||||
app:layout_constraintStart_toStartOf="@id/title"
|
||||
app:layout_constraintEnd_toEndOf="@id/title"/>
|
||||
app:layout_constraintStart_toStartOf="@id/third_party_login_title"
|
||||
app:layout_constraintEnd_toEndOf="@id/third_party_login_title"/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/header_style"
|
||||
|
|
@ -260,8 +260,8 @@
|
|||
app:layout_constraintWidth_max="@dimen/text_input_max_width"
|
||||
app:layout_constraintTop_toBottomOf="@id/transport_label"
|
||||
app:layout_constraintBottom_toTopOf="@id/login"
|
||||
app:layout_constraintStart_toStartOf="@id/title"
|
||||
app:layout_constraintEnd_toEndOf="@id/title"/>
|
||||
app:layout_constraintStart_toStartOf="@id/third_party_login_title"
|
||||
app:layout_constraintEnd_toEndOf="@id/third_party_login_title"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/transport_caret"
|
||||
|
|
@ -290,7 +290,7 @@
|
|||
app:layout_constraintWidth_max="@dimen/button_max_width"
|
||||
app:layout_constraintTop_toBottomOf="@id/transport"
|
||||
app:layout_constraintBottom_toTopOf="@id/mountains"
|
||||
app:layout_constraintStart_toStartOf="@id/title" />
|
||||
app:layout_constraintStart_toStartOf="@id/third_party_login_title" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/section_header_style"
|
||||
|
|
@ -307,9 +307,9 @@
|
|||
android:drawablePadding="10dp"
|
||||
android:background="@drawable/squircle_transparent_button_background"
|
||||
app:layout_constraintWidth_max="@dimen/button_max_width"
|
||||
app:layout_constraintStart_toEndOf="@id/title"
|
||||
app:layout_constraintStart_toEndOf="@id/third_party_login_title"
|
||||
app:layout_constraintEnd_toStartOf="@id/logo"
|
||||
app:layout_constraintTop_toBottomOf="@id/title" />
|
||||
app:layout_constraintTop_toBottomOf="@id/third_party_login_title" />
|
||||
|
||||
<androidx.constraintlayout.widget.Group
|
||||
android:id="@+id/advanced_settings_group"
|
||||
|
|
|
|||
|
|
@ -53,13 +53,13 @@
|
|||
android:contentDescription="@string/content_description_go_back_icon"
|
||||
android:background="@drawable/circle_transparent_button_background"
|
||||
app:tint="?attr/color_main2_500"
|
||||
app:layout_constraintTop_toTopOf="@id/title"
|
||||
app:layout_constraintTop_toTopOf="@id/third_party_warning_title"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/title"/>
|
||||
app:layout_constraintEnd_toStartOf="@id/third_party_warning_title"/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/assistant_page_title_style"
|
||||
android:id="@+id/title"
|
||||
android:id="@+id/third_party_warning_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="@dimen/top_bar_height"
|
||||
android:layout_marginStart="10dp"
|
||||
|
|
@ -86,9 +86,9 @@
|
|||
app:tint="?attr/color_main2_500"
|
||||
app:layout_constraintHorizontal_chainStyle="packed"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
app:layout_constraintStart_toStartOf="@id/title"
|
||||
app:layout_constraintStart_toStartOf="@id/third_party_warning_title"
|
||||
app:layout_constraintEnd_toStartOf="@id/no_video"
|
||||
app:layout_constraintTop_toBottomOf="@id/title"
|
||||
app:layout_constraintTop_toBottomOf="@id/third_party_warning_title"
|
||||
app:layout_constraintBottom_toTopOf="@id/message"/>
|
||||
|
||||
<ImageView
|
||||
|
|
@ -114,7 +114,7 @@
|
|||
android:textSize="14sp"
|
||||
android:gravity="start"
|
||||
app:layout_constraintWidth_max="@dimen/button_max_width"
|
||||
app:layout_constraintStart_toStartOf="@id/title"
|
||||
app:layout_constraintStart_toStartOf="@id/third_party_warning_title"
|
||||
app:layout_constraintTop_toBottomOf="@id/no_chat"
|
||||
app:layout_constraintBottom_toTopOf="@id/contact"/>
|
||||
|
||||
|
|
@ -151,7 +151,7 @@
|
|||
android:text="@string/assistant_third_party_sip_account_create_linphone_account"
|
||||
app:layout_constraintWidth_max="@dimen/button_max_width"
|
||||
app:layout_constraintVertical_bias="1"
|
||||
app:layout_constraintStart_toStartOf="@id/title"
|
||||
app:layout_constraintStart_toStartOf="@id/third_party_warning_title"
|
||||
app:layout_constraintEnd_toEndOf="@id/message"
|
||||
app:layout_constraintTop_toBottomOf="@id/contact"
|
||||
app:layout_constraintBottom_toTopOf="@id/continue_third_party_account_login" />
|
||||
|
|
@ -169,7 +169,7 @@
|
|||
app:layout_constraintWidth_max="@dimen/button_max_width"
|
||||
app:layout_constraintTop_toBottomOf="@id/create_linphone_account"
|
||||
app:layout_constraintBottom_toTopOf="@id/mountains"
|
||||
app:layout_constraintStart_toStartOf="@id/title"
|
||||
app:layout_constraintStart_toStartOf="@id/third_party_warning_title"
|
||||
app:layout_constraintEnd_toEndOf="@id/message" />
|
||||
|
||||
<ImageView
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@
|
|||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/assistant_page_title_style"
|
||||
android:id="@+id/title"
|
||||
android:id="@+id/login_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/assistant_account_login"
|
||||
|
|
@ -84,8 +84,8 @@
|
|||
android:background="@drawable/squircle_transparent_button_background"
|
||||
app:drawableTint="?attr/color_main2_500"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/title"
|
||||
app:layout_constraintBottom_toBottomOf="@id/title"/>
|
||||
app:layout_constraintTop_toTopOf="@id/login_title"
|
||||
app:layout_constraintBottom_toBottomOf="@id/login_title"/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/header_style"
|
||||
|
|
@ -96,7 +96,7 @@
|
|||
android:layout_marginEnd="16dp"
|
||||
android:labelFor="@id/sip_identity"
|
||||
android:text="@{@string/username + `*`, default=`Username*`}"
|
||||
app:layout_constraintTop_toBottomOf="@id/title"
|
||||
app:layout_constraintTop_toBottomOf="@id/login_title"
|
||||
app:layout_constraintStart_toStartOf="@id/sip_identity"/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatEditText
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@
|
|||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/assistant_page_title_style"
|
||||
android:id="@+id/title"
|
||||
android:id="@+id/grant_permissions_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/assistant_permissions_title"
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@
|
|||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/assistant_page_title_style"
|
||||
android:id="@+id/title"
|
||||
android:id="@+id/scan_qr_code_title"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="100dp"
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/assistant_page_title_style"
|
||||
android:id="@+id/title"
|
||||
android:id="@+id/register_code_confirmation_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/assistant_account_creation_sms_confirmation_title"
|
||||
|
|
@ -58,7 +58,7 @@
|
|||
android:textSize="14sp"
|
||||
android:textColor="?attr/color_main2_600"
|
||||
android:gravity="center_horizontal"
|
||||
app:layout_constraintTop_toBottomOf="@id/title"
|
||||
app:layout_constraintTop_toBottomOf="@id/register_code_confirmation_title"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"/>
|
||||
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@
|
|||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/assistant_page_title_style"
|
||||
android:id="@+id/title"
|
||||
android:id="@+id/register_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/assistant_account_register"
|
||||
|
|
@ -92,7 +92,7 @@
|
|||
app:tint="?attr/color_main2_500"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/title"/>
|
||||
app:layout_constraintTop_toBottomOf="@id/register_title"/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/header_style"
|
||||
|
|
@ -117,7 +117,7 @@
|
|||
android:layout_marginEnd="16dp"
|
||||
android:labelFor="@id/username"
|
||||
android:text="@{@string/username + `*`}"
|
||||
app:layout_constraintTop_toBottomOf="@id/title"
|
||||
app:layout_constraintTop_toBottomOf="@id/register_title"
|
||||
app:layout_constraintStart_toStartOf="@id/username"/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatEditText
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@
|
|||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/assistant_page_title_style"
|
||||
android:id="@+id/title"
|
||||
android:id="@+id/third_party_login_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/assistant_login_third_party_sip_account_title"
|
||||
|
|
@ -65,7 +65,7 @@
|
|||
android:layout_marginEnd="16dp"
|
||||
android:labelFor="@id/username"
|
||||
android:text="@{@string/username + `*`}"
|
||||
app:layout_constraintTop_toBottomOf="@id/title"
|
||||
app:layout_constraintTop_toBottomOf="@id/third_party_login_title"
|
||||
app:layout_constraintStart_toStartOf="@id/username"/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatEditText
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@
|
|||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/assistant_page_title_style"
|
||||
android:id="@+id/title"
|
||||
android:id="@+id/third_party_warning_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/assistant_login_third_party_sip_account_title"
|
||||
|
|
@ -67,7 +67,7 @@
|
|||
app:layout_constraintHorizontal_chainStyle="packed"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/no_video"
|
||||
app:layout_constraintTop_toBottomOf="@id/title"/>
|
||||
app:layout_constraintTop_toBottomOf="@id/third_party_warning_title"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/no_video"
|
||||
|
|
@ -81,7 +81,7 @@
|
|||
app:tint="?attr/color_main2_500"
|
||||
app:layout_constraintStart_toEndOf="@id/no_chat"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/title"/>
|
||||
app:layout_constraintTop_toBottomOf="@id/third_party_warning_title"/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/default_text_style"
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ test = "1.7.0"
|
|||
monitor = "1.8.0"
|
||||
junit = "1.3.0"
|
||||
espresso = "3.7.0"
|
||||
uiautomator = "2.3.0"
|
||||
|
||||
[libraries]
|
||||
androidx-annotations = { group = "androidx.annotation", name = "annotation", version.ref = "annotations" }
|
||||
|
|
@ -83,6 +84,8 @@ androidx-test-runner = { group = "androidx.test", name = "runner", version.ref =
|
|||
androidx-monitor = { group = "androidx.test", name = "monitor", version.ref = "monitor" }
|
||||
androidx-junit = { group = "androidx.test.ext", name = "junit-ktx", version.ref = "junit" }
|
||||
androidx-espresso = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espresso" }
|
||||
androidx-espresso-intents = { group = "androidx.test.espresso", name = "espresso-intents", version.ref = "espresso" }
|
||||
androidx-uiautomator = { group = "androidx.test.uiautomator", name = "uiautomator", version.ref = "uiautomator" }
|
||||
|
||||
[plugins]
|
||||
androidApplication = { id = "com.android.application", version.ref = "agp" }
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue