136 lines
4.8 KiB
Kotlin
136 lines
4.8 KiB
Kotlin
@file:Suppress("ktlint:standard:filename")
|
|
|
|
package co.electriccoin.zcash.ui.screen.receive
|
|
|
|
import android.content.Context
|
|
import android.graphics.Bitmap
|
|
import androidx.activity.ComponentActivity
|
|
import androidx.activity.viewModels
|
|
import androidx.compose.material3.SnackbarHostState
|
|
import androidx.compose.runtime.Composable
|
|
import androidx.compose.runtime.remember
|
|
import androidx.compose.runtime.rememberCoroutineScope
|
|
import androidx.compose.ui.graphics.asAndroidBitmap
|
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
|
import co.electriccoin.zcash.spackle.ClipboardManagerUtil
|
|
import co.electriccoin.zcash.spackle.Twig
|
|
import co.electriccoin.zcash.spackle.getInternalCacheDirSuspend
|
|
import co.electriccoin.zcash.ui.R
|
|
import co.electriccoin.zcash.ui.common.model.VersionInfo
|
|
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
|
|
import co.electriccoin.zcash.ui.screen.receive.view.Receive
|
|
import co.electriccoin.zcash.ui.util.FileShareUtil
|
|
import kotlinx.coroutines.Dispatchers
|
|
import kotlinx.coroutines.channels.awaitClose
|
|
import kotlinx.coroutines.flow.Flow
|
|
import kotlinx.coroutines.flow.callbackFlow
|
|
import kotlinx.coroutines.launch
|
|
import kotlinx.coroutines.withContext
|
|
import java.io.File
|
|
|
|
@Composable
|
|
internal fun WrapReceive(
|
|
activity: ComponentActivity,
|
|
onSettings: () -> Unit,
|
|
) {
|
|
val viewModel by activity.viewModels<WalletViewModel>()
|
|
val walletAddresses = viewModel.addresses.collectAsStateWithLifecycle().value
|
|
|
|
val snackbarHostState = remember { SnackbarHostState() }
|
|
val scope = rememberCoroutineScope()
|
|
|
|
val versionInfo = VersionInfo.new(activity.applicationContext)
|
|
|
|
Receive(
|
|
walletAddress = walletAddresses,
|
|
snackbarHostState = snackbarHostState,
|
|
onAdjustBrightness = { /* Just for testing purposes */ },
|
|
onAddrCopyToClipboard = { address ->
|
|
ClipboardManagerUtil.copyToClipboard(
|
|
activity.applicationContext,
|
|
activity.getString(R.string.receive_clipboard_tag),
|
|
address
|
|
)
|
|
},
|
|
onQrImageShare = { imageBitmap ->
|
|
scope.launch {
|
|
shareData(
|
|
context = activity.applicationContext,
|
|
snackbarHostState = snackbarHostState,
|
|
qrImageBitmap = imageBitmap.asAndroidBitmap(),
|
|
versionInfo = versionInfo
|
|
).collect { shareResult ->
|
|
Twig.info {
|
|
if (shareResult) {
|
|
"Sharing the address QR code was successful"
|
|
} else {
|
|
"Sharing the address QR code failed"
|
|
}
|
|
}
|
|
// No other action for now
|
|
}
|
|
}
|
|
},
|
|
onSettings = onSettings,
|
|
versionInfo = versionInfo
|
|
)
|
|
}
|
|
|
|
private const val CACHE_SUBDIR = "zcash_address_qr_images" // NON-NLS
|
|
private const val TEMP_FILE_NAME_PREFIX = "zcash_address_qr_" // NON-NLS
|
|
private const val TEMP_FILE_NAME_SUFFIX = ".png" // NON-NLS
|
|
|
|
fun shareData(
|
|
context: Context,
|
|
snackbarHostState: SnackbarHostState,
|
|
qrImageBitmap: Bitmap,
|
|
versionInfo: VersionInfo
|
|
): Flow<Boolean> =
|
|
callbackFlow {
|
|
// Initialize cache directory
|
|
val cacheDir = context.getInternalCacheDirSuspend(CACHE_SUBDIR)
|
|
|
|
// Save the bitmap to a temporary file in the cache directory
|
|
val bitmapFile =
|
|
withContext(Dispatchers.IO) {
|
|
File.createTempFile(
|
|
TEMP_FILE_NAME_PREFIX,
|
|
TEMP_FILE_NAME_SUFFIX,
|
|
cacheDir,
|
|
).also {
|
|
it.storeBitmap(qrImageBitmap)
|
|
}
|
|
}
|
|
|
|
// Example of the expected temporary file path:
|
|
// /data/user/0/co.electriccoin.zcash.debug/cache/zcash_address_qr_images/
|
|
// zcash_address_qr_6455164324646067652.png
|
|
|
|
val shareIntent =
|
|
FileShareUtil.newShareContentIntent(
|
|
context = context,
|
|
dataFilePath = bitmapFile.absolutePath,
|
|
versionInfo = versionInfo,
|
|
fileType = FileShareUtil.ZASHI_QR_CODE_MIME_TYPE
|
|
)
|
|
runCatching {
|
|
context.startActivity(shareIntent)
|
|
trySend(true)
|
|
}.onFailure {
|
|
snackbarHostState.showSnackbar(message = context.getString(R.string.receive_data_unable_to_share))
|
|
trySend(false)
|
|
}
|
|
awaitClose {
|
|
// No resources to release
|
|
}
|
|
}
|
|
|
|
suspend fun File.storeBitmap(bitmap: Bitmap) =
|
|
withContext(Dispatchers.IO) {
|
|
outputStream().use { fOut ->
|
|
@Suppress("MagicNumber")
|
|
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fOut)
|
|
fOut.flush()
|
|
}
|
|
}
|