zcash-android-wallet-sdk/demo-app/src/main/java/cash/z/ecc/android/sdk/demoapp/BaseDemoFragment.kt

114 lines
4.2 KiB
Kotlin

package cash.z.ecc.android.sdk.demoapp
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.viewbinding.ViewBinding
import cash.z.ecc.android.sdk.demoapp.util.BenchmarkTrace
import cash.z.ecc.android.sdk.demoapp.util.ProvideAddressBenchmarkTrace
import cash.z.ecc.android.sdk.demoapp.util.SyncBlockchainBenchmarkTrace
import cash.z.ecc.android.sdk.demoapp.util.mainActivity
import com.google.android.material.snackbar.Snackbar
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
abstract class BaseDemoFragment<T : ViewBinding> : Fragment() {
/**
* Since the lightwalletClient is not a component that apps typically use, directly, we provide
* this from one place. Everything that can be done with the service can/should be done with the
* synchronizer because it wraps the service.
*/
val lightWalletClient get() = mainActivity()?.lightwalletClient
// contains view information provided by the user
val sharedViewModel: SharedViewModel by activityViewModels()
lateinit var binding: T
internal val traceScope = CoroutineScope(Dispatchers.Main)
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = inflateBinding(layoutInflater)
return binding.root
}
override fun onResume() {
super.onResume()
registerActionButtonListener()
}
override fun onPause() {
super.onPause()
unregisterActionButtonListener()
(activity as? MainActivity)?.hideKeyboard()
}
private fun registerActionButtonListener() {
(activity as? MainActivity)?.fabListener = this
}
private fun unregisterActionButtonListener() {
(activity as? MainActivity)?.apply {
if (fabListener === this@BaseDemoFragment) fabListener = null
}
}
/**
* Callback that gets invoked on the visible fragment whenever the floating action button is
* tapped. This provides a convenient placeholder for the developer to extend the
* behavior for a demo, for instance by copying the address to the clipboard, whenever the FAB
* is tapped on the address screen.
*/
open fun onActionButtonClicked() {
// Show a message so that it's easy for developers to find how to replace this behavior for
// each fragment. Simply override this [onActionButtonClicked] callback to add behavior to a
// demo. In other words, this function probably doesn't need to change because desired
// behavior should go in the child fragment, which overrides this.
Snackbar.make(requireView(), "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action") { /* auto-close */ }.show()
}
/**
* Convenience function to the given text to the clipboard.
*/
open fun copyToClipboard(text: String, description: String = "Copied to clipboard!") {
(activity?.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager)
.setPrimaryClip(ClipData.newPlainText("DemoAppClip", text))
toast(description)
}
/**
* Convenience function to show a toast in the main activity.
*/
fun toast(message: String) {
Toast.makeText(activity, message, Toast.LENGTH_SHORT).show()
}
/**
* Inflate the ViewBinding. Unfortunately, the `inflate` function is not part of the ViewBinding
* interface so the base class cannot take care of this behavior without some help.
*/
abstract fun inflateBinding(layoutInflater: LayoutInflater): T
internal fun reportTraceEvent(event: BenchmarkTrace.Event?) {
traceScope.launch {
when (event) {
is ProvideAddressBenchmarkTrace.Event -> ProvideAddressBenchmarkTrace.writeEvent(event)
is SyncBlockchainBenchmarkTrace.Event -> SyncBlockchainBenchmarkTrace.writeEvent(event)
}
}
}
}