[#866] Clipboardmanager on Android level 21 in Demo-app

* [#866] Clipboardmanager on Android level 21 in Demo-app

- Notification with Toast on API 32 and less added to let users know they have it copied in the clipboard.

* Replace Toast with Snackbar

- Tested with Android API level 21, 23, 29, 31, 33
This commit is contained in:
Honza Rychnovsky 2023-01-09 14:12:04 +01:00 committed by GitHub
parent 1dd36b582e
commit 327b47cc12
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 53 additions and 14 deletions

View File

@ -1,12 +1,14 @@
package cash.z.ecc.android.sdk.demoapp
import android.annotation.TargetApi
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.os.Build
import androidx.activity.viewModels
import androidx.compose.material3.SnackbarDuration
import androidx.compose.material3.SnackbarHostState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.lifecycle.compose.ExperimentalLifecycleComposeApi
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.NavHostController
@ -21,6 +23,9 @@ import cash.z.ecc.android.sdk.demoapp.ui.screen.addresses.view.Addresses
import cash.z.ecc.android.sdk.demoapp.ui.screen.home.view.Home
import cash.z.ecc.android.sdk.demoapp.ui.screen.home.viewmodel.WalletViewModel
import cash.z.ecc.android.sdk.demoapp.ui.screen.send.view.Send
import cash.z.ecc.android.sdk.demoapp.util.AndroidApiVersion
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
@OptIn(ExperimentalLifecycleComposeApi::class)
@Composable
@ -47,14 +52,23 @@ internal fun ComposeActivity.Navigation() {
if (null == synchronizer) {
// Display loading indicator
} else {
val scope = rememberCoroutineScope()
val snackbarHostState = remember { SnackbarHostState() }
// I don't like giving synchronizer directly over to the view, but for now it isolates each of the
// demo app views
Addresses(
synchronizer = synchronizer,
copyToClipboard = { tag, textToCopy ->
copyToClipboard(applicationContext, tag, textToCopy)
copyToClipboard(
applicationContext,
tag,
textToCopy,
scope,
snackbarHostState
)
},
onBack = { navController.popBackStackJustOnce(WALLET_ADDRESS_DETAILS) }
onBack = { navController.popBackStackJustOnce(WALLET_ADDRESS_DETAILS) },
snackbarHostState = snackbarHostState
)
}
}
@ -107,16 +121,35 @@ private fun NavHostController.popBackStackJustOnce(currentRouteToBePopped: Strin
popBackStack()
}
// Note: this requires API level 23 (current min is 21 for the Demo-app). We should address this requirement, or set
// our Demo-app min to 23
@TargetApi(Build.VERSION_CODES.M)
fun copyToClipboard(context: Context, tag: String, textToCopy: String) {
val clipboardManager = context.getSystemService(ClipboardManager::class.java)
fun copyToClipboard(
context: Context,
tag: String,
textToCopy: String,
scope: CoroutineScope,
snackbarHostState: SnackbarHostState
) {
val clipboardManager = if (AndroidApiVersion.isAtLeastM) {
context.getSystemService(ClipboardManager::class.java)
} else {
context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
}
val data = ClipData.newPlainText(
tag,
textToCopy
)
clipboardManager.setPrimaryClip(data)
// Notify users with Snackbar only on Android level 32 and lower, as 33 and higher notifies users by its own system
// way
if (!AndroidApiVersion.isAtLeastT) {
scope.launch {
snackbarHostState.showSnackbar(
message = context.getString(R.string.address_copied, textToCopy),
duration = SnackbarDuration.Short
)
}
}
}
object NavigationTargets {

View File

@ -13,6 +13,8 @@ import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
@ -41,11 +43,13 @@ import kotlinx.coroutines.flow.flow
fun Addresses(
synchronizer: Synchronizer,
copyToClipboard: (String, String) -> Unit,
onBack: () -> Unit
onBack: () -> Unit,
snackbarHostState: SnackbarHostState
) {
Scaffold(topBar = {
AddressesTopAppBar(onBack)
}) { paddingValues ->
Scaffold(
topBar = { AddressesTopAppBar(onBack) },
snackbarHost = { SnackbarHost(snackbarHostState) }
) { paddingValues ->
// TODO [#846]: Slow addresses providing
// TODO [#846]: https://github.com/zcash/zcash-android-wallet-sdk/issues/846
val walletAddresses = flow {

View File

@ -1,4 +1,4 @@
<resources>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Demo App</string>
<string name="navigation_drawer_open">Open navigation drawer</string>
<string name="navigation_drawer_close">Close navigation drawer</string>
@ -37,6 +37,8 @@
<string name="unified_address_tag">Zcash unified address</string>
<string name="sapling_address_tag">Zcash sapling address</string>
<string name="transparent_address_tag">Zcash transparent address</string>
<string name="address_copied" formatted="true"><xliff:g id="address" example="t1TdMMj5zzMtt...">Copied to
clipboard: %1$s</xliff:g></string>
<string name="configure_seed">Please select your wallet secret phrase</string>
<string name="person_alyssa">Alyssa P. Hacker</string>