fixes to scoping and job cancellation
Utilize fragmentscope in the AndroidInjector subcomponents for fragments and also allow presenters to restart jobs
This commit is contained in:
parent
ab58b03db6
commit
e79c68fd20
|
@ -3,4 +3,5 @@ package cash.z.android.wallet.di.annotation
|
||||||
import javax.inject.Scope
|
import javax.inject.Scope
|
||||||
|
|
||||||
@Scope
|
@Scope
|
||||||
annotation class ActivityScoped
|
@Retention(AnnotationRetention.SOURCE)
|
||||||
|
annotation class ActivityScope
|
|
@ -0,0 +1,7 @@
|
||||||
|
package cash.z.android.wallet.di.annotation
|
||||||
|
|
||||||
|
import javax.inject.Scope
|
||||||
|
|
||||||
|
@Scope
|
||||||
|
@Retention(AnnotationRetention.SOURCE)
|
||||||
|
annotation class ApplicationScope
|
|
@ -3,4 +3,5 @@ package cash.z.android.wallet.di.annotation
|
||||||
import javax.inject.Scope
|
import javax.inject.Scope
|
||||||
|
|
||||||
@Scope
|
@Scope
|
||||||
annotation class ApplicationScoped
|
@Retention(AnnotationRetention.SOURCE)
|
||||||
|
annotation class FragmentScope
|
|
@ -23,9 +23,9 @@ import javax.inject.Singleton
|
||||||
MainActivityModule::class,
|
MainActivityModule::class,
|
||||||
|
|
||||||
// Injected Fragments
|
// Injected Fragments
|
||||||
|
HomeFragmentModule::class,
|
||||||
AboutFragmentModule::class,
|
AboutFragmentModule::class,
|
||||||
HistoryFragmentModule::class,
|
HistoryFragmentModule::class,
|
||||||
HomeFragmentModule::class,
|
|
||||||
WelcomeFragmentModule::class,
|
WelcomeFragmentModule::class,
|
||||||
ReceiveFragmentModule::class,
|
ReceiveFragmentModule::class,
|
||||||
RequestFragmentModule::class,
|
RequestFragmentModule::class,
|
||||||
|
|
|
@ -56,10 +56,10 @@ class MainActivity : BaseActivity() {
|
||||||
// used to manage the drawer and drawerToggle interactions
|
// used to manage the drawer and drawerToggle interactions
|
||||||
private lateinit var appBarConfiguration: AppBarConfiguration
|
private lateinit var appBarConfiguration: AppBarConfiguration
|
||||||
lateinit var navController: NavController
|
lateinit var navController: NavController
|
||||||
private val multiStartNavigationUi = MultiStartNavigationUI(listOf(
|
// private val multiStartNavigationUi = MultiStartNavigationUI(listOf(
|
||||||
R.id.nav_home_fragment,
|
// R.id.nav_home_fragment,
|
||||||
R.id.nav_welcome_fragment
|
// R.id.nav_welcome_fragment
|
||||||
))
|
// ))
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
@ -114,10 +114,10 @@ class MainActivity : BaseActivity() {
|
||||||
navController = Navigation.findNavController(this, R.id.nav_host_fragment).also { n ->
|
navController = Navigation.findNavController(this, R.id.nav_host_fragment).also { n ->
|
||||||
appBarConfiguration = AppBarConfiguration(n.graph, binding.drawerLayout).also { a ->
|
appBarConfiguration = AppBarConfiguration(n.graph, binding.drawerLayout).also { a ->
|
||||||
binding.navView.setupWithNavController(n)
|
binding.navView.setupWithNavController(n)
|
||||||
multiStartNavigationUi.setupActionBarWithNavController(this, n, binding.drawerLayout)
|
setupActionBarWithNavController(n, binding.drawerLayout)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
navController.addOnNavigatedListener { _, _ ->
|
navController.addOnDestinationChangedListener { _, _, _ ->
|
||||||
// hide the keyboard anytime we change destinations
|
// hide the keyboard anytime we change destinations
|
||||||
getSystemService<InputMethodManager>()?.hideSoftInputFromWindow(binding.navView.windowToken, HIDE_NOT_ALWAYS)
|
getSystemService<InputMethodManager>()?.hideSoftInputFromWindow(binding.navView.windowToken, HIDE_NOT_ALWAYS)
|
||||||
}
|
}
|
||||||
|
@ -170,80 +170,80 @@ abstract class MainActivityModule {
|
||||||
abstract fun contributeMainActivity(): MainActivity
|
abstract fun contributeMainActivity(): MainActivity
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
class MultiStartNavigationUI(private val startDestinations: List<Int>) {
|
//class MultiStartNavigationUI(private val startDestinations: List<Int>) {
|
||||||
fun setupActionBarWithNavController(activity: AppCompatActivity, navController: NavController,
|
// fun setupActionBarWithNavController(activity: AppCompatActivity, navController: NavController,
|
||||||
drawerLayout: DrawerLayout?) {
|
// drawerLayout: DrawerLayout?) {
|
||||||
|
//
|
||||||
navController.addOnNavigatedListener(ActionBarOnNavigatedListener(
|
// navController.addOnNavigatedListener(ActionBarOnNavigatedListener(
|
||||||
activity, startDestinations, drawerLayout))
|
// activity, startDestinations, drawerLayout))
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
fun navigateUp(drawerLayout: DrawerLayout?, navController: NavController): Boolean {
|
// fun navigateUp(drawerLayout: DrawerLayout?, navController: NavController): Boolean {
|
||||||
if (drawerLayout != null && startDestinations.contains(navController.currentDestination?.id)) {
|
// if (drawerLayout != null && startDestinations.contains(navController.currentDestination?.id)) {
|
||||||
drawerLayout.openDrawer(GravityCompat.START)
|
// drawerLayout.openDrawer(GravityCompat.START)
|
||||||
return true
|
// return true
|
||||||
} else {
|
// } else {
|
||||||
return navController.navigateUp()
|
// return navController.navigateUp()
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
fun onBackPressed(activity: AppCompatActivity,
|
// fun onBackPressed(activity: AppCompatActivity,
|
||||||
navController: NavController): Boolean {
|
// navController: NavController): Boolean {
|
||||||
if (startDestinations.contains(navController.currentDestination?.id)) {
|
// if (startDestinations.contains(navController.currentDestination?.id)) {
|
||||||
ActivityCompat.finishAfterTransition(activity)
|
// ActivityCompat.finishAfterTransition(activity)
|
||||||
return true
|
// return true
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
return false
|
// return false
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
private class ActionBarOnNavigatedListener(
|
// private class ActionBarOnNavigatedListener(
|
||||||
private val mActivity: AppCompatActivity,
|
// private val mActivity: AppCompatActivity,
|
||||||
private val startDestinations: List<Int>,
|
// private val startDestinations: List<Int>,
|
||||||
private val mDrawerLayout: DrawerLayout?
|
// private val mDrawerLayout: DrawerLayout?
|
||||||
) : NavController.OnNavigatedListener {
|
// ) : NavController.OnNavigatedListener {
|
||||||
private var mArrowDrawable: DrawerArrowDrawable? = null
|
// private var mArrowDrawable: DrawerArrowDrawable? = null
|
||||||
private var mAnimator: ValueAnimator? = null
|
// private var mAnimator: ValueAnimator? = null
|
||||||
|
//
|
||||||
override fun onNavigated(controller: NavController, destination: NavDestination) {
|
// override fun onNavigated(controller: NavController, destination: NavDestination) {
|
||||||
val actionBar = mActivity.supportActionBar
|
// val actionBar = mActivity.supportActionBar
|
||||||
|
//
|
||||||
val title = destination.label
|
// val title = destination.label
|
||||||
if (!title.isNullOrEmpty()) {
|
// if (!title.isNullOrEmpty()) {
|
||||||
actionBar?.title = title
|
// actionBar?.title = title
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
val isStartDestination = startDestinations.contains(destination.id)
|
// val isStartDestination = startDestinations.contains(destination.id)
|
||||||
actionBar?.setDisplayHomeAsUpEnabled(this.mDrawerLayout != null || !isStartDestination)
|
// actionBar?.setDisplayHomeAsUpEnabled(this.mDrawerLayout != null || !isStartDestination)
|
||||||
setActionBarUpIndicator(mDrawerLayout != null && isStartDestination)
|
// setActionBarUpIndicator(mDrawerLayout != null && isStartDestination)
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
private fun setActionBarUpIndicator(showAsDrawerIndicator: Boolean) {
|
// private fun setActionBarUpIndicator(showAsDrawerIndicator: Boolean) {
|
||||||
val delegate = mActivity.drawerToggleDelegate
|
// val delegate = mActivity.drawerToggleDelegate
|
||||||
var animate = true
|
// var animate = true
|
||||||
if (mArrowDrawable == null) {
|
// if (mArrowDrawable == null) {
|
||||||
mArrowDrawable = DrawerArrowDrawable(delegate!!.actionBarThemedContext)
|
// mArrowDrawable = DrawerArrowDrawable(delegate!!.actionBarThemedContext)
|
||||||
delegate.setActionBarUpIndicator(mArrowDrawable, 0)
|
// delegate.setActionBarUpIndicator(mArrowDrawable, 0)
|
||||||
animate = false
|
// animate = false
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
mArrowDrawable?.let {
|
// mArrowDrawable?.let {
|
||||||
val endValue = if (showAsDrawerIndicator) 0.0f else 1.0f
|
// val endValue = if (showAsDrawerIndicator) 0.0f else 1.0f
|
||||||
|
//
|
||||||
if (animate) {
|
// if (animate) {
|
||||||
val startValue = it.progress
|
// val startValue = it.progress
|
||||||
mAnimator?.cancel()
|
// mAnimator?.cancel()
|
||||||
|
//
|
||||||
@SuppressLint("ObjectAnimatorBinding")
|
// @SuppressLint("ObjectAnimatorBinding")
|
||||||
mAnimator = ObjectAnimator.ofFloat(it, "progress", startValue, endValue)
|
// mAnimator = ObjectAnimator.ofFloat(it, "progress", startValue, endValue)
|
||||||
mAnimator?.start()
|
// mAnimator?.start()
|
||||||
} else {
|
// } else {
|
||||||
it.progress = endValue
|
// it.progress = endValue
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
//}
|
|
@ -6,6 +6,7 @@ import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.core.view.doOnPreDraw
|
import androidx.core.view.doOnPreDraw
|
||||||
import androidx.databinding.DataBindingUtil
|
import androidx.databinding.DataBindingUtil
|
||||||
|
import androidx.navigation.NavOptions
|
||||||
import androidx.transition.Transition
|
import androidx.transition.Transition
|
||||||
import androidx.transition.TransitionInflater
|
import androidx.transition.TransitionInflater
|
||||||
import cash.z.android.wallet.R
|
import cash.z.android.wallet.R
|
||||||
|
@ -38,7 +39,12 @@ class FirstrunFragment : ProgressFragment(R.id.progress_firstrun), Transition.Tr
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
postponeEnterTransition()
|
postponeEnterTransition()
|
||||||
binding.buttonNext.setOnClickListener {
|
binding.buttonNext.setOnClickListener {
|
||||||
mainActivity?.navController?.navigate(R.id.nav_sync_fragment)
|
mainActivity?.navController?.navigate(
|
||||||
|
R.id.action_firstrun_fragment_to_sync_fragment,
|
||||||
|
null,
|
||||||
|
NavOptions.Builder().setPopUpTo(R.id.mobile_navigation, true).build(),
|
||||||
|
null
|
||||||
|
)
|
||||||
}
|
}
|
||||||
// binding.buttonNext.alpha = 0f
|
// binding.buttonNext.alpha = 0f
|
||||||
// binding.textProgressFirstrun.alpha = 0f
|
// binding.textProgressFirstrun.alpha = 0f
|
||||||
|
|
|
@ -11,15 +11,13 @@ import cash.z.android.wallet.R
|
||||||
import cash.z.android.wallet.databinding.FragmentHistoryBinding
|
import cash.z.android.wallet.databinding.FragmentHistoryBinding
|
||||||
import cash.z.android.wallet.ui.adapter.TransactionAdapter
|
import cash.z.android.wallet.ui.adapter.TransactionAdapter
|
||||||
import cash.z.android.wallet.ui.presenter.HistoryPresenter
|
import cash.z.android.wallet.ui.presenter.HistoryPresenter
|
||||||
import cash.z.android.wallet.ui.presenter.Presenter
|
import cash.z.android.wallet.ui.presenter.HistoryPresenterModule
|
||||||
import cash.z.android.wallet.ui.util.AlternatingRowColorDecoration
|
import cash.z.android.wallet.ui.util.AlternatingRowColorDecoration
|
||||||
import cash.z.wallet.sdk.dao.WalletTransaction
|
import cash.z.wallet.sdk.dao.WalletTransaction
|
||||||
import dagger.Binds
|
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.android.ContributesAndroidInjector
|
import dagger.android.ContributesAndroidInjector
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
|
||||||
|
|
||||||
|
|
||||||
class HistoryFragment : BaseFragment(), HistoryPresenter.HistoryView {
|
class HistoryFragment : BaseFragment(), HistoryPresenter.HistoryView {
|
||||||
|
@ -73,10 +71,6 @@ class HistoryFragment : BaseFragment(), HistoryPresenter.HistoryView {
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
abstract class HistoryFragmentModule {
|
abstract class HistoryFragmentModule {
|
||||||
@ContributesAndroidInjector
|
@ContributesAndroidInjector(modules = [HistoryPresenterModule::class])
|
||||||
abstract fun contributeHistoryFragment(): HistoryFragment
|
abstract fun contributeHistoryFragment(): HistoryFragment
|
||||||
|
|
||||||
@Binds
|
|
||||||
@Singleton
|
|
||||||
abstract fun providePresenter(historyPresenter: HistoryPresenter): Presenter
|
|
||||||
}
|
}
|
|
@ -22,10 +22,12 @@ import androidx.transition.Transition
|
||||||
import androidx.transition.TransitionInflater
|
import androidx.transition.TransitionInflater
|
||||||
import cash.z.android.wallet.R
|
import cash.z.android.wallet.R
|
||||||
import cash.z.android.wallet.databinding.FragmentHomeBinding
|
import cash.z.android.wallet.databinding.FragmentHomeBinding
|
||||||
|
import cash.z.android.wallet.di.annotation.FragmentScope
|
||||||
import cash.z.android.wallet.extention.*
|
import cash.z.android.wallet.extention.*
|
||||||
import cash.z.android.wallet.sample.SampleProperties
|
import cash.z.android.wallet.sample.SampleProperties
|
||||||
import cash.z.android.wallet.ui.adapter.TransactionAdapter
|
import cash.z.android.wallet.ui.adapter.TransactionAdapter
|
||||||
import cash.z.android.wallet.ui.presenter.HomePresenter
|
import cash.z.android.wallet.ui.presenter.HomePresenter
|
||||||
|
import cash.z.android.wallet.ui.presenter.HomePresenterModule
|
||||||
import cash.z.android.wallet.ui.presenter.Presenter
|
import cash.z.android.wallet.ui.presenter.Presenter
|
||||||
import cash.z.android.wallet.ui.util.AlternatingRowColorDecoration
|
import cash.z.android.wallet.ui.util.AlternatingRowColorDecoration
|
||||||
import cash.z.android.wallet.ui.util.LottieLooper
|
import cash.z.android.wallet.ui.util.LottieLooper
|
||||||
|
@ -43,7 +45,6 @@ import dagger.Module
|
||||||
import dagger.android.ContributesAndroidInjector
|
import dagger.android.ContributesAndroidInjector
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
import kotlin.random.nextLong
|
import kotlin.random.nextLong
|
||||||
|
|
||||||
|
@ -59,6 +60,7 @@ class HomeFragment : BaseFragment(), SwipeRefreshLayout.OnRefreshListener, HomeP
|
||||||
|
|
||||||
private lateinit var binding: FragmentHomeBinding
|
private lateinit var binding: FragmentHomeBinding
|
||||||
private lateinit var zcashLogoAnimation: LottieLooper
|
private lateinit var zcashLogoAnimation: LottieLooper
|
||||||
|
private var maxTransactionsShown: Int = 12
|
||||||
private var snackbar: Snackbar? = null
|
private var snackbar: Snackbar? = null
|
||||||
private var viewsInitialized = false
|
private var viewsInitialized = false
|
||||||
|
|
||||||
|
@ -66,6 +68,11 @@ class HomeFragment : BaseFragment(), SwipeRefreshLayout.OnRefreshListener, HomeP
|
||||||
private var clock: Handler = Handler()
|
private var clock: Handler = Handler()
|
||||||
private val tickIfNeeded = Ticker()
|
private val tickIfNeeded = Ticker()
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// LifeCycle
|
||||||
|
//
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater, container: ViewGroup?,
|
inflater: LayoutInflater, container: ViewGroup?,
|
||||||
savedInstanceState: Bundle?
|
savedInstanceState: Bundle?
|
||||||
|
@ -89,7 +96,6 @@ class HomeFragment : BaseFragment(), SwipeRefreshLayout.OnRefreshListener, HomeP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
initTemp()
|
initTemp()
|
||||||
|
@ -128,15 +134,64 @@ class HomeFragment : BaseFragment(), SwipeRefreshLayout.OnRefreshListener, HomeP
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// SendView Implementation
|
||||||
|
//
|
||||||
|
|
||||||
|
override fun setTransactions(transactions: List<WalletTransaction>) {
|
||||||
|
val recent = if(transactions.size > maxTransactionsShown) transactions.subList(0, maxTransactionsShown) else transactions
|
||||||
|
with (binding.includeContent.recyclerTransactions) {
|
||||||
|
(adapter as TransactionAdapter).submitList(recent)
|
||||||
|
postDelayed({
|
||||||
|
smoothScrollToPosition(0)
|
||||||
|
}, 100L)
|
||||||
|
}
|
||||||
|
// Show "See All" when we have a sublist on screen
|
||||||
|
if (recent.size != transactions.size) {
|
||||||
|
binding.includeContent.textTransactionHeaderSeeAll.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
onContentRefreshComplete(transactions.isEmpty())
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: pull some of this logic into the presenter, particularly the part that deals with ZEC <-> USD price conversion
|
||||||
|
override fun updateBalance(old: Long, new: Long) {
|
||||||
|
val zecValue = new.convertZatoshiToZec()
|
||||||
|
setZecValue(zecValue.toZecString(3))
|
||||||
|
setUsdValue(zecValue.convertZecToUsd(SampleProperties.USD_PER_ZEC).toUsdString())
|
||||||
|
|
||||||
|
onContentRefreshComplete(new <= 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setActiveTransactions(activeTransactionMap: Map<ActiveTransaction, TransactionState>) {
|
||||||
|
if (activeTransactionMap.isEmpty()) {
|
||||||
|
twig("A.T.: setActiveTransactionsShown(false) because map is empty")
|
||||||
|
setActiveTransactionsShown(false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val transactions = activeTransactionMap.entries.toTypedArray()
|
||||||
|
// primary is the last one that was inserted
|
||||||
|
val primaryEntry = transactions[transactions.size - 1]
|
||||||
|
updatePrimaryTransaction(primaryEntry.key, primaryEntry.value)
|
||||||
|
|
||||||
|
onContentRefreshComplete(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCancelledTooLate() {
|
||||||
|
snackbar = snackbar.showOk(view!!, "Oops! It was too late to cancel!")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// View API
|
// View API
|
||||||
//
|
//
|
||||||
|
|
||||||
fun setContentViewShown(isShown: Boolean) {
|
fun setContentViewShown(isShown: Boolean) {
|
||||||
with(binding.includeContent) {
|
// with(binding.includeContent) {
|
||||||
groupEmptyViewItems.visibility = if (isShown) View.GONE else View.VISIBLE
|
// groupEmptyViewItems.visibility = if (isShown) View.GONE else View.VISIBLE
|
||||||
groupContentViewItems.visibility = if (isShown) View.VISIBLE else View.GONE
|
// groupContentViewItems.visibility = if (isShown) View.VISIBLE else View.GONE
|
||||||
}
|
// }
|
||||||
toggleViews(!isShown)
|
toggleViews(!isShown)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,30 +217,6 @@ class HomeFragment : BaseFragment(), SwipeRefreshLayout.OnRefreshListener, HomeP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//TODO: pull some of this logic into the presenter, particularly the part that deals with ZEC <-> USD price conversion
|
|
||||||
override fun updateBalance(old: Long, new: Long) {
|
|
||||||
val zecValue = new.convertZatoshiToZec()
|
|
||||||
setZecValue(zecValue.toZecString(3))
|
|
||||||
setUsdValue(zecValue.convertZecToUsd(SampleProperties.USD_PER_ZEC).toUsdString())
|
|
||||||
|
|
||||||
onContentRefreshComplete(new)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setTransactions(transactions: List<WalletTransaction>) {
|
|
||||||
val recent = if(transactions.size > 12) transactions.subList(0, 12) else transactions
|
|
||||||
with (binding.includeContent.recyclerTransactions) {
|
|
||||||
(adapter as TransactionAdapter).submitList(recent)
|
|
||||||
postDelayed({
|
|
||||||
smoothScrollToPosition(0)
|
|
||||||
}, 100L)
|
|
||||||
}
|
|
||||||
if (recent.size != transactions.size) {
|
|
||||||
binding.includeContent.textTransactionHeaderSeeAll.visibility = View.VISIBLE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun onInitialLoadComplete() {
|
private fun onInitialLoadComplete() {
|
||||||
val isEmpty = (binding.includeContent.recyclerTransactions?.adapter?.itemCount ?: 0).let { it == 0 }
|
val isEmpty = (binding.includeContent.recyclerTransactions?.adapter?.itemCount ?: 0).let { it == 0 }
|
||||||
twig("onInitialLoadComplete and isEmpty == $isEmpty")
|
twig("onInitialLoadComplete and isEmpty == $isEmpty")
|
||||||
|
@ -196,25 +227,6 @@ class HomeFragment : BaseFragment(), SwipeRefreshLayout.OnRefreshListener, HomeP
|
||||||
setRefreshAnimationPlaying(false).also { twig("refresh false from onInitialLoadComplete") }
|
setRefreshAnimationPlaying(false).also { twig("refresh false from onInitialLoadComplete") }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun setActiveTransactions(activeTransactionMap: Map<ActiveTransaction, TransactionState>) {
|
|
||||||
if (activeTransactionMap.isEmpty()) {
|
|
||||||
twig("A.T.: setActiveTransactionsShown(false) because map is empty")
|
|
||||||
setActiveTransactionsShown(false)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val transactions = activeTransactionMap.entries.toTypedArray()
|
|
||||||
// primary is the last one that was inserted
|
|
||||||
val primaryEntry = transactions[transactions.size - 1]
|
|
||||||
updatePrimaryTransaction(primaryEntry.key, primaryEntry.value)
|
|
||||||
// TODO: update remaining transactions
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCancelledTooLate() {
|
|
||||||
snackbar = snackbar.showOk(view!!, "Oops! It was too late to cancel!")
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updatePrimaryTransaction(transaction: ActiveTransaction, transactionState: TransactionState) {
|
private fun updatePrimaryTransaction(transaction: ActiveTransaction, transactionState: TransactionState) {
|
||||||
|
|
||||||
twig("setting transaction state to ${transactionState::class.simpleName}")
|
twig("setting transaction state to ${transactionState::class.simpleName}")
|
||||||
|
@ -294,7 +306,7 @@ class HomeFragment : BaseFragment(), SwipeRefreshLayout.OnRefreshListener, HomeP
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Private View API
|
// Internal View Logic
|
||||||
//
|
//
|
||||||
|
|
||||||
private fun setActiveTransactionsShown(isShown: Boolean, delay: Long = 0L) {
|
private fun setActiveTransactionsShown(isShown: Boolean, delay: Long = 0L) {
|
||||||
|
@ -329,6 +341,7 @@ class HomeFragment : BaseFragment(), SwipeRefreshLayout.OnRefreshListener, HomeP
|
||||||
setColorSchemeColors(R.color.zcashBlack.toAppColor())
|
setColorSchemeColors(R.color.zcashBlack.toAppColor())
|
||||||
setProgressBackgroundColorSchemeColor(R.color.zcashYellow.toAppColor())
|
setProgressBackgroundColorSchemeColor(R.color.zcashYellow.toAppColor())
|
||||||
}
|
}
|
||||||
|
maxTransactionsShown = calculateMaxTransactions()
|
||||||
|
|
||||||
// hide content
|
// hide content
|
||||||
setContentViewShown(false)
|
setContentViewShown(false)
|
||||||
|
@ -336,6 +349,10 @@ class HomeFragment : BaseFragment(), SwipeRefreshLayout.OnRefreshListener, HomeP
|
||||||
setRefreshAnimationPlaying(true).also { twig("refresh true from init") }
|
setRefreshAnimationPlaying(true).also { twig("refresh true from init") }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun calculateMaxTransactions(): Int {
|
||||||
|
return 12 //TODO: measure the screen and get optimal number for this device
|
||||||
|
}
|
||||||
|
|
||||||
// initialize the stuff that is temporary and needs to go ASAP
|
// initialize the stuff that is temporary and needs to go ASAP
|
||||||
private fun initTemp() {
|
private fun initTemp() {
|
||||||
|
|
||||||
|
@ -407,14 +424,13 @@ class HomeFragment : BaseFragment(), SwipeRefreshLayout.OnRefreshListener, HomeP
|
||||||
* If the balance changes from zero, the wallet is no longer empty so hide the empty view.
|
* If the balance changes from zero, the wallet is no longer empty so hide the empty view.
|
||||||
* But don't do either of these things if the situation has not changed.
|
* But don't do either of these things if the situation has not changed.
|
||||||
*/
|
*/
|
||||||
private fun onContentRefreshComplete(value: Long) {
|
private fun onContentRefreshComplete(isEmpty: Boolean) {
|
||||||
val isEmpty = value <= 0L
|
|
||||||
// wasEmpty isn't enough info. it must be considered along with whether these views were ever initialized
|
// wasEmpty isn't enough info. it must be considered along with whether these views were ever initialized
|
||||||
val wasEmpty = binding.includeContent.groupEmptyViewItems.visibility == View.VISIBLE
|
val wasEmpty = binding.includeContent.groupEmptyViewItems.visibility == View.VISIBLE
|
||||||
// situation has changed when we weren't initialized but now we have a balance or emptiness has changed
|
// situation has changed when we weren't initialized but now we have a balance or emptiness has changed
|
||||||
val situationHasChanged = !viewsInitialized || (isEmpty != wasEmpty)
|
val situationHasChanged = !viewsInitialized || (isEmpty != wasEmpty)
|
||||||
|
|
||||||
twig("updateEmptyViews called with value: $value initialized: $viewsInitialized isEmpty: $isEmpty wasEmpty: $wasEmpty")
|
twig("onContentRefreshComplete called initialized: $viewsInitialized isEmpty: $isEmpty wasEmpty: $wasEmpty")
|
||||||
if (situationHasChanged) {
|
if (situationHasChanged) {
|
||||||
twig("The situation has changed! toggling views!")
|
twig("The situation has changed! toggling views!")
|
||||||
setContentViewShown(!isEmpty)
|
setContentViewShown(!isEmpty)
|
||||||
|
@ -464,6 +480,7 @@ class HomeFragment : BaseFragment(), SwipeRefreshLayout.OnRefreshListener, HomeP
|
||||||
|
|
||||||
private inner class Ticker : Runnable {
|
private inner class Ticker : Runnable {
|
||||||
override fun run() {
|
override fun run() {
|
||||||
|
if (mainActivity == null) return
|
||||||
binding.includeContent.recyclerTransactions.apply {
|
binding.includeContent.recyclerTransactions.apply {
|
||||||
if ((adapter?.itemCount ?: 0) > 0) {
|
if ((adapter?.itemCount ?: 0) > 0) {
|
||||||
adapter?.notifyDataSetChanged()
|
adapter?.notifyDataSetChanged()
|
||||||
|
@ -624,14 +641,11 @@ class HomeFragment : BaseFragment(), SwipeRefreshLayout.OnRefreshListener, HomeP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
abstract class HomeFragmentModule {
|
abstract class HomeFragmentModule {
|
||||||
@ContributesAndroidInjector
|
@FragmentScope
|
||||||
|
@ContributesAndroidInjector(modules = [HomePresenterModule::class])
|
||||||
abstract fun contributeHomeFragment(): HomeFragment
|
abstract fun contributeHomeFragment(): HomeFragment
|
||||||
|
|
||||||
@Binds
|
|
||||||
@Singleton
|
|
||||||
abstract fun providePresenter(homePresenter: HomePresenter): Presenter
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,8 @@ abstract class ProgressFragment(
|
||||||
|
|
||||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||||
super.onActivityCreated(savedInstanceState)
|
super.onActivityCreated(savedInstanceState)
|
||||||
|
// construct here rather than inject to make scoping easier
|
||||||
|
// so that we reduce the chances of updating progress on the wrong fragment
|
||||||
progressPresenter = ProgressPresenter(this, synchronizer)
|
progressPresenter = ProgressPresenter(this, synchronizer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,15 +23,13 @@ import cash.z.android.wallet.R
|
||||||
import cash.z.android.wallet.databinding.FragmentSendBinding
|
import cash.z.android.wallet.databinding.FragmentSendBinding
|
||||||
import cash.z.android.wallet.extention.*
|
import cash.z.android.wallet.extention.*
|
||||||
import cash.z.android.wallet.sample.SampleProperties
|
import cash.z.android.wallet.sample.SampleProperties
|
||||||
import cash.z.android.wallet.ui.presenter.Presenter
|
|
||||||
import cash.z.android.wallet.ui.presenter.SendPresenter
|
import cash.z.android.wallet.ui.presenter.SendPresenter
|
||||||
|
import cash.z.android.wallet.ui.presenter.SendPresenterModule
|
||||||
import cash.z.wallet.sdk.ext.convertZatoshiToZecString
|
import cash.z.wallet.sdk.ext.convertZatoshiToZecString
|
||||||
import dagger.Binds
|
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.android.ContributesAndroidInjector
|
import dagger.android.ContributesAndroidInjector
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fragment for sending Zcash.
|
* Fragment for sending Zcash.
|
||||||
|
@ -386,10 +384,6 @@ class SendFragment : BaseFragment(), SendPresenter.SendView, ScanFragment.Barcod
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
abstract class SendFragmentModule {
|
abstract class SendFragmentModule {
|
||||||
@ContributesAndroidInjector
|
@ContributesAndroidInjector(modules = [SendPresenterModule::class])
|
||||||
abstract fun contributeSendFragment(): SendFragment
|
abstract fun contributeSendFragment(): SendFragment
|
||||||
|
|
||||||
@Binds
|
|
||||||
@Singleton
|
|
||||||
abstract fun providePresenter(sendPresenter: SendPresenter): Presenter
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.core.view.doOnPreDraw
|
import androidx.core.view.doOnPreDraw
|
||||||
import androidx.databinding.DataBindingUtil
|
import androidx.databinding.DataBindingUtil
|
||||||
|
import androidx.navigation.NavOptions
|
||||||
import androidx.transition.TransitionInflater
|
import androidx.transition.TransitionInflater
|
||||||
import cash.z.android.wallet.R
|
import cash.z.android.wallet.R
|
||||||
import cash.z.android.wallet.databinding.FragmentSyncBinding
|
import cash.z.android.wallet.databinding.FragmentSyncBinding
|
||||||
|
@ -43,7 +44,11 @@ class SyncFragment : ProgressFragment(R.id.progress_sync) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
postponeEnterTransition()
|
postponeEnterTransition()
|
||||||
binding.buttonNext.setOnClickListener {
|
binding.buttonNext.setOnClickListener {
|
||||||
mainActivity?.navController?.navigate(R.id.nav_home_fragment)
|
mainActivity?.navController?.navigate(R.id.action_sync_fragment_to_home_fragment,
|
||||||
|
null,
|
||||||
|
NavOptions.Builder().setPopUpTo(R.id.mobile_navigation, true).build(),
|
||||||
|
null
|
||||||
|
)
|
||||||
}
|
}
|
||||||
binding.progressSync.visibility = View.INVISIBLE
|
binding.progressSync.visibility = View.INVISIBLE
|
||||||
binding.textProgressSync.visibility = View.INVISIBLE
|
binding.textProgressSync.visibility = View.INVISIBLE
|
||||||
|
|
|
@ -5,34 +5,16 @@ import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.databinding.DataBindingUtil
|
import androidx.databinding.DataBindingUtil
|
||||||
|
import androidx.navigation.NavOptions
|
||||||
import androidx.navigation.fragment.FragmentNavigatorExtras
|
import androidx.navigation.fragment.FragmentNavigatorExtras
|
||||||
|
import androidx.transition.TransitionInflater
|
||||||
|
import cash.z.android.wallet.BuildConfig
|
||||||
import cash.z.android.wallet.R
|
import cash.z.android.wallet.R
|
||||||
import cash.z.android.wallet.databinding.FragmentWelcomeBinding
|
import cash.z.android.wallet.databinding.FragmentWelcomeBinding
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.android.ContributesAndroidInjector
|
import dagger.android.ContributesAndroidInjector
|
||||||
import kotlinx.coroutines.coroutineScope
|
import kotlinx.coroutines.coroutineScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import android.graphics.Bitmap
|
|
||||||
import android.R.attr.top
|
|
||||||
import android.R.attr.left
|
|
||||||
import android.graphics.RectF
|
|
||||||
import android.os.Parcelable
|
|
||||||
import androidx.core.app.ActivityCompat.setExitSharedElementCallback
|
|
||||||
import android.graphics.Canvas
|
|
||||||
import android.graphics.Matrix
|
|
||||||
import android.util.Log
|
|
||||||
import androidx.core.app.SharedElementCallback
|
|
||||||
import androidx.transition.TransitionInflater
|
|
||||||
import cash.z.android.wallet.BuildConfig
|
|
||||||
import cash.z.android.wallet.ui.presenter.Presenter
|
|
||||||
import cash.z.android.wallet.ui.presenter.ProgressPresenter
|
|
||||||
import dagger.Binds
|
|
||||||
import dagger.BindsInstance
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import javax.inject.Inject
|
|
||||||
import javax.inject.Named
|
|
||||||
import javax.inject.Singleton
|
|
||||||
|
|
||||||
|
|
||||||
class WelcomeFragment : ProgressFragment(R.id.progress_welcome) {
|
class WelcomeFragment : ProgressFragment(R.id.progress_welcome) {
|
||||||
|
@ -109,7 +91,9 @@ class WelcomeFragment : ProgressFragment(R.id.progress_welcome) {
|
||||||
private suspend fun onNext() = coroutineScope {
|
private suspend fun onNext() = coroutineScope {
|
||||||
if (mainActivity != null) {
|
if (mainActivity != null) {
|
||||||
val isFirstRun = mainActivity!!.synchronizer.isFirstRun()
|
val isFirstRun = mainActivity!!.synchronizer.isFirstRun()
|
||||||
val destination = if (isFirstRun) R.id.nav_firstrun_fragment else R.id.nav_sync_fragment
|
val destination =
|
||||||
|
if (isFirstRun) R.id.action_welcome_fragment_to_firstrun_fragment
|
||||||
|
else R.id.action_welcome_fragment_to_sync_fragment
|
||||||
|
|
||||||
// var extras = with(binding) {
|
// var extras = with(binding) {
|
||||||
// listOf(progressWelcome, textProgressWelcome)
|
// listOf(progressWelcome, textProgressWelcome)
|
||||||
|
@ -119,10 +103,11 @@ class WelcomeFragment : ProgressFragment(R.id.progress_welcome) {
|
||||||
val extras = FragmentNavigatorExtras(
|
val extras = FragmentNavigatorExtras(
|
||||||
binding.progressWelcome to binding.progressWelcome.transitionName
|
binding.progressWelcome to binding.progressWelcome.transitionName
|
||||||
)
|
)
|
||||||
|
|
||||||
mainActivity?.navController?.navigate(
|
mainActivity?.navController?.navigate(
|
||||||
destination,
|
destination,
|
||||||
null,
|
null,
|
||||||
null,
|
NavOptions.Builder().setPopUpTo(R.id.mobile_navigation, true).build(),
|
||||||
extras
|
extras
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
package cash.z.android.wallet.ui.presenter
|
package cash.z.android.wallet.ui.presenter
|
||||||
|
|
||||||
|
import cash.z.android.wallet.di.annotation.FragmentScope
|
||||||
import cash.z.android.wallet.ui.fragment.HistoryFragment
|
import cash.z.android.wallet.ui.fragment.HistoryFragment
|
||||||
import cash.z.android.wallet.ui.presenter.Presenter.PresenterView
|
import cash.z.android.wallet.ui.presenter.Presenter.PresenterView
|
||||||
import cash.z.wallet.sdk.dao.WalletTransaction
|
import cash.z.wallet.sdk.dao.WalletTransaction
|
||||||
import cash.z.wallet.sdk.data.Synchronizer
|
import cash.z.wallet.sdk.data.Synchronizer
|
||||||
import cash.z.wallet.sdk.data.twig
|
import cash.z.wallet.sdk.data.twig
|
||||||
|
import dagger.Binds
|
||||||
|
import dagger.Module
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
|
@ -16,23 +19,24 @@ import kotlin.coroutines.CoroutineContext
|
||||||
class HistoryPresenter @Inject constructor(
|
class HistoryPresenter @Inject constructor(
|
||||||
private val view: HistoryFragment,
|
private val view: HistoryFragment,
|
||||||
private var synchronizer: Synchronizer
|
private var synchronizer: Synchronizer
|
||||||
) : Presenter, CoroutineScope {
|
) : Presenter {
|
||||||
|
|
||||||
private val job = Job()
|
private var job: Job? = null
|
||||||
override val coroutineContext: CoroutineContext get() = Dispatchers.Main + job
|
|
||||||
|
|
||||||
interface HistoryView : PresenterView {
|
interface HistoryView : PresenterView {
|
||||||
fun setTransactions(transactions: List<WalletTransaction>)
|
fun setTransactions(transactions: List<WalletTransaction>)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun start() {
|
override suspend fun start() {
|
||||||
|
job?.cancel()
|
||||||
|
job = Job()
|
||||||
twig("historyPresenter starting!")
|
twig("historyPresenter starting!")
|
||||||
launchTransactionBinder(synchronizer.allTransactions())
|
view.launchTransactionBinder(synchronizer.allTransactions())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun stop() {
|
override fun stop() {
|
||||||
twig("historyPresenter stopping!")
|
twig("historyPresenter stopping!")
|
||||||
job.cancel()
|
job?.cancel()?.also { job = null }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun CoroutineScope.launchTransactionBinder(channel: ReceiveChannel<List<WalletTransaction>>) = launch {
|
private fun CoroutineScope.launchTransactionBinder(channel: ReceiveChannel<List<WalletTransaction>>) = launch {
|
||||||
|
@ -58,3 +62,10 @@ class HistoryPresenter @Inject constructor(
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Module
|
||||||
|
abstract class HistoryPresenterModule {
|
||||||
|
@Binds
|
||||||
|
@FragmentScope
|
||||||
|
abstract fun providePresenter(historyPresenter: HistoryPresenter): Presenter
|
||||||
|
}
|
|
@ -1,24 +1,23 @@
|
||||||
package cash.z.android.wallet.ui.presenter
|
package cash.z.android.wallet.ui.presenter
|
||||||
|
|
||||||
import android.util.Log
|
import cash.z.android.wallet.di.annotation.FragmentScope
|
||||||
import cash.z.android.wallet.ZcashWalletApplication
|
|
||||||
import cash.z.android.wallet.ui.fragment.HomeFragment
|
import cash.z.android.wallet.ui.fragment.HomeFragment
|
||||||
import cash.z.android.wallet.ui.presenter.Presenter.PresenterView
|
import cash.z.android.wallet.ui.presenter.Presenter.PresenterView
|
||||||
import cash.z.wallet.sdk.dao.WalletTransaction
|
import cash.z.wallet.sdk.dao.WalletTransaction
|
||||||
import cash.z.wallet.sdk.data.*
|
import cash.z.wallet.sdk.data.*
|
||||||
|
import dagger.Binds
|
||||||
|
import dagger.Module
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import kotlinx.coroutines.Dispatchers.Main
|
import kotlinx.coroutines.Dispatchers.Main
|
||||||
import kotlinx.coroutines.channels.ReceiveChannel
|
import kotlinx.coroutines.channels.ReceiveChannel
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.coroutines.CoroutineContext
|
|
||||||
|
|
||||||
class HomePresenter @Inject constructor(
|
class HomePresenter @Inject constructor(
|
||||||
private val view: HomeFragment,
|
private val view: HomeFragment,
|
||||||
private val synchronizer: Synchronizer
|
private val synchronizer: Synchronizer
|
||||||
) : Presenter, CoroutineScope {
|
) : Presenter {
|
||||||
|
|
||||||
private val job = Job()
|
private var job: Job? = null
|
||||||
override val coroutineContext: CoroutineContext get() = Dispatchers.IO + job
|
|
||||||
|
|
||||||
interface HomeView : PresenterView {
|
interface HomeView : PresenterView {
|
||||||
fun setTransactions(transactions: List<WalletTransaction>)
|
fun setTransactions(transactions: List<WalletTransaction>)
|
||||||
|
@ -28,15 +27,19 @@ class HomePresenter @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun start() {
|
override suspend fun start() {
|
||||||
twig("homePresenter starting!")
|
job?.cancel()
|
||||||
launchBalanceBinder(synchronizer.balance())
|
job = Job()
|
||||||
launchTransactionBinder(synchronizer.allTransactions())
|
twig("homePresenter starting! from ${this.hashCode()}")
|
||||||
launchActiveTransactionMonitor(synchronizer.activeTransactions())
|
with(view) {
|
||||||
|
launchBalanceBinder(synchronizer.balance())
|
||||||
|
launchTransactionBinder(synchronizer.allTransactions())
|
||||||
|
launchActiveTransactionMonitor(synchronizer.activeTransactions())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun stop() {
|
override fun stop() {
|
||||||
twig("homePresenter stopping!")
|
twig("homePresenter stopping!")
|
||||||
job.cancel()
|
job?.cancel()?.also { job = null }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun CoroutineScope.launchBalanceBinder(channel: ReceiveChannel<Long>) = launch {
|
private fun CoroutineScope.launchBalanceBinder(channel: ReceiveChannel<Long>) = launch {
|
||||||
|
@ -71,20 +74,20 @@ class HomePresenter @Inject constructor(
|
||||||
// View Callbacks on Main Thread
|
// View Callbacks on Main Thread
|
||||||
//
|
//
|
||||||
|
|
||||||
private fun bind(old: Long?, new: Long) = onMain {
|
private fun bind(old: Long?, new: Long) {
|
||||||
twig("binding balance of $new")
|
twig("binding balance of $new")
|
||||||
view.updateBalance(old ?: 0L, new)
|
view.updateBalance(old ?: 0L, new)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun bind(transactions: List<WalletTransaction>) = onMain {
|
private fun bind(transactions: List<WalletTransaction>) {
|
||||||
twig("binding ${transactions.size} walletTransactions")
|
twig("binding ${transactions.size} walletTransactions")
|
||||||
view.setTransactions(transactions.sortedByDescending {
|
view.setTransactions(transactions.sortedByDescending {
|
||||||
if (!it.isMined && it.isSend) Long.MAX_VALUE else it.timeInSeconds
|
if (!it.isMined && it.isSend) Long.MAX_VALUE else it.timeInSeconds
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun bind(activeTransactionMap: Map<ActiveTransaction, TransactionState>) = onMain {
|
private fun bind(activeTransactionMap: Map<ActiveTransaction, TransactionState>) {
|
||||||
twig("binding a.t. map of size ${activeTransactionMap.size}")
|
twig("binding a.t. map of size ${activeTransactionMap.size}")
|
||||||
if (activeTransactionMap.isNotEmpty()) view.setActiveTransactions(activeTransactionMap)
|
if (activeTransactionMap.isNotEmpty()) view.setActiveTransactions(activeTransactionMap)
|
||||||
}
|
}
|
||||||
|
@ -97,13 +100,11 @@ class HomePresenter @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onMain(block: () -> Unit) = launch {
|
|
||||||
withContext(Main) {
|
|
||||||
twig("running task on main thread - start ${coroutineContext[Job]} | ${coroutineContext[CoroutineName]}")
|
|
||||||
block()
|
|
||||||
twig("running task on main thread - complete")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Module
|
||||||
|
abstract class HomePresenterModule {
|
||||||
|
@Binds
|
||||||
|
@FragmentScope
|
||||||
|
abstract fun providePresenter(homePresenter: HomePresenter): Presenter
|
||||||
|
}
|
|
@ -12,28 +12,31 @@ import kotlin.coroutines.CoroutineContext
|
||||||
class ProgressPresenter @Inject constructor(
|
class ProgressPresenter @Inject constructor(
|
||||||
private val view: ProgressView,
|
private val view: ProgressView,
|
||||||
private var synchronizer: Synchronizer
|
private var synchronizer: Synchronizer
|
||||||
) : Presenter, CoroutineScope {
|
) : Presenter {
|
||||||
|
|
||||||
private val job = Job()
|
private var job: Job? = null
|
||||||
override val coroutineContext: CoroutineContext get() = Dispatchers.Main + job
|
|
||||||
|
|
||||||
interface ProgressView : PresenterView {
|
interface ProgressView : PresenterView {
|
||||||
fun showProgress(progress: Int)
|
fun showProgress(progress: Int)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// LifeCycle
|
// LifeCycle
|
||||||
//
|
//
|
||||||
|
|
||||||
override suspend fun start() {
|
override suspend fun start() {
|
||||||
|
job?.cancel()
|
||||||
|
job = Job()
|
||||||
Twig.sprout("ProgressPresenter")
|
Twig.sprout("ProgressPresenter")
|
||||||
twig("starting")
|
twig("starting")
|
||||||
launchProgressMonitor(synchronizer.progress())
|
view.launchProgressMonitor(synchronizer.progress())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun stop() {
|
override fun stop() {
|
||||||
Twig.clip("ProgressPresenter")
|
Twig.clip("ProgressPresenter")
|
||||||
twig("stopping")
|
twig("stopping")
|
||||||
|
job?.cancel()?.also { job = null }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun CoroutineScope.launchProgressMonitor(channel: ReceiveChannel<Int>) = launch {
|
private fun CoroutineScope.launchProgressMonitor(channel: ReceiveChannel<Int>) = launch {
|
||||||
|
@ -46,7 +49,7 @@ class ProgressPresenter @Inject constructor(
|
||||||
twig("progress monitor exiting!")
|
twig("progress monitor exiting!")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun bind(progress: Int) = launch {
|
private fun bind(progress: Int) = view.launch {
|
||||||
twig("binding progress of $progress on thread ${Thread.currentThread().name}!")
|
twig("binding progress of $progress on thread ${Thread.currentThread().name}!")
|
||||||
view.showProgress(progress)
|
view.showProgress(progress)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package cash.z.android.wallet.ui.presenter
|
package cash.z.android.wallet.ui.presenter
|
||||||
|
|
||||||
import cash.z.android.wallet.R
|
import cash.z.android.wallet.R
|
||||||
|
import cash.z.android.wallet.di.annotation.FragmentScope
|
||||||
import cash.z.android.wallet.extention.toAppString
|
import cash.z.android.wallet.extention.toAppString
|
||||||
import cash.z.android.wallet.sample.SampleProperties
|
import cash.z.android.wallet.sample.SampleProperties
|
||||||
import cash.z.android.wallet.ui.fragment.SendFragment
|
import cash.z.android.wallet.ui.fragment.SendFragment
|
||||||
|
@ -9,6 +10,8 @@ import cash.z.wallet.sdk.data.Synchronizer
|
||||||
import cash.z.wallet.sdk.data.twig
|
import cash.z.wallet.sdk.data.twig
|
||||||
import cash.z.wallet.sdk.data.Twig
|
import cash.z.wallet.sdk.data.Twig
|
||||||
import cash.z.wallet.sdk.ext.*
|
import cash.z.wallet.sdk.ext.*
|
||||||
|
import dagger.Binds
|
||||||
|
import dagger.Module
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
|
@ -61,9 +64,9 @@ class SendPresenter @Inject constructor(
|
||||||
twig("sendPresenter starting!")
|
twig("sendPresenter starting!")
|
||||||
// set the currency to zec and update the view, initializing everything to zero
|
// set the currency to zec and update the view, initializing everything to zero
|
||||||
inputToggleCurrency()
|
inputToggleCurrency()
|
||||||
with(view) {
|
balanceJob?.cancel()
|
||||||
balanceJob = launchBalanceBinder(synchronizer.balance())
|
balanceJob = Job()
|
||||||
}
|
balanceJob = view.launchBalanceBinder(synchronizer.balance())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun stop() {
|
override fun stop() {
|
||||||
|
@ -347,4 +350,12 @@ class SendPresenter @Inject constructor(
|
||||||
val toAddress: String = "",
|
val toAddress: String = "",
|
||||||
val memo: String = ""
|
val memo: String = ""
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Module
|
||||||
|
abstract class SendPresenterModule {
|
||||||
|
@Binds
|
||||||
|
@FragmentScope
|
||||||
|
abstract fun providePresenter(sendPresenter: SendPresenter): Presenter
|
||||||
}
|
}
|
|
@ -1,17 +1,4 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?><!--
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
Copyright (C) 2018 The Android Open Source Project
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
-->
|
|
||||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools">
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
|
@ -12,12 +12,18 @@
|
||||||
tools:layout="@layout/fragment_welcome">
|
tools:layout="@layout/fragment_welcome">
|
||||||
<action
|
<action
|
||||||
android:id="@+id/action_welcome_fragment_to_firstrun_fragment"
|
android:id="@+id/action_welcome_fragment_to_firstrun_fragment"
|
||||||
|
app:popUpTo="@navigation/mobile_navigation"
|
||||||
|
app:popUpToInclusive="true"
|
||||||
app:destination="@id/nav_firstrun_fragment" />
|
app:destination="@id/nav_firstrun_fragment" />
|
||||||
<action
|
<action
|
||||||
android:id="@+id/action_welcome_fragment_to_sync_fragment"
|
android:id="@+id/action_welcome_fragment_to_sync_fragment"
|
||||||
|
app:popUpTo="@navigation/mobile_navigation"
|
||||||
|
app:popUpToInclusive="true"
|
||||||
app:destination="@id/nav_sync_fragment" />
|
app:destination="@id/nav_sync_fragment" />
|
||||||
<action
|
<action
|
||||||
android:id="@+id/action_welcome_fragment_to_home_fragment"
|
android:id="@+id/action_welcome_fragment_to_home_fragment"
|
||||||
|
app:popUpTo="@navigation/mobile_navigation"
|
||||||
|
app:popUpToInclusive="true"
|
||||||
app:destination="@id/nav_home_fragment" />
|
app:destination="@id/nav_home_fragment" />
|
||||||
</fragment>
|
</fragment>
|
||||||
<fragment
|
<fragment
|
||||||
|
@ -27,6 +33,8 @@
|
||||||
tools:layout="@layout/fragment_firstrun">
|
tools:layout="@layout/fragment_firstrun">
|
||||||
<action
|
<action
|
||||||
android:id="@+id/action_firstrun_fragment_to_sync_fragment"
|
android:id="@+id/action_firstrun_fragment_to_sync_fragment"
|
||||||
|
app:popUpTo="@navigation/mobile_navigation"
|
||||||
|
app:popUpToInclusive="true"
|
||||||
app:destination="@id/nav_sync_fragment" />
|
app:destination="@id/nav_sync_fragment" />
|
||||||
</fragment>
|
</fragment>
|
||||||
<fragment
|
<fragment
|
||||||
|
@ -36,6 +44,8 @@
|
||||||
tools:layout="@layout/fragment_sync">
|
tools:layout="@layout/fragment_sync">
|
||||||
<action
|
<action
|
||||||
android:id="@+id/action_sync_fragment_to_home_fragment"
|
android:id="@+id/action_sync_fragment_to_home_fragment"
|
||||||
|
app:popUpTo="@navigation/mobile_navigation"
|
||||||
|
app:popUpToInclusive="true"
|
||||||
app:destination="@id/nav_home_fragment" />
|
app:destination="@id/nav_home_fragment" />
|
||||||
</fragment>
|
</fragment>
|
||||||
<fragment
|
<fragment
|
||||||
|
|
|
@ -17,7 +17,8 @@ internal object SynchronizerModule {
|
||||||
|
|
||||||
// const val MOCK_LOAD_DURATION = 3_000L
|
// const val MOCK_LOAD_DURATION = 3_000L
|
||||||
const val MOCK_LOAD_DURATION = 12_000L
|
const val MOCK_LOAD_DURATION = 12_000L
|
||||||
const val MOCK_TX_INTERVAL = 20_000L
|
// const val MOCK_TX_INTERVAL = 20_000L
|
||||||
|
const val MOCK_TX_INTERVAL = 5_000L
|
||||||
const val MOCK_ACTIVE_TX_STATE_CHANGE_INTERVAL = 7_000L
|
const val MOCK_ACTIVE_TX_STATE_CHANGE_INTERVAL = 7_000L
|
||||||
const val MOCK_IS_FIRST_RUN: Boolean = true
|
const val MOCK_IS_FIRST_RUN: Boolean = true
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ buildscript {
|
||||||
'dagger': '2.19',
|
'dagger': '2.19',
|
||||||
'kotlin': '1.3.11',
|
'kotlin': '1.3.11',
|
||||||
'coroutines': '1.1.0',
|
'coroutines': '1.1.0',
|
||||||
'navigation': '1.0.0-alpha07'
|
'navigation': '1.0.0-rc01'
|
||||||
]
|
]
|
||||||
ext.deps = [
|
ext.deps = [
|
||||||
'androidx': [
|
'androidx': [
|
||||||
|
|
Loading…
Reference in New Issue