mirror of
https://gitlab.linphone.org/BC/public/linphone-android.git
synced 2026-01-17 11:28:06 +00:00
Started account login & proper display of accounts
This commit is contained in:
parent
faa4309ece
commit
5e1c681a8d
15 changed files with 402 additions and 23 deletions
|
|
@ -22,9 +22,13 @@ package org.linphone.contacts
|
|||
import androidx.loader.app.LoaderManager
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
import org.linphone.core.Friend
|
||||
import org.linphone.core.tools.Log
|
||||
import org.linphone.ui.main.MainActivity
|
||||
import org.linphone.utils.LinphoneUtils
|
||||
|
||||
class ContactsManager {
|
||||
val localFriends = arrayListOf<Friend>()
|
||||
|
||||
private val listeners = arrayListOf<ContactsListener>()
|
||||
|
||||
fun loadContacts(activity: MainActivity) {
|
||||
|
|
@ -54,6 +58,8 @@ class ContactsManager {
|
|||
fun onContactsLoaded() {
|
||||
// UI thread
|
||||
coreContext.postOnCoreThread {
|
||||
updateLocalContacts()
|
||||
|
||||
for (listener in listeners) {
|
||||
listener.onContactsLoaded()
|
||||
}
|
||||
|
|
@ -65,8 +71,28 @@ class ContactsManager {
|
|||
return coreContext.core.defaultFriendList?.findFriendByRefKey(id)
|
||||
}
|
||||
|
||||
fun updateLocalContacts() {
|
||||
// Core thread
|
||||
Log.i("[Contacts Manager] Updating local contact(s)")
|
||||
localFriends.clear()
|
||||
|
||||
for (account in coreContext.core.accountList) {
|
||||
val friend = coreContext.core.createFriend()
|
||||
friend.name = LinphoneUtils.getDisplayName(account.params.identityAddress)
|
||||
|
||||
val address = account.params.identityAddress ?: continue
|
||||
friend.address = address
|
||||
|
||||
Log.i(
|
||||
"[Contacts Manager] Local contact created for account [${address.asString()}] and picture [${friend.photo}]"
|
||||
)
|
||||
localFriends.add(friend)
|
||||
}
|
||||
}
|
||||
|
||||
fun onCoreStarted() {
|
||||
// Core thread
|
||||
updateLocalContacts()
|
||||
}
|
||||
|
||||
fun onCoreStopped() {
|
||||
|
|
|
|||
|
|
@ -51,15 +51,22 @@ class CorePreferences constructor(private val context: Context) {
|
|||
editor.apply()
|
||||
}
|
||||
|
||||
val defaultDomain: String
|
||||
get() = config.getString("app", "default_domain", "sip.linphone.org")!!
|
||||
|
||||
val configPath: String
|
||||
get() = context.filesDir.absolutePath + "/.linphonerc"
|
||||
|
||||
val factoryConfigPath: String
|
||||
get() = context.filesDir.absolutePath + "/linphonerc"
|
||||
|
||||
val linphoneDefaultValuesPath: String
|
||||
get() = context.filesDir.absolutePath + "/assistant_linphone_default_values"
|
||||
|
||||
fun copyAssetsFromPackage() {
|
||||
copy("linphonerc_default", configPath)
|
||||
copy("linphonerc_factory", factoryConfigPath, true)
|
||||
copy("assistant_linphone_default_values", linphoneDefaultValuesPath, true)
|
||||
}
|
||||
|
||||
private fun copy(from: String, to: String, overrideIfExists: Boolean = false) {
|
||||
|
|
|
|||
|
|
@ -24,12 +24,19 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.navigation.navGraphViewModels
|
||||
import org.linphone.R
|
||||
import org.linphone.databinding.AssistantLoginFragmentBinding
|
||||
import org.linphone.ui.assistant.viewmodel.AssistantViewModel
|
||||
import org.linphone.ui.main.fragment.GenericFragment
|
||||
|
||||
class LoginFragment : GenericFragment() {
|
||||
private lateinit var binding: AssistantLoginFragmentBinding
|
||||
|
||||
private val viewModel: AssistantViewModel by navGraphViewModels(
|
||||
R.id.loginFragment
|
||||
)
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
|
|
@ -47,10 +54,17 @@ class LoginFragment : GenericFragment() {
|
|||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
binding.lifecycleOwner = viewLifecycleOwner
|
||||
binding.viewModel = viewModel
|
||||
|
||||
binding.setRegisterClickListener {
|
||||
val action = LoginFragmentDirections.actionLoginFragmentToRegisterFragment()
|
||||
findNavController().navigate(action)
|
||||
}
|
||||
|
||||
viewModel.accountLoggedInEvent.observe(viewLifecycleOwner) {
|
||||
it.consume {
|
||||
goBack()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
* 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.assistant.viewmodel
|
||||
|
||||
import androidx.lifecycle.MediatorLiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
import org.linphone.LinphoneApplication.Companion.corePreferences
|
||||
import org.linphone.core.Account
|
||||
import org.linphone.core.AuthInfo
|
||||
import org.linphone.core.Core
|
||||
import org.linphone.core.CoreListenerStub
|
||||
import org.linphone.core.Factory
|
||||
import org.linphone.core.RegistrationState
|
||||
import org.linphone.core.tools.Log
|
||||
import org.linphone.utils.Event
|
||||
|
||||
class AssistantViewModel : ViewModel() {
|
||||
companion object {
|
||||
const val TAG = "[Assistant ViewModel]"
|
||||
}
|
||||
val username = MutableLiveData<String>()
|
||||
|
||||
val password = MutableLiveData<String>()
|
||||
|
||||
val loginEnabled = MediatorLiveData<Boolean>()
|
||||
|
||||
val registrationInProgress = MutableLiveData<Boolean>()
|
||||
|
||||
val accountLoggedInEvent = MutableLiveData<Event<Boolean>>()
|
||||
|
||||
private lateinit var newlyCreatedAuthInfo: AuthInfo
|
||||
private lateinit var newlyCreatedAccount: Account
|
||||
|
||||
private val coreListener = object : CoreListenerStub() {
|
||||
override fun onAccountRegistrationStateChanged(
|
||||
core: Core,
|
||||
account: Account,
|
||||
state: RegistrationState?,
|
||||
message: String
|
||||
) {
|
||||
// Core thread
|
||||
if (account == newlyCreatedAccount) {
|
||||
Log.i("$TAG Newly created account registration state is [$state] ($message)")
|
||||
|
||||
if (state == RegistrationState.Ok) {
|
||||
registrationInProgress.postValue(false)
|
||||
core.removeListener(this)
|
||||
|
||||
// Set new account as default
|
||||
core.defaultAccount = newlyCreatedAccount
|
||||
coreContext.contactsManager.updateLocalContacts()
|
||||
accountLoggedInEvent.postValue(Event(true))
|
||||
} else if (state == RegistrationState.Failed) {
|
||||
registrationInProgress.postValue(false)
|
||||
core.removeListener(this)
|
||||
|
||||
// TODO FIXME: show error
|
||||
|
||||
Log.e("$TAG Account failed to REGISTER, removing it")
|
||||
core.removeAuthInfo(newlyCreatedAuthInfo)
|
||||
core.removeAccount(newlyCreatedAccount)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
registrationInProgress.value = false
|
||||
|
||||
loginEnabled.addSource(username) {
|
||||
loginEnabled.value = isLoginButtonEnabled()
|
||||
}
|
||||
loginEnabled.addSource(password) {
|
||||
loginEnabled.value = isLoginButtonEnabled()
|
||||
}
|
||||
}
|
||||
|
||||
fun login() {
|
||||
// UI thread
|
||||
coreContext.postOnCoreThread { core ->
|
||||
core.loadConfigFromXml(corePreferences.linphoneDefaultValuesPath)
|
||||
|
||||
val user = username.value.orEmpty()
|
||||
val domain = corePreferences.defaultDomain
|
||||
|
||||
newlyCreatedAuthInfo = Factory.instance().createAuthInfo(
|
||||
user,
|
||||
null,
|
||||
password.value.orEmpty(),
|
||||
null,
|
||||
null,
|
||||
domain
|
||||
)
|
||||
core.addAuthInfo(newlyCreatedAuthInfo)
|
||||
|
||||
val accountParams = core.createAccountParams()
|
||||
val identityAddress = Factory.instance().createAddress("sip:$user@$domain")
|
||||
accountParams.identityAddress = identityAddress
|
||||
newlyCreatedAccount = core.createAccount(accountParams)
|
||||
|
||||
registrationInProgress.postValue(true)
|
||||
core.addListener(coreListener)
|
||||
core.addAccount(newlyCreatedAccount)
|
||||
}
|
||||
}
|
||||
|
||||
private fun isLoginButtonEnabled(): Boolean {
|
||||
return username.value.orEmpty().isNotEmpty() && password.value.orEmpty().isNotEmpty()
|
||||
}
|
||||
}
|
||||
|
|
@ -61,8 +61,12 @@ class NewContactFragment : GenericFragment() {
|
|||
}
|
||||
|
||||
viewModel.saveChangesEvent.observe(viewLifecycleOwner) {
|
||||
it.consume {
|
||||
goBack() // TODO FIXME : go to contact detail view
|
||||
it.consume { ok ->
|
||||
if (ok) {
|
||||
goBack() // TODO FIXME : go to contact detail view
|
||||
} else {
|
||||
// TODO : show error
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@ import org.linphone.utils.LinphoneUtils
|
|||
class ContactAvatarModel(val friend: Friend) {
|
||||
val id = friend.refKey
|
||||
|
||||
val avatar = MutableLiveData<Uri>()
|
||||
|
||||
val initials = LinphoneUtils.getInitials(friend.name.orEmpty())
|
||||
|
||||
val presenceStatus = MutableLiveData<ConsolidatedPresence>()
|
||||
|
|
@ -53,6 +55,7 @@ class ContactAvatarModel(val friend: Friend) {
|
|||
// Core thread
|
||||
name.postValue(friend.name)
|
||||
presenceStatus.postValue(friend.consolidatedPresence)
|
||||
avatar.postValue(getAvatarUri())
|
||||
|
||||
friend.addListener(friendListener)
|
||||
|
||||
|
|
@ -64,8 +67,13 @@ class ContactAvatarModel(val friend: Friend) {
|
|||
friend.removeListener(friendListener)
|
||||
}
|
||||
|
||||
fun getAvatarUri(): Uri? {
|
||||
private fun getAvatarUri(): Uri? {
|
||||
// Core thread
|
||||
val picturePath = friend.photo
|
||||
if (!picturePath.isNullOrEmpty()) {
|
||||
return Uri.parse(picturePath)
|
||||
}
|
||||
|
||||
val refKey = friend.refKey
|
||||
if (refKey != null) {
|
||||
val lookupUri = ContentUris.withAppendedId(
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ class ContactNewOrEditViewModel() : ViewModel() {
|
|||
friendFoundEvent.postValue(Event(true))
|
||||
} else {
|
||||
Log.e("$TAG No friend found using ref key [$refKey]")
|
||||
// TODO : generate unique ref key
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
105
app/src/main/java/org/linphone/ui/main/model/AccountModel.kt
Normal file
105
app/src/main/java/org/linphone/ui/main/model/AccountModel.kt
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* 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.model
|
||||
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
import org.linphone.core.Account
|
||||
import org.linphone.core.AccountListenerStub
|
||||
import org.linphone.core.Friend
|
||||
import org.linphone.core.RegistrationState
|
||||
import org.linphone.ui.main.contacts.model.ContactAvatarModel
|
||||
|
||||
class AccountModel(private val account: Account) {
|
||||
val friend: Friend?
|
||||
|
||||
val contact = MutableLiveData<ContactAvatarModel>()
|
||||
|
||||
val registrationState = MutableLiveData<String>()
|
||||
|
||||
val isConnected = MutableLiveData<Boolean>()
|
||||
|
||||
val inError = MutableLiveData<Boolean>()
|
||||
|
||||
val isDefault = MutableLiveData<Boolean>()
|
||||
|
||||
private val accountListener = object : AccountListenerStub() {
|
||||
override fun onRegistrationStateChanged(
|
||||
account: Account,
|
||||
state: RegistrationState?,
|
||||
message: String
|
||||
) {
|
||||
updateRegistrationState()
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
// Core thread
|
||||
account.addListener(accountListener)
|
||||
isDefault.postValue(coreContext.core.defaultAccount == account)
|
||||
|
||||
friend = coreContext.contactsManager.localFriends.find {
|
||||
it.addresses.find { address ->
|
||||
address.weakEqual(account.params.identityAddress!!)
|
||||
} != null
|
||||
}
|
||||
|
||||
if (friend != null) {
|
||||
contact.postValue(ContactAvatarModel(friend))
|
||||
}
|
||||
|
||||
updateRegistrationState()
|
||||
}
|
||||
|
||||
fun destroy() {
|
||||
// Core thread
|
||||
account.removeListener(accountListener)
|
||||
}
|
||||
|
||||
fun setAsDefault() {
|
||||
// UI thread
|
||||
coreContext.postOnCoreThread { core ->
|
||||
core.defaultAccount = account
|
||||
isDefault.postValue(true)
|
||||
}
|
||||
}
|
||||
|
||||
fun refreshRegister() {
|
||||
// UI thread
|
||||
coreContext.postOnCoreThread { core ->
|
||||
core.refreshRegisters()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateRegistrationState() {
|
||||
// Core thread
|
||||
val state = when (account.state) {
|
||||
RegistrationState.None, RegistrationState.Cleared -> "Disabled"
|
||||
RegistrationState.Progress -> "Connection..."
|
||||
RegistrationState.Failed -> "Error"
|
||||
RegistrationState.Ok -> "Connected"
|
||||
RegistrationState.Refreshing -> "Refreshing"
|
||||
else -> "${account.state}"
|
||||
}
|
||||
isConnected.postValue(account.state == RegistrationState.Ok)
|
||||
inError.postValue(account.state == RegistrationState.Failed)
|
||||
registrationState.postValue(state)
|
||||
}
|
||||
}
|
||||
|
|
@ -21,9 +21,16 @@ package org.linphone.ui.main.viewmodel
|
|||
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
import org.linphone.core.Account
|
||||
import org.linphone.core.Core
|
||||
import org.linphone.core.CoreListenerStub
|
||||
import org.linphone.core.RegistrationState
|
||||
import org.linphone.ui.main.model.AccountModel
|
||||
import org.linphone.utils.Event
|
||||
|
||||
class DrawerMenuViewModel : ViewModel() {
|
||||
val accounts = MutableLiveData<ArrayList<AccountModel>>()
|
||||
|
||||
val startAssistantEvent: MutableLiveData<Event<Boolean>> by lazy {
|
||||
MutableLiveData<Event<Boolean>>()
|
||||
|
|
@ -33,6 +40,33 @@ class DrawerMenuViewModel : ViewModel() {
|
|||
MutableLiveData<Event<Boolean>>()
|
||||
}
|
||||
|
||||
private val coreListener = object : CoreListenerStub() {
|
||||
override fun onAccountRegistrationStateChanged(
|
||||
core: Core,
|
||||
account: Account,
|
||||
state: RegistrationState?,
|
||||
message: String
|
||||
) {
|
||||
// Core thread
|
||||
computeAccountsList()
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
coreContext.postOnCoreThread { core ->
|
||||
core.addListener(coreListener)
|
||||
computeAccountsList()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
super.onCleared()
|
||||
|
||||
coreContext.postOnCoreThread { core ->
|
||||
core.removeListener(coreListener)
|
||||
}
|
||||
}
|
||||
|
||||
fun closeDrawerMenu() {
|
||||
// UI thread
|
||||
closeDrawerEvent.value = Event(true)
|
||||
|
|
@ -42,4 +76,16 @@ class DrawerMenuViewModel : ViewModel() {
|
|||
// UI thread
|
||||
startAssistantEvent.value = Event(true)
|
||||
}
|
||||
|
||||
private fun computeAccountsList() {
|
||||
// Core thread
|
||||
accounts.value.orEmpty().forEach(AccountModel::destroy)
|
||||
|
||||
val list = arrayListOf<AccountModel>()
|
||||
for (account in coreContext.core.accountList) {
|
||||
val model = AccountModel(account)
|
||||
list.add(model)
|
||||
}
|
||||
accounts.postValue(list)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,11 +21,15 @@ package org.linphone.ui.main.viewmodel
|
|||
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
import org.linphone.ui.main.model.AccountModel
|
||||
import org.linphone.utils.Event
|
||||
|
||||
class TopBarViewModel : ViewModel() {
|
||||
val title = MutableLiveData<String>()
|
||||
|
||||
val account = MutableLiveData<AccountModel>()
|
||||
|
||||
val searchBarVisible = MutableLiveData<Boolean>()
|
||||
|
||||
val searchFilter = MutableLiveData<String>()
|
||||
|
|
@ -40,10 +44,21 @@ class TopBarViewModel : ViewModel() {
|
|||
|
||||
init {
|
||||
searchBarVisible.value = false
|
||||
|
||||
coreContext.postOnCoreThread { core ->
|
||||
if (core.accountList.isNotEmpty()) {
|
||||
val defaultAccount = core.defaultAccount ?: core.accountList.first()
|
||||
account.postValue(AccountModel(defaultAccount))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
super.onCleared()
|
||||
|
||||
coreContext.postOnCoreThread {
|
||||
account.value?.destroy()
|
||||
}
|
||||
}
|
||||
|
||||
fun openDrawerMenu() {
|
||||
|
|
|
|||
|
|
@ -131,6 +131,7 @@ fun AppCompatTextView.setDrawableTint(color: Int) {
|
|||
|
||||
@BindingAdapter("coilContact")
|
||||
fun loadContactPictureWithCoil2(imageView: ImageView, contact: ContactData?) {
|
||||
// UI thread !
|
||||
if (contact == null) {
|
||||
imageView.load(R.drawable.contact_avatar)
|
||||
} else {
|
||||
|
|
@ -143,6 +144,7 @@ fun loadContactPictureWithCoil2(imageView: ImageView, contact: ContactData?) {
|
|||
|
||||
@BindingAdapter("contactAvatar")
|
||||
fun AvatarView.loadContactPicture(contact: ContactAvatarModel?) {
|
||||
// UI thread !
|
||||
if (contact == null) {
|
||||
loadImage(R.drawable.contact_avatar)
|
||||
} else {
|
||||
|
|
@ -152,7 +154,7 @@ fun AvatarView.loadContactPicture(contact: ContactAvatarModel?) {
|
|||
}
|
||||
indicatorEnabled = contact.presenceStatus.value != ConsolidatedPresence.Offline
|
||||
|
||||
val uri = contact.getAvatarUri()
|
||||
val uri = contact.avatar.value
|
||||
loadImage(
|
||||
data = uri,
|
||||
onStart = {
|
||||
|
|
|
|||
|
|
@ -8,18 +8,22 @@
|
|||
<import type="android.graphics.Typeface" />
|
||||
<variable
|
||||
name="model"
|
||||
type="org.linphone.ui.main.contacts.model.ContactAvatarModel" />
|
||||
<variable
|
||||
name="onClickListener"
|
||||
type="View.OnClickListener" />
|
||||
type="org.linphone.ui.main.model.AccountModel" />
|
||||
</data>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:onClick="@{onClickListener}"
|
||||
android:onClick="@{() -> model.setAsDefault()}"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/shape_conversation_cell_background">
|
||||
|
||||
<androidx.constraintlayout.widget.Barrier
|
||||
android:id="@+id/left_barrier"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:barrierDirection="right"
|
||||
app:constraint_referenced_ids="name, register_status" />
|
||||
|
||||
<io.getstream.avatarview.AvatarView
|
||||
android:id="@+id/avatar"
|
||||
android:layout_width="@dimen/avatar_list_cell_size"
|
||||
|
|
@ -28,8 +32,7 @@
|
|||
android:layout_marginTop="5dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:adjustViewBounds="true"
|
||||
contactAvatar="@{model}"
|
||||
app:avatarViewInitials="JD"
|
||||
contactAvatar="@{model.contact}"
|
||||
app:avatarViewPlaceholder="@drawable/contact_avatar"
|
||||
app:avatarViewInitialsBackgroundColor="@color/blue_outgoing_message"
|
||||
app:avatarViewInitialsTextColor="@color/gray_9"
|
||||
|
|
@ -53,7 +56,7 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:layout_marginTop="5dp"
|
||||
android:text="John Doe"
|
||||
android:text="@{model.contact.name, default=`John Doe`}"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@color/gray_8"
|
||||
android:layout_marginStart="10dp"
|
||||
|
|
@ -62,6 +65,7 @@
|
|||
app:layout_constraintBottom_toTopOf="@id/register_status"/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:onClick="@{() -> model.refreshRegister()}"
|
||||
style="@style/default_text_style_300"
|
||||
android:id="@+id/register_status"
|
||||
android:layout_width="wrap_content"
|
||||
|
|
@ -73,13 +77,29 @@
|
|||
android:paddingBottom="4dp"
|
||||
android:background="@drawable/shape_chip_gray_background"
|
||||
android:gravity="center"
|
||||
android:text="Connected"
|
||||
android:textColor="@color/green_online"
|
||||
android:text="@{model.registrationState, default=`Connected`}"
|
||||
android:textColor="@{model.isConnected ? @color/green_online : model.inError ? @color/red_danger : @color/gray_1, default=@color/green_online}"
|
||||
android:textSize="12sp"
|
||||
app:layout_constraintStart_toStartOf="@id/name"
|
||||
app:layout_constraintTop_toBottomOf="@id/name"
|
||||
app:layout_constraintBottom_toTopOf="@id/separator"/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/default_text_style_300"
|
||||
android:visibility="@{model.isDefault ? View.VISIBLE : View.GONE}"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Default"
|
||||
android:textSize="12sp"
|
||||
android:gravity="center"
|
||||
android:drawableStart="@drawable/check"
|
||||
android:drawablePadding="3dp"
|
||||
app:drawableTint="@color/primary_color"
|
||||
app:layout_constraintStart_toEndOf="@id/left_barrier"
|
||||
app:layout_constraintEnd_toStartOf="@id/menu"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/menu"
|
||||
android:layout_width="wrap_content"
|
||||
|
|
|
|||
|
|
@ -8,6 +8,9 @@
|
|||
<variable
|
||||
name="registerClickListener"
|
||||
type="View.OnClickListener" />
|
||||
<variable
|
||||
name="viewModel"
|
||||
type="org.linphone.ui.assistant.viewmodel.AssistantViewModel" />
|
||||
</data>
|
||||
|
||||
<ScrollView
|
||||
|
|
@ -55,7 +58,7 @@
|
|||
android:layout_marginEnd="16dp"
|
||||
android:paddingStart="20dp"
|
||||
android:paddingEnd="20dp"
|
||||
android:text="John Doe"
|
||||
android:text="@={viewModel.username, default=`johndoe`}"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@color/gray_9"
|
||||
android:background="@drawable/shape_edit_text_background"
|
||||
|
|
@ -86,7 +89,7 @@
|
|||
android:layout_marginEnd="16dp"
|
||||
android:paddingStart="20dp"
|
||||
android:paddingEnd="20dp"
|
||||
android:text="John Doe"
|
||||
android:text="@={viewModel.password, default=`johndoe`}"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@color/gray_9"
|
||||
android:background="@drawable/shape_edit_text_background"
|
||||
|
|
@ -98,6 +101,8 @@
|
|||
app:layout_constraintEnd_toEndOf="parent"/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:onClick="@{() -> viewModel.login()}"
|
||||
android:enabled="@{viewModel.loginEnabled && !viewModel.registrationInProgress, default=false}"
|
||||
style="@style/default_text_style_600"
|
||||
android:id="@+id/login"
|
||||
android:layout_width="0dp"
|
||||
|
|
|
|||
|
|
@ -60,12 +60,9 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="5dp"
|
||||
android:layout_marginEnd="5dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<include
|
||||
layout="@layout/account_list_cell" />
|
||||
|
||||
</LinearLayout>
|
||||
android:orientation="vertical"
|
||||
entries="@{viewModel.accounts}"
|
||||
layout="@{@layout/account_list_cell}"/>
|
||||
|
||||
</ScrollView>
|
||||
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
android:layout_width="@dimen/avatar_list_cell_size"
|
||||
android:layout_height="@dimen/avatar_list_cell_size"
|
||||
android:layout_marginStart="15dp"
|
||||
contactAvatar="@{viewModel.account.contact}"
|
||||
app:avatarViewBorderColor="@color/trusted_blue"
|
||||
app:avatarViewBorderWidth="2dp"
|
||||
app:avatarViewIndicatorSizeCriteria="3"
|
||||
|
|
@ -52,7 +53,6 @@
|
|||
app:avatarViewInitialsTextStyle="bold"
|
||||
app:avatarViewPlaceholder="@drawable/contact_avatar"
|
||||
app:avatarViewShape="circle"
|
||||
app:avatarViewInitials="SB"
|
||||
app:layout_constraintBottom_toBottomOf="@id/title"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/title" />
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue