Replaced deprecated ProxyConfig object by Account

This commit is contained in:
Sylvain Berfini 2020-10-21 09:22:52 +02:00
parent 4f6b416b7e
commit daa789e672
25 changed files with 264 additions and 159 deletions

View file

@ -102,7 +102,7 @@ class MainActivity : GenericActivity(), SnackBarActivity, NavController.OnDestin
startActivity(intent)
}
if (coreContext.core.proxyConfigList.isEmpty()) {
if (coreContext.core.accountList.isEmpty()) {
if (corePreferences.firstStart) {
corePreferences.firstStart = false
startActivity(Intent(this, AssistantActivity::class.java))
@ -371,7 +371,7 @@ class MainActivity : GenericActivity(), SnackBarActivity, NavController.OnDestin
val peerAddress = coreContext.core.interpretUrl(addressToIM)?.asStringUriOnly()
val localAddress =
coreContext.core.defaultProxyConfig?.contact?.asStringUriOnly()
coreContext.core.defaultAccount?.params?.identityAddress?.asStringUriOnly()
val deepLink = "linphone-android://chat-room/$localAddress/$peerAddress"
Log.i("[Main Activity] Starting deep link: $deepLink")
findNavController(R.id.nav_host_fragment).navigate(Uri.parse(deepLink))

View file

@ -101,7 +101,7 @@ class ChatRoomCreationContactsAdapter(
securityEnabled: Boolean
) {
val searchAddress = searchResult.address
val isMyself = securityEnabled && searchAddress != null && coreContext.core.defaultProxyConfig?.identityAddress?.weakEqual(searchAddress) ?: false
val isMyself = securityEnabled && searchAddress != null && coreContext.core.defaultAccount?.params?.identityAddress?.weakEqual(searchAddress) ?: false
val limeCheck = !securityEnabled || (securityEnabled && searchResult.hasCapability(FriendCapability.LimeX3Dh))
val groupCheck = !groupChatEnabled || (groupChatEnabled && searchResult.hasCapability(FriendCapability.GroupChat))
val disabled = if (searchResult.friend != null) !limeCheck || !groupCheck || isMyself else false // Generated entry from search filter

View file

@ -107,7 +107,7 @@ class ChatRoomCreationViewModel : ErrorReportingViewModel() {
}
fun updateContactsList() {
val domain = if (sipContactsSelected.value == true) coreContext.core.defaultProxyConfig?.domain ?: "" else ""
val domain = if (sipContactsSelected.value == true) coreContext.core.defaultAccount?.params?.domain ?: "" else ""
val results = coreContext.contactsManager.magicSearch.getContactListFromFilter(filter.value.orEmpty(), domain)
val list = arrayListOf<SearchResult>()
@ -145,7 +145,7 @@ class ChatRoomCreationViewModel : ErrorReportingViewModel() {
fun createOneToOneChat(searchResult: SearchResult) {
waitForChatRoomCreation.value = true
val defaultProxyConfig = coreContext.core.defaultProxyConfig
val defaultAccount = coreContext.core.defaultAccount
var room: ChatRoom?
val address = searchResult.address ?: coreContext.core.interpretUrl(searchResult.phoneNumber ?: "")
@ -167,12 +167,13 @@ class ChatRoomCreationViewModel : ErrorReportingViewModel() {
}
val participants = arrayOf(address)
val localAddress = defaultProxyConfig?.identityAddress
val localAddress: Address? = defaultAccount?.params?.identityAddress
room = coreContext.core.searchChatRoom(params, localAddress, null, participants)
if (room == null) {
Log.w("[Chat Room Creation] Couldn't find existing 1-1 chat room with remote ${address.asStringUriOnly()}, encryption=$encrypted and local identity ${localAddress?.asStringUriOnly()}")
room = coreContext.core.createChatRoom(params, localAddress, participants)
if (encrypted) {
room?.addListener(listener)
} else {

View file

@ -125,7 +125,7 @@ class GroupInfoViewModel(val chatRoom: ChatRoom?) : ErrorReportingViewModel() {
index += 1
}
val chatRoom: ChatRoom? = coreContext.core.createChatRoom(params, coreContext.core.defaultProxyConfig?.identityAddress, addresses)
val chatRoom: ChatRoom? = coreContext.core.createChatRoom(params, coreContext.core.defaultAccount?.params?.identityAddress, addresses)
chatRoom?.addListener(listener)
if (chatRoom == null) {
Log.e("[Chat Room Group Info] Couldn't create chat room!")

View file

@ -169,9 +169,9 @@ class ContactViewModel(private val c: Contact) : ErrorReportingViewModel(), Cont
val value = address.asStringUriOnly()
val presenceModel = contact.friend?.getPresenceModelForUriOrTel(value)
val hasPresence = presenceModel?.basicStatus == PresenceBasicStatus.Open
val isMe = coreContext.core.defaultProxyConfig?.identityAddress?.weakEqual(address) ?: false
val isMe = coreContext.core.defaultAccount?.params?.identityAddress?.weakEqual(address) ?: false
val secureChatAllowed = !isMe && contact.friend?.getPresenceModelForUriOrTel(value)?.hasCapability(FriendCapability.LimeX3Dh) ?: false
val displayValue = if (coreContext.core.defaultProxyConfig?.domain == address.domain) (address.username ?: value) else value
val displayValue = if (coreContext.core.defaultAccount?.params?.domain == address.domain) (address.username ?: value) else value
val noa = ContactNumberOrAddressViewModel(address, hasPresence, displayValue, showSecureChat = secureChatAllowed, listener = listener)
list.add(noa)
}
@ -181,7 +181,7 @@ class ContactViewModel(private val c: Contact) : ErrorReportingViewModel(), Cont
val hasPresence = presenceModel != null && presenceModel.basicStatus == PresenceBasicStatus.Open
val contactAddress = presenceModel?.contact ?: number
val address = coreContext.core.interpretUrl(contactAddress)
val isMe = if (address != null) coreContext.core.defaultProxyConfig?.identityAddress?.weakEqual(address) ?: false else false
val isMe = if (address != null) coreContext.core.defaultAccount?.params?.identityAddress?.weakEqual(address) ?: false else false
val secureChatAllowed = !isMe && contact.friend?.getPresenceModelForUriOrTel(number)?.hasCapability(FriendCapability.LimeX3Dh) ?: false
val noa = ContactNumberOrAddressViewModel(address, hasPresence, number, isSip = false, showSecureChat = secureChatAllowed, typeLabel = phoneNumber.typeLabel, listener = listener)
list.add(noa)

View file

@ -48,11 +48,11 @@ class StatusFragment : GenericFragment<StatusFragmentBinding>() {
ViewModelProvider(this).get(SharedMainViewModel::class.java)
}
sharedViewModel.proxyConfigRemoved.observe(viewLifecycleOwner, {
Log.i("[Status Fragment] A proxy config was removed, update default proxy state")
val defaultProxy = coreContext.core.defaultProxyConfig
if (defaultProxy != null) {
viewModel.updateDefaultProxyConfigRegistrationStatus(defaultProxy.state)
sharedViewModel.accountRemoved.observe(viewLifecycleOwner, {
Log.i("[Status Fragment] An account was removed, update default account state")
val defaultAccount = coreContext.core.defaultAccount
if (defaultAccount != null) {
viewModel.updateDefaultAccountRegistrationStatus(defaultAccount.state)
}
})

View file

@ -56,9 +56,9 @@ class AccountSettingsFragment : GenericFragment<SettingsAccountFragmentBinding>(
viewModel.linkPhoneNumberEvent.observe(viewLifecycleOwner, {
it.consume {
val authInfo = viewModel.proxyConfig.findAuthInfo()
val authInfo = viewModel.account.findAuthInfo()
if (authInfo == null) {
Log.e("[Account Settings] Failed to find auth info for proxy config ${viewModel.proxyConfig}")
Log.e("[Account Settings] Failed to find auth info for account ${viewModel.account}")
} else {
val args = Bundle()
args.putString("Username", authInfo.username)
@ -69,9 +69,9 @@ class AccountSettingsFragment : GenericFragment<SettingsAccountFragmentBinding>(
}
})
viewModel.proxyConfigRemovedEvent.observe(viewLifecycleOwner, {
viewModel.accountRemovedEvent.observe(viewLifecycleOwner, {
it.consume {
sharedViewModel.proxyConfigRemoved.value = true
sharedViewModel.accountRemoved.value = true
findNavController().navigateUp()
}
})

View file

@ -54,8 +54,8 @@ class SettingsFragment : SecureFragment<SettingsFragmentBinding>() {
binding.setBackClickListener { findNavController().popBackStack() }
sharedViewModel.proxyConfigRemoved.observe(viewLifecycleOwner, {
Log.i("[Settings] Proxy config removed, update accounts list")
sharedViewModel.accountRemoved.observe(viewLifecycleOwner, {
Log.i("[Settings] Account removed, update accounts list")
viewModel.updateAccountsList()
})
@ -68,7 +68,7 @@ class SettingsFragment : SecureFragment<SettingsFragmentBinding>() {
viewModel.accountsSettingsListener = object : SettingListenerStub() {
override fun onAccountClicked(identity: String) {
Log.i("[Settings] Navigation to settings for proxy with identity: $identity")
Log.i("[Settings] Navigation to settings for account with identity: $identity")
navigateToAccountSettings(identity)
}
}

View file

@ -38,16 +38,16 @@ class AccountSettingsViewModelFactory(private val identity: String) :
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
for (proxy in coreContext.core.proxyConfigList) {
if (proxy.identityAddress?.asStringUriOnly() == identity) {
return AccountSettingsViewModel(proxy) as T
for (account in coreContext.core.accountList) {
if (account.params.identityAddress?.asStringUriOnly() == identity) {
return AccountSettingsViewModel(account) as T
}
}
return AccountSettingsViewModel(coreContext.core.defaultProxyConfig!!) as T
return AccountSettingsViewModel(coreContext.core.defaultAccount!!) as T
}
}
class AccountSettingsViewModel(val proxyConfig: ProxyConfig) : GenericSettingsViewModel() {
class AccountSettingsViewModel(val account: Account) : GenericSettingsViewModel() {
val isDefault = MutableLiveData<Boolean>()
val displayName = MutableLiveData<String>()
@ -61,25 +61,24 @@ class AccountSettingsViewModel(val proxyConfig: ProxyConfig) : GenericSettingsVi
val waitForUnregister = MutableLiveData<Boolean>()
val proxyConfigRemovedEvent: MutableLiveData<Event<Boolean>> by lazy {
val accountRemovedEvent: MutableLiveData<Event<Boolean>> by lazy {
MutableLiveData<Event<Boolean>>()
}
val displayUsernameInsteadOfIdentity = corePreferences.replaceSipUriByUsername
private var proxyConfigToDelete: ProxyConfig? = null
private var accountToDelete: Account? = null
val listener: CoreListenerStub = object : CoreListenerStub() {
val listener: AccountListenerStub = object : AccountListenerStub() {
override fun onRegistrationStateChanged(
core: Core,
cfg: ProxyConfig,
account: Account,
state: RegistrationState,
message: String
) {
if (state == RegistrationState.Cleared && cfg == proxyConfigToDelete) {
Log.i("[Account Settings] Proxy config to remove registration is now cleared")
if (state == RegistrationState.Cleared && account == accountToDelete) {
Log.i("[Account Settings] Account to remove registration is now cleared")
waitForUnregister.value = false
deleteProxyConfig(cfg)
deleteAccount(account)
} else {
update()
}
@ -90,44 +89,94 @@ class AccountSettingsViewModel(val proxyConfig: ProxyConfig) : GenericSettingsVi
val userNameListener = object : SettingListenerStub() {
override fun onTextValueChanged(newValue: String) {
// TODO
val params = account.params.clone()
val identity = params.identityAddress
if (identity != null) {
identity.username = newValue
params.identityAddress = identity
account.params = params
} else {
Log.e("[Account Settings] Account doesn't have an identity yet")
}
}
}
val userName = MutableLiveData<String>()
val userIdListener = object : SettingListenerStub() {
override fun onTextValueChanged(newValue: String) {
// TODO
val authInfo = account.findAuthInfo()
if (authInfo != null) {
authInfo.userid = newValue
} else {
Log.e("[Account Settings] Failed to find the matching auth info")
}
}
}
val userId = MutableLiveData<String>()
val passwordListener = object : SettingListenerStub() {
override fun onTextValueChanged(newValue: String) {
// TODO
val authInfo = account.findAuthInfo()
if (authInfo != null) {
authInfo.password = newValue
} else {
Log.w("[Account Settings] Failed to find the matching auth info")
val params = account.params
val identity = params.identityAddress
if (identity != null && identity.username != null) {
val newAuthInfo = Factory.instance()
.createAuthInfo(identity.username!!, userId.value, newValue, null, null, identity.domain)
core.addAuthInfo(newAuthInfo)
} else {
Log.e("[Account Settings] Failed to find the user's identity, can't create a new auth info")
}
}
}
}
val password = MutableLiveData<String>()
val domainListener = object : SettingListenerStub() {
override fun onTextValueChanged(newValue: String) {
// TODO
val params = account.params.clone()
val identity = params.identityAddress
if (identity != null) {
val authInfo = account.findAuthInfo()
if (authInfo != null) {
authInfo.domain = newValue
} else {
Log.e("[Account Settings] Failed to find the matching auth info")
}
identity.domain = newValue
params.identityAddress = identity
account.params = params
} else {
Log.e("[Account Settings] Account doesn't have an identity yet")
}
}
}
val domain = MutableLiveData<String>()
val displayNameListener = object : SettingListenerStub() {
override fun onTextValueChanged(newValue: String) {
proxyConfig.identityAddress?.displayName = newValue
val params = account.params.clone()
val identity = params.identityAddress
if (identity != null) {
identity.displayName = newValue
params.identityAddress = identity
account.params = params
} else {
Log.e("[Account Settings] Account doesn't have an identity yet")
}
}
}
// displayName mutable is above
val disableListener = object : SettingListenerStub() {
override fun onBoolValueChanged(newValue: Boolean) {
proxyConfig.edit()
proxyConfig.enableRegister(!newValue)
proxyConfig.done()
val params = account.params.clone()
params.registerEnabled = !newValue
account.params = params
}
}
val disable = MutableLiveData<Boolean>()
@ -135,14 +184,14 @@ class AccountSettingsViewModel(val proxyConfig: ProxyConfig) : GenericSettingsVi
val isDefaultListener = object : SettingListenerStub() {
override fun onBoolValueChanged(newValue: Boolean) {
if (newValue) {
core.defaultProxyConfig = proxyConfig
core.defaultAccount = account
}
}
}
// isDefault mutable is above
private fun deleteProxyConfig(cfg: ProxyConfig) {
val authInfo = cfg.findAuthInfo()
private fun deleteAccount(account: Account) {
val authInfo = account.findAuthInfo()
if (authInfo != null) {
Log.i("[Account Settings] Found auth info $authInfo, removing it.")
core.removeAuthInfo(authInfo)
@ -150,42 +199,44 @@ class AccountSettingsViewModel(val proxyConfig: ProxyConfig) : GenericSettingsVi
Log.w("[Account Settings] Couldn't find matching auth info...")
}
core.removeProxyConfig(cfg)
proxyConfigRemovedEvent.value = Event(true)
core.removeAccount(account)
accountRemovedEvent.value = Event(true)
}
val deleteListener = object : SettingListenerStub() {
override fun onClicked() {
proxyConfigToDelete = proxyConfig
accountToDelete = account
val registered = proxyConfig.state == RegistrationState.Ok
val registered = account.state == RegistrationState.Ok
waitForUnregister.value = registered
if (core.defaultProxyConfig == proxyConfig) {
Log.i("[Account Settings] Proxy config was default, let's look for a replacement")
for (proxyConfigIterator in core.proxyConfigList) {
if (proxyConfig != proxyConfigIterator) {
core.defaultProxyConfig = proxyConfigIterator
Log.i("[Account Settings] New default proxy config is $proxyConfigIterator")
if (core.defaultAccount == account) {
Log.i("[Account Settings] Account was default, let's look for a replacement")
for (accountIterator in core.accountList) {
if (account != accountIterator) {
core.defaultAccount = accountIterator
Log.i("[Account Settings] New default account is $accountIterator")
break
}
}
}
proxyConfig.edit()
proxyConfig.enableRegister(false)
proxyConfig.done()
val params = account.params.clone()
params.registerEnabled = false
account.params = params
if (!registered) {
Log.w("[Account Settings] Proxy config isn't registered, don't unregister before removing it")
deleteProxyConfig(proxyConfig)
Log.w("[Account Settings] Account isn't registered, don't unregister before removing it")
deleteAccount(account)
}
}
}
val pushNotificationListener = object : SettingListenerStub() {
override fun onBoolValueChanged(newValue: Boolean) {
proxyConfig.isPushNotificationAllowed = newValue
val params = account.params.clone()
params.pushNotificationAllowed = newValue
account.params = params
}
}
val pushNotification = MutableLiveData<Boolean>()
@ -193,7 +244,10 @@ class AccountSettingsViewModel(val proxyConfig: ProxyConfig) : GenericSettingsVi
val transportListener = object : SettingListenerStub() {
override fun onListValueChanged(position: Int) {
// TODO
val params = account.params.clone()
params.transport = TransportType.fromInt(position)
account.params = params
proxy.value = account.params.serverAddr
}
}
val transportIndex = MutableLiveData<Int>()
@ -201,40 +255,48 @@ class AccountSettingsViewModel(val proxyConfig: ProxyConfig) : GenericSettingsVi
val proxyListener = object : SettingListenerStub() {
override fun onTextValueChanged(newValue: String) {
proxyConfig.serverAddr = newValue
if (outboundProxy.value == true) {
// TODO
}
val params = account.params.clone()
params.serverAddr = newValue
account.params = params
transportIndex.value = account.params.transport.toInt()
}
}
val proxy = MutableLiveData<String>()
val outboundProxyListener = object : SettingListenerStub() {
override fun onBoolValueChanged(newValue: Boolean) {
// TODO
val params = account.params.clone()
params.outboundProxyEnabled = newValue
account.params = params
}
}
val outboundProxy = MutableLiveData<Boolean>()
val stunServerListener = object : SettingListenerStub() {
override fun onTextValueChanged(newValue: String) {
proxyConfig.natPolicy?.stunServer = newValue
val params = account.params.clone()
params.natPolicy?.stunServer = newValue
if (newValue.isEmpty()) ice.value = false
stunServer.value = newValue
account.params = params
}
}
val stunServer = MutableLiveData<String>()
val iceListener = object : SettingListenerStub() {
override fun onBoolValueChanged(newValue: Boolean) {
proxyConfig.natPolicy?.enableIce(newValue)
val params = account.params.clone()
params.natPolicy?.enableIce(newValue)
account.params = params
}
}
val ice = MutableLiveData<Boolean>()
val avpfListener = object : SettingListenerStub() {
override fun onBoolValueChanged(newValue: Boolean) {
proxyConfig.avpfMode = if (newValue) AVPFMode.Enabled else AVPFMode.Disabled
val params = account.params.clone()
params.avpfMode = if (newValue) AVPFMode.Enabled else AVPFMode.Disabled
account.params = params
}
}
val avpf = MutableLiveData<Boolean>()
@ -242,8 +304,11 @@ class AccountSettingsViewModel(val proxyConfig: ProxyConfig) : GenericSettingsVi
val avpfRrIntervalListener = object : SettingListenerStub() {
override fun onTextValueChanged(newValue: String) {
try {
proxyConfig.avpfRrInterval = newValue.toInt()
val params = account.params.clone()
params.avpfRrInterval = newValue.toInt()
account.params = params
} catch (nfe: NumberFormatException) {
Log.e("[Account Settings] Failed to set AVPF RR interval ($newValue): $nfe")
}
}
}
@ -252,23 +317,39 @@ class AccountSettingsViewModel(val proxyConfig: ProxyConfig) : GenericSettingsVi
val expiresListener = object : SettingListenerStub() {
override fun onTextValueChanged(newValue: String) {
try {
proxyConfig.expires = newValue.toInt()
val params = account.params.clone()
params.expires = newValue.toInt()
account.params = params
} catch (nfe: NumberFormatException) {
Log.e("[Account Settings] Failed to set expires ($newValue): $nfe")
}
}
}
val expires = MutableLiveData<Int>()
val dialPrefixListener = object : SettingListenerStub() {
val prefixListener = object : SettingListenerStub() {
override fun onTextValueChanged(newValue: String) {
proxyConfig.dialPrefix = newValue
val params = account.params.clone()
params.internationalPrefix = newValue
account.params = params
}
}
val dialPrefix = MutableLiveData<String>()
val prefix = MutableLiveData<String>()
val dialPrefixListener = object : SettingListenerStub() {
override fun onBoolValueChanged(newValue: Boolean) {
val params = account.params.clone()
params.useInternationalPrefixForCallsAndChats = newValue
account.params = params
}
}
val dialPrefix = MutableLiveData<Boolean>()
val escapePlusListener = object : SettingListenerStub() {
override fun onBoolValueChanged(newValue: Boolean) {
proxyConfig.dialEscapePlus = newValue
val params = account.params.clone()
params.dialEscapePlusEnabled = newValue
account.params = params
}
}
val escapePlus = MutableLiveData<Boolean>()
@ -282,61 +363,67 @@ class AccountSettingsViewModel(val proxyConfig: ProxyConfig) : GenericSettingsVi
init {
update()
core.addListener(listener)
account.addListener(listener)
initTransportList()
}
override fun onCleared() {
core.removeListener(listener)
account.removeListener(listener)
super.onCleared()
}
private fun update() {
isDefault.value = core.defaultProxyConfig == proxyConfig
val identityAddress = proxyConfig.identityAddress
isDefault.value = core.defaultAccount == account
val params = account.params
val identityAddress = params.identityAddress
if (identityAddress != null) {
displayName.value = identityAddress.displayName ?: ""
identity.value = identityAddress.asStringUriOnly()
}
iconResource.value = when (proxyConfig.state) {
iconResource.value = when (account.state) {
RegistrationState.Ok -> R.drawable.led_registered
RegistrationState.Failed -> R.drawable.led_error
RegistrationState.Progress -> R.drawable.led_registration_in_progress
else -> R.drawable.led_not_registered
}
iconContentDescription.value = when (proxyConfig.state) {
iconContentDescription.value = when (account.state) {
RegistrationState.Ok -> R.string.status_connected
RegistrationState.Progress -> R.string.status_in_progress
RegistrationState.Failed -> R.string.status_error
else -> R.string.status_not_connected
}
userName.value = proxyConfig.identityAddress?.username
userId.value = proxyConfig.findAuthInfo()?.userid
domain.value = proxyConfig.identityAddress?.domain
disable.value = !proxyConfig.registerEnabled()
pushNotification.value = proxyConfig.isPushNotificationAllowed
userName.value = params.identityAddress?.username
userId.value = account.findAuthInfo()?.userid
domain.value = params.identityAddress?.domain
disable.value = !params.registerEnabled
pushNotification.value = params.pushNotificationAllowed
pushNotificationsAvailable.value = core.isPushNotificationAvailable
proxy.value = proxyConfig.serverAddr
outboundProxy.value = proxyConfig.serverAddr == proxyConfig.routes.firstOrNull()
stunServer.value = proxyConfig.natPolicy?.stunServer
ice.value = proxyConfig.natPolicy?.iceEnabled()
avpf.value = proxyConfig.avpfEnabled()
avpfRrInterval.value = proxyConfig.avpfRrInterval
expires.value = proxyConfig.expires
dialPrefix.value = proxyConfig.dialPrefix
escapePlus.value = proxyConfig.dialEscapePlus
proxy.value = params.serverAddr
outboundProxy.value = params.outboundProxyEnabled
stunServer.value = params.natPolicy?.stunServer
ice.value = params.natPolicy?.iceEnabled()
avpf.value = params.avpfMode == AVPFMode.Enabled
avpfRrInterval.value = params.avpfRrInterval
expires.value = params.expires
prefix.value = params.internationalPrefix
dialPrefix.value = params.useInternationalPrefixForCallsAndChats
escapePlus.value = params.dialEscapePlusEnabled
}
private fun initTransportList() {
val labels = arrayListOf<String>()
// Keep following in the same order as TransportType enum
labels.add(prefs.getString(R.string.account_settings_transport_udp))
labels.add(prefs.getString(R.string.account_settings_transport_tcp))
labels.add(prefs.getString(R.string.account_settings_transport_tls))
if (corePreferences.allowDtlsTransport) {
labels.add(prefs.getString(R.string.account_settings_transport_dtls))
}
transportLabels.value = labels
transportIndex.value = labels.indexOf(proxyConfig.transport.toUpperCase(Locale.getDefault()))
transportIndex.value = account.params.transport.toInt()
}
}

View file

@ -70,9 +70,9 @@ class SettingsViewModel : ViewModel() {
fun updateAccountsList() {
val list = arrayListOf<AccountSettingsViewModel>()
if (coreContext.core.proxyConfigList.isNotEmpty()) {
for (proxy in coreContext.core.proxyConfigList) {
val viewModel = AccountSettingsViewModel(proxy)
if (coreContext.core.accountList.isNotEmpty()) {
for (account in coreContext.core.accountList) {
val viewModel = AccountSettingsViewModel(account)
viewModel.accountsSettingsListener = accountClickListener
list.add(viewModel)
}

View file

@ -67,8 +67,8 @@ class SideMenuFragment : GenericFragment<SideMenuFragmentBinding>() {
ViewModelProvider(this).get(SharedMainViewModel::class.java)
}
sharedViewModel.proxyConfigRemoved.observe(viewLifecycleOwner, {
Log.i("[Side Menu] Proxy config removed, update accounts list")
sharedViewModel.accountRemoved.observe(viewLifecycleOwner, {
Log.i("[Side Menu] Account removed, update accounts list")
viewModel.updateAccountsList()
})
@ -76,7 +76,7 @@ class SideMenuFragment : GenericFragment<SideMenuFragmentBinding>() {
override fun onAccountClicked(identity: String) {
val args = Bundle()
args.putString("Identity", identity)
Log.i("[Side Menu] Navigation to settings for proxy with identity: $identity")
Log.i("[Side Menu] Navigation to settings for account with identity: $identity")
sharedViewModel.toggleDrawerEvent.value = Event(true)
navigateToAccountSettings(identity)

View file

@ -35,7 +35,7 @@ class SideMenuViewModel : ViewModel() {
val showAbout: Boolean = corePreferences.showAboutInSideMenu
val showQuit: Boolean = corePreferences.showQuitInSideMenu
val defaultAccount = MutableLiveData<AccountSettingsViewModel>()
val defaultAccountViewModel = MutableLiveData<AccountSettingsViewModel>()
val defaultAccountFound = MutableLiveData<Boolean>()
val defaultAccountAvatar = MutableLiveData<String>()
@ -50,14 +50,14 @@ class SideMenuViewModel : ViewModel() {
}
private val listener: CoreListenerStub = object : CoreListenerStub() {
override fun onRegistrationStateChanged(
override fun onAccountRegistrationStateChanged(
core: Core,
cfg: ProxyConfig,
account: Account,
state: RegistrationState,
message: String
) {
if (coreContext.core.proxyConfigList.size != accounts.value?.size) {
// Only refresh the list if a proxy has been added or removed
if (coreContext.core.accountList.size != accounts.value?.size) {
// Only refresh the list if an account has been added or removed
updateAccountsList()
}
}
@ -77,18 +77,18 @@ class SideMenuViewModel : ViewModel() {
fun updateAccountsList() {
val list = arrayListOf<AccountSettingsViewModel>()
if (coreContext.core.proxyConfigList.isNotEmpty()) {
val defaultProxyConfig = coreContext.core.defaultProxyConfig
if (defaultProxyConfig != null) {
val defaultViewModel = AccountSettingsViewModel(defaultProxyConfig)
if (coreContext.core.accountList.isNotEmpty()) {
val defaultAccount = coreContext.core.defaultAccount
if (defaultAccount != null) {
val defaultViewModel = AccountSettingsViewModel(defaultAccount)
defaultViewModel.accountsSettingsListener = accountClickListener
defaultAccount.value = defaultViewModel
defaultAccountViewModel.value = defaultViewModel
defaultAccountFound.value = true
}
for (proxy in coreContext.core.proxyConfigList) {
if (proxy != coreContext.core.defaultProxyConfig) {
val viewModel = AccountSettingsViewModel(proxy)
for (account in coreContext.core.accountList) {
if (account != coreContext.core.defaultAccount) {
val viewModel = AccountSettingsViewModel(account)
viewModel.accountsSettingsListener = accountClickListener
list.add(viewModel)
}

View file

@ -58,7 +58,7 @@ class SharedMainViewModel : ViewModel() {
/* Accounts */
val proxyConfigRemoved = MutableLiveData<Boolean>()
val accountRemoved = MutableLiveData<Boolean>()
/* Call */

View file

@ -35,13 +35,15 @@ open class StatusViewModel : ViewModel() {
val voiceMailCount = MutableLiveData<Int>()
private val listener: CoreListenerStub = object : CoreListenerStub() {
override fun onRegistrationStateChanged(
override fun onAccountRegistrationStateChanged(
core: Core,
proxyConfig: ProxyConfig,
account: Account,
state: RegistrationState,
message: String
) {
updateDefaultProxyConfigRegistrationStatus(state)
if (account == core.defaultAccount) {
updateDefaultAccountRegistrationStatus(state)
}
}
override fun onNotifyReceived(
@ -71,11 +73,11 @@ open class StatusViewModel : ViewModel() {
core.addListener(listener)
var state: RegistrationState = RegistrationState.None
val defaultProxyConfig = core.defaultProxyConfig
if (defaultProxyConfig != null) {
state = defaultProxyConfig.state
val defaultAccount = core.defaultAccount
if (defaultAccount != null) {
state = defaultAccount.state
}
updateDefaultProxyConfigRegistrationStatus(state)
updateDefaultAccountRegistrationStatus(state)
}
override fun onCleared() {
@ -87,7 +89,7 @@ open class StatusViewModel : ViewModel() {
coreContext.core.refreshRegisters()
}
fun updateDefaultProxyConfigRegistrationStatus(state: RegistrationState) {
fun updateDefaultAccountRegistrationStatus(state: RegistrationState) {
registrationStatusText.value = getStatusIconText(state)
registrationStatusDrawable.value = getStatusIconResource(state)
}

View file

@ -133,7 +133,7 @@ class ContactsManager(private val context: Context) {
}
fun shouldDisplaySipContactsList(): Boolean {
return coreContext.core.defaultProxyConfig?.identityAddress?.domain == corePreferences.defaultDomain
return coreContext.core.defaultAccount?.params?.identityAddress?.domain == corePreferences.defaultDomain
}
@Synchronized

View file

@ -312,15 +312,15 @@ class CoreContext(val context: Context, coreConfig: Config) {
computeUserAgent()
for (lpc in core.proxyConfigList) {
if (lpc.identityAddress?.domain == corePreferences.defaultDomain) {
for (account in core.accountList) {
if (account.params.identityAddress?.domain == corePreferences.defaultDomain) {
// Ensure conference URI is set on sip.linphone.org proxy configs
if (lpc.conferenceFactoryUri == null) {
lpc.edit()
if (account.params.conferenceFactoryUri == null) {
val params = account.params.clone()
val uri = corePreferences.conferenceServerUri
Log.i("[Context] Setting conference factory on proxy config ${lpc.identityAddress?.asString()} to default value: $uri")
lpc.conferenceFactoryUri = uri
lpc.done()
Log.i("[Context] Setting conference factory on proxy config ${params.identityAddress?.asString()} to default value: $uri")
params.conferenceFactoryUri = uri
account.params = params
}
// Ensure LIME server URL is set if at least one sip.linphone.org proxy

View file

@ -391,6 +391,9 @@ class CorePreferences constructor(private val context: Context) {
/* Settings */
val allowDtlsTransport: Boolean
get() = config.getBool("app", "allow_dtls_transport", false)
val showAccountSettings: Boolean
get() = config.getBool("app", "settings_accounts", true)

View file

@ -56,17 +56,17 @@ class LinphoneUtils {
val core = coreContext.core
return core.limeX3DhAvailable() && core.limeX3DhEnabled() &&
core.limeX3DhServerUrl != null &&
core.defaultProxyConfig?.conferenceFactoryUri != null
core.defaultAccount?.params?.conferenceFactoryUri != null
}
fun isGroupChatAvailable(): Boolean {
val core = coreContext.core
return core.defaultProxyConfig?.conferenceFactoryUri != null
return core.defaultAccount?.params?.conferenceFactoryUri != null
}
fun createOneToOneChatRoom(participant: Address, isSecured: Boolean = false): ChatRoom? {
val core: Core = coreContext.core
val defaultProxyConfig = core.defaultProxyConfig
val defaultAccount = core.defaultAccount
val params = core.createDefaultChatRoomParams()
params.enableGroup(false)
@ -79,8 +79,8 @@ class LinphoneUtils {
val participants = arrayOf(participant)
return core.searchChatRoom(params, defaultProxyConfig?.contact, null, participants)
?: core.createChatRoom(params, defaultProxyConfig?.contact, participants)
return core.searchChatRoom(params, defaultAccount?.contactAddress, null, participants)
?: core.createChatRoom(params, defaultAccount?.contactAddress, participants)
}
fun deleteFilesAttachedToEventLog(eventLog: EventLog) {

View file

@ -88,7 +88,7 @@
linphone:subtitle="@{@string/account_settings_password_summary}"
linphone:listener="@{viewModel.passwordListener}"
linphone:defaultValue="@{viewModel.password}"
linphone:inputType="@{InputType.TYPE_TEXT_VARIATION_PASSWORD}"/>
linphone:inputType="@{InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD}"/>
<include
layout="@layout/settings_widget_text"
@ -224,12 +224,19 @@
<include
layout="@layout/settings_widget_text"
linphone:title="@{@string/account_settings_dial_prefix_title}"
linphone:subtitle="@{@string/account_settings_dial_prefix_summary}"
linphone:listener="@{viewModel.dialPrefixListener}"
linphone:defaultValue="@{viewModel.dialPrefix.toString()}"
linphone:title="@{@string/account_settings_prefix_title}"
linphone:subtitle="@{@string/account_settings_prefix_summary}"
linphone:listener="@{viewModel.prefixListener}"
linphone:defaultValue="@{viewModel.prefix}"
linphone:inputType="@{InputType.TYPE_CLASS_NUMBER}"/>
<include
layout="@layout/settings_widget_switch"
linphone:title="@{@string/account_settings_apply_prefix_for_calls_title}"
linphone:subtitle="@{@string/account_settings_apply_prefix_for_calls_summary}"
linphone:listener="@{viewModel.dialPrefixListener}"
linphone:checked="@={viewModel.dialPrefix}"/>
<include
layout="@layout/settings_widget_switch"
linphone:title="@{@string/account_settings_escape_plus_title}"

View file

@ -35,7 +35,7 @@
<RelativeLayout
android:id="@+id/main_account"
android:onClick="@{() -> viewModel.defaultAccount.accountsSettingsListener.onAccountClicked(viewModel.defaultAccount.identity)}"
android:onClick="@{() -> viewModel.defaultAccountViewModel.accountsSettingsListener.onAccountClicked(viewModel.defaultAccountViewModel.identity)}"
android:enabled="@{viewModel.defaultAccountFound}"
android:visibility="@{viewModel.showAccounts ? View.VISIBLE : View.GONE}"
android:layout_width="match_parent"
@ -82,7 +82,7 @@
<TextView
android:visibility="@{viewModel.defaultAccountFound ? View.VISIBLE : View.GONE}"
android:text="@{viewModel.defaultAccount.displayName.isEmpty() ? viewModel.defaultAccount.userName : viewModel.defaultAccount.displayName}"
android:text="@{viewModel.defaultAccountViewModel.displayName.isEmpty() ? viewModel.defaultAccountViewModel.userName : viewModel.defaultAccountViewModel.displayName}"
android:textColor="?attr/lightToolbarTextColor"
android:textStyle="bold"
android:textSize="18sp"
@ -91,7 +91,7 @@
<TextView
android:visibility="@{viewModel.defaultAccountFound ? View.VISIBLE : View.GONE}"
android:text="@{viewModel.defaultAccount.displayUsernameInsteadOfIdentity ? viewModel.defaultAccount.userName : viewModel.defaultAccount.identity}"
android:text="@{viewModel.defaultAccountViewModel.displayUsernameInsteadOfIdentity ? viewModel.defaultAccountViewModel.userName : viewModel.defaultAccountViewModel.identity}"
style="@style/sip_uri_small_font"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
@ -100,8 +100,8 @@
<ImageView
android:background="@drawable/led_background"
android:src="@{viewModel.defaultAccount.iconResource, default=@drawable/led_not_registered}"
android:contentDescription="@{viewModel.defaultAccount.iconContentDescription}"
android:src="@{viewModel.defaultAccountViewModel.iconResource, default=@drawable/led_not_registered}"
android:contentDescription="@{viewModel.defaultAccountViewModel.iconContentDescription}"
android:layout_width="20dp"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"

View file

@ -541,6 +541,7 @@
<string name="account_settings_transport_title">Transporte</string>
<string name="account_settings_transport_tcp">TCP</string>
<string name="account_settings_transport_tls">TLS</string>
<string name="account_settings_transport_dtls">DTLS</string>
<string name="account_settings_proxy_title">Proxy SIP</string>
<string name="account_settings_outbound_proxy_summary">Enruta todas las llamadas a través del proxy SIP de arriba</string>
<string name="account_settings_stun_server_title">Servidor STUN / TURN</string>
@ -549,8 +550,8 @@
<string name="account_settings_avpf_rr_interval_title">AVPF de intervalo regular de RTCP</string>
<string name="account_settings_expires_title">Caduce</string>
<string name="account_settings_expires_summary">en segundos</string>
<string name="account_settings_dial_prefix_title">Prefijo de tu país</string>
<string name="account_settings_dial_prefix_summary">sin el +</string>
<string name="account_settings_prefix_title">Prefijo de tu país</string>
<string name="account_settings_prefix_summary">sin el +</string>
<string name="account_settings_escape_plus_title">Reemplazar + por 00</string>
<string name="notification_channel_incoming_call_name">&appName; notificaciones de llamadas entrantes</string>
<string name="notification_channel_chat_name">&appName; notificaciones de mensajes</string>

View file

@ -389,6 +389,7 @@
<string name="account_settings_transport_udp">UDP</string>
<string name="account_settings_transport_tcp">TCP</string>
<string name="account_settings_transport_tls">TLS</string>
<string name="account_settings_transport_dtls">DTLS</string>
<string name="account_settings_proxy_title">Proxy SIP</string>
<string name="account_settings_outbound_proxy_title">Outbound proxy</string>
<string name="account_settings_stun_server_title">Serveur TURN / STUN</string>
@ -397,8 +398,8 @@
<string name="account_settings_avpf_rr_interval_summary">en secondes (entre 1 et 5)</string>
<string name="account_settings_expires_title">Expiration</string>
<string name="account_settings_expires_summary">en secondes</string>
<string name="account_settings_dial_prefix_summary">(sans le +)</string>
<string name="account_settings_dial_prefix_title">Préfixe de votre pays</string>
<string name="account_settings_prefix_summary">(sans le +)</string>
<string name="account_settings_prefix_title">Préfixe de votre pays</string>
<string name="account_settings_escape_plus_title">Remplacer + par 00</string>
<string name="notification_channel_incoming_call_name">Notifications d\'appels entrants &appName;</string>
<string name="incoming_call_notification_title">Appel entrant</string>

View file

@ -160,8 +160,8 @@
<string name="account_settings_avpf_rr_interval_summary">以秒为单位1到5之间</string>
<string name="account_settings_expires_title">到期</string>
<string name="account_settings_expires_summary">以秒为单位</string>
<string name="account_settings_dial_prefix_title">您所在国家的前缀</string>
<string name="account_settings_dial_prefix_summary">不包含 +</string>
<string name="account_settings_prefix_title">您所在国家的前缀</string>
<string name="account_settings_prefix_summary">不包含 +</string>
<string name="account_settings_escape_plus_title">用00代替+</string>
<string name="notification_channel_service_name">&appName; 服务通知</string>
<string name="notification_channel_chat_name">&appName; 即时通讯通知</string>

View file

@ -421,8 +421,8 @@
<string name="account_settings_avpf_rr_interval_summary">以秒為單位1到5之間</string>
<string name="account_settings_expires_title">到期</string>
<string name="account_settings_expires_summary">以秒為單位</string>
<string name="account_settings_dial_prefix_title">您所在國家的前綴</string>
<string name="account_settings_dial_prefix_summary">不包含+</string>
<string name="account_settings_prefix_title">您所在國家的前綴</string>
<string name="account_settings_prefix_summary">不包含+</string>
<string name="account_settings_escape_plus_title">用00代替+</string>
<string name="notification_channel_incoming_call_name">&appName;來電通知</string>
<string name="notification_channel_chat_name">&appName;即時通訊通知</string>

View file

@ -528,6 +528,7 @@
<string name="account_settings_transport_udp">UDP</string>
<string name="account_settings_transport_tcp">TCP</string>
<string name="account_settings_transport_tls">TLS</string>
<string name="account_settings_transport_dtls">DTLS</string>
<string name="account_settings_proxy_title">SIP proxy</string>
<string name="account_settings_proxy_summary"></string>
<string name="account_settings_outbound_proxy_title">Outbound proxy</string>
@ -542,8 +543,10 @@
<string name="account_settings_avpf_rr_interval_summary">in seconds (between 1 and 5)</string>
<string name="account_settings_expires_title">Expire</string>
<string name="account_settings_expires_summary">in seconds</string>
<string name="account_settings_dial_prefix_title">Prefix for your country</string>
<string name="account_settings_dial_prefix_summary">without the +</string>
<string name="account_settings_prefix_title">Prefix for your country</string>
<string name="account_settings_prefix_summary">without the +</string>
<string name="account_settings_apply_prefix_for_calls_title">Apply prefix for outgoing calls and chat</string>
<string name="account_settings_apply_prefix_for_calls_summary">If a number is entered, apply prefix to number</string>
<string name="account_settings_escape_plus_title">Replace + by 00</string>
<string name="account_settings_escape_plus_summary"></string>