mirror of
https://github.com/oxen-io/session-android.git
synced 2025-01-12 19:03:39 +00:00
Handle scan recovery phrase QR
This commit is contained in:
parent
2555b34d8e
commit
9e270c7ac0
@ -7,6 +7,8 @@ import android.os.Bundle
|
|||||||
import android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS
|
import android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
import androidx.camera.core.CameraSelector
|
import androidx.camera.core.CameraSelector
|
||||||
|
import androidx.camera.core.ExperimentalGetImage
|
||||||
|
import androidx.camera.core.ImageAnalysis
|
||||||
import androidx.camera.core.Preview
|
import androidx.camera.core.Preview
|
||||||
import androidx.camera.lifecycle.ProcessCameraProvider
|
import androidx.camera.lifecycle.ProcessCameraProvider
|
||||||
import androidx.camera.view.PreviewView
|
import androidx.camera.view.PreviewView
|
||||||
@ -59,19 +61,28 @@ import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
|||||||
import com.google.accompanist.permissions.isGranted
|
import com.google.accompanist.permissions.isGranted
|
||||||
import com.google.accompanist.permissions.rememberPermissionState
|
import com.google.accompanist.permissions.rememberPermissionState
|
||||||
import com.google.accompanist.permissions.shouldShowRationale
|
import com.google.accompanist.permissions.shouldShowRationale
|
||||||
|
import com.google.mlkit.vision.barcode.BarcodeScanner
|
||||||
|
import com.google.mlkit.vision.barcode.BarcodeScannerOptions
|
||||||
|
import com.google.mlkit.vision.barcode.BarcodeScanning
|
||||||
|
import com.google.mlkit.vision.barcode.common.Barcode
|
||||||
|
import com.google.mlkit.vision.common.InputImage
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
import org.session.libsession.utilities.TextSecurePreferences
|
import org.session.libsession.utilities.TextSecurePreferences
|
||||||
|
import org.session.libsignal.utilities.Log
|
||||||
import org.thoughtcrime.securesms.BaseActionBarActivity
|
import org.thoughtcrime.securesms.BaseActionBarActivity
|
||||||
import org.thoughtcrime.securesms.ui.AppTheme
|
import org.thoughtcrime.securesms.ui.AppTheme
|
||||||
import org.thoughtcrime.securesms.ui.OutlineButton
|
import org.thoughtcrime.securesms.ui.OutlineButton
|
||||||
import org.thoughtcrime.securesms.ui.baseBold
|
import org.thoughtcrime.securesms.ui.baseBold
|
||||||
import org.thoughtcrime.securesms.ui.colorDestructive
|
import org.thoughtcrime.securesms.ui.colorDestructive
|
||||||
|
import java.util.concurrent.Executors
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
private const val TAG = "LinkDeviceActivity"
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
|
@androidx.annotation.OptIn(ExperimentalGetImage::class)
|
||||||
class LinkDeviceActivity : BaseActionBarActivity() {
|
class LinkDeviceActivity : BaseActionBarActivity() {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@ -134,16 +145,20 @@ class LinkDeviceActivity : BaseActionBarActivity() {
|
|||||||
val localContext = LocalContext.current
|
val localContext = LocalContext.current
|
||||||
val cameraProvider = remember { ProcessCameraProvider.getInstance(localContext) }
|
val cameraProvider = remember { ProcessCameraProvider.getInstance(localContext) }
|
||||||
|
|
||||||
|
val options = BarcodeScannerOptions.Builder()
|
||||||
|
.setBarcodeFormats(Barcode.FORMAT_QR_CODE)
|
||||||
|
.build()
|
||||||
|
val scanner = BarcodeScanning.getClient(options)
|
||||||
|
|
||||||
runCatching {
|
runCatching {
|
||||||
when (title) {
|
when (title) {
|
||||||
R.string.activity_link_device_scan_qr_code -> {
|
R.string.activity_link_device_scan_qr_code -> {
|
||||||
cameraProvider.get().bindToLifecycle(LocalLifecycleOwner.current, selector, preview)
|
|
||||||
LocalSoftwareKeyboardController.current?.hide()
|
LocalSoftwareKeyboardController.current?.hide()
|
||||||
|
cameraProvider.get().bindToLifecycle(LocalLifecycleOwner.current, selector, preview, buildAnalysisUseCase(scanner, viewModel::onQrPhrase))
|
||||||
}
|
}
|
||||||
else -> cameraProvider.get().unbind(preview)
|
else -> cameraProvider.get().unbind(preview)
|
||||||
}
|
}
|
||||||
}
|
}.onFailure { Log.e(TAG, "error binding camera", it) }
|
||||||
|
|
||||||
when (title) {
|
when (title) {
|
||||||
R.string.activity_recovery_password -> RecoveryPassword(state, onChange, onContinue)
|
R.string.activity_recovery_password -> RecoveryPassword(state, onChange, onContinue)
|
||||||
R.string.activity_link_device_scan_qr_code -> MaybeScanQrCode()
|
R.string.activity_link_device_scan_qr_code -> MaybeScanQrCode()
|
||||||
@ -167,7 +182,7 @@ class LinkDeviceActivity : BaseActionBarActivity() {
|
|||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
"Camera Permission permanently denied. Configure in settings.",
|
"Camera Permission permanently denied. Configure in settings.",
|
||||||
textAlign = TextAlign.Center
|
textAlign = TextAlign.Center
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.size(20.dp))
|
Spacer(modifier = Modifier.size(20.dp))
|
||||||
OutlineButton(
|
OutlineButton(
|
||||||
@ -196,11 +211,7 @@ fun ScanQrCode(preview: Preview) {
|
|||||||
Box {
|
Box {
|
||||||
AndroidView(
|
AndroidView(
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
factory = { context ->
|
factory = { PreviewView(it).apply { preview.setSurfaceProvider(surfaceProvider) } }
|
||||||
PreviewView(context).apply {
|
|
||||||
preview.setSurfaceProvider(surfaceProvider)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
@ -270,3 +281,26 @@ fun RecoveryPassword(state: LinkDeviceState, onChange: (String) -> Unit = {}, on
|
|||||||
fun Context.startLinkDeviceActivity() {
|
fun Context.startLinkDeviceActivity() {
|
||||||
Intent(this, LinkDeviceActivity::class.java).let(::startActivity)
|
Intent(this, LinkDeviceActivity::class.java).let(::startActivity)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun buildAnalysisUseCase(
|
||||||
|
scanner: BarcodeScanner,
|
||||||
|
onBarcodeScanned: (String) -> Unit
|
||||||
|
): ImageAnalysis = ImageAnalysis.Builder()
|
||||||
|
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
|
||||||
|
.build().apply {
|
||||||
|
setAnalyzer(Executors.newSingleThreadExecutor()) { imageProxy ->
|
||||||
|
InputImage.fromMediaImage(
|
||||||
|
imageProxy.image!!,
|
||||||
|
imageProxy.imageInfo.rotationDegrees
|
||||||
|
).let(scanner::process).apply {
|
||||||
|
addOnSuccessListener { barcodes ->
|
||||||
|
barcodes.forEach {
|
||||||
|
it.takeIf { it.valueType == Barcode.TYPE_TEXT }?.rawValue?.let(onBarcodeScanned)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addOnCompleteListener {
|
||||||
|
imageProxy.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -30,7 +30,14 @@ class LinkDeviceViewModel @Inject constructor(
|
|||||||
|
|
||||||
fun onRecoveryPhrase() {
|
fun onRecoveryPhrase() {
|
||||||
val mnemonic = state.value.recoveryPhrase
|
val mnemonic = state.value.recoveryPhrase
|
||||||
|
tryPhrase(mnemonic)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onQrPhrase(string: String) {
|
||||||
|
tryPhrase(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun tryPhrase(mnemonic: String) {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
try {
|
try {
|
||||||
MnemonicCodec { MnemonicUtilities.loadFileContents(getApplication(), it) }
|
MnemonicCodec { MnemonicUtilities.loadFileContents(getApplication(), it) }
|
||||||
@ -39,10 +46,14 @@ class LinkDeviceViewModel @Inject constructor(
|
|||||||
.let(::LinkDeviceEvent)
|
.let(::LinkDeviceEvent)
|
||||||
.let { event.send(it) }
|
.let { event.send(it) }
|
||||||
} catch (exception: Exception) {
|
} catch (exception: Exception) {
|
||||||
when (exception) {
|
state.update {
|
||||||
is MnemonicCodec.DecodingError -> exception.description
|
it.copy(
|
||||||
else -> "An error occurred."
|
error = when (exception) {
|
||||||
}.let { error -> state.update { it.copy(error = error) } }
|
is MnemonicCodec.DecodingError -> exception.description
|
||||||
|
else -> "An error occurred."
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user