feat: testnet clearing network data on delete and differentiating dialogs

This commit is contained in:
jubb
2021-06-18 16:01:34 +10:00
parent 11f64a1d1a
commit fdc042e6d4
15 changed files with 156 additions and 64 deletions

View File

@@ -42,12 +42,6 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
return TextSecurePreferences.getLocalNumber(context)
}
override fun getUserKeyPair(): Pair<String, ByteArray>? {
val userPublicKey = TextSecurePreferences.getLocalNumber(context) ?: return null
val userPrivateKey = IdentityKeyUtil.getIdentityKeyPair(context).privateKey.serialize()
return Pair(userPublicKey, userPrivateKey)
}
override fun getUserX25519KeyPair(): ECKeyPair {
return DatabaseFactory.getLokiAPIDatabase(context).getUserX25519KeyPair()
}

View File

@@ -92,6 +92,7 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
helpTranslateButton.setOnClickListener { helpTranslate() }
seedButton.setOnClickListener { showSeed() }
clearAllDataButton.setOnClickListener { clearAllData() }
clearAllDataAndNetworkButton.setOnClickListener { clearAllDataIncludingNetwork() }
versionTextView.text = String.format(getString(R.string.version_s), "${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})")
}
@@ -302,8 +303,13 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
}
private fun clearAllData() {
ClearAllDataDialog().show(supportFragmentManager, "Clear All Data Dialog")
ClearAllDataDialog(deleteNetworkMessages = false).show(supportFragmentManager, "Clear All Data Dialog")
}
private fun clearAllDataIncludingNetwork() {
ClearAllDataDialog(deleteNetworkMessages = true).show(supportFragmentManager, "Clear All Data Dialog")
}
// endregion
private inner class DisplayNameEditActionModeCallback: ActionMode.Callback {

View File

@@ -1,6 +1,7 @@
package org.thoughtcrime.securesms.loki.dialogs
import android.app.Dialog
import android.content.DialogInterface
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
@@ -11,22 +12,23 @@ import androidx.fragment.app.DialogFragment
import androidx.lifecycle.lifecycleScope
import kotlinx.android.synthetic.main.dialog_clear_all_data.*
import kotlinx.android.synthetic.main.dialog_clear_all_data.view.*
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.*
import network.loki.messenger.R
import nl.komponents.kovenant.Promise
import org.session.libsession.messaging.MessagingModuleConfiguration
import org.session.libsession.snode.SnodeAPI
import org.session.libsession.snode.SnodeDeleteMessage
import org.session.libsession.utilities.KeyPairUtilities
import org.session.libsignal.utilities.Log
import org.thoughtcrime.securesms.ApplicationContext
import org.thoughtcrime.securesms.loki.protocol.MultiDeviceProtocol
import java.util.concurrent.Executors
class ClearAllDataDialog : DialogFragment() {
class ClearAllDataDialog(val deleteNetworkMessages: Boolean) : DialogFragment() {
var clearJob: Job? = null
set(value) {
field = value
updateUI()
}
set(value) {
field = value
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val builder = AlertDialog.Builder(requireContext())
@@ -40,41 +42,73 @@ class ClearAllDataDialog : DialogFragment() {
return result
}
private fun updateUI() {
if (clearJob?.isActive == true) {
// clear background job is running, prevent interaction
dialog?.let { view ->
view.cancelButton.isVisible = false
view.clearAllDataButton.isVisible = false
}
} else {
dialog?.let { view ->
view.cancelButton.isVisible = false
view.clearAllDataButton.isVisible = false
}
override fun onDismiss(dialog: DialogInterface) {
super.onDismiss(dialog)
}
override fun onStart() {
super.onStart()
isCancelable = false
dialog?.setCanceledOnTouchOutside(false)
}
private fun updateUI(isLoading: Boolean) {
dialog?.let { view ->
view.cancelButton.isVisible = !isLoading
view.clearAllDataButton.isVisible = !isLoading
view.progressBar.isVisible = isLoading
}
}
private fun clearAllData() {
if (KeyPairUtilities.hasV2KeyPair(requireContext())) {
clearJob = lifecycleScope.launch {
delay(5_000)
// finish
val userPublicKey = MessagingModuleConfiguration.shared.storage.getUserPublicKey()
clearJob = lifecycleScope.launch(Dispatchers.IO) {
withContext(Dispatchers.Main) {
updateUI(true)
}
if (!deleteNetworkMessages) {
try {
MultiDeviceProtocol.forceSyncConfigurationNowIfNeeded(requireContext()).get()
ApplicationContext.getInstance(context).clearAllData(false)
withContext(Dispatchers.Main) {
dismiss()
}
} catch (e: Exception) {
Log.e("Loki", "Failed to force sync", e)
}
} else {
// finish
val promises = SnodeAPI.deleteAllMessages(requireContext()).get()
val deleteMessage = SnodeDeleteMessage(userKey, System.currentTimeMillis(), )
SnodeAPI.deleteAllMessages()
// TODO: re-add the clear data here
//ApplicationContext.getInstance(context).clearAllData(false)
val rawResponses = promises.map {
try {
it.get()
} catch (e: Exception) {
null
}
}
// TODO: process the responses here
if (rawResponses.any { it == null || it["failed"] as? Boolean == true }) {
// didn't succeed (at least one)
withContext(Dispatchers.Main) {
updateUI(false)
}
} else {
// don't force sync because all the messages are deleted?
ApplicationContext.getInstance(context).clearAllData(false)
withContext(Dispatchers.Main) {
dismiss()
}
}
}
}
} else {
val dialog = AlertDialog.Builder(requireContext())
val message = "Weve upgraded the way Session IDs are generated, so you will be unable to restore your current Session ID."
dialog.setMessage(message)
dialog.setPositiveButton("Yes") { _, _ ->
// TODO: re-add the clear data here
// ApplicationContext.getInstance(context).clearAllData(false)
ApplicationContext.getInstance(context).clearAllData(false)
}
dialog.setNegativeButton("Cancel") { _, _ ->
// Do nothing

View File

@@ -2,6 +2,7 @@ package org.thoughtcrime.securesms.loki.protocol
import android.content.Context
import com.google.protobuf.ByteString
import nl.komponents.kovenant.Promise
import org.session.libsession.messaging.MessagingModuleConfiguration
import org.session.libsession.messaging.messages.Destination
import org.session.libsession.messaging.messages.control.ConfigurationMessage
@@ -28,16 +29,17 @@ object MultiDeviceProtocol {
TextSecurePreferences.setLastConfigurationSyncTime(context, now)
}
fun forceSyncConfigurationNowIfNeeded(context: Context) {
val userPublicKey = TextSecurePreferences.getLocalNumber(context) ?: return
fun forceSyncConfigurationNowIfNeeded(context: Context): Promise<Unit, Exception> {
val userPublicKey = TextSecurePreferences.getLocalNumber(context) ?: return Promise.ofSuccess(Unit)
val contacts = ContactUtilities.getAllContacts(context).filter { recipient ->
!recipient.isGroupRecipient && !recipient.isBlocked && !recipient.name.isNullOrEmpty() && !recipient.isLocalNumber && recipient.address.serialize().isNotEmpty()
}.map { recipient ->
ConfigurationMessage.Contact(recipient.address.serialize(), recipient.name!!, recipient.profileAvatar, recipient.profileKey)
}
val configurationMessage = ConfigurationMessage.getCurrent(contacts) ?: return
MessageSender.send(configurationMessage, Destination.from(Address.fromSerialized(userPublicKey)))
val configurationMessage = ConfigurationMessage.getCurrent(contacts) ?: return Promise.ofSuccess(Unit)
val promise = MessageSender.send(configurationMessage, Destination.from(Address.fromSerialized(userPublicKey)))
TextSecurePreferences.setLastConfigurationSyncTime(context, System.currentTimeMillis())
return promise
}
}