mirror of
https://github.com/oxen-io/session-android.git
synced 2025-02-19 21:28:26 +00:00
Fix QR code scan & display
This commit is contained in:
parent
ff6c0fb6f5
commit
39c7f27c7d
@ -24,11 +24,11 @@ import org.thoughtcrime.securesms.crypto.KeyPairUtilities
|
||||
import org.thoughtcrime.securesms.dependencies.ConfigFactory
|
||||
|
||||
internal class PickDisplayNameViewModel(
|
||||
pickNewName: Boolean,
|
||||
private val loadFailed: Boolean,
|
||||
private val prefs: TextSecurePreferences,
|
||||
private val configFactory: ConfigFactory
|
||||
): ViewModel() {
|
||||
private val _states = MutableStateFlow(if (pickNewName) pickNewNameState() else State())
|
||||
private val _states = MutableStateFlow(if (loadFailed) pickNewNameState() else State())
|
||||
val states = _states.asStateFlow()
|
||||
|
||||
private val _events = MutableSharedFlow<Event>()
|
||||
@ -48,23 +48,25 @@ internal class PickDisplayNameViewModel(
|
||||
else -> {
|
||||
prefs.setProfileName(displayName)
|
||||
|
||||
// This is here to resolve a case where the app restarts before a user completes onboarding
|
||||
// which can result in an invalid database state
|
||||
database.clearAllLastMessageHashes()
|
||||
database.clearReceivedMessageHashValues()
|
||||
if (!loadFailed) {
|
||||
// This is here to resolve a case where the app restarts before a user completes onboarding
|
||||
// which can result in an invalid database state
|
||||
database.clearAllLastMessageHashes()
|
||||
database.clearReceivedMessageHashValues()
|
||||
|
||||
val keyPairGenerationResult = KeyPairUtilities.generate()
|
||||
val seed = keyPairGenerationResult.seed
|
||||
val ed25519KeyPair = keyPairGenerationResult.ed25519KeyPair
|
||||
val x25519KeyPair = keyPairGenerationResult.x25519KeyPair
|
||||
val keyPairGenerationResult = KeyPairUtilities.generate()
|
||||
val seed = keyPairGenerationResult.seed
|
||||
val ed25519KeyPair = keyPairGenerationResult.ed25519KeyPair
|
||||
val x25519KeyPair = keyPairGenerationResult.x25519KeyPair
|
||||
|
||||
KeyPairUtilities.store(context, seed, ed25519KeyPair, x25519KeyPair)
|
||||
configFactory.keyPairChanged()
|
||||
val userHexEncodedPublicKey = x25519KeyPair.hexEncodedPublicKey
|
||||
val registrationID = KeyHelper.generateRegistrationId(false)
|
||||
prefs.setLocalRegistrationId(registrationID)
|
||||
prefs.setLocalNumber(userHexEncodedPublicKey)
|
||||
prefs.setRestorationTime(0)
|
||||
KeyPairUtilities.store(context, seed, ed25519KeyPair, x25519KeyPair)
|
||||
configFactory.keyPairChanged()
|
||||
val userHexEncodedPublicKey = x25519KeyPair.hexEncodedPublicKey
|
||||
val registrationID = KeyHelper.generateRegistrationId(false)
|
||||
prefs.setLocalRegistrationId(registrationID)
|
||||
prefs.setLocalNumber(userHexEncodedPublicKey)
|
||||
prefs.setRestorationTime(0)
|
||||
}
|
||||
|
||||
viewModelScope.launch { _events.emit(Event.DONE) }
|
||||
}
|
||||
@ -82,18 +84,18 @@ internal class PickDisplayNameViewModel(
|
||||
|
||||
@dagger.assisted.AssistedFactory
|
||||
interface AssistedFactory {
|
||||
fun create(pickNewName: Boolean): Factory
|
||||
fun create(loadFailed: Boolean): Factory
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
class Factory @AssistedInject constructor(
|
||||
@Assisted private val pickNewName: Boolean,
|
||||
@Assisted private val loadFailed: Boolean,
|
||||
private val prefs: TextSecurePreferences,
|
||||
private val configFactory: ConfigFactory
|
||||
) : ViewModelProvider.Factory {
|
||||
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return PickDisplayNameViewModel(pickNewName, prefs, configFactory) as T
|
||||
return PickDisplayNameViewModel(loadFailed, prefs, configFactory) as T
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,8 +32,6 @@ import org.thoughtcrime.securesms.ui.SessionShieldIcon
|
||||
import org.thoughtcrime.securesms.ui.base
|
||||
import org.thoughtcrime.securesms.ui.color.Colors
|
||||
import org.thoughtcrime.securesms.ui.color.LocalColors
|
||||
import org.thoughtcrime.securesms.ui.components.ButtonStyle
|
||||
import org.thoughtcrime.securesms.ui.components.OutlineCopyButton
|
||||
import org.thoughtcrime.securesms.ui.components.QrImage
|
||||
import org.thoughtcrime.securesms.ui.components.SlimOutlineButton
|
||||
import org.thoughtcrime.securesms.ui.components.SlimOutlineCopyButton
|
||||
@ -44,7 +42,8 @@ import org.thoughtcrime.securesms.ui.h8
|
||||
|
||||
@Composable
|
||||
internal fun RecoveryPasswordScreen(
|
||||
seed: String = "",
|
||||
mnemonic: String,
|
||||
seed: String? = null,
|
||||
copySeed:() -> Unit = {},
|
||||
onHide:() -> Unit = {}
|
||||
) {
|
||||
@ -55,13 +54,17 @@ internal fun RecoveryPasswordScreen(
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(bottom = LocalDimensions.current.xsMargin)
|
||||
) {
|
||||
RecoveryPasswordCell(seed, copySeed)
|
||||
RecoveryPasswordCell(mnemonic, seed, copySeed)
|
||||
HideRecoveryPasswordCell(onHide)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun RecoveryPasswordCell(seed: String, copySeed:() -> Unit = {}) {
|
||||
private fun RecoveryPasswordCell(
|
||||
mnemonic: String,
|
||||
seed: String?,
|
||||
copySeed:() -> Unit = {}
|
||||
) {
|
||||
var showQr by remember {
|
||||
mutableStateOf(false)
|
||||
}
|
||||
@ -85,7 +88,7 @@ private fun RecoveryPasswordCell(seed: String, copySeed:() -> Unit = {}) {
|
||||
)
|
||||
|
||||
AnimatedVisibility(!showQr) {
|
||||
RecoveryPassword(seed)
|
||||
RecoveryPassword(mnemonic)
|
||||
}
|
||||
|
||||
AnimatedVisibility(
|
||||
@ -128,9 +131,9 @@ private fun RecoveryPasswordCell(seed: String, copySeed:() -> Unit = {}) {
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun RecoveryPassword(seed: String) {
|
||||
private fun RecoveryPassword(mnemonic: String) {
|
||||
Text(
|
||||
seed,
|
||||
mnemonic,
|
||||
modifier = Modifier
|
||||
.contentDescription(R.string.AccessibilityId_recovery_password_container)
|
||||
.padding(vertical = LocalDimensions.current.smallMargin)
|
||||
@ -178,6 +181,6 @@ private fun PreviewRecoveryPasswordScreen(
|
||||
@PreviewParameter(SessionColorsParameterProvider::class) colors: Colors
|
||||
) {
|
||||
PreviewTheme(colors) {
|
||||
RecoveryPasswordScreen(seed = "Voyage urban toyed maverick peculiar tuxedo penguin tree grass building listen speak withdraw terminal plane")
|
||||
RecoveryPasswordScreen(mnemonic = "voyage urban toyed maverick peculiar tuxedo penguin tree grass building listen speak withdraw terminal plane")
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,8 @@ package org.thoughtcrime.securesms.recoverypassword
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.activity.viewModels
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import network.loki.messenger.R
|
||||
import org.thoughtcrime.securesms.BaseActionBarActivity
|
||||
import org.thoughtcrime.securesms.showSessionDialog
|
||||
@ -16,10 +18,15 @@ class RecoveryPasswordActivity : BaseActionBarActivity() {
|
||||
supportActionBar!!.title = resources.getString(R.string.sessionRecoveryPassword)
|
||||
|
||||
setComposeContent {
|
||||
val mnemonic by viewModel.mnemonic.collectAsState("")
|
||||
val seed by viewModel.seed.collectAsState(null)
|
||||
|
||||
RecoveryPasswordScreen(
|
||||
viewModel.seed,
|
||||
{ viewModel.copySeed(this) }
|
||||
) { onHide() }
|
||||
mnemonic = mnemonic,
|
||||
seed = seed,
|
||||
copySeed = { viewModel.copySeed(this) },
|
||||
onHide = ::onHide
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,15 @@ import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.launch
|
||||
import org.session.libsession.utilities.AppTextSecurePreferences
|
||||
import org.session.libsession.utilities.TextSecurePreferences
|
||||
import org.session.libsignal.crypto.MnemonicCodec
|
||||
@ -20,21 +28,26 @@ class RecoveryPasswordViewModel @Inject constructor(
|
||||
): AndroidViewModel(application) {
|
||||
val prefs = AppTextSecurePreferences(application)
|
||||
|
||||
val seed = MutableStateFlow<String?>(null)
|
||||
val mnemonic = seed.filterNotNull()
|
||||
.map { MnemonicCodec { MnemonicUtilities.loadFileContents(application, it) }.encode(it, MnemonicCodec.Language.Configuration.english) }
|
||||
|
||||
fun permanentlyHidePassword() {
|
||||
prefs.setHidePassword(true)
|
||||
}
|
||||
|
||||
fun copySeed(context: Context) {
|
||||
val seed = seed.value ?: return
|
||||
TextSecurePreferences.setHasViewedSeed(context, true)
|
||||
val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
val clip = ClipData.newPlainText("Seed", seed)
|
||||
clipboard.setPrimaryClip(clip)
|
||||
}
|
||||
|
||||
val seed by lazy {
|
||||
val hexEncodedSeed = IdentityKeyUtil.retrieve(application, IdentityKeyUtil.LOKI_SEED)
|
||||
?: IdentityKeyUtil.getIdentityKeyPair(application).hexEncodedPrivateKey // Legacy account
|
||||
MnemonicCodec { MnemonicUtilities.loadFileContents(application, it) }
|
||||
.encode(hexEncodedSeed, MnemonicCodec.Language.Configuration.english)
|
||||
init {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
seed.emit(IdentityKeyUtil.retrieve(application, IdentityKeyUtil.LOKI_SEED)
|
||||
?: IdentityKeyUtil.getIdentityKeyPair(application).hexEncodedPrivateKey) // Legacy account
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ import org.thoughtcrime.securesms.util.QRCodeUtilities
|
||||
|
||||
@Composable
|
||||
fun QrImage(
|
||||
string: String,
|
||||
string: String?,
|
||||
modifier: Modifier = Modifier,
|
||||
icon: Int = R.drawable.session_shield
|
||||
) {
|
||||
@ -47,7 +47,7 @@ fun QrImage(
|
||||
|
||||
val scope = rememberCoroutineScope()
|
||||
LaunchedEffect(string) {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
if (string != null) scope.launch(Dispatchers.IO) {
|
||||
bitmap = (300..500 step 100).firstNotNullOf {
|
||||
runCatching { QRCodeUtilities.encode(string, it) }.getOrNull()
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user