Skip to content

Commit

Permalink
Implement ManageAccount module
Browse files Browse the repository at this point in the history
  • Loading branch information
omurovch authored and abdrasulov committed Apr 20, 2021
1 parent ed05d8b commit 43028f8
Show file tree
Hide file tree
Showing 16 changed files with 400 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ interface IAccountManager {
val accountsDeletedFlowable: Flowable<Unit>

fun account(coinType: CoinType): Account?
fun account(id: String): Account?
fun loadAccounts()
fun save(account: Account)
fun update(account: Account)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ class AccountManager(private val storage: IAccountsStorage, private val accountC
return accounts.find { account -> coinType.canSupport(account.type) }
}

override fun account(id: String): Account? {
return accounts.find { account -> account.id == id }
}

override fun loadAccounts() {
val accounts = storage.allAccounts()
cache.set(accounts)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@ import android.os.Parcelable
import io.horizontalsystems.bankwallet.R
import io.horizontalsystems.coinkit.models.CoinType
import kotlinx.android.parcel.Parcelize
import java.util.*

@Parcelize
class Account(val id: String,
val name: String,
var name: String,
val type: AccountType,
val origin: AccountOrigin,
var isBackedUp: Boolean = false
Expand All @@ -23,7 +22,7 @@ class Account(val id: String,
}

override fun hashCode(): Int {
return Objects.hash(name, type)
return id.hashCode()
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package io.horizontalsystems.bankwallet.modules.manageaccount

import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.view.LayoutInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.viewModels
import io.horizontalsystems.bankwallet.R
import io.horizontalsystems.bankwallet.core.BaseFragment
import io.horizontalsystems.bankwallet.modules.manageaccount.ManageAccountModule.ACCOUNT_ID_KEY
import io.horizontalsystems.bankwallet.modules.manageaccount.ManageAccountViewModel.KeyActionState
import io.horizontalsystems.core.findNavController
import kotlinx.android.synthetic.main.fragment_manage_account.*
import kotlinx.android.synthetic.main.fragment_manage_accounts.toolbar

class ManageAccountFragment : BaseFragment() {
private var saveMenuItem: MenuItem? = null

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
}

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_manage_account, container, false)
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

val accountId = arguments?.getString(ACCOUNT_ID_KEY)!!
val viewModel by viewModels<ManageAccountViewModel> { ManageAccountModule.Factory(accountId) }

saveMenuItem = toolbar.menu.findItem(R.id.menuSave)

toolbar.setNavigationOnClickListener {
findNavController().popBackStack()
}

toolbar.setOnMenuItemClickListener { item ->
when (item.itemId) {
R.id.menuSave -> {
viewModel.onSave()
true
}
else -> false
}
}

toolbar.title = viewModel.accountName
name.setText(viewModel.accountName)

val textWatcher = object : TextWatcher {
override fun afterTextChanged(s: Editable) {
if (s.isNotEmpty()) {
viewModel.onChange(s.toString())
}
}

override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
}
name.addTextChangedListener(textWatcher)

viewModel.keyActionStateLiveData.observe(viewLifecycleOwner, { keyActionState ->
when (keyActionState) {
KeyActionState.ShowRecoveryPhrase -> {
actionButton.showAttention(false)
actionButton.showTitle(getString(R.string.ManageAccount_RecoveryPhraseShow))
}
KeyActionState.BackupRecoveryPhrase -> {
actionButton.showAttention(true)
actionButton.showTitle(getString(R.string.ManageAccount_RecoveryPhraseBackup))
}
}
})

viewModel.saveEnabledLiveData.observe(viewLifecycleOwner, {
saveMenuItem?.isEnabled = it
})

viewModel.finishLiveEvent.observe(viewLifecycleOwner, {
findNavController().popBackStack()
})
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package io.horizontalsystems.bankwallet.modules.manageaccount

import androidx.core.os.bundleOf
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.NavOptions
import io.horizontalsystems.bankwallet.R
import io.horizontalsystems.bankwallet.core.App
import io.horizontalsystems.core.findNavController

object ManageAccountModule {
const val ACCOUNT_ID_KEY = "account_id_key"

class Factory(private val accountId: String) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
val service = ManageAccountService(accountId, App.accountManager)

return ManageAccountViewModel(service, listOf(service)) as T
}
}

fun start(fragment: Fragment, navOptions: NavOptions, accountId: String) {
fragment.findNavController().navigate(R.id.manageAccountsFragment_to_manageAccount, bundleOf(ACCOUNT_ID_KEY to accountId), navOptions)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package io.horizontalsystems.bankwallet.modules.manageaccount

import io.horizontalsystems.bankwallet.core.Clearable
import io.horizontalsystems.bankwallet.core.IAccountManager
import io.horizontalsystems.bankwallet.core.subscribeIO
import io.horizontalsystems.bankwallet.entities.Account
import io.reactivex.BackpressureStrategy
import io.reactivex.Flowable
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.subjects.PublishSubject

class ManageAccountService(
accountId: String,
private val accountManager: IAccountManager
) : Clearable {
private val disposable = CompositeDisposable()

private val accountSubject = PublishSubject.create<Account>()
val accountObservable: Flowable<Account> = accountSubject.toFlowable(BackpressureStrategy.BUFFER)
var account: Account = accountManager.account(accountId)!!
private set(value) {
field = value
accountSubject.onNext(value)
}

private var newName = account.name

private val stateSubject = PublishSubject.create<State>()
val stateObservable: Flowable<State> = stateSubject.toFlowable(BackpressureStrategy.BUFFER)
var state: State = State.CannotSave
private set(value) {
field = value
stateSubject.onNext(value)
}

init {
accountManager.accountsFlowable
.subscribeIO { handleUpdatedAccounts(it) }
.let { disposable.add(it) }

syncState()
}

private fun syncState() {
state = when {
newName.isNotEmpty() && newName != account.name -> State.CanSave
else -> State.CannotSave
}
}

private fun handleUpdatedAccounts(accounts: List<Account>) {
accounts.find { it.id == account.id }?.let {
account == it
}
}

fun setName(name: String) {
newName = name.trim().replace("\n", " ")
syncState()
}

fun saveAccount() {
account.name = newName
accountManager.update(account)
}

override fun clear() {
disposable.clear()
}

enum class State {
CanSave, CannotSave
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package io.horizontalsystems.bankwallet.modules.manageaccount

import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import io.horizontalsystems.bankwallet.core.Clearable
import io.horizontalsystems.bankwallet.core.subscribeIO
import io.horizontalsystems.bankwallet.entities.Account
import io.horizontalsystems.core.SingleLiveEvent
import io.reactivex.disposables.CompositeDisposable

class ManageAccountViewModel(
private val service: ManageAccountService,
private val clearables: List<Clearable>
) : ViewModel() {
val disposable = CompositeDisposable()

val keyActionStateLiveData = MutableLiveData<KeyActionState>()
val saveEnabledLiveData = MutableLiveData<Boolean>()
val finishLiveEvent = SingleLiveEvent<Unit>()

val accountName: String
get() = service.account.name

init {
service.stateObservable
.subscribeIO { syncState(it) }
.let { disposable.add(it) }
service.accountObservable
.subscribeIO { syncAccount(it) }
.let { disposable.add(it) }

syncState(service.state)
syncAccount(service.account)
}

private fun syncState(state: ManageAccountService.State) {
when (state) {
ManageAccountService.State.CanSave -> saveEnabledLiveData.postValue(true)
ManageAccountService.State.CannotSave -> saveEnabledLiveData.postValue(false)
}
}

private fun syncAccount(account: Account) {
keyActionStateLiveData.postValue(if (account.isBackedUp) KeyActionState.ShowRecoveryPhrase else KeyActionState.BackupRecoveryPhrase)
}

fun onChange(name: String?) {
service.setName(name ?: "")
}

fun onSave() {
service.saveAccount()
finishLiveEvent.postValue(Unit)
}

override fun onCleared() {
disposable.clear()
clearables.forEach(Clearable::clear)
}

enum class KeyActionState {
ShowRecoveryPhrase, BackupRecoveryPhrase
}

}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package io.horizontalsystems.bankwallet.modules.manageaccounts

import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
Expand All @@ -12,6 +11,7 @@ import androidx.recyclerview.widget.RecyclerView
import io.horizontalsystems.bankwallet.R
import io.horizontalsystems.bankwallet.core.BaseFragment
import io.horizontalsystems.bankwallet.core.setOnSingleClickListener
import io.horizontalsystems.bankwallet.modules.manageaccount.ManageAccountModule
import io.horizontalsystems.bankwallet.modules.manageaccounts.ManageAccountsModule.AccountViewItem
import io.horizontalsystems.bankwallet.modules.manageaccounts.ManageAccountsModule.ActionViewItem
import io.horizontalsystems.core.findNavController
Expand Down Expand Up @@ -53,19 +53,19 @@ class ManageAccountsFragment : BaseFragment(), AccountViewHolder.Listener {
}

private fun onClickCreateWallet() {
Log.e("AAA", "onClickCreateWallet")

}

private fun onClickRestoreWallet() {
Log.e("AAA", "onClickRestoreWallet")

}

override fun onSelect(accountViewItem: AccountViewItem) {
viewModel.onSelect(accountViewItem)
}

override fun onEdit(accountViewItem: AccountViewItem) {
viewModel.onEdit(accountViewItem)
ManageAccountModule.start(this, navOptions(), accountViewItem.accountId)
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ object ManageAccountsModule {
}

data class AccountViewItem(
val id: String,
val accountId: String,
val title: String,
val subtitle: String,
val selected: Boolean,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package io.horizontalsystems.bankwallet.modules.manageaccounts

import android.util.Log
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import io.horizontalsystems.bankwallet.core.subscribeIO
Expand Down Expand Up @@ -43,14 +42,8 @@ class ManageAccountsViewModel(
}

fun onSelect(accountViewItem: AccountViewItem) {
Log.e("AAA", "onSelect ${accountViewItem.title} - ${accountViewItem.subtitle}")

viewItemsLiveData.postValue(service.accounts.map { getViewItem(it, it.id == accountViewItem.id) })
viewItemsLiveData.postValue(service.accounts.map { getViewItem(it, it.id == accountViewItem.accountId) })
}

fun onEdit(accountViewItem: AccountViewItem) {
Log.e("AAA", "onEdit: ${accountViewItem.title} - ${accountViewItem.subtitle}")
}


}
Loading

0 comments on commit 43028f8

Please sign in to comment.