Add test restore flow to staging reg.

This commit is contained in:
Clark 2024-03-08 16:27:39 -05:00 committed by Cody Henthorne
parent 9d46b52786
commit 742c348998
5 changed files with 218 additions and 1 deletions

View file

@ -216,6 +216,7 @@ android {
buildConfigField("String", "BADGE_STATIC_ROOT", "\"https://updates2.signal.org/static/badges/\"") buildConfigField("String", "BADGE_STATIC_ROOT", "\"https://updates2.signal.org/static/badges/\"")
buildConfigField("String", "STRIPE_PUBLISHABLE_KEY", "\"pk_live_6cmGZopuTsV8novGgJJW9JpC00vLIgtQ1D\"") buildConfigField("String", "STRIPE_PUBLISHABLE_KEY", "\"pk_live_6cmGZopuTsV8novGgJJW9JpC00vLIgtQ1D\"")
buildConfigField("boolean", "TRACING_ENABLED", "false") buildConfigField("boolean", "TRACING_ENABLED", "false")
buildConfigField("boolean", "MESSAGE_BACKUP_RESTORE_ENABLED", "false")
ndk { ndk {
abiFilters += listOf("armeabi-v7a", "arm64-v8a", "x86", "x86_64") abiFilters += listOf("armeabi-v7a", "arm64-v8a", "x86", "x86_64")
@ -390,6 +391,7 @@ android {
buildConfigField("String", "BUILD_ENVIRONMENT_TYPE", "\"Staging\"") buildConfigField("String", "BUILD_ENVIRONMENT_TYPE", "\"Staging\"")
buildConfigField("String", "STRIPE_PUBLISHABLE_KEY", "\"pk_test_sngOd8FnXNkpce9nPXawKrJD00kIDngZkD\"") buildConfigField("String", "STRIPE_PUBLISHABLE_KEY", "\"pk_test_sngOd8FnXNkpce9nPXawKrJD00kIDngZkD\"")
buildConfigField("boolean", "MESSAGE_BACKUP_RESTORE_ENABLED", "true")
} }
} }

View file

@ -961,6 +961,10 @@
android:windowSoftInputMode="stateVisible|adjustResize" android:windowSoftInputMode="stateVisible|adjustResize"
android:exported="false"/> android:exported="false"/>
<activity android:name=".backup.v2.ui.MessageBackupsTestRestoreActivity"
android:theme="@style/TextSecure.LightRegistrationTheme"
android:exported="false"/>
<activity android:name=".profiles.manage.EditProfileActivity" <activity android:name=".profiles.manage.EditProfileActivity"
android:theme="@style/TextSecure.LightTheme" android:theme="@style/TextSecure.LightTheme"
android:windowSoftInputMode="stateVisible|adjustResize" android:windowSoftInputMode="stateVisible|adjustResize"

View file

