mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-21 00:59:49 +01:00
Improve error reporting for SMS export.
This commit is contained in:
@@ -99,6 +99,7 @@ public abstract class MessageDatabase extends Database implements MmsSmsColumns,
|
||||
public abstract List<MessageRecord> getProfileChangeDetailsRecords(long threadId, long afterTimestamp);
|
||||
public abstract Set<Long> getAllRateLimitedMessageIds();
|
||||
public abstract Cursor getUnexportedInsecureMessages(int limit);
|
||||
public abstract long getUnexportedInsecureMessagesEstimatedSize();
|
||||
public abstract void deleteExportedMessages();
|
||||
|
||||
public abstract void markExpireStarted(long messageId);
|
||||
@@ -380,15 +381,15 @@ public abstract class MessageDatabase extends Database implements MmsSmsColumns,
|
||||
}
|
||||
|
||||
protected String getInsecureMessageClause(long threadId) {
|
||||
String isSent = "(" + getTypeField() + " & " + Types.BASE_TYPE_MASK + ") = " + Types.BASE_SENT_TYPE;
|
||||
String isReceived = "(" + getTypeField() + " & " + Types.BASE_TYPE_MASK + ") = " + Types.BASE_INBOX_TYPE;
|
||||
String isSecure = "(" + getTypeField() + " & " + (Types.SECURE_MESSAGE_BIT | Types.PUSH_MESSAGE_BIT) + ")";
|
||||
String isNotSecure = "(" + getTypeField() + " <= " + (Types.BASE_TYPE_MASK | Types.MESSAGE_ATTRIBUTE_MASK) + ")";
|
||||
String isSent = "(" + getTableName() + "." + getTypeField() + " & " + Types.BASE_TYPE_MASK + ") = " + Types.BASE_SENT_TYPE;
|
||||
String isReceived = "(" + getTableName() + "." + getTypeField() + " & " + Types.BASE_TYPE_MASK + ") = " + Types.BASE_INBOX_TYPE;
|
||||
String isSecure = "(" + getTableName() + "." + getTypeField() + " & " + (Types.SECURE_MESSAGE_BIT | Types.PUSH_MESSAGE_BIT) + ")";
|
||||
String isNotSecure = "(" + getTableName() + "." + getTypeField() + " <= " + (Types.BASE_TYPE_MASK | Types.MESSAGE_ATTRIBUTE_MASK) + ")";
|
||||
|
||||
String whereClause = String.format(Locale.ENGLISH, "(%s OR %s) AND NOT %s AND %s", isSent, isReceived, isSecure, isNotSecure);
|
||||
|
||||
if (threadId != -1) {
|
||||
whereClause += " AND " + THREAD_ID + " = " + threadId;
|
||||
whereClause += " AND " + getTableName() + "." + THREAD_ID + " = " + threadId;
|
||||
}
|
||||
|
||||
return whereClause;
|
||||
@@ -417,7 +418,7 @@ public abstract class MessageDatabase extends Database implements MmsSmsColumns,
|
||||
|
||||
SQLiteDatabaseExtensionsKt.update(getWritableDatabase(), getTableName())
|
||||
.values(values)
|
||||
.where(EXPORTED + " < ?", MessageExportStatus.UNEXPORTED.getCode())
|
||||
.where(EXPORTED + " < ?", MessageExportStatus.UNEXPORTED)
|
||||
.run();
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ import net.zetetic.database.sqlcipher.SQLiteStatement;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.signal.core.util.CursorExtensionsKt;
|
||||
import org.signal.core.util.CursorUtil;
|
||||
import org.signal.core.util.SQLiteDatabaseExtensionsKt;
|
||||
import org.signal.core.util.SqlUtil;
|
||||
@@ -2463,6 +2464,24 @@ public class MmsDatabase extends MessageDatabase {
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getUnexportedInsecureMessagesEstimatedSize() {
|
||||
Cursor messageTextSize = SQLiteDatabaseExtensionsKt.select(getReadableDatabase(), "SUM(LENGTH(" + BODY + "))")
|
||||
.from(TABLE_NAME)
|
||||
.where(getInsecureMessageClause() + " AND " + EXPORTED + " < ?", MessageExportStatus.EXPORTED)
|
||||
.run();
|
||||
|
||||
long bodyTextSize = CursorExtensionsKt.readToSingleLong(messageTextSize);
|
||||
|
||||
String select = "SUM(" + AttachmentDatabase.TABLE_NAME + "." + AttachmentDatabase.SIZE + ") AS s";
|
||||
String fromJoin = TABLE_NAME + " INNER JOIN " + AttachmentDatabase.TABLE_NAME + " ON " + TABLE_NAME + "." + ID + " = " + AttachmentDatabase.TABLE_NAME + "." + AttachmentDatabase.MMS_ID;
|
||||
String where = getInsecureMessageClause() + " AND " + EXPORTED + " < " + MessageExportStatus.EXPORTED.serialize();
|
||||
|
||||
long fileSize = CursorExtensionsKt.readToSingleLong(getReadableDatabase().rawQuery("SELECT " + select + " FROM " + fromJoin + " WHERE " + where, null));
|
||||
|
||||
return bodyTextSize + fileSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteExportedMessages() {
|
||||
beginTransaction();
|
||||
|
||||
@@ -33,11 +33,13 @@ import com.google.protobuf.InvalidProtocolBufferException;
|
||||
|
||||
import net.zetetic.database.sqlcipher.SQLiteStatement;
|
||||
|
||||
import org.signal.core.util.CursorExtensionsKt;
|
||||
import org.signal.core.util.CursorUtil;
|
||||
import org.signal.core.util.SQLiteDatabaseExtensionsKt;
|
||||
import org.signal.core.util.SqlUtil;
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.signal.libsignal.protocol.util.Pair;
|
||||
import org.thoughtcrime.securesms.components.settings.app.chats.sms.SmsExportState;
|
||||
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
|
||||
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatchSet;
|
||||
import org.thoughtcrime.securesms.database.documents.NetworkFailure;
|
||||
@@ -921,6 +923,16 @@ public class SmsDatabase extends MessageDatabase {
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getUnexportedInsecureMessagesEstimatedSize() {
|
||||
Cursor cursor = SQLiteDatabaseExtensionsKt.select(getReadableDatabase(), "SUM(LENGTH(" + BODY + "))")
|
||||
.from(TABLE_NAME)
|
||||
.where(getInsecureMessageClause() + " AND " + EXPORTED + " < ?", MessageExportStatus.EXPORTED)
|
||||
.run();
|
||||
|
||||
return CursorExtensionsKt.readToSingleLong(cursor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteExportedMessages() {
|
||||
beginTransaction();
|
||||
|
||||
@@ -6,6 +6,7 @@ import androidx.fragment.app.Fragment
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.navigation.fragment.navArgs
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.SmsExportDirections
|
||||
import org.thoughtcrime.securesms.databinding.ExportSmsCompleteFragmentBinding
|
||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
|
||||
@@ -20,7 +21,7 @@ class ExportSmsCompleteFragment : Fragment(R.layout.export_sms_complete_fragment
|
||||
val exportSuccessCount = args.exportMessageCount - args.exportMessageFailureCount
|
||||
|
||||
val binding = ExportSmsCompleteFragmentBinding.bind(view)
|
||||
binding.exportCompleteNext.setOnClickListener { findNavController().safeNavigate(ExportSmsCompleteFragmentDirections.actionExportingSmsMessagesFragmentToChooseANewDefaultSmsAppFragment()) }
|
||||
binding.exportCompleteNext.setOnClickListener { findNavController().safeNavigate(SmsExportDirections.actionDirectToChooseANewDefaultSmsAppFragment()) }
|
||||
binding.exportCompleteStatus.text = resources.getQuantityString(R.plurals.ExportSmsCompleteFragment__d_of_d_messages_exported, args.exportMessageCount, exportSuccessCount, args.exportMessageCount)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
package org.thoughtcrime.securesms.exporter.flow
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.view.ContextThemeWrapper
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.navigation.fragment.navArgs
|
||||
import org.thoughtcrime.securesms.LoggingFragment
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.SmsExportDirections
|
||||
import org.thoughtcrime.securesms.databinding.ExportSmsFullErrorFragmentBinding
|
||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
|
||||
/**
|
||||
* Fragment shown when all export messages failed.
|
||||
*/
|
||||
class ExportSmsFullErrorFragment : LoggingFragment(R.layout.export_sms_full_error_fragment) {
|
||||
private val args: ExportSmsFullErrorFragmentArgs by navArgs()
|
||||
|
||||
override fun onGetLayoutInflater(savedInstanceState: Bundle?): LayoutInflater {
|
||||
val inflater = super.onGetLayoutInflater(savedInstanceState)
|
||||
val contextThemeWrapper: Context = ContextThemeWrapper(requireContext(), R.style.Signal_DayNight)
|
||||
return inflater.cloneInContext(contextThemeWrapper)
|
||||
}
|
||||
|
||||
@Suppress("UsePropertyAccessSyntax")
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
val binding = ExportSmsFullErrorFragmentBinding.bind(view)
|
||||
|
||||
val exportSuccessCount = args.exportMessageCount - args.exportMessageFailureCount
|
||||
binding.exportCompleteStatus.text = resources.getQuantityString(R.plurals.ExportSmsCompleteFragment__d_of_d_messages_exported, args.exportMessageCount, exportSuccessCount, args.exportMessageCount)
|
||||
binding.retryButton.setOnClickListener { findNavController().safeNavigate(SmsExportDirections.actionDirectToExportYourSmsMessagesFragment()) }
|
||||
binding.pleaseTryAgain.apply {
|
||||
setLinkColor(ContextCompat.getColor(requireContext(), R.color.signal_colorPrimary))
|
||||
setLearnMoreVisible(true, R.string.ExportSmsPartiallyComplete__contact_us)
|
||||
setOnLinkClickListener {
|
||||
findNavController().safeNavigate(SmsExportDirections.actionDirectToHelpFragment())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package org.thoughtcrime.securesms.exporter.flow
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.text.format.Formatter
|
||||
import android.view.ContextThemeWrapper
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.navigation.fragment.navArgs
|
||||
import org.signal.core.util.concurrent.SimpleTask
|
||||
import org.thoughtcrime.securesms.LoggingFragment
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.SmsExportDirections
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.databinding.ExportSmsPartiallyCompleteFragmentBinding
|
||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
|
||||
/**
|
||||
* Fragment shown when some messages exported and some failed.
|
||||
*/
|
||||
class ExportSmsPartiallyCompleteFragment : LoggingFragment(R.layout.export_sms_partially_complete_fragment) {
|
||||
|
||||
private val args: ExportSmsPartiallyCompleteFragmentArgs by navArgs()
|
||||
|
||||
override fun onGetLayoutInflater(savedInstanceState: Bundle?): LayoutInflater {
|
||||
val inflater = super.onGetLayoutInflater(savedInstanceState)
|
||||
val contextThemeWrapper: Context = ContextThemeWrapper(requireContext(), R.style.Signal_DayNight)
|
||||
return inflater.cloneInContext(contextThemeWrapper)
|
||||
}
|
||||
|
||||
@Suppress("UsePropertyAccessSyntax")
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
val binding = ExportSmsPartiallyCompleteFragmentBinding.bind(view)
|
||||
|
||||
val exportSuccessCount = args.exportMessageCount - args.exportMessageFailureCount
|
||||
binding.exportCompleteStatus.text = resources.getQuantityString(R.plurals.ExportSmsCompleteFragment__d_of_d_messages_exported, args.exportMessageCount, exportSuccessCount, args.exportMessageCount)
|
||||
binding.retryButton.setOnClickListener { findNavController().safeNavigate(SmsExportDirections.actionDirectToExportYourSmsMessagesFragment()) }
|
||||
binding.continueButton.setOnClickListener { findNavController().safeNavigate(SmsExportDirections.actionDirectToChooseANewDefaultSmsAppFragment()) }
|
||||
binding.bullet3Text.apply {
|
||||
setLinkColor(ContextCompat.getColor(requireContext(), R.color.signal_colorPrimary))
|
||||
setLearnMoreVisible(true, R.string.ExportSmsPartiallyComplete__contact_us)
|
||||
setOnLinkClickListener {
|
||||
findNavController().safeNavigate(SmsExportDirections.actionDirectToHelpFragment())
|
||||
}
|
||||
}
|
||||
|
||||
SimpleTask.runWhenValid(
|
||||
viewLifecycleOwner.lifecycle,
|
||||
{ SignalDatabase.sms.getUnexportedInsecureMessagesEstimatedSize() + SignalDatabase.mms.getUnexportedInsecureMessagesEstimatedSize() },
|
||||
{ totalSize ->
|
||||
binding.bullet1Text.setText(getString(R.string.ExportSmsPartiallyComplete__ensure_you_have_an_additional_s_free_on_your_phone_to_export_your_messages, Formatter.formatFileSize(requireContext(), totalSize)))
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,6 @@ import org.signal.smsexporter.DefaultSmsHelper
|
||||
import org.signal.smsexporter.SmsExportProgress
|
||||
import org.signal.smsexporter.SmsExportService
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.SmsExportDirections
|
||||
import org.thoughtcrime.securesms.databinding.ExportYourSmsMessagesFragmentBinding
|
||||
import org.thoughtcrime.securesms.util.Material3OnScrollHelper
|
||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
@@ -46,9 +45,7 @@ class ExportYourSmsMessagesFragment : Fragment(R.layout.export_your_sms_messages
|
||||
.progressState
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe {
|
||||
if (it is SmsExportProgress.Done) {
|
||||
findNavController().safeNavigate(SmsExportDirections.actionDirectToExportSmsCompleteFragment(it.errorCount, it.total))
|
||||
} else if (it is SmsExportProgress.InProgress) {
|
||||
if (it !is SmsExportProgress.Init) {
|
||||
findNavController().safeNavigate(ExportYourSmsMessagesFragmentDirections.actionExportYourSmsMessagesFragmentToExportingSmsMessagesFragment())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,13 @@ package org.thoughtcrime.securesms.exporter.flow
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.text.format.Formatter
|
||||
import android.view.ContextThemeWrapper
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.rxjava3.disposables.Disposable
|
||||
import org.signal.smsexporter.SmsExportProgress
|
||||
@@ -15,6 +17,7 @@ import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.databinding.ExportingSmsMessagesFragmentBinding
|
||||
import org.thoughtcrime.securesms.exporter.SignalSmsExportService
|
||||
import org.thoughtcrime.securesms.util.LifecycleDisposable
|
||||
import org.thoughtcrime.securesms.util.mb
|
||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
|
||||
/**
|
||||
@@ -32,14 +35,22 @@ class ExportingSmsMessagesFragment : Fragment(R.layout.exporting_sms_messages_fr
|
||||
return inflater.cloneInContext(contextThemeWrapper)
|
||||
}
|
||||
|
||||
@Suppress("KotlinConstantConditions")
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
navigationDisposable = SmsExportService
|
||||
.progressState
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe {
|
||||
if (it is SmsExportProgress.Done) {
|
||||
findNavController().safeNavigate(ExportingSmsMessagesFragmentDirections.actionExportingSmsMessagesFragmentToExportSmsCompleteFragment(it.total, it.errorCount))
|
||||
.subscribe { smsExportProgress ->
|
||||
if (smsExportProgress is SmsExportProgress.Done) {
|
||||
SmsExportService.clearProgressState()
|
||||
if (smsExportProgress.errorCount == 0) {
|
||||
findNavController().safeNavigate(ExportingSmsMessagesFragmentDirections.actionExportingSmsMessagesFragmentToExportSmsCompleteFragment(smsExportProgress.total, smsExportProgress.errorCount))
|
||||
} else if (smsExportProgress.errorCount == smsExportProgress.total) {
|
||||
findNavController().safeNavigate(ExportingSmsMessagesFragmentDirections.actionExportingSmsMessagesFragmentToExportSmsFullErrorFragment(smsExportProgress.total, smsExportProgress.errorCount))
|
||||
} else {
|
||||
findNavController().safeNavigate(ExportingSmsMessagesFragmentDirections.actionExportingSmsMessagesFragmentToExportSmsPartiallyCompleteFragment(smsExportProgress.total, smsExportProgress.errorCount))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -55,18 +66,34 @@ class ExportingSmsMessagesFragment : Fragment(R.layout.exporting_sms_messages_fr
|
||||
lifecycleDisposable.bindTo(viewLifecycleOwner)
|
||||
lifecycleDisposable += SmsExportService.progressState.observeOn(AndroidSchedulers.mainThread()).subscribe {
|
||||
when (it) {
|
||||
is SmsExportProgress.Done -> Unit
|
||||
SmsExportProgress.Init -> binding.progress.isIndeterminate = true
|
||||
SmsExportProgress.Starting -> binding.progress.isIndeterminate = true
|
||||
is SmsExportProgress.InProgress -> {
|
||||
binding.progress.isIndeterminate = false
|
||||
binding.progress.max = it.total
|
||||
binding.progress.progress = it.progress
|
||||
binding.progressLabel.text = resources.getQuantityString(R.plurals.ExportingSmsMessagesFragment__exporting_d_of_d, it.total, it.progress, it.total)
|
||||
}
|
||||
SmsExportProgress.Init -> binding.progress.isIndeterminate = true
|
||||
SmsExportProgress.Starting -> binding.progress.isIndeterminate = true
|
||||
is SmsExportProgress.Done -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
SignalSmsExportService.start(requireContext())
|
||||
lifecycleDisposable += ExportingSmsRepository()
|
||||
.getSmsExportSizeEstimations()
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe { (internalFreeSpace, estimatedRequiredSpace) ->
|
||||
val adjustedFreeSpace = internalFreeSpace - estimatedRequiredSpace - 100.mb
|
||||
if (estimatedRequiredSpace > adjustedFreeSpace) {
|
||||
MaterialAlertDialogBuilder(requireContext())
|
||||
.setTitle(R.string.ExportingSmsMessagesFragment__you_may_not_have_enough_disk_space)
|
||||
.setMessage(getString(R.string.ExportingSmsMessagesFragment__you_need_approximately_s_to_export_your_messages_ensure_you_have_enough_space_before_continuing, Formatter.formatFileSize(requireContext(), estimatedRequiredSpace)))
|
||||
.setPositiveButton(R.string.ExportingSmsMessagesFragment__continue_anyway) { _, _ -> SignalSmsExportService.start(requireContext()) }
|
||||
.setNegativeButton(android.R.string.cancel) { _, _ -> findNavController().safeNavigate(ExportingSmsMessagesFragmentDirections.actionDirectToExportYourSmsMessagesFragment()) }
|
||||
.setCancelable(false)
|
||||
.show()
|
||||
} else {
|
||||
SignalSmsExportService.start(requireContext())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package org.thoughtcrime.securesms.exporter.flow
|
||||
|
||||
import android.app.Application
|
||||
import android.os.Build
|
||||
import android.os.storage.StorageManager
|
||||
import androidx.core.content.ContextCompat
|
||||
import io.reactivex.rxjava3.core.Single
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
||||
import java.io.File
|
||||
|
||||
class ExportingSmsRepository(private val context: Application = ApplicationDependencies.getApplication()) {
|
||||
|
||||
@Suppress("UsePropertyAccessSyntax")
|
||||
fun getSmsExportSizeEstimations(): Single<SmsExportSizeEstimations> {
|
||||
return Single.fromCallable {
|
||||
val internalStorageFile = if (Build.VERSION.SDK_INT < 24) {
|
||||
File(context.applicationInfo.dataDir)
|
||||
} else {
|
||||
context.dataDir
|
||||
}
|
||||
|
||||
val internalFreeSpace: Long = if (Build.VERSION.SDK_INT < 26) {
|
||||
internalStorageFile.usableSpace
|
||||
} else {
|
||||
val storageManagerFreeSpace = ContextCompat.getSystemService(context, StorageManager::class.java)?.let { storageManager ->
|
||||
storageManager.getAllocatableBytes(storageManager.getUuidForPath(internalStorageFile))
|
||||
}
|
||||
storageManagerFreeSpace ?: internalStorageFile.usableSpace
|
||||
}
|
||||
|
||||
SmsExportSizeEstimations(internalFreeSpace, SignalDatabase.sms.getUnexportedInsecureMessagesEstimatedSize() + SignalDatabase.mms.getUnexportedInsecureMessagesEstimatedSize())
|
||||
}.subscribeOn(Schedulers.io())
|
||||
}
|
||||
|
||||
data class SmsExportSizeEstimations(val estimatedInternalFreeSpace: Long, val estimatedRequiredSpace: Long)
|
||||
}
|
||||
@@ -2,8 +2,11 @@ package org.thoughtcrime.securesms.exporter.flow
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.navigation.findNavController
|
||||
import androidx.navigation.fragment.NavHostFragment
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.FragmentWrapperActivity
|
||||
@@ -18,10 +21,23 @@ class SmsExportActivity : FragmentWrapperActivity() {
|
||||
NotificationManagerCompat.from(this).cancel(NotificationIds.SMS_EXPORT_COMPLETE)
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?, ready: Boolean) {
|
||||
super.onCreate(savedInstanceState, ready)
|
||||
onBackPressedDispatcher.addCallback(this, OnBackPressed())
|
||||
}
|
||||
|
||||
override fun getFragment(): Fragment {
|
||||
return NavHostFragment.create(R.navigation.sms_export)
|
||||
}
|
||||
|
||||
private inner class OnBackPressed : OnBackPressedCallback(true) {
|
||||
override fun handleOnBackPressed() {
|
||||
if (!findNavController(R.id.fragment_container).popBackStack()) {
|
||||
finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun createIntent(context: Context): Intent = Intent(context, SmsExportActivity::class.java)
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package org.thoughtcrime.securesms.exporter.flow
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import org.thoughtcrime.securesms.LoggingFragment
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.databinding.SmsExportHelpFragmentBinding
|
||||
import org.thoughtcrime.securesms.help.HelpFragment
|
||||
|
||||
/**
|
||||
* Fragment wrapper around the app settings help fragment to provide a toolbar and set default category for sms export.
|
||||
*/
|
||||
class SmsExportHelpFragment : LoggingFragment(R.layout.sms_export_help_fragment) {
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
val binding = SmsExportHelpFragmentBinding.bind(view)
|
||||
|
||||
binding.toolbar.setOnClickListener {
|
||||
if (!findNavController().popBackStack()) {
|
||||
requireActivity().finish()
|
||||
}
|
||||
}
|
||||
|
||||
childFragmentManager
|
||||
.beginTransaction()
|
||||
.replace(binding.smsExportHelpFragmentFragment.id, HelpFragment().apply { arguments = bundleOf(HelpFragment.START_CATEGORY_INDEX to HelpFragment.SMS_EXPORT_INDEX) })
|
||||
.commitNow()
|
||||
}
|
||||
}
|
||||
@@ -40,6 +40,7 @@ public class HelpFragment extends LoggingFragment {
|
||||
public static final String START_CATEGORY_INDEX = "start_category_index";
|
||||
public static final int PAYMENT_INDEX = 6;
|
||||
public static final int DONATION_INDEX = 7;
|
||||
public static final int SMS_EXPORT_INDEX = 8;
|
||||
|
||||
private EditText problem;
|
||||
private CheckBox includeDebugLogs;
|
||||
@@ -93,7 +94,7 @@ public class HelpFragment extends LoggingFragment {
|
||||
emoji.add(view.findViewById(feeling.getViewId()));
|
||||
}
|
||||
|
||||
categoryAdapter = ArrayAdapter.createFromResource(requireContext(), R.array.HelpFragment__categories_4, android.R.layout.simple_spinner_item);
|
||||
categoryAdapter = ArrayAdapter.createFromResource(requireContext(), R.array.HelpFragment__categories_5, android.R.layout.simple_spinner_item);
|
||||
categoryAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
|
||||
categorySpinner.setAdapter(categoryAdapter);
|
||||
@@ -209,7 +210,7 @@ public class HelpFragment extends LoggingFragment {
|
||||
suffix.append(getString(feeling.getStringId()));
|
||||
}
|
||||
|
||||
String[] englishCategories = ResourceUtil.getEnglishResources(requireContext()).getStringArray(R.array.HelpFragment__categories_4);
|
||||
String[] englishCategories = ResourceUtil.getEnglishResources(requireContext()).getStringArray(R.array.HelpFragment__categories_5);
|
||||
String category = (helpViewModel.getCategoryIndex() >= 0 && helpViewModel.getCategoryIndex() < englishCategories.length) ? englishCategories[helpViewModel.getCategoryIndex()]
|
||||
: categoryAdapter.getItem(helpViewModel.getCategoryIndex()).toString();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user