Newer
Older
* Copyright (C) 2004-2023 Savoir-faire Linux Inc.
* 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 <https://www.gnu.org/licenses/>.
*/
package cx.ring.client
import android.content.Context
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ArrayAdapter
import cx.ring.R
import cx.ring.databinding.ItemToolbarSpinnerBinding
import cx.ring.utils.DeviceUtils
import cx.ring.views.AvatarDrawable
import io.reactivex.rxjava3.core.Observable
import io.reactivex.rxjava3.disposables.CompositeDisposable
import net.jami.model.Account
import net.jami.model.Profile
import net.jami.services.AccountService
import net.jami.services.ConversationFacade
/**
* Adapter allowing to select account user want to use.
*/
class AccountAdapter(
context: Context,
accounts: List<Account>,
val disposable: CompositeDisposable,
var mAccountService: AccountService,
var mConversationFacade: ConversationFacade,
) : ArrayAdapter<Account>(context, R.layout.item_toolbar_spinner, accounts) {
private val mInflater: LayoutInflater = LayoutInflater.from(context)
private val ip2ipString = context.getString(R.string.account_type_ip2ip)
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
// Try to recycle the view
val holder: ViewHolder
if (view != null) {
holder = view.tag as ViewHolder
holder.loader.clear()
holder.binding.logo.setImageDrawable(null)
holder.binding.title.text = null
holder.binding.subtitle.text = null
} else { // Create a new view
holder = ViewHolder(
ItemToolbarSpinnerBinding.inflate(mInflater, parent, false),
disposable
)
view = holder.binding.root
view.setTag(holder)
}
// Items can be:
// - available accounts (type=TYPE_ACCOUNT)
// - a button to create a new account (type=TYPE_CREATE_ACCOUNT)
val type = getItemViewType(position)
if (type == TYPE_ACCOUNT) {
val account = getItem(position)!!
// Update the unread counter (sum of unread conversations and pending conversations)
holder.loader.add(
mAccountService.getObservableAccountProfile(account.accountId).switchMap {
Observable.combineLatest(
account.unreadConversations,
account.getPendingSubject()
) { unreadConversationCounter, pendingConversationList ->
unreadConversationCounter + pendingConversationList.size
}
}
.observeOn(DeviceUtils.uiScheduler)
.subscribe {
if (it > 0) {
holder.binding.invitationBadge.visibility = View.VISIBLE
holder.binding.invitationBadge.text = it.toString()
} else holder.binding.invitationBadge.visibility = View.GONE
}
)
// Subscribe to account profile changes to update:
// - avatar
// - name (will display the jami if name is not setup)
holder.loader.add(mAccountService.getObservableAccountProfile(account.accountId)
.observeOn(DeviceUtils.uiScheduler)
.subscribe({ profile ->
val subtitle = getUri(account, ip2ipString)
holder.binding.logo.setImageDrawable(
AvatarDrawable.build(
holder.binding.root.context,
profile.first,
profile.second,
true,
profile.first.isRegistered
)
)
holder.binding.title.text = getTitle(profile.first, profile.second)
if (holder.binding.title.text == subtitle) {
holder.binding.subtitle.visibility = View.GONE
} else {
holder.binding.subtitle.visibility = View.VISIBLE
holder.binding.subtitle.text = subtitle
}
}) { e: Throwable -> Log.e(TAG, "Error loading avatar", e) })
holder.binding.invitationBadge.visibility = View.GONE
if (type == TYPE_CREATE_ACCOUNT) R.string.add_ring_account_title
else R.string.add_sip_account_title
)
holder.binding.logo.setImageResource(R.drawable.baseline_add_24)
holder.binding.subtitle.visibility = View.GONE
}
override fun getItemViewType(position: Int): Int {
if (position == super.getCount()) {
return TYPE_CREATE_ACCOUNT
override fun getCount(): Int = super.getCount() + 1
private fun getTitle(account: Account, profile: Profile): String =
profile.displayName.orEmpty().ifEmpty {
account.registeredName.ifEmpty {
account.alias.orEmpty().ifEmpty {
if (account.isSip) context.getString(R.string.sip_account)
else context.getString(R.string.ring_account)
private class ViewHolder(val binding: ItemToolbarSpinnerBinding, parentDisposable: CompositeDisposable) {
val loader = CompositeDisposable().apply { parentDisposable.add(this) }
private fun getUri(account: Account, defaultNameSip: CharSequence): String =
if (account.isIP2IP) defaultNameSip.toString() else account.displayUri!!
private val TAG = AccountAdapter::class.simpleName!!
const val TYPE_CREATE_ACCOUNT = 1