@ -0,0 +1,148 @@
/*
* Copyright 2024 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.backup.v2.ui
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.widget.Toast
import androidx.activity.compose.setContent
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import org.signal.core.ui.Buttons
import org.signal.core.ui.Dividers
import org.signal.core.util.getLength
import org.thoughtcrime.securesms.BaseActivity
import org.thoughtcrime.securesms.MainActivity
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
import org.thoughtcrime.securesms.jobs.ProfileUploadJob
import org.thoughtcrime.securesms.profiles.AvatarHelper
import org.thoughtcrime.securesms.profiles.edit.CreateProfileActivity
import org.thoughtcrime.securesms.recipients.Recipient
import org.thoughtcrime.securesms.registration.RegistrationUtil
class MessageBackupsTestRestoreActivity : BaseActivity() {
companion object {
fun getIntent(context: Context): Intent {
return Intent(context, MessageBackupsTestRestoreActivity::class.java)
}
}
private val viewModel: MessageBackupsTestRestoreViewModel by viewModels()
private lateinit var importFileLauncher: ActivityResultLauncher<Intent>
private fun onPlaintextClicked() {
viewModel.onPlaintextToggled()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
importFileLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == RESULT_OK) {
result.data?.data?.let { uri ->
contentResolver.getLength(uri)?.let { length ->
viewModel.import(length) { contentResolver.openInputStream(uri)!! }
}
} ?: Toast.makeText(this, "No URI selected", Toast.LENGTH_SHORT).show()
}
}
setContent {
val state by viewModel.state
Surface {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
modifier = Modifier
.fillMaxSize()
.padding(16.dp)
) {
Row(
verticalAlignment = Alignment.CenterVertically
) {
StateLabel(text = "Plaintext?")
Spacer(modifier = Modifier.width(8.dp))
Switch(
checked = state.plaintext,
onCheckedChange = { onPlaintextClicked() }
)
}
Spacer(modifier = Modifier.height(8.dp))
Buttons.LargePrimary(
onClick = {
val intent = Intent().apply {
action = Intent.ACTION_GET_CONTENT
type = "application/octet-stream"
addCategory(Intent.CATEGORY_OPENABLE)
}
importFileLauncher.launch(intent)
},
enabled = !state.importState.inProgress
) {
Text("Import from file")
}
Spacer(modifier = Modifier.height(8.dp))
Dividers.Default()
Buttons.LargeTonal(
onClick = { continueRegistration() },
enabled = !state.importState.inProgress
) {
Text("Continue Reg Flow")
}
}
}
}
}
private fun continueRegistration() {
if (Recipient.self().profileName.isEmpty || !AvatarHelper.hasAvatar(this, Recipient.self().id)) {
val main = MainActivity.clearTop(this)
val profile = CreateProfileActivity.getIntentForUserProfile(this)
profile.putExtra("next_intent", main)
startActivity(profile)
} else {
RegistrationUtil.maybeMarkRegistrationComplete()
ApplicationDependencies.getJobManager().add(ProfileUploadJob())
startActivity(MainActivity.clearTop(this))
}
finish()
}
@Composable
private fun StateLabel(text: String) {
Text(
text = text,
style = MaterialTheme.typography.labelSmall,
textAlign = TextAlign.Center
)
}
}

View file

@ -0,0 +1,59 @@
/*
* Copyright 2024 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.backup.v2.ui
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.core.Single
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import io.reactivex.rxjava3.kotlin.subscribeBy
import io.reactivex.rxjava3.schedulers.Schedulers
import org.signal.libsignal.zkgroup.profiles.ProfileKey
import org.thoughtcrime.securesms.backup.v2.BackupRepository
import org.thoughtcrime.securesms.recipients.Recipient
import java.io.InputStream
class MessageBackupsTestRestoreViewModel : ViewModel() {
val disposables = CompositeDisposable()
private val _state: MutableState<ScreenState> = mutableStateOf(ScreenState(importState = ImportState.NONE, plaintext = false))
val state: State<ScreenState> = _state
fun import(length: Long, inputStreamFactory: () -> InputStream) {
_state.value = _state.value.copy(importState = ImportState.IN_PROGRESS)
val self = Recipient.self()
val selfData = BackupRepository.SelfData(self.aci.get(), self.pni.get(), self.e164.get(), ProfileKey(self.profileKey))
disposables += Single.fromCallable { BackupRepository.import(length, inputStreamFactory, selfData, plaintext = _state.value.plaintext) }
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeBy {
_state.value = _state.value.copy(importState = ImportState.NONE)
}
}
fun onPlaintextToggled() {
_state.value = _state.value.copy(plaintext = !_state.value.plaintext)
}
override fun onCleared() {
disposables.clear()
}
data class ScreenState(
val importState: ImportState,
val plaintext: Boolean
)
enum class ImportState(val inProgress: Boolean = false) {
NONE, IN_PROGRESS(true)
}
}

View file

@ -23,9 +23,11 @@ import com.google.android.material.button.MaterialButton;
import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import org.signal.core.util.logging.Log; import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.BuildConfig;
import org.thoughtcrime.securesms.LoggingFragment; import org.thoughtcrime.securesms.LoggingFragment;
import org.thoughtcrime.securesms.MainActivity; import org.thoughtcrime.securesms.MainActivity;
import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.backup.v2.ui.MessageBackupsTestRestoreActivity;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.jobs.ProfileUploadJob; import org.thoughtcrime.securesms.jobs.ProfileUploadJob;
import org.thoughtcrime.securesms.keyvalue.SignalStore; import org.thoughtcrime.securesms.keyvalue.SignalStore;
@ -236,7 +238,9 @@ public class PinRestoreEntryFragment extends LoggingFragment {
Activity activity = requireActivity(); Activity activity = requireActivity();
if (Recipient.self().getProfileName().isEmpty() || !AvatarHelper.hasAvatar(activity, Recipient.self().getId())) { if (BuildConfig.MESSAGE_BACKUP_RESTORE_ENABLED) {
startActivity(MessageBackupsTestRestoreActivity.Companion.getIntent(activity));
} else if (Recipient.self().getProfileName().isEmpty() || !AvatarHelper.hasAvatar(activity, Recipient.self().getId())) {
final Intent main = MainActivity.clearTop(activity); final Intent main = MainActivity.clearTop(activity);
final Intent profile = CreateProfileActivity.getIntentForUserProfile(activity); final Intent profile = CreateProfileActivity.getIntentForUserProfile(activity);