Improve error reporting for SMS export.

fork-5.53.8
Cody Henthorne 2022-10-19 22:11:31 -04:00 zatwierdzone przez GitHub
rodzic 262f762d7f
commit 690e1e60ba
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
33 zmienionych plików z 933 dodań i 95 usunięć

Wyświetl plik

@ -99,6 +99,7 @@ public abstract class MessageDatabase extends Database implements MmsSmsColumns,
public abstract List<MessageRecord> getProfileChangeDetailsRecords(long threadId, long afterTimestamp); public abstract List<MessageRecord> getProfileChangeDetailsRecords(long threadId, long afterTimestamp);
public abstract Set<Long> getAllRateLimitedMessageIds(); public abstract Set<Long> getAllRateLimitedMessageIds();
public abstract Cursor getUnexportedInsecureMessages(int limit); public abstract Cursor getUnexportedInsecureMessages(int limit);
public abstract long getUnexportedInsecureMessagesEstimatedSize();
public abstract void deleteExportedMessages(); public abstract void deleteExportedMessages();
public abstract void markExpireStarted(long messageId); public abstract void markExpireStarted(long messageId);
@ -380,15 +381,15 @@ public abstract class MessageDatabase extends Database implements MmsSmsColumns,
} }
protected String getInsecureMessageClause(long threadId) { protected String getInsecureMessageClause(long threadId) {
String isSent = "(" + getTypeField() + " & " + Types.BASE_TYPE_MASK + ") = " + Types.BASE_SENT_TYPE; String isSent = "(" + getTableName() + "." + getTypeField() + " & " + Types.BASE_TYPE_MASK + ") = " + Types.BASE_SENT_TYPE;
String isReceived = "(" + getTypeField() + " & " + Types.BASE_TYPE_MASK + ") = " + Types.BASE_INBOX_TYPE; String isReceived = "(" + getTableName() + "." + getTypeField() + " & " + Types.BASE_TYPE_MASK + ") = " + Types.BASE_INBOX_TYPE;
String isSecure = "(" + getTypeField() + " & " + (Types.SECURE_MESSAGE_BIT | Types.PUSH_MESSAGE_BIT) + ")"; String isSecure = "(" + getTableName() + "." + getTypeField() + " & " + (Types.SECURE_MESSAGE_BIT | Types.PUSH_MESSAGE_BIT) + ")";
String isNotSecure = "(" + getTypeField() + " <= " + (Types.BASE_TYPE_MASK | Types.MESSAGE_ATTRIBUTE_MASK) + ")"; 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); String whereClause = String.format(Locale.ENGLISH, "(%s OR %s) AND NOT %s AND %s", isSent, isReceived, isSecure, isNotSecure);
if (threadId != -1) { if (threadId != -1) {
whereClause += " AND " + THREAD_ID + " = " + threadId; whereClause += " AND " + getTableName() + "." + THREAD_ID + " = " + threadId;
} }
return whereClause; return whereClause;
@ -417,7 +418,7 @@ public abstract class MessageDatabase extends Database implements MmsSmsColumns,
SQLiteDatabaseExtensionsKt.update(getWritableDatabase(), getTableName()) SQLiteDatabaseExtensionsKt.update(getWritableDatabase(), getTableName())
.values(values) .values(values)
.where(EXPORTED + " < ?", MessageExportStatus.UNEXPORTED.getCode()) .where(EXPORTED + " < ?", MessageExportStatus.UNEXPORTED)
.run(); .run();
} }

Wyświetl plik

@ -36,6 +36,7 @@ import net.zetetic.database.sqlcipher.SQLiteStatement;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import org.signal.core.util.CursorExtensionsKt;
import org.signal.core.util.CursorUtil; import org.signal.core.util.CursorUtil;
import org.signal.core.util.SQLiteDatabaseExtensionsKt; import org.signal.core.util.SQLiteDatabaseExtensionsKt;
import org.signal.core.util.SqlUtil; 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 @Override
public void deleteExportedMessages() { public void deleteExportedMessages() {
beginTransaction(); beginTransaction();

Wyświetl plik

@ -33,11 +33,13 @@ import com.google.protobuf.InvalidProtocolBufferException;
import net.zetetic.database.sqlcipher.SQLiteStatement; import net.zetetic.database.sqlcipher.SQLiteStatement;
import org.signal.core.util.CursorExtensionsKt;
import org.signal.core.util.CursorUtil; import org.signal.core.util.CursorUtil;
import org.signal.core.util.SQLiteDatabaseExtensionsKt; import org.signal.core.util.SQLiteDatabaseExtensionsKt;
import org.signal.core.util.SqlUtil; import org.signal.core.util.SqlUtil;
import org.signal.core.util.logging.Log; import org.signal.core.util.logging.Log;
import org.signal.libsignal.protocol.util.Pair; 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.IdentityKeyMismatch;
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatchSet; import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatchSet;
import org.thoughtcrime.securesms.database.documents.NetworkFailure; 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 @Override
public void deleteExportedMessages() { public void deleteExportedMessages() {
beginTransaction(); beginTransaction();

Wyświetl plik

@ -6,6 +6,7 @@ import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs import androidx.navigation.fragment.navArgs
import org.thoughtcrime.securesms.R import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.SmsExportDirections
import org.thoughtcrime.securesms.databinding.ExportSmsCompleteFragmentBinding import org.thoughtcrime.securesms.databinding.ExportSmsCompleteFragmentBinding
import org.thoughtcrime.securesms.util.navigation.safeNavigate 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 exportSuccessCount = args.exportMessageCount - args.exportMessageFailureCount
val binding = ExportSmsCompleteFragmentBinding.bind(view) 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) binding.exportCompleteStatus.text = resources.getQuantityString(R.plurals.ExportSmsCompleteFragment__d_of_d_messages_exported, args.exportMessageCount, exportSuccessCount, args.exportMessageCount)
} }
} }

Wyświetl plik

@ -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())
}
}
}
}

Wyświetl plik

@ -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)))
}
)
}
}

Wyświetl plik

@ -10,7 +10,6 @@ import org.signal.smsexporter.DefaultSmsHelper
import org.signal.smsexporter.SmsExportProgress import org.signal.smsexporter.SmsExportProgress
import org.signal.smsexporter.SmsExportService import org.signal.smsexporter.SmsExportService
import org.thoughtcrime.securesms.R import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.SmsExportDirections
import org.thoughtcrime.securesms.databinding.ExportYourSmsMessagesFragmentBinding import org.thoughtcrime.securesms.databinding.ExportYourSmsMessagesFragmentBinding
import org.thoughtcrime.securesms.util.Material3OnScrollHelper import org.thoughtcrime.securesms.util.Material3OnScrollHelper
import org.thoughtcrime.securesms.util.navigation.safeNavigate import org.thoughtcrime.securesms.util.navigation.safeNavigate
@ -46,9 +45,7 @@ class ExportYourSmsMessagesFragment : Fragment(R.layout.export_your_sms_messages
.progressState .progressState
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe { .subscribe {
if (it is SmsExportProgress.Done) { if (it !is SmsExportProgress.Init) {
findNavController().safeNavigate(SmsExportDirections.actionDirectToExportSmsCompleteFragment(it.errorCount, it.total))
} else if (it is SmsExportProgress.InProgress) {
findNavController().safeNavigate(ExportYourSmsMessagesFragmentDirections.actionExportYourSmsMessagesFragmentToExportingSmsMessagesFragment()) findNavController().safeNavigate(ExportYourSmsMessagesFragmentDirections.actionExportYourSmsMessagesFragmentToExportingSmsMessagesFragment())
} }
} }

Wyświetl plik

@ -2,11 +2,13 @@ package org.thoughtcrime.securesms.exporter.flow
import android.content.Context import android.content.Context
import android.os.Bundle import android.os.Bundle
import android.text.format.Formatter
import android.view.ContextThemeWrapper import android.view.ContextThemeWrapper
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.disposables.Disposable import io.reactivex.rxjava3.disposables.Disposable
import org.signal.smsexporter.SmsExportProgress import org.signal.smsexporter.SmsExportProgress
@ -15,6 +17,7 @@ import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.databinding.ExportingSmsMessagesFragmentBinding import org.thoughtcrime.securesms.databinding.ExportingSmsMessagesFragmentBinding
import org.thoughtcrime.securesms.exporter.SignalSmsExportService import org.thoughtcrime.securesms.exporter.SignalSmsExportService
import org.thoughtcrime.securesms.util.LifecycleDisposable import org.thoughtcrime.securesms.util.LifecycleDisposable
import org.thoughtcrime.securesms.util.mb
import org.thoughtcrime.securesms.util.navigation.safeNavigate import org.thoughtcrime.securesms.util.navigation.safeNavigate
/** /**
@ -32,14 +35,22 @@ class ExportingSmsMessagesFragment : Fragment(R.layout.exporting_sms_messages_fr
return inflater.cloneInContext(contextThemeWrapper) return inflater.cloneInContext(contextThemeWrapper)
} }
@Suppress("KotlinConstantConditions")
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
navigationDisposable = SmsExportService navigationDisposable = SmsExportService
.progressState .progressState
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe { .subscribe { smsExportProgress ->
if (it is SmsExportProgress.Done) { if (smsExportProgress is SmsExportProgress.Done) {
findNavController().safeNavigate(ExportingSmsMessagesFragmentDirections.actionExportingSmsMessagesFragmentToExportSmsCompleteFragment(it.total, it.errorCount)) 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.bindTo(viewLifecycleOwner)
lifecycleDisposable += SmsExportService.progressState.observeOn(AndroidSchedulers.mainThread()).subscribe { lifecycleDisposable += SmsExportService.progressState.observeOn(AndroidSchedulers.mainThread()).subscribe {
when (it) { when (it) {
is SmsExportProgress.Done -> Unit SmsExportProgress.Init -> binding.progress.isIndeterminate = true
SmsExportProgress.Starting -> binding.progress.isIndeterminate = true
is SmsExportProgress.InProgress -> { is SmsExportProgress.InProgress -> {
binding.progress.isIndeterminate = false binding.progress.isIndeterminate = false
binding.progress.max = it.total binding.progress.max = it.total
binding.progress.progress = it.progress binding.progress.progress = it.progress
binding.progressLabel.text = resources.getQuantityString(R.plurals.ExportingSmsMessagesFragment__exporting_d_of_d, it.total, it.progress, it.total) binding.progressLabel.text = resources.getQuantityString(R.plurals.ExportingSmsMessagesFragment__exporting_d_of_d, it.total, it.progress, it.total)
} }
SmsExportProgress.Init -> binding.progress.isIndeterminate = true is SmsExportProgress.Done -> Unit
SmsExportProgress.Starting -> binding.progress.isIndeterminate = true
} }
} }
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())
}
}
} }
} }

Wyświetl plik

@ -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)
}

Wyświetl plik

@ -2,8 +2,11 @@ package org.thoughtcrime.securesms.exporter.flow
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.os.Bundle
import androidx.activity.OnBackPressedCallback
import androidx.core.app.NotificationManagerCompat import androidx.core.app.NotificationManagerCompat
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.navigation.findNavController
import androidx.navigation.fragment.NavHostFragment import androidx.navigation.fragment.NavHostFragment
import org.thoughtcrime.securesms.R import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.components.FragmentWrapperActivity import org.thoughtcrime.securesms.components.FragmentWrapperActivity
@ -18,10 +21,23 @@ class SmsExportActivity : FragmentWrapperActivity() {
NotificationManagerCompat.from(this).cancel(NotificationIds.SMS_EXPORT_COMPLETE) 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 { override fun getFragment(): Fragment {
return NavHostFragment.create(R.navigation.sms_export) 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 { companion object {
@JvmStatic @JvmStatic
fun createIntent(context: Context): Intent = Intent(context, SmsExportActivity::class.java) fun createIntent(context: Context): Intent = Intent(context, SmsExportActivity::class.java)

Wyświetl plik

@ -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()
}
}

Wyświetl plik

@ -40,6 +40,7 @@ public class HelpFragment extends LoggingFragment {
public static final String START_CATEGORY_INDEX = "start_category_index"; public static final String START_CATEGORY_INDEX = "start_category_index";
public static final int PAYMENT_INDEX = 6; public static final int PAYMENT_INDEX = 6;
public static final int DONATION_INDEX = 7; public static final int DONATION_INDEX = 7;
public static final int SMS_EXPORT_INDEX = 8;
private EditText problem; private EditText problem;
private CheckBox includeDebugLogs; private CheckBox includeDebugLogs;
@ -93,7 +94,7 @@ public class HelpFragment extends LoggingFragment {
emoji.add(view.findViewById(feeling.getViewId())); 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); categoryAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
categorySpinner.setAdapter(categoryAdapter); categorySpinner.setAdapter(categoryAdapter);
@ -209,7 +210,7 @@ public class HelpFragment extends LoggingFragment {
suffix.append(getString(feeling.getStringId())); 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()] String category = (helpViewModel.getCategoryIndex() >= 0 && helpViewModel.getCategoryIndex() < englishCategories.length) ? englishCategories[helpViewModel.getCategoryIndex()]
: categoryAdapter.getItem(helpViewModel.getCategoryIndex()).toString(); : categoryAdapter.getItem(helpViewModel.getCategoryIndex()).toString();

Wyświetl plik

@ -6,22 +6,22 @@
android:viewportHeight="240" android:viewportHeight="240"
tools:ignore="VectorRaster"> tools:ignore="VectorRaster">
<path <path
android:pathData="M9,40C9,17.91 26.91,0 49,0H209C231.09,0 249,17.91 249,40V200C249,222.09 231.09,240 209,240H49C26.91,240 9,222.09 9,200V40Z" android:pathData="M9,40C9,17.91 26.91,0 49,0h160c22.09,0 40,17.91 40,40v160c0,22.09 -17.91,40 -40,40H49c-22.09,0 -40,-17.91 -40,-40V40Z"
android:fillColor="#1B1C1F"/> android:fillColor="#1B1C1F"/>
<path <path
android:pathData="M9,40C9,17.91 26.91,0 49,0H209C231.09,0 249,17.91 249,40V200C249,222.09 231.09,240 209,240H49C26.91,240 9,222.09 9,200V40Z" android:pathData="M9,40C9,17.91 26.91,0 49,0h160c22.09,0 40,17.91 40,40v160c0,22.09 -17.91,40 -40,40H49c-22.09,0 -40,-17.91 -40,-40V40Z"
android:fillColor="#B6C5FA" android:fillColor="#B6C5FA"
android:fillAlpha="0.08"/> android:fillAlpha="0.08"/>
<path <path
android:pathData="M209,6H49C30.22,6 15,21.22 15,40V200C15,218.78 30.22,234 49,234H209C227.78,234 243,218.78 243,200V40C243,21.22 227.78,6 209,6ZM49,0C26.91,0 9,17.91 9,40V200C9,222.09 26.91,240 49,240H209C231.09,240 249,222.09 249,200V40C249,17.91 231.09,0 209,0H49Z" android:pathData="M209,6H49C30.22,6 15,21.22 15,40v160c0,18.78 15.22,34 34,34h160c18.78,0 34,-15.22 34,-34V40c0,-18.78 -15.22,-34 -34,-34ZM49,0C26.91,0 9,17.91 9,40v160c0,22.09 17.91,40 40,40h160c22.09,0 40,-17.91 40,-40V40c0,-22.09 -17.91,-40 -40,-40H49Z"
android:fillColor="#5C5E65" android:fillColor="#5C5E65"
android:fillType="evenOdd"/> android:fillType="evenOdd"/>
<path <path
android:pathData="M53,104m-18,0a18,18 0,1 1,36 0a18,18 0,1 1,-36 0" android:pathData="M53,104m-18,0a18,18 0,1 1,36 0a18,18 0,1 1,-36 0"
android:fillColor="#3A76F0"/> android:fillColor="#3A76F0"/>
<path <path
android:pathData="M50.18,92.6L50.45,93.67C49.41,93.93 48.41,94.34 47.5,94.89L46.93,93.95C47.94,93.34 49.04,92.89 50.18,92.6V92.6ZM55.82,92.6L55.55,93.67C56.59,93.93 57.59,94.34 58.5,94.89L59.07,93.95C58.06,93.34 56.96,92.89 55.82,92.6V92.6ZM42.95,97.93C42.34,98.94 41.89,100.04 41.6,101.18L42.67,101.45C42.93,100.41 43.34,99.41 43.89,98.5L42.95,97.93ZM42.36,104C42.36,103.47 42.4,102.93 42.48,102.41L41.39,102.24C41.22,103.41 41.22,104.59 41.39,105.76L42.48,105.59C42.4,105.07 42.36,104.53 42.36,104V104ZM59.07,114.05L58.5,113.11C57.59,113.66 56.59,114.07 55.56,114.33L55.82,115.4C56.96,115.11 58.06,114.66 59.07,114.05V114.05ZM63.64,104C63.64,104.53 63.6,105.07 63.52,105.59L64.61,105.76C64.78,104.59 64.78,103.41 64.61,102.24L63.52,102.41C63.6,102.93 63.64,103.47 63.64,104V104ZM64.4,106.82L63.33,106.55C63.07,107.59 62.66,108.59 62.11,109.5L63.05,110.07C63.66,109.06 64.11,107.96 64.4,106.82V106.82ZM54.59,114.52C53.54,114.68 52.46,114.68 51.41,114.52L51.24,115.61C52.41,115.79 53.59,115.79 54.76,115.61L54.59,114.52ZM61.56,110.31C60.93,111.17 60.17,111.93 59.31,112.56L59.96,113.45C60.91,112.75 61.75,111.92 62.45,110.97L61.56,110.31ZM59.31,95.44C60.17,96.07 60.93,96.83 61.56,97.69L62.45,97.03C61.75,96.08 60.92,95.25 59.97,94.55L59.31,95.44ZM44.44,97.69C45.07,96.83 45.83,96.07 46.69,95.44L46.03,94.55C45.08,95.25 44.25,96.08 43.55,97.03L44.44,97.69ZM63.05,97.93L62.11,98.5C62.66,99.41 63.07,100.4 63.33,101.44L64.4,101.18C64.11,100.04 63.66,98.94 63.05,97.93V97.93ZM51.41,93.48C52.46,93.32 53.54,93.32 54.59,93.48L54.76,92.39C53.59,92.22 52.41,92.22 51.24,92.39L51.41,93.48ZM45,113.74L42.73,114.27L43.26,112L42.19,111.75L41.66,114.02C41.61,114.2 41.62,114.39 41.67,114.57C41.72,114.75 41.82,114.92 41.95,115.05C42.08,115.18 42.25,115.28 42.43,115.33C42.61,115.38 42.8,115.39 42.98,115.34L45.25,114.82L45,113.74ZM42.42,110.77L43.49,111.02L43.85,109.44C43.32,108.54 42.92,107.57 42.67,106.55L41.6,106.82C41.84,107.79 42.21,108.73 42.69,109.61L42.42,110.77ZM47.55,113.15L45.98,113.52L46.23,114.59L47.39,114.32C48.27,114.8 49.2,115.16 50.18,115.4L50.44,114.33C49.43,114.08 48.46,113.68 47.56,113.14L47.55,113.15ZM53,94.46C51.3,94.46 49.62,94.92 48.16,95.79C46.69,96.65 45.48,97.9 44.66,99.39C43.83,100.88 43.42,102.57 43.47,104.27C43.52,105.97 44.02,107.63 44.93,109.07L44.01,112.99L47.92,112.07C49.18,112.86 50.59,113.35 52.07,113.49C53.54,113.64 55.02,113.44 56.4,112.91C57.79,112.39 59.03,111.55 60.03,110.46C61.03,109.37 61.76,108.06 62.17,106.64C62.58,105.22 62.66,103.72 62.39,102.27C62.12,100.82 61.52,99.44 60.63,98.26C59.74,97.08 58.59,96.12 57.26,95.46C55.94,94.8 54.48,94.46 53,94.46V94.46Z" android:pathData="m50.18,92.6 l0.26,1.07c-1.04,0.26 -2.03,0.67 -2.95,1.22l-0.56,-0.94a11.69,11.69 0,0 1,3.25 -1.34ZM55.82,92.6 L55.55,93.67c1.04,0.26 2.03,0.67 2.95,1.22l0.57,-0.94a11.69,11.69 0,0 0,-3.26 -1.34ZM42.95,97.93a11.7,11.7 0,0 0,-1.34 3.25l1.07,0.26a10.61,10.61 0,0 1,1.22 -2.95l-0.94,-0.56ZM42.36,104c0,-0.53 0.04,-1.07 0.12,-1.59l-1.09,-0.17a11.79,11.79 0,0 0,0 3.52l1.09,-0.17c-0.08,-0.53 -0.12,-1.06 -0.12,-1.59ZM59.07,114.05 L58.5,113.11c-0.92,0.55 -1.91,0.96 -2.95,1.22l0.26,1.07a11.69,11.69 0,0 0,3.25 -1.34ZM63.64,104a10.63,10.63 0,0 1,-0.12 1.59l1.09,0.17a11.78,11.78 0,0 0,0 -3.52l-1.09,0.17c0.08,0.53 0.12,1.06 0.12,1.59ZM64.4,106.82 L63.33,106.55a10.61,10.61 0,0 1,-1.22 2.95l0.94,0.57a11.68,11.68 0,0 0,1.34 -3.25ZM54.59,114.52a10.71,10.71 0,0 1,-3.19 0l-0.17,1.09c1.17,0.18 2.35,0.18 3.52,0l-0.17,-1.09ZM61.56,110.31a10.69,10.69 0,0 1,-2.25 2.25l0.65,0.89a11.73,11.73 0,0 0,2.49 -2.48l-0.89,-0.66ZM59.31,95.44c0.86,0.63 1.62,1.39 2.25,2.25l0.89,-0.66a11.76,11.76 0,0 0,-2.48 -2.48l-0.66,0.89ZM44.44,97.69c0.63,-0.86 1.39,-1.62 2.25,-2.25l-0.66,-0.89a11.76,11.76 0,0 0,-2.48 2.48l0.89,0.66ZM63.05,97.93 L62.11,98.5c0.55,0.92 0.96,1.91 1.22,2.95l1.07,-0.26a11.69,11.69 0,0 0,-1.34 -3.25ZM51.41,93.48a10.71,10.71 0,0 1,3.19 0l0.17,-1.09a11.78,11.78 0,0 0,-3.52 0l0.17,1.09ZM45,113.74 L42.73,114.27 43.26,112 42.19,111.75 41.66,114.02a1.1,1.1 0,0 0,1.32 1.32l2.27,-0.52 -0.25,-1.08ZM42.42,110.77 L43.49,111.02 43.86,109.44a10.58,10.58 0,0 1,-1.18 -2.89l-1.07,0.26c0.24,0.97 0.6,1.91 1.08,2.79l-0.27,1.16ZM47.55,113.15 L45.98,113.52 46.23,114.59 47.39,114.32c0.88,0.48 1.82,0.84 2.79,1.08l0.26,-1.07a10.62,10.62 0,0 1,-2.88 -1.19l-0.01,0.01ZM53,94.46a9.54,9.54 0,0 0,-8.07 14.61l-0.92,3.91 3.91,-0.92a9.54,9.54 0,0 0,12.1 -1.61,9.53 9.53,0 0,0 2.36,-8.19A9.54,9.54 0,0 0,53 94.46Z"
android:fillColor="#ffffff"/> android:fillColor="#fff"/>
<path <path
android:pathData="M53,44m-16,0a16,16 0,1 1,32 0a16,16 0,1 1,-32 0" android:pathData="M53,44m-16,0a16,16 0,1 1,32 0a16,16 0,1 1,-32 0"
android:fillColor="#5C5E65"/> android:fillColor="#5C5E65"/>
@ -29,22 +29,10 @@
android:pathData="M53,164m-16,0a16,16 0,1 1,32 0a16,16 0,1 1,-32 0" android:pathData="M53,164m-16,0a16,16 0,1 1,32 0a16,16 0,1 1,-32 0"
android:fillColor="#5C5E65"/> android:fillColor="#5C5E65"/>
<path <path
android:pathData="M85,44C85,42.34 86.34,41 88,41H164C165.66,41 167,42.34 167,44C167,45.66 165.66,47 164,47H88C86.34,47 85,45.66 85,44Z" android:pathData="M85,44a3,3 0,0 1,3 -3h76a3,3 0,1 1,0 6L88,47a3,3 0,0 1,-3 -3ZM85,104a3,3 0,0 1,3 -3h76a3,3 0,1 1,0 6L88,107a3,3 0,0 1,-3 -3ZM85,164a3,3 0,0 1,3 -3h76a3,3 0,1 1,0 6L88,167a3,3 0,0 1,-3 -3ZM161,213a3,3 0,0 1,3 -3h54a3,3 0,1 1,0 6h-54a3,3 0,0 1,-3 -3ZM85,213a3,3 0,0 1,3 -3h54a3,3 0,1 1,0 6L88,216a3,3 0,0 1,-3 -3Z"
android:fillColor="#5C5E65"/> android:fillColor="#5C5E65"/>
<path <path
android:pathData="M85,104C85,102.34 86.34,101 88,101H164C165.66,101 167,102.34 167,104C167,105.66 165.66,107 164,107H88C86.34,107 85,105.66 85,104Z" android:pathData="M19,73h220c10.49,0 19,8.51 19,19v24c0,10.49 -8.51,19 -19,19L19,135c-10.49,0 -19,-8.51 -19,-19L0,92c0,-10.49 8.51,-19 19,-19ZM19,76c-8.84,0 -16,7.16 -16,16v24c0,8.84 7.16,16 16,16h220c8.84,0 16,-7.16 16,-16L255,92c0,-8.84 -7.16,-16 -16,-16L19,76Z"
android:fillColor="#5C5E65"/>
<path
android:pathData="M85,164C85,162.34 86.34,161 88,161H164C165.66,161 167,162.34 167,164C167,165.66 165.66,167 164,167H88C86.34,167 85,165.66 85,164Z"
android:fillColor="#5C5E65"/>
<path
android:pathData="M161,213C161,211.34 162.34,210 164,210H218C219.66,210 221,211.34 221,213C221,214.66 219.66,216 218,216H164C162.34,216 161,214.66 161,213Z"
android:fillColor="#5C5E65"/>
<path
android:pathData="M85,213C85,211.34 86.34,210 88,210H142C143.66,210 145,211.34 145,213C145,214.66 143.66,216 142,216H88C86.34,216 85,214.66 85,213Z"
android:fillColor="#5C5E65"/>
<path
android:pathData="M19,73H239C249.49,73 258,81.51 258,92V116C258,126.49 249.49,135 239,135H19C8.51,135 0,126.49 0,116V92C0,81.51 8.51,73 19,73ZM19,76C10.16,76 3,83.16 3,92V116C3,124.84 10.16,132 19,132H239C247.84,132 255,124.84 255,116V92C255,83.16 247.84,76 239,76H19Z"
android:fillColor="#3A76F0" android:fillColor="#3A76F0"
android:fillType="evenOdd"/> android:fillType="evenOdd"/>
</vector> </vector>

Wyświetl plik

@ -0,0 +1,17 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="134dp"
android:height="112dp"
android:viewportWidth="134"
android:viewportHeight="112">
<path
android:pathData="M67,56m-56,0a56,56 0,1 1,112 0a56,56 0,1 1,-112 0"
android:fillColor="#1B1C1F"/>
<path
android:pathData="M67,56m-56,0a56,56 0,1 1,112 0a56,56 0,1 1,-112 0"
android:fillColor="#B6C5FA"
android:fillAlpha="0.08"/>
<path
android:pathData="M87.62,34.47a3,3 0,0 1,0.91 4.14l-24.32,38a3,3 0,0 1,-4.89 0.23l-13.68,-17.48a3,3 0,1 1,4.72 -3.7L61.43,69.82l22.04,-34.44a3,3 0,0 1,4.14 -0.91Z"
android:fillColor="#4CAF50"
android:fillType="evenOdd"/>
</vector>

Wyświetl plik

@ -5,7 +5,7 @@
android:viewportHeight="112"> android:viewportHeight="112">
<group> <group>
<clip-path <clip-path
android:pathData="M0,0h134v112h-134z"/> android:pathData="M0,0h134v112H0z"/>
<path <path
android:pathData="M67,56m-56,0a56,56 0,1 1,112 0a56,56 0,1 1,-112 0" android:pathData="M67,56m-56,0a56,56 0,1 1,112 0a56,56 0,1 1,-112 0"
android:fillColor="#1B1C1F"/> android:fillColor="#1B1C1F"/>
@ -14,23 +14,23 @@
android:fillColor="#B6C5FA" android:fillColor="#B6C5FA"
android:fillAlpha="0.08"/> android:fillAlpha="0.08"/>
<path <path
android:pathData="M33.3,16.1L6.9,16C3.1,16 -0,19.1 -0,22.9L-0.1,89C-0.1,92.8 3,95.9 6.8,95.9L33.1,96C36.9,96 40,92.9 40,89.1L40.2,23C40.2,19.2 37.1,16.1 33.3,16.1ZM36.8,89.1C36.8,91.1 35.1,92.8 33.1,92.8L6.7,92.7C4.7,92.7 3,91 3,89L3.1,22.9C3.1,20.9 4.8,19.2 6.8,19.2L33.2,19.3C35.2,19.3 36.9,21 36.9,23L36.8,89.1Z" android:pathData="M33.3,16.1 L6.9,16C3.1,16 0,19.1 0,22.9L-0.1,89c0,3.8 3.1,6.9 6.9,6.9l26.3,0.1c3.8,0 6.9,-3.1 6.9,-6.9l0.2,-66.1c0,-3.8 -3.1,-6.9 -6.9,-6.9ZM36.8,89.1c0,2 -1.7,3.7 -3.7,3.7l-26.4,-0.1C4.7,92.7 3,91 3,89l0.1,-66.1c0,-2 1.7,-3.7 3.7,-3.7l26.4,0.1c2,0 3.7,1.7 3.7,3.7l-0.1,66.1Z"
android:fillColor="#5C5E65"/> android:fillColor="#5C5E65"/>
<path <path
android:pathData="M36.8,89.1C36.8,91.1 35.1,92.8 33.1,92.8L6.7,92.7C4.7,92.7 3,91 3,89L3.1,22.9C3.1,20.9 4.8,19.2 6.8,19.2L33.2,19.3C35.2,19.3 36.9,21 36.9,23L36.8,89.1Z" android:pathData="M36.8,89.1c0,2 -1.7,3.7 -3.7,3.7l-26.4,-0.1C4.7,92.7 3,91 3,89l0.1,-66.1c0,-2 1.7,-3.7 3.7,-3.7l26.4,0.1c2,0 3.7,1.7 3.7,3.7l-0.1,66.1Z"
android:fillColor="#1B1C1F"/> android:fillColor="#1B1C1F"/>
<path <path
android:pathData="M25.63,43C22.11,43 19.25,45.91 19.25,49.49V53.64C18.93,53.64 18.58,53.64 18.2,53.64H14.07C11.95,53.64 10.89,53.64 10.07,54.06C9.36,54.43 8.78,55.02 8.41,55.75C8,56.57 8,57.66 8,59.82V61.81C8,63.98 8,65.06 8.41,65.89C8.78,66.62 9.36,67.21 10.07,67.58C10.89,68 11.95,68 14.07,68H18.2C20.32,68 21.39,68 22.2,67.58C22.91,67.21 23.49,66.62 23.86,65.89C24.27,65.06 24.27,63.98 24.27,61.81V59.82C24.27,57.66 24.27,56.57 23.86,55.75C23.49,55.02 22.91,54.43 22.2,54.06C22.04,53.98 21.88,53.91 21.69,53.86V49.49C21.69,47.28 23.46,45.49 25.63,45.49C27.8,45.49 29.56,47.28 29.56,49.49V51.43C29.56,52.11 30.11,52.67 30.78,52.67C31.45,52.67 32,52.11 32,51.43V49.49C32,45.91 29.15,43 25.63,43ZM17.08,61.09C17.57,60.77 17.9,60.21 17.9,59.57C17.9,58.58 17.11,57.78 16.14,57.78C15.16,57.78 14.37,58.58 14.37,59.57C14.37,60.21 14.7,60.77 15.19,61.09V63.03C15.19,63.56 15.61,63.99 16.14,63.99C16.66,63.99 17.08,63.56 17.08,63.03V61.09Z" android:pathData="M25.63,43c-3.52,0 -6.37,2.91 -6.37,6.49v4.15c-0.32,-0 -0.67,-0 -1.06,-0h-4.12c-2.13,0 -3.19,0 -4,0.42a3.83,3.83 0,0 0,-1.66 1.69C8,56.57 8,57.66 8,59.82v1.99c0,2.16 0,3.25 0.41,4.07 0.36,0.73 0.94,1.32 1.66,1.69 0.81,0.42 1.88,0.42 4,0.42h4.12c2.13,0 3.19,0 4,-0.42a3.83,3.83 0,0 0,1.66 -1.69c0.41,-0.83 0.41,-1.91 0.41,-4.08v-1.99c0,-2.17 0,-3.25 -0.41,-4.08a3.83,3.83 0,0 0,-1.66 -1.69,2.78 2.78,0 0,0 -0.5,-0.2v-4.36c0,-2.21 1.76,-4.01 3.93,-4.01 2.17,0 3.93,1.79 3.93,4.01v1.93c0,0.69 0.55,1.24 1.22,1.24 0.68,0 1.22,-0.56 1.22,-1.24v-1.93C32,45.91 29.15,43 25.63,43ZM17.09,61.09c0.49,-0.32 0.81,-0.88 0.81,-1.51 0,-0.99 -0.79,-1.8 -1.76,-1.8 -0.97,0 -1.76,0.8 -1.76,1.8 0,0.63 0.32,1.19 0.81,1.51v1.94c0,0.53 0.43,0.97 0.95,0.97a0.96,0.96 0,0 0,0.95 -0.97v-1.94Z"
android:fillColor="#3A76F0" android:fillColor="#3A76F0"
android:fillType="evenOdd"/> android:fillType="evenOdd"/>
<path <path
android:pathData="M127.3,16.1L100.9,16C97.1,16 94,19.1 94,22.9L93.9,89C93.9,92.8 97,95.9 100.8,95.9L127.2,96C131,96 134.1,92.9 134.1,89.1L134.2,23C134.2,19.2 131.1,16.1 127.3,16.1ZM130.8,89.1C130.8,91.1 129.1,92.8 127.1,92.8L100.7,92.7C98.7,92.7 97,91 97,89L97.1,22.9C97.1,20.9 98.8,19.2 100.8,19.2L127.2,19.3C129.2,19.3 130.9,21 130.9,23L130.8,89.1Z" android:pathData="m127.3,16.1 l-26.4,-0.1c-3.8,0 -6.9,3.1 -6.9,6.9L93.9,89c0,3.8 3.1,6.9 6.9,6.9l26.4,0.1c3.8,0 6.9,-3.1 6.9,-6.9l0.1,-66.1c0,-3.8 -3.1,-6.9 -6.9,-6.9ZM130.8,89.1c0,2 -1.7,3.7 -3.7,3.7l-26.4,-0.1c-2,0 -3.7,-1.7 -3.7,-3.7l0.1,-66.1c0,-2 1.7,-3.7 3.7,-3.7l26.4,0.1c2,0 3.7,1.7 3.7,3.7l-0.1,66.1Z"
android:fillColor="#5C5E65"/> android:fillColor="#5C5E65"/>
<path <path
android:pathData="M130.8,89.1C130.8,91.1 129.1,92.8 127.1,92.8L100.7,92.7C98.7,92.7 97,91 97,89L97.1,22.9C97.1,20.9 98.8,19.2 100.8,19.2L127.2,19.3C129.2,19.3 130.9,21 130.9,23L130.8,89.1Z" android:pathData="M130.8,89.1c0,2 -1.7,3.7 -3.7,3.7l-26.4,-0.1c-2,0 -3.7,-1.7 -3.7,-3.7l0.1,-66.1c0,-2 1.7,-3.7 3.7,-3.7l26.4,0.1c2,0 3.7,1.7 3.7,3.7l-0.1,66.1Z"
android:fillColor="#1B1C1F"/> android:fillColor="#1B1C1F"/>
<path <path
android:pathData="M79.34,48.93L85.71,55.29C86.1,55.68 86.1,56.32 85.71,56.71L79.34,63.07C78.95,63.46 78.32,63.46 77.93,63.07C77.54,62.68 77.54,62.05 77.93,61.66L82.59,57L50,57C49.45,57 49,56.55 49,56C49,55.45 49.45,55 50,55L82.59,55L77.93,50.34C77.54,49.95 77.54,49.32 77.93,48.93C78.32,48.54 78.95,48.54 79.34,48.93Z" android:pathData="m79.34,48.93 l6.36,6.36a1,1 0,0 1,0 1.41l-6.36,6.36a1,1 0,0 1,-1.41 -1.41L82.59,57H50a1,1 0,1 1,0 -2h32.59l-4.66,-4.66a1,1 0,0 1,1.41 -1.41Z"
android:fillColor="#3A76F0" android:fillColor="#3A76F0"
android:fillType="evenOdd"/> android:fillType="evenOdd"/>
</group> </group>

Wyświetl plik

@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="134dp"
android:height="112dp"
android:viewportWidth="134"
android:viewportHeight="112">
<path
android:pathData="M67,56m-56,0a56,56 0,1 1,112 0a56,56 0,1 1,-112 0"
android:fillColor="#930006"/>
<path
android:pathData="M67,32a3.49,3.49 0,0 0,-3.49 3.56l0.49,26.5a3,3 0,0 0,6 0l0.49,-26.5A3.49,3.49 0,0 0,67 32ZM67,79a4,4 0,1 0,0 -8,4 4,0 0,0 0,8Z"
android:fillColor="#FFDAD4"/>
</vector>

Wyświetl plik

@ -0,0 +1,23 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="134dp"
android:height="112dp"
android:viewportWidth="134"
android:viewportHeight="112">
<path
android:pathData="M67,56m-56,0a56,56 0,1 1,112 0a56,56 0,1 1,-112 0"
android:fillColor="#1B1C1F"/>
<path
android:pathData="M67,56m-56,0a56,56 0,1 1,112 0a56,56 0,1 1,-112 0"
android:fillColor="#B6C5FA"
android:fillAlpha="0.08"/>
<path
android:pathData="M87.62,34.47a3,3 0,0 1,0.91 4.14l-24.32,38a3,3 0,0 1,-4.89 0.23l-13.68,-17.48a3,3 0,1 1,4.72 -3.7L61.43,69.82l22.04,-34.44a3,3 0,0 1,4.14 -0.91Z"
android:fillColor="#4CAF50"
android:fillType="evenOdd"/>
<path
android:pathData="M107,88m-20,0a20,20 0,1 1,40 0a20,20 0,1 1,-40 0"
android:fillColor="#930006"/>
<path
android:pathData="M107,77a2.24,2.24 0,0 0,-2.24 2.29l0.24,11a2,2 0,0 0,4 0l0.25,-11A2.24,2.24 0,0 0,107 77ZM107,99.75a2.5,2.5 0,1 0,0 -5,2.5 2.5,0 0,0 0,5Z"
android:fillColor="#FFDAD4"/>
</vector>

Wyświetl plik

@ -11,15 +11,15 @@
android:fillColor="#B6C5FA" android:fillColor="#B6C5FA"
android:fillAlpha="0.08"/> android:fillAlpha="0.08"/>
<path <path
android:pathData="M15,32C8.37,32 3,37.37 3,44V68C3,74.63 8.37,80 15,80H19V93.17C19,94.95 21.15,95.85 22.41,94.59L37,80H119C125.63,80 131,74.63 131,68V44C131,37.37 125.63,32 119,32H15Z" android:pathData="M15,32C8.37,32 3,37.37 3,44v24c0,6.63 5.37,12 12,12h4v13.17c0,1.78 2.15,2.67 3.41,1.41L37,80h82c6.63,0 12,-5.37 12,-12V44c0,-6.63 -5.37,-12 -12,-12H15Z"
android:fillColor="#1B1C1F" android:fillColor="#1B1C1F"
android:fillType="evenOdd"/> android:fillType="evenOdd"/>
<path <path
android:pathData="M0,44C0,35.72 6.72,29 15,29H119C127.28,29 134,35.72 134,44V68C134,76.28 127.28,83 119,83H38.24L24.54,96.71C21.39,99.86 16,97.63 16,93.17V83H15C6.72,83 0,76.28 0,68V44ZM15,80C8.37,80 3,74.63 3,68V44C3,37.37 8.37,32 15,32H119C125.63,32 131,37.37 131,44V68C131,74.63 125.63,80 119,80H37L22.41,94.59C21.15,95.85 19,94.95 19,93.17V80H15Z" android:pathData="M0,44c0,-8.28 6.72,-15 15,-15h104c8.28,0 15,6.72 15,15v24c0,8.28 -6.72,15 -15,15L38.24,83L24.53,96.71c-3.15,3.15 -8.53,0.92 -8.53,-3.54L16,83h-1C6.72,83 0,76.28 0,68L0,44ZM15,80C8.37,80 3,74.63 3,68L3,44c0,-6.63 5.37,-12 12,-12h104c6.63,0 12,5.37 12,12v24c0,6.63 -5.37,12 -12,12L37,80L22.41,94.59c-1.26,1.26 -3.41,0.37 -3.41,-1.41L19,80h-4Z"
android:fillColor="#5C5E65" android:fillColor="#5C5E65"
android:fillType="evenOdd"/> android:fillType="evenOdd"/>
<path <path
android:pathData="M74.63,43C71.11,43 68.25,45.91 68.25,49.49V53.64C67.93,53.64 67.58,53.64 67.2,53.64H63.07C60.95,53.64 59.89,53.64 59.07,54.06C58.36,54.43 57.78,55.02 57.41,55.75C57,56.57 57,57.66 57,59.82V61.81C57,63.98 57,65.06 57.41,65.89C57.78,66.62 58.36,67.21 59.07,67.58C59.89,68 60.95,68 63.07,68H67.2C69.32,68 70.39,68 71.2,67.58C71.91,67.21 72.49,66.62 72.86,65.89C73.27,65.06 73.27,63.98 73.27,61.81V59.82C73.27,57.66 73.27,56.57 72.86,55.75C72.49,55.02 71.91,54.43 71.2,54.06C71.04,53.98 70.88,53.91 70.69,53.86V49.49C70.69,47.28 72.46,45.49 74.63,45.49C76.8,45.49 78.56,47.28 78.56,49.49V51.43C78.56,52.11 79.11,52.67 79.78,52.67C80.45,52.67 81,52.11 81,51.43V49.49C81,45.91 78.15,43 74.63,43ZM66.08,61.09C66.57,60.77 66.9,60.21 66.9,59.57C66.9,58.58 66.11,57.78 65.14,57.78C64.16,57.78 63.37,58.58 63.37,59.57C63.37,60.21 63.7,60.77 64.19,61.09V63.03C64.19,63.56 64.61,63.99 65.14,63.99C65.66,63.99 66.08,63.56 66.08,63.03V61.09Z" android:pathData="M74.63,43c-3.52,0 -6.37,2.91 -6.37,6.49v4.15c-0.32,-0 -0.67,-0 -1.06,-0h-4.12c-2.13,0 -3.19,0 -4,0.42a3.83,3.83 0,0 0,-1.66 1.69C57,56.57 57,57.66 57,59.82v1.99c0,2.16 0,3.25 0.41,4.07 0.36,0.73 0.94,1.32 1.66,1.69 0.81,0.42 1.88,0.42 4,0.42h4.12c2.13,0 3.19,0 4,-0.42a3.83,3.83 0,0 0,1.66 -1.69c0.41,-0.83 0.41,-1.91 0.41,-4.08v-1.99c0,-2.17 0,-3.25 -0.41,-4.08a3.83,3.83 0,0 0,-1.66 -1.69,2.78 2.78,0 0,0 -0.5,-0.2v-4.36c0,-2.21 1.76,-4.01 3.93,-4.01 2.17,0 3.93,1.79 3.93,4.01v1.93c0,0.69 0.55,1.24 1.22,1.24 0.68,0 1.22,-0.56 1.22,-1.24v-1.93C81,45.91 78.15,43 74.63,43ZM66.08,61.09c0.49,-0.32 0.81,-0.88 0.81,-1.51 0,-0.99 -0.79,-1.8 -1.76,-1.8 -0.97,0 -1.76,0.8 -1.76,1.8 0,0.63 0.32,1.19 0.81,1.51v1.94c0,0.53 0.43,0.97 0.95,0.97a0.96,0.96 0,0 0,0.95 -0.97v-1.94Z"
android:fillColor="#3A76F0" android:fillColor="#3A76F0"
android:fillType="evenOdd"/> android:fillType="evenOdd"/>
</vector> </vector>

Wyświetl plik

@ -6,18 +6,18 @@
android:viewportHeight="240" android:viewportHeight="240"
tools:ignore="VectorRaster"> tools:ignore="VectorRaster">
<path <path
android:pathData="M9,40C9,17.91 26.91,0 49,0H209C231.09,0 249,17.91 249,40V200C249,222.09 231.09,240 209,240H49C26.91,240 9,222.09 9,200V40Z" android:pathData="M9,40C9,17.91 26.91,0 49,0h160c22.09,0 40,17.91 40,40v160c0,22.09 -17.91,40 -40,40H49c-22.09,0 -40,-17.91 -40,-40V40Z"
android:fillColor="#ffffff"/> android:fillColor="#fff"/>
<path <path
android:pathData="M209,6H49C30.22,6 15,21.22 15,40V200C15,218.78 30.22,234 49,234H209C227.78,234 243,218.78 243,200V40C243,21.22 227.78,6 209,6ZM49,0C26.91,0 9,17.91 9,40V200C9,222.09 26.91,240 49,240H209C231.09,240 249,222.09 249,200V40C249,17.91 231.09,0 209,0H49Z" android:pathData="M209,6H49C30.22,6 15,21.22 15,40v160c0,18.78 15.22,34 34,34h160c18.78,0 34,-15.22 34,-34V40c0,-18.78 -15.22,-34 -34,-34ZM49,0C26.91,0 9,17.91 9,40v160c0,22.09 17.91,40 40,40h160c22.09,0 40,-17.91 40,-40V40c0,-22.09 -17.91,-40 -40,-40H49Z"
android:fillColor="#D6D9DF" android:fillColor="#D6D9DF"
android:fillType="evenOdd"/> android:fillType="evenOdd"/>
<path <path
android:pathData="M53,104m-18,0a18,18 0,1 1,36 0a18,18 0,1 1,-36 0" android:pathData="M53,104m-18,0a18,18 0,1 1,36 0a18,18 0,1 1,-36 0"
android:fillColor="#3A76F0"/> android:fillColor="#3A76F0"/>
<path <path
android:pathData="M50.18,92.6L50.45,93.67C49.41,93.93 48.41,94.34 47.5,94.89L46.93,93.95C47.94,93.34 49.04,92.89 50.18,92.6ZM55.82,92.6L55.55,93.67C56.59,93.93 57.59,94.34 58.5,94.89L59.07,93.95C58.06,93.34 56.96,92.89 55.82,92.6ZM42.95,97.93C42.34,98.94 41.89,100.04 41.6,101.18L42.67,101.45C42.93,100.41 43.34,99.41 43.89,98.5L42.95,97.93ZM42.36,104C42.36,103.47 42.4,102.93 42.48,102.41L41.39,102.24C41.22,103.41 41.22,104.59 41.39,105.76L42.48,105.59C42.4,105.07 42.36,104.53 42.36,104ZM59.07,114.05L58.5,113.11C57.59,113.66 56.59,114.07 55.56,114.33L55.82,115.4C56.96,115.11 58.06,114.66 59.07,114.05ZM63.64,104C63.64,104.53 63.6,105.07 63.52,105.59L64.61,105.76C64.78,104.59 64.78,103.41 64.61,102.24L63.52,102.41C63.6,102.93 63.64,103.47 63.64,104ZM64.4,106.82L63.33,106.55C63.07,107.59 62.66,108.59 62.11,109.5L63.05,110.07C63.66,109.06 64.11,107.96 64.4,106.82ZM54.59,114.52C53.54,114.68 52.46,114.68 51.41,114.52L51.24,115.61C52.41,115.79 53.59,115.79 54.76,115.61L54.59,114.52ZM61.56,110.31C60.93,111.17 60.17,111.93 59.31,112.56L59.96,113.45C60.91,112.75 61.75,111.92 62.45,110.97L61.56,110.31ZM59.31,95.44C60.17,96.07 60.93,96.83 61.56,97.69L62.45,97.03C61.75,96.08 60.92,95.25 59.97,94.55L59.31,95.44ZM44.44,97.69C45.07,96.83 45.83,96.07 46.69,95.44L46.03,94.55C45.08,95.25 44.25,96.08 43.55,97.03L44.44,97.69ZM63.05,97.93L62.11,98.5C62.66,99.41 63.07,100.4 63.33,101.44L64.4,101.18C64.11,100.04 63.66,98.94 63.05,97.93ZM51.41,93.48C52.46,93.32 53.54,93.32 54.59,93.48L54.76,92.39C53.59,92.22 52.41,92.22 51.24,92.39L51.41,93.48ZM45,113.74L42.73,114.27L43.26,112L42.19,111.75L41.66,114.02C41.61,114.2 41.62,114.39 41.67,114.57C41.72,114.75 41.82,114.92 41.95,115.05C42.08,115.18 42.25,115.28 42.43,115.33C42.61,115.38 42.8,115.39 42.98,115.34L45.25,114.82L45,113.74ZM42.42,110.77L43.49,111.02L43.85,109.44C43.32,108.54 42.92,107.57 42.67,106.55L41.6,106.82C41.84,107.79 42.21,108.73 42.69,109.61L42.42,110.77ZM47.55,113.15L45.98,113.52L46.23,114.59L47.39,114.32C48.26,114.8 49.2,115.16 50.18,115.4L50.44,114.33C49.43,114.08 48.46,113.68 47.56,113.14L47.55,113.15ZM53,94.46C51.3,94.46 49.62,94.92 48.16,95.79C46.69,96.65 45.48,97.9 44.66,99.39C43.83,100.88 43.42,102.57 43.47,104.27C43.52,105.97 44.02,107.63 44.93,109.07L44.01,112.99L47.92,112.07C49.18,112.86 50.59,113.35 52.06,113.49C53.54,113.64 55.02,113.44 56.4,112.91C57.79,112.39 59.03,111.55 60.03,110.46C61.03,109.37 61.76,108.06 62.17,106.64C62.58,105.22 62.66,103.72 62.39,102.27C62.12,100.82 61.52,99.44 60.63,98.26C59.74,97.08 58.58,96.12 57.26,95.46C55.94,94.8 54.48,94.46 53,94.46Z" android:pathData="m50.18,92.6 l0.26,1.07a10.61,10.61 0,0 0,-2.95 1.22l-0.56,-0.94a11.69,11.69 0,0 1,3.25 -1.34ZM55.82,92.6 L55.55,93.67c1.04,0.26 2.03,0.67 2.95,1.22l0.57,-0.94a11.69,11.69 0,0 0,-3.25 -1.34ZM42.95,97.93a11.7,11.7 0,0 0,-1.34 3.25l1.07,0.26a10.61,10.61 0,0 1,1.22 -2.95l-0.94,-0.56ZM42.36,104c0,-0.53 0.04,-1.07 0.12,-1.59l-1.09,-0.17a11.78,11.78 0,0 0,0 3.52l1.09,-0.17c-0.08,-0.53 -0.12,-1.06 -0.12,-1.59ZM59.07,114.05 L58.5,113.11c-0.92,0.55 -1.91,0.96 -2.95,1.22l0.26,1.07a11.7,11.7 0,0 0,3.25 -1.34ZM63.64,104c0,0.53 -0.04,1.07 -0.12,1.59l1.09,0.17a11.79,11.79 0,0 0,0 -3.52l-1.09,0.17c0.08,0.53 0.12,1.06 0.12,1.59ZM64.4,106.82 L63.33,106.55a10.61,10.61 0,0 1,-1.22 2.95l0.94,0.57a11.68,11.68 0,0 0,1.34 -3.25ZM54.59,114.52a10.71,10.71 0,0 1,-3.19 0l-0.17,1.09c1.17,0.18 2.35,0.18 3.52,0l-0.17,-1.09ZM61.56,110.31a10.69,10.69 0,0 1,-2.25 2.25l0.65,0.89a11.74,11.74 0,0 0,2.49 -2.48l-0.89,-0.66ZM59.31,95.44c0.86,0.63 1.62,1.39 2.25,2.25l0.89,-0.66a11.76,11.76 0,0 0,-2.48 -2.48l-0.66,0.89ZM44.44,97.69c0.63,-0.86 1.39,-1.62 2.25,-2.25l-0.66,-0.89a11.76,11.76 0,0 0,-2.48 2.48l0.89,0.66ZM63.05,97.93 L62.11,98.5c0.55,0.92 0.96,1.91 1.22,2.95l1.07,-0.26a11.69,11.69 0,0 0,-1.34 -3.25ZM51.41,93.48a10.71,10.71 0,0 1,3.19 0l0.17,-1.09a11.78,11.78 0,0 0,-3.52 0l0.17,1.09ZM45,113.74 L42.73,114.27 43.26,112 42.19,111.75 41.66,114.02a1.1,1.1 0,0 0,1.32 1.32l2.27,-0.52 -0.25,-1.08ZM42.42,110.77 L43.49,111.02 43.86,109.44a10.58,10.58 0,0 1,-1.18 -2.89l-1.07,0.26c0.24,0.97 0.6,1.91 1.08,2.79l-0.27,1.16ZM47.55,113.15 L45.98,113.52 46.23,114.59 47.39,114.32c0.88,0.48 1.82,0.84 2.79,1.08l0.26,-1.07a10.62,10.62 0,0 1,-2.88 -1.19l-0.01,0.01ZM53,94.46a9.54,9.54 0,0 0,-8.07 14.61l-0.92,3.91 3.91,-0.92a9.54,9.54 0,0 0,12.1 -1.61,9.53 9.53,0 0,0 0.6,-12.19 9.54,9.54 0,0 0,-7.63 -3.8Z"
android:fillColor="#ffffff"/> android:fillColor="#fff"/>
<path <path
android:pathData="M53,44m-16,0a16,16 0,1 1,32 0a16,16 0,1 1,-32 0" android:pathData="M53,44m-16,0a16,16 0,1 1,32 0a16,16 0,1 1,-32 0"
android:fillColor="#D6D9DF"/> android:fillColor="#D6D9DF"/>
@ -25,22 +25,10 @@
android:pathData="M53,164m-16,0a16,16 0,1 1,32 0a16,16 0,1 1,-32 0" android:pathData="M53,164m-16,0a16,16 0,1 1,32 0a16,16 0,1 1,-32 0"
android:fillColor="#D6D9DF"/> android:fillColor="#D6D9DF"/>
<path <path
android:pathData="M85,44C85,42.34 86.34,41 88,41H164C165.66,41 167,42.34 167,44C167,45.66 165.66,47 164,47H88C86.34,47 85,45.66 85,44Z" android:pathData="M85,44a3,3 0,0 1,3 -3h76a3,3 0,1 1,0 6L88,47a3,3 0,0 1,-3 -3ZM85,104a3,3 0,0 1,3 -3h76a3,3 0,1 1,0 6L88,107a3,3 0,0 1,-3 -3ZM85,164a3,3 0,0 1,3 -3h76a3,3 0,1 1,0 6L88,167a3,3 0,0 1,-3 -3ZM161,213a3,3 0,0 1,3 -3h54a3,3 0,1 1,0 6h-54a3,3 0,0 1,-3 -3ZM85,213a3,3 0,0 1,3 -3h54a3,3 0,1 1,0 6L88,216a3,3 0,0 1,-3 -3Z"
android:fillColor="#D6D9DF"/> android:fillColor="#D6D9DF"/>
<path <path
android:pathData="M85,104C85,102.34 86.34,101 88,101H164C165.66,101 167,102.34 167,104C167,105.66 165.66,107 164,107H88C86.34,107 85,105.66 85,104Z" android:pathData="M19,73h220c10.49,0 19,8.51 19,19v24c0,10.49 -8.51,19 -19,19L19,135c-10.49,0 -19,-8.51 -19,-19L0,92c0,-10.49 8.51,-19 19,-19ZM19,76c-8.84,0 -16,7.16 -16,16v24c0,8.84 7.16,16 16,16h220c8.84,0 16,-7.16 16,-16L255,92c0,-8.84 -7.16,-16 -16,-16L19,76Z"
android:fillColor="#D6D9DF"/>
<path
android:pathData="M85,164C85,162.34 86.34,161 88,161H164C165.66,161 167,162.34 167,164C167,165.66 165.66,167 164,167H88C86.34,167 85,165.66 85,164Z"
android:fillColor="#D6D9DF"/>
<path
android:pathData="M161,213C161,211.34 162.34,210 164,210H218C219.66,210 221,211.34 221,213C221,214.66 219.66,216 218,216H164C162.34,216 161,214.66 161,213Z"
android:fillColor="#D6D9DF"/>
<path
android:pathData="M85,213C85,211.34 86.34,210 88,210H142C143.66,210 145,211.34 145,213C145,214.66 143.66,216 142,216H88C86.34,216 85,214.66 85,213Z"
android:fillColor="#D6D9DF"/>
<path
android:pathData="M19,73H239C249.49,73 258,81.51 258,92V116C258,126.49 249.49,135 239,135H19C8.51,135 0,126.49 0,116V92C0,81.51 8.51,73 19,73ZM19,76C10.16,76 3,83.16 3,92V116C3,124.84 10.16,132 19,132H239C247.84,132 255,124.84 255,116V92C255,83.16 247.84,76 239,76H19Z"
android:fillColor="#3A76F0" android:fillColor="#3A76F0"
android:fillType="evenOdd"/> android:fillType="evenOdd"/>
</vector> </vector>

Wyświetl plik

@ -0,0 +1,17 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="134dp"
android:height="112dp"
android:viewportWidth="134"
android:viewportHeight="112">
<path
android:pathData="M67,56m-56,0a56,56 0,1 1,112 0a56,56 0,1 1,-112 0"
android:fillColor="#FBFCFE"/>
<path
android:pathData="M67,56m-56,0a56,56 0,1 1,112 0a56,56 0,1 1,-112 0"
android:fillColor="#50679F"
android:fillAlpha="0.08"/>
<path
android:pathData="M87.62,34.47a3,3 0,0 1,0.91 4.14l-24.32,38a3,3 0,0 1,-4.89 0.23l-13.68,-17.48a3,3 0,1 1,4.72 -3.7L61.43,69.82l22.04,-34.44a3,3 0,0 1,4.14 -0.91Z"
android:fillColor="#4CAF50"
android:fillType="evenOdd"/>
</vector>

Wyświetl plik

@ -5,7 +5,7 @@
android:viewportHeight="112"> android:viewportHeight="112">
<group> <group>
<clip-path <clip-path
android:pathData="M0,0h134v112h-134z"/> android:pathData="M0,0h134v112H0z"/>
<path <path
android:pathData="M67,56m-56,0a56,56 0,1 1,112 0a56,56 0,1 1,-112 0" android:pathData="M67,56m-56,0a56,56 0,1 1,112 0a56,56 0,1 1,-112 0"
android:fillColor="#FBFCFE"/> android:fillColor="#FBFCFE"/>
@ -14,23 +14,23 @@
android:fillColor="#50679F" android:fillColor="#50679F"
android:fillAlpha="0.08"/> android:fillAlpha="0.08"/>
<path <path
android:pathData="M33.3,16.1L6.9,16C3.1,16 -0,19.1 -0,22.9L-0.1,89C-0.1,92.8 3,95.9 6.8,95.9L33.1,96C36.9,96 40,92.9 40,89.1L40.2,23C40.2,19.2 37.1,16.1 33.3,16.1ZM36.8,89.1C36.8,91.1 35.1,92.8 33.1,92.8L6.7,92.7C4.7,92.7 3,91 3,89L3.1,22.9C3.1,20.9 4.8,19.2 6.8,19.2L33.2,19.3C35.2,19.3 36.9,21 36.9,23L36.8,89.1Z" android:pathData="M33.3,16.1 L6.9,16C3.1,16 0,19.1 0,22.9L-0.1,89c0,3.8 3.1,6.9 6.9,6.9l26.3,0.1c3.8,0 6.9,-3.1 6.9,-6.9l0.2,-66.1c0,-3.8 -3.1,-6.9 -6.9,-6.9ZM36.8,89.1c0,2 -1.7,3.7 -3.7,3.7l-26.4,-0.1C4.7,92.7 3,91 3,89l0.1,-66.1c0,-2 1.7,-3.7 3.7,-3.7l26.4,0.1c2,0 3.7,1.7 3.7,3.7l-0.1,66.1Z"
android:fillColor="#D6D9DF"/> android:fillColor="#D6D9DF"/>
<path <path
android:pathData="M36.8,89.1C36.8,91.1 35.1,92.8 33.1,92.8L6.7,92.7C4.7,92.7 3,91 3,89L3.1,22.9C3.1,20.9 4.8,19.2 6.8,19.2L33.2,19.3C35.2,19.3 36.9,21 36.9,23L36.8,89.1Z" android:pathData="M36.8,89.1c0,2 -1.7,3.7 -3.7,3.7l-26.4,-0.1C4.7,92.7 3,91 3,89l0.1,-66.1c0,-2 1.7,-3.7 3.7,-3.7l26.4,0.1c2,0 3.7,1.7 3.7,3.7l-0.1,66.1Z"
android:fillColor="#ffffff"/> android:fillColor="#fff"/>
<path <path
android:pathData="M25.63,43C22.11,43 19.25,45.91 19.25,49.49V53.64C18.93,53.64 18.58,53.64 18.2,53.64H14.07C11.95,53.64 10.89,53.64 10.07,54.06C9.36,54.43 8.78,55.02 8.41,55.75C8,56.57 8,57.66 8,59.82V61.81C8,63.98 8,65.06 8.41,65.89C8.78,66.62 9.36,67.21 10.07,67.58C10.89,68 11.95,68 14.07,68H18.2C20.32,68 21.39,68 22.2,67.58C22.91,67.21 23.49,66.62 23.86,65.89C24.27,65.06 24.27,63.98 24.27,61.81V59.82C24.27,57.66 24.27,56.57 23.86,55.75C23.49,55.02 22.91,54.43 22.2,54.06C22.04,53.98 21.88,53.91 21.69,53.86V49.49C21.69,47.28 23.46,45.49 25.63,45.49C27.8,45.49 29.56,47.28 29.56,49.49V51.43C29.56,52.11 30.11,52.67 30.78,52.67C31.45,52.67 32,52.11 32,51.43V49.49C32,45.91 29.15,43 25.63,43ZM17.08,61.09C17.57,60.77 17.9,60.21 17.9,59.57C17.9,58.58 17.11,57.78 16.14,57.78C15.16,57.78 14.37,58.58 14.37,59.57C14.37,60.21 14.7,60.77 15.19,61.09V63.03C15.19,63.56 15.61,63.99 16.14,63.99C16.66,63.99 17.08,63.56 17.08,63.03V61.09Z" android:pathData="M25.63,43c-3.52,0 -6.37,2.91 -6.37,6.49v4.15c-0.32,-0 -0.67,-0 -1.06,-0h-4.12c-2.13,0 -3.19,0 -4,0.42a3.83,3.83 0,0 0,-1.66 1.69C8,56.57 8,57.66 8,59.82v1.99c0,2.16 0,3.25 0.41,4.07 0.36,0.73 0.94,1.32 1.66,1.69 0.81,0.42 1.88,0.42 4,0.42h4.12c2.13,0 3.19,0 4,-0.42a3.83,3.83 0,0 0,1.66 -1.69c0.41,-0.83 0.41,-1.91 0.41,-4.08v-1.99c0,-2.17 0,-3.25 -0.41,-4.08a3.83,3.83 0,0 0,-1.66 -1.69,2.78 2.78,0 0,0 -0.5,-0.2v-4.36c0,-2.21 1.76,-4.01 3.93,-4.01 2.17,0 3.93,1.79 3.93,4.01v1.93c0,0.69 0.55,1.24 1.22,1.24 0.68,0 1.22,-0.56 1.22,-1.24v-1.93C32,45.91 29.15,43 25.63,43ZM17.09,61.09c0.49,-0.32 0.81,-0.88 0.81,-1.51 0,-0.99 -0.79,-1.8 -1.76,-1.8 -0.97,0 -1.76,0.8 -1.76,1.8 0,0.63 0.32,1.19 0.81,1.51v1.94c0,0.53 0.43,0.97 0.95,0.97a0.96,0.96 0,0 0,0.95 -0.97v-1.94Z"
android:fillColor="#3A76F0" android:fillColor="#3A76F0"
android:fillType="evenOdd"/> android:fillType="evenOdd"/>
<path <path
android:pathData="M127.3,16.1L100.9,16C97.1,16 94,19.1 94,22.9L93.9,89C93.9,92.8 97,95.9 100.8,95.9L127.2,96C131,96 134.1,92.9 134.1,89.1L134.2,23C134.2,19.2 131.1,16.1 127.3,16.1ZM130.8,89.1C130.8,91.1 129.1,92.8 127.1,92.8L100.7,92.7C98.7,92.7 97,91 97,89L97.1,22.9C97.1,20.9 98.8,19.2 100.8,19.2L127.2,19.3C129.2,19.3 130.9,21 130.9,23L130.8,89.1Z" android:pathData="m127.3,16.1 l-26.4,-0.1c-3.8,0 -6.9,3.1 -6.9,6.9L93.9,89c0,3.8 3.1,6.9 6.9,6.9l26.4,0.1c3.8,0 6.9,-3.1 6.9,-6.9l0.1,-66.1c0,-3.8 -3.1,-6.9 -6.9,-6.9ZM130.8,89.1c0,2 -1.7,3.7 -3.7,3.7l-26.4,-0.1c-2,0 -3.7,-1.7 -3.7,-3.7l0.1,-66.1c0,-2 1.7,-3.7 3.7,-3.7l26.4,0.1c2,0 3.7,1.7 3.7,3.7l-0.1,66.1Z"
android:fillColor="#D6D9DF"/> android:fillColor="#D6D9DF"/>
<path <path
android:pathData="M130.8,89.1C130.8,91.1 129.1,92.8 127.1,92.8L100.7,92.7C98.7,92.7 97,91 97,89L97.1,22.9C97.1,20.9 98.8,19.2 100.8,19.2L127.2,19.3C129.2,19.3 130.9,21 130.9,23L130.8,89.1Z" android:pathData="M130.8,89.1c0,2 -1.7,3.7 -3.7,3.7l-26.4,-0.1c-2,0 -3.7,-1.7 -3.7,-3.7l0.1,-66.1c0,-2 1.7,-3.7 3.7,-3.7l26.4,0.1c2,0 3.7,1.7 3.7,3.7l-0.1,66.1Z"
android:fillColor="#ffffff"/> android:fillColor="#fff"/>
<path <path
android:pathData="M79.34,48.93L85.71,55.29C86.1,55.68 86.1,56.32 85.71,56.71L79.34,63.07C78.95,63.46 78.32,63.46 77.93,63.07C77.54,62.68 77.54,62.05 77.93,61.66L82.59,57L50,57C49.45,57 49,56.55 49,56C49,55.45 49.45,55 50,55L82.59,55L77.93,50.34C77.54,49.95 77.54,49.32 77.93,48.93C78.32,48.54 78.95,48.54 79.34,48.93Z" android:pathData="m79.34,48.93 l6.36,6.36a1,1 0,0 1,0 1.41l-6.36,6.36a1,1 0,0 1,-1.41 -1.41L82.59,57H50a1,1 0,1 1,0 -2h32.59l-4.66,-4.66a1,1 0,0 1,1.41 -1.41Z"
android:fillColor="#3A76F0" android:fillColor="#3A76F0"
android:fillType="evenOdd"/> android:fillType="evenOdd"/>
</group> </group>

Wyświetl plik

@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="134dp"
android:height="112dp"
android:viewportWidth="134"
android:viewportHeight="112">
<path
android:pathData="M67,56m-56,0a56,56 0,1 1,112 0a56,56 0,1 1,-112 0"
android:fillColor="#FFDAD4"/>
<path
android:pathData="M67,32a3.49,3.49 0,0 0,-3.49 3.56l0.49,26.5a3,3 0,0 0,6 0l0.49,-26.5A3.49,3.49 0,0 0,67 32ZM67,79a4,4 0,1 0,0 -8,4 4,0 0,0 0,8Z"
android:fillColor="#BA1B1B"/>
</vector>

Wyświetl plik

@ -0,0 +1,23 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="134dp"
android:height="112dp"
android:viewportWidth="134"
android:viewportHeight="112">
<path
android:pathData="M67,56m-56,0a56,56 0,1 1,112 0a56,56 0,1 1,-112 0"
android:fillColor="#FBFCFE"/>
<path
android:pathData="M67,56m-56,0a56,56 0,1 1,112 0a56,56 0,1 1,-112 0"
android:fillColor="#50679F"
android:fillAlpha="0.08"/>
<path
android:pathData="M107,88m-20,0a20,20 0,1 1,40 0a20,20 0,1 1,-40 0"
android:fillColor="#FFDAD4"/>
<path
android:pathData="M107,77a2.24,2.24 0,0 0,-2.24 2.29l0.24,11a2,2 0,0 0,4 0l0.25,-11A2.24,2.24 0,0 0,107 77ZM107,99.75a2.5,2.5 0,1 0,0 -5,2.5 2.5,0 0,0 0,5Z"
android:fillColor="#BA1B1B"/>
<path
android:pathData="M87.62,34.47a3,3 0,0 1,0.91 4.14l-24.32,38a3,3 0,0 1,-4.89 0.23l-13.68,-17.48a3,3 0,1 1,4.72 -3.7L61.43,69.82l22.04,-34.44a3,3 0,0 1,4.14 -0.91Z"
android:fillColor="#4CAF50"
android:fillType="evenOdd"/>
</vector>

Wyświetl plik

@ -11,15 +11,15 @@
android:fillColor="#50679F" android:fillColor="#50679F"
android:fillAlpha="0.08"/> android:fillAlpha="0.08"/>
<path <path
android:pathData="M15,32C8.37,32 3,37.37 3,44V68C3,74.63 8.37,80 15,80H19V93.17C19,94.95 21.15,95.85 22.41,94.59L37,80H119C125.63,80 131,74.63 131,68V44C131,37.37 125.63,32 119,32H15Z" android:pathData="M15,32C8.37,32 3,37.37 3,44v24c0,6.63 5.37,12 12,12h4v13.17c0,1.78 2.15,2.67 3.41,1.41L37,80h82c6.63,0 12,-5.37 12,-12V44c0,-6.63 -5.37,-12 -12,-12H15Z"
android:fillColor="#ffffff" android:fillColor="#fff"
android:fillType="evenOdd"/> android:fillType="evenOdd"/>
<path <path
android:pathData="M0,44C0,35.72 6.72,29 15,29H119C127.28,29 134,35.72 134,44V68C134,76.28 127.28,83 119,83H38.24L24.54,96.71C21.39,99.86 16,97.63 16,93.17V83H15C6.72,83 0,76.28 0,68V44ZM15,80C8.37,80 3,74.63 3,68V44C3,37.37 8.37,32 15,32H119C125.63,32 131,37.37 131,44V68C131,74.63 125.63,80 119,80H37L22.41,94.59C21.15,95.85 19,94.95 19,93.17V80H15Z" android:pathData="M0,44c0,-8.28 6.72,-15 15,-15h104c8.28,0 15,6.72 15,15v24c0,8.28 -6.72,15 -15,15L38.24,83L24.53,96.71c-3.15,3.15 -8.53,0.92 -8.53,-3.54L16,83h-1C6.72,83 0,76.28 0,68L0,44ZM15,80C8.37,80 3,74.63 3,68L3,44c0,-6.63 5.37,-12 12,-12h104c6.63,0 12,5.37 12,12v24c0,6.63 -5.37,12 -12,12L37,80L22.41,94.59c-1.26,1.26 -3.41,0.37 -3.41,-1.41L19,80h-4Z"
android:fillColor="#D6D9DF" android:fillColor="#D6D9DF"
android:fillType="evenOdd"/> android:fillType="evenOdd"/>
<path <path
android:pathData="M74.63,43C71.11,43 68.25,45.91 68.25,49.49V53.64C67.93,53.64 67.58,53.64 67.2,53.64H63.07C60.95,53.64 59.89,53.64 59.07,54.06C58.36,54.43 57.78,55.02 57.41,55.75C57,56.57 57,57.66 57,59.82V61.81C57,63.98 57,65.06 57.41,65.89C57.78,66.62 58.36,67.21 59.07,67.58C59.89,68 60.95,68 63.07,68H67.2C69.32,68 70.39,68 71.2,67.58C71.91,67.21 72.49,66.62 72.86,65.89C73.27,65.06 73.27,63.98 73.27,61.81V59.82C73.27,57.66 73.27,56.57 72.86,55.75C72.49,55.02 71.91,54.43 71.2,54.06C71.04,53.98 70.88,53.91 70.69,53.86V49.49C70.69,47.28 72.46,45.49 74.63,45.49C76.8,45.49 78.56,47.28 78.56,49.49V51.43C78.56,52.11 79.11,52.67 79.78,52.67C80.45,52.67 81,52.11 81,51.43V49.49C81,45.91 78.15,43 74.63,43ZM66.08,61.09C66.57,60.77 66.9,60.21 66.9,59.57C66.9,58.58 66.11,57.78 65.14,57.78C64.16,57.78 63.37,58.58 63.37,59.57C63.37,60.21 63.7,60.77 64.19,61.09V63.03C64.19,63.56 64.61,63.99 65.14,63.99C65.66,63.99 66.08,63.56 66.08,63.03V61.09Z" android:pathData="M74.63,43c-3.52,0 -6.37,2.91 -6.37,6.49v4.15c-0.32,-0 -0.67,-0 -1.06,-0h-4.12c-2.13,0 -3.19,0 -4,0.42a3.83,3.83 0,0 0,-1.66 1.69C57,56.57 57,57.66 57,59.82v1.99c0,2.16 0,3.25 0.41,4.07 0.36,0.73 0.94,1.32 1.66,1.69 0.81,0.42 1.88,0.42 4,0.42h4.12c2.13,0 3.19,0 4,-0.42a3.83,3.83 0,0 0,1.66 -1.69c0.41,-0.83 0.41,-1.91 0.41,-4.08v-1.99c0,-2.17 0,-3.25 -0.41,-4.08a3.83,3.83 0,0 0,-1.66 -1.69,2.78 2.78,0 0,0 -0.5,-0.2v-4.36c0,-2.21 1.76,-4.01 3.93,-4.01 2.17,0 3.93,1.79 3.93,4.01v1.93c0,0.69 0.55,1.24 1.22,1.24 0.68,0 1.22,-0.56 1.22,-1.24v-1.93C81,45.91 78.15,43 74.63,43ZM66.08,61.09c0.49,-0.32 0.81,-0.88 0.81,-1.51 0,-0.99 -0.79,-1.8 -1.76,-1.8 -0.97,0 -1.76,0.8 -1.76,1.8 0,0.63 0.32,1.19 0.81,1.51v1.94c0,0.53 0.43,0.97 0.95,0.97a0.96,0.96 0,0 0,0.95 -0.97v-1.94Z"
android:fillColor="#3A76F0" android:fillColor="#3A76F0"
android:fillType="evenOdd"/> android:fillType="evenOdd"/>
</vector> </vector>

Wyświetl plik

@ -0,0 +1,94 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.core.widget.NestedScrollView
android:id="@+id/scroll_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/hero"
android:layout_width="112dp"
android:layout_height="112dp"
android:layout_marginTop="84dp"
android:layout_marginBottom="16dp"
app:layout_constraintBottom_toTopOf="@+id/export_complete_title"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/sms_export_error"
tools:ignore="UnusedAttribute,ImageContrastCheck" />
<TextView
android:id="@+id/headline"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="32dp"
android:layout_marginTop="40dp"
android:gravity="center"
android:text="@string/ExportSmsFullError__error_exporting_sms_messages"
android:textAppearance="@style/Signal.Text.TitleLarge"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/hero" />
<TextView
android:id="@+id/export_complete_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:textAppearance="@style/Signal.Text.BodySmall"
android:textColor="@color/signal_colorOnSurfaceVariant"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/headline"
tools:text="248 of 248 messages exported" />
<org.thoughtcrime.securesms.util.views.LearnMoreTextView
android:id="@+id/please_try_again"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginTop="60dp"
android:layout_marginEnd="32dp"
android:text="@string/ExportSmsFullError__please_try_again_if_the_problem_persists"
android:textAlignment="center"
android:textAppearance="@style/Signal.Text.BodyLarge"
android:textColor="@color/signal_colorOnSurfaceVariant"
app:layout_constraintBottom_toTopOf="@+id/retry_button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/export_complete_status"
app:layout_constraintVertical_chainStyle="spread_inside" />
<com.google.android.material.button.MaterialButton
android:id="@+id/retry_button"
style="@style/Signal.Widget.Button.Large.Tonal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="32dp"
android:layout_marginTop="48dp"
android:layout_marginBottom="44dp"
android:minWidth="220dp"
android:text="@string/ExportSmsPartiallyComplete__retry"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/please_try_again"
app:layout_constraintVertical_bias="1" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>

Wyświetl plik

@ -0,0 +1,250 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.core.widget.NestedScrollView
android:id="@+id/scroll_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/hero"
android:layout_width="112dp"
android:layout_height="112dp"
android:layout_marginTop="84dp"
android:layout_marginBottom="16dp"
android:scaleType="centerInside"
app:layout_constraintBottom_toTopOf="@+id/export_complete_title"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/sms_export_partial_complete"
tools:ignore="UnusedAttribute,ImageContrastCheck" />
<TextView
android:id="@+id/headline"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="32dp"
android:layout_marginTop="40dp"
android:gravity="center"
android:text="@string/ExportSmsPartiallyComplete__export_partially_complete"
android:textAppearance="@style/Signal.Text.TitleLarge"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/hero" />
<TextView
android:id="@+id/export_complete_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:textAppearance="@style/Signal.Text.BodySmall"
android:textColor="@color/signal_colorOnSurfaceVariant"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/headline"
tools:text="248 of 248 messages exported" />
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@drawable/circle_tintable"
android:backgroundTint="@color/signal_colorSurface3"
app:layout_constraintBottom_toBottomOf="@+id/bullet_1"
app:layout_constraintEnd_toEndOf="@+id/bullet_1"
app:layout_constraintStart_toStartOf="@+id/bullet_1"
app:layout_constraintTop_toTopOf="@+id/bullet_1" />
<TextView
android:id="@+id/bullet_1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginTop="60dp"
android:gravity="center"
android:minWidth="28dp"
android:minHeight="28dp"
android:padding="4dp"
android:text="@string/ChooseANewDefaultSmsAppFragment__bullet_1"
android:textAppearance="@style/Signal.Text.BodyMedium"
android:textStyle="bold"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/export_complete_status" />
<TextView
android:id="@+id/bullet_1_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="59dp"
android:layout_marginEnd="32dp"
android:minWidth="28dp"
android:minHeight="28dp"
android:padding="4dp"
android:text="@string/ExportSmsPartiallyComplete__ensure_you_have_an_additional_s_free_on_your_phone_to_export_your_messages"
android:textAlignment="viewStart"
android:textAppearance="@style/Signal.Text.BodyLarge"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/bullet_1"
app:layout_constraintTop_toBottomOf="@id/export_complete_status" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/bullet_1_barrier"
android:layout_width="match_parent"
android:layout_height="1dp"
android:orientation="horizontal"
app:barrierDirection="bottom"
app:constraint_referenced_ids="bullet_1,bullet_1_text" />
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@drawable/circle_tintable"
android:backgroundTint="@color/signal_colorSurface3"
app:layout_constraintBottom_toBottomOf="@+id/bullet_2"
app:layout_constraintEnd_toEndOf="@+id/bullet_2"
app:layout_constraintStart_toStartOf="@+id/bullet_2"
app:layout_constraintTop_toTopOf="@+id/bullet_2" />
<TextView
android:id="@+id/bullet_2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginTop="24dp"
android:gravity="center"
android:minWidth="28dp"
android:minHeight="28dp"
android:padding="4dp"
android:text="@string/ChooseANewDefaultSmsAppFragment__bullet_2"
android:textAppearance="@style/Signal.Text.BodyMedium"
android:textStyle="bold"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/bullet_1_barrier" />
<TextView
android:id="@+id/bullet_2_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="23dp"
android:layout_marginEnd="32dp"
android:minWidth="28dp"
android:minHeight="28dp"
android:padding="4dp"
android:text="@string/ExportSmsPartiallyComplete__retry_export_which_will_only_retry_messages_that_have_not_yet_been_exported"
android:textAlignment="viewStart"
android:textAppearance="@style/Signal.Text.BodyLarge"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/bullet_2"
app:layout_constraintTop_toBottomOf="@id/bullet_1_barrier" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/bullet_2_barrier"
android:layout_width="match_parent"
android:layout_height="1dp"
android:orientation="horizontal"
app:barrierDirection="bottom"
app:constraint_referenced_ids="bullet_2,bullet_2_text" />
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@drawable/circle_tintable"
android:backgroundTint="@color/signal_colorSurface3"
app:layout_constraintBottom_toBottomOf="@+id/bullet_3"
app:layout_constraintEnd_toEndOf="@+id/bullet_3"
app:layout_constraintStart_toStartOf="@+id/bullet_3"
app:layout_constraintTop_toTopOf="@+id/bullet_3" />
<TextView
android:id="@+id/bullet_3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginTop="24dp"
android:gravity="center"
android:minWidth="28dp"
android:minHeight="28dp"
android:padding="4dp"
android:text="@string/ChooseANewDefaultSmsAppFragment__bullet_3"
android:textAppearance="@style/Signal.Text.BodyMedium"
android:textStyle="bold"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/bullet_2_barrier" />
<org.thoughtcrime.securesms.util.views.LearnMoreTextView
android:id="@+id/bullet_3_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="23dp"
android:layout_marginEnd="32dp"
android:minWidth="28dp"
android:minHeight="28dp"
android:padding="4dp"
android:text="@string/ExportSmsPartiallyComplete__if_the_problem_persists"
android:textAlignment="viewStart"
android:textAppearance="@style/Signal.Text.BodyLarge"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/bullet_3"
app:layout_constraintTop_toBottomOf="@id/bullet_2_barrier" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/bullet_3_barrier"
android:layout_width="match_parent"
android:layout_height="1dp"
android:orientation="horizontal"
app:barrierDirection="bottom"
app:constraint_referenced_ids="bullet_3,bullet_3_text" />
<com.google.android.material.button.MaterialButton
android:id="@+id/retry_button"
style="@style/Signal.Widget.Button.Large.Tonal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="32dp"
android:layout_marginTop="48dp"
android:layout_marginBottom="16dp"
android:minWidth="220dp"
android:text="@string/ExportSmsPartiallyComplete__retry"
app:layout_constraintBottom_toTopOf="@+id/continue_button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/bullet_3_barrier"
app:layout_constraintVertical_bias="1" />
<com.google.android.material.button.MaterialButton
android:id="@+id/continue_button"
style="@style/Signal.Widget.Button.Large.Secondary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="32dp"
android:layout_marginTop="48dp"
android:layout_marginBottom="44dp"
android:minWidth="220dp"
android:text="@string/ExportSmsPartiallyComplete__continue_anyway"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/bullet_3_barrier"
app:layout_constraintVertical_bias="1" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>

Wyświetl plik

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="64dp"
android:minHeight="64dp"
app:title="@string/preferences__help"
app:navigationIcon="@drawable/ic_arrow_left_24" />
<androidx.fragment.app.FragmentContainerView
android:id="@+id/sms_export_help_fragment_fragment"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>

Wyświetl plik

@ -16,7 +16,10 @@
app:enterAnim="@anim/fragment_open_enter" app:enterAnim="@anim/fragment_open_enter"
app:exitAnim="@anim/fragment_open_exit" app:exitAnim="@anim/fragment_open_exit"
app:popEnterAnim="@anim/fragment_close_enter" app:popEnterAnim="@anim/fragment_close_enter"
app:popExitAnim="@anim/fragment_close_exit" /> app:popExitAnim="@anim/fragment_close_exit"
app:popUpTo="@id/sms_export"
app:popUpToInclusive="true" />
<action <action
android:id="@+id/action_exportYourSmsMessagesFragment_to_setSignalAsDefaultSmsAppFragment" android:id="@+id/action_exportYourSmsMessagesFragment_to_setSignalAsDefaultSmsAppFragment"
app:destination="@id/setSignalAsDefaultSmsAppFragment" app:destination="@id/setSignalAsDefaultSmsAppFragment"
@ -48,13 +51,37 @@
android:name="org.thoughtcrime.securesms.exporter.flow.ExportingSmsMessagesFragment" android:name="org.thoughtcrime.securesms.exporter.flow.ExportingSmsMessagesFragment"
android:label="fragment_exporting_sms_messages" android:label="fragment_exporting_sms_messages"
tools:layout="@layout/exporting_sms_messages_fragment"> tools:layout="@layout/exporting_sms_messages_fragment">
<action <action
android:id="@+id/action_exportingSmsMessagesFragment_to_exportSmsCompleteFragment" android:id="@+id/action_exportingSmsMessagesFragment_to_exportSmsCompleteFragment"
app:destination="@id/exportSmsCompleteFragment" app:destination="@id/exportSmsCompleteFragment"
app:enterAnim="@anim/fragment_open_enter" app:enterAnim="@anim/fragment_open_enter"
app:exitAnim="@anim/fragment_open_exit" app:exitAnim="@anim/fragment_open_exit"
app:popEnterAnim="@anim/fragment_close_enter" app:popEnterAnim="@anim/fragment_close_enter"
app:popExitAnim="@anim/fragment_close_exit" /> app:popExitAnim="@anim/fragment_close_exit"
app:popUpTo="@+id/sms_export"
app:popUpToInclusive="true" />
<action
android:id="@+id/action_exportingSmsMessagesFragment_to_exportSmsPartiallyCompleteFragment"
app:destination="@id/exportSmsPartiallyCompleteFragment"
app:enterAnim="@anim/fragment_open_enter"
app:exitAnim="@anim/fragment_open_exit"
app:popEnterAnim="@anim/fragment_close_enter"
app:popExitAnim="@anim/fragment_close_exit"
app:popUpTo="@id/sms_export"
app:popUpToInclusive="true" />
<action
android:id="@+id/action_exportingSmsMessagesFragment_to_exportSmsFullErrorFragment"
app:destination="@id/exportSmsFullErrorFragment"
app:enterAnim="@anim/fragment_open_enter"
app:exitAnim="@anim/fragment_open_exit"
app:popEnterAnim="@anim/fragment_close_enter"
app:popExitAnim="@anim/fragment_close_exit"
app:popUpTo="@id/sms_export"
app:popUpToInclusive="true" />
</fragment> </fragment>
<fragment <fragment
@ -70,14 +97,6 @@
android:name="export_message_failure_count" android:name="export_message_failure_count"
app:argType="integer" /> app:argType="integer" />
<action
android:id="@+id/action_exportingSmsMessagesFragment_to_chooseANewDefaultSmsAppFragment"
app:destination="@id/chooseANewDefaultSmsAppFragment"
app:enterAnim="@anim/fragment_open_enter"
app:exitAnim="@anim/fragment_open_exit"
app:popEnterAnim="@anim/fragment_close_enter"
app:popExitAnim="@anim/fragment_close_exit" />
</fragment> </fragment>
<fragment <fragment
@ -86,14 +105,67 @@
android:label="fragment_choose_a_new_default_sms_app" android:label="fragment_choose_a_new_default_sms_app"
tools:layout="@layout/choose_a_new_default_sms_app_fragment" /> tools:layout="@layout/choose_a_new_default_sms_app_fragment" />
<fragment
android:id="@+id/exportSmsPartiallyCompleteFragment"
android:name="org.thoughtcrime.securesms.exporter.flow.ExportSmsPartiallyCompleteFragment"
tools:layout="@layout/export_sms_partially_complete_fragment">
<argument
android:name="export_message_count"
app:argType="integer" />
<argument
android:name="export_message_failure_count"
app:argType="integer" />
</fragment>
<fragment
android:id="@+id/exportSmsFullErrorFragment"
android:name="org.thoughtcrime.securesms.exporter.flow.ExportSmsFullErrorFragment"
tools:layout="@layout/export_sms_full_error_fragment">
<argument
android:name="export_message_count"
app:argType="integer" />
<argument
android:name="export_message_failure_count"
app:argType="integer" />
</fragment>
<fragment
android:id="@+id/smsExportHelpFragment"
android:name="org.thoughtcrime.securesms.exporter.flow.SmsExportHelpFragment"
tools:layout="@layout/sms_export_help_fragment" />
<action <action
android:id="@+id/action_direct_to_exportSmsCompleteFragment" android:id="@+id/action_direct_to_exportYourSmsMessagesFragment"
app:destination="@id/exportSmsCompleteFragment" app:destination="@id/exportYourSmsMessagesFragment"
app:enterAnim="@anim/fragment_open_enter" app:enterAnim="@anim/fragment_open_enter"
app:exitAnim="@anim/fragment_open_exit" app:exitAnim="@anim/fragment_open_exit"
app:popEnterAnim="@anim/fragment_close_enter" app:popEnterAnim="@anim/fragment_close_enter"
app:popExitAnim="@anim/fragment_close_exit" app:popExitAnim="@anim/fragment_close_exit"
app:popUpTo="@+id/exportYourSmsMessagesFragment" app:popUpTo="@id/sms_export"
app:popUpToInclusive="true" /> app:popUpToInclusive="true" />
<action
android:id="@+id/action_direct_to_chooseANewDefaultSmsAppFragment"
app:destination="@id/chooseANewDefaultSmsAppFragment"
app:enterAnim="@anim/fragment_open_enter"
app:exitAnim="@anim/fragment_open_exit"
app:popEnterAnim="@anim/fragment_close_enter"
app:popExitAnim="@anim/fragment_close_exit"
app:popUpTo="@+id/sms_export"
app:popUpToInclusive="true" />
<action
android:id="@+id/action_direct_to_helpFragment"
app:destination="@id/smsExportHelpFragment"
app:enterAnim="@anim/fragment_open_enter"
app:exitAnim="@anim/fragment_open_exit"
app:popEnterAnim="@anim/fragment_close_enter"
app:popExitAnim="@anim/fragment_close_exit" />
</navigation> </navigation>

Wyświetl plik

@ -2516,7 +2516,7 @@
<string name="HelpFragment__debug_log">Debug Log:</string> <string name="HelpFragment__debug_log">Debug Log:</string>
<string name="HelpFragment__could_not_upload_logs">Could not upload logs</string> <string name="HelpFragment__could_not_upload_logs">Could not upload logs</string>
<string name="HelpFragment__please_be_as_descriptive_as_possible">Please be as descriptive as possible to help us understand the issue.</string> <string name="HelpFragment__please_be_as_descriptive_as_possible">Please be as descriptive as possible to help us understand the issue.</string>
<string-array name="HelpFragment__categories_4"> <string-array name="HelpFragment__categories_5">
<item>\-\- Please select an option \-\-</item> <item>\-\- Please select an option \-\-</item>
<item>Something\'s Not Working</item> <item>Something\'s Not Working</item>
<item>Feature Request</item> <item>Feature Request</item>
@ -2525,6 +2525,7 @@
<item>Other</item> <item>Other</item>
<item>Payments (MobileCoin)</item> <item>Payments (MobileCoin)</item>
<item>Donations &amp; Badges</item> <item>Donations &amp; Badges</item>
<item>SMS Export</item>
</string-array> </string-array>
<!-- ReactWithAnyEmojiBottomSheetDialogFragment --> <!-- ReactWithAnyEmojiBottomSheetDialogFragment -->
@ -5347,6 +5348,12 @@
<item quantity="one">Exporting %1$d of %2$d…</item> <item quantity="one">Exporting %1$d of %2$d…</item>
<item quantity="other">Exporting %1$d of %2$d…</item> <item quantity="other">Exporting %1$d of %2$d…</item>
</plurals> </plurals>
<!-- Alert dialog title shown when we think a user may not have enough local storage available to export sms messages -->
<string name="ExportingSmsMessagesFragment__you_may_not_have_enough_disk_space">You may not have enough disk space</string>
<!-- Alert dialog message shown when we think a user may not have enough local storage available to export sms messages, placeholder is the file size, e.g., 128kB -->
<string name="ExportingSmsMessagesFragment__you_need_approximately_s_to_export_your_messages_ensure_you_have_enough_space_before_continuing">You need approximately %1$s to export your messages, ensure you have enough space before continuing.</string>
<!-- Alert dialog button to continue with exporting sms after seeing the lack of storage warning -->
<string name="ExportingSmsMessagesFragment__continue_anyway">Continue anyway</string>
<!-- ChooseANewDefaultSmsAppFragment --> <!-- ChooseANewDefaultSmsAppFragment -->
<!-- Title of the screen --> <!-- Title of the screen -->
@ -5444,6 +5451,26 @@
<item quantity="other">%1$d of %2$d messages exported</item> <item quantity="other">%1$d of %2$d messages exported</item>
</plurals> </plurals>
<!-- Title of screen shown when some sms messages did not export -->
<string name="ExportSmsPartiallyComplete__export_partially_complete">Export partially complete</string>
<!-- Debug step 1 on screen shown when some sms messages did not export -->
<string name="ExportSmsPartiallyComplete__ensure_you_have_an_additional_s_free_on_your_phone_to_export_your_messages">Ensure you have an additional %1$s free on your phone to export your messages</string>
<!-- Debug step 2 on screen shown when some sms messages dit not export -->
<string name="ExportSmsPartiallyComplete__retry_export_which_will_only_retry_messages_that_have_not_yet_been_exported">Retry export, which will only retry messages that have not yet been exported</string>
<!-- Partial sentence for Debug step 3 on screen shown when some sms messages did not export, is combined with 'contact us' -->
<string name="ExportSmsPartiallyComplete__if_the_problem_persists">If the problem persists, </string>
<!-- Partial sentence for deubg step 3 on screen shown when some sms messages did not export, combined with 'If the problem persists', link text to open contact support view -->
<string name="ExportSmsPartiallyComplete__contact_us">contact us</string>
<!-- Button text to retry sms export -->
<string name="ExportSmsPartiallyComplete__retry">Retry</string>
<!-- Button text to continue sms export flow and not retry failed message exports -->
<string name="ExportSmsPartiallyComplete__continue_anyway">Continue anyway</string>
<!-- Title of screen shown when all sms messages failed to export -->
<string name="ExportSmsFullError__error_exporting_sms_messages">Error exporting SMS messages</string>
<!-- Helper text shown when all sms messages failed to export -->
<string name="ExportSmsFullError__please_try_again_if_the_problem_persists">Please try again. If the problem persists, </string>
<!-- EOF --> <!-- EOF -->
</resources> </resources>

Wyświetl plik

@ -48,6 +48,7 @@ dependencies {
api libs.androidx.annotation api libs.androidx.annotation
implementation libs.androidx.core.ktx implementation libs.androidx.core.ktx
implementation libs.androidx.lifecycle.common.java8
implementation libs.google.protobuf.javalite implementation libs.google.protobuf.javalite
implementation libs.androidx.sqlite implementation libs.androidx.sqlite
implementation libs.rxjava3.rxjava implementation libs.rxjava3.rxjava

Wyświetl plik

@ -67,6 +67,17 @@ fun <T> Cursor.requireObject(column: String, serializer: StringSerializer<T>): T
return serializer.deserialize(CursorUtil.requireString(this, column)) return serializer.deserialize(CursorUtil.requireString(this, column))
} }
@JvmOverloads
fun Cursor.readToSingleLong(defaultValue: Long = 0): Long {
return use {
if (it.moveToFirst()) {
it.getLong(0)
} else {
defaultValue
}
}
}
inline fun <T> Cursor.readToList(predicate: (T) -> Boolean = { true }, mapper: (Cursor) -> T): List<T> { inline fun <T> Cursor.readToList(predicate: (T) -> Boolean = { true }, mapper: (Cursor) -> T): List<T> {
val list = mutableListOf<T>() val list = mutableListOf<T>()
use { use {

Wyświetl plik

@ -4,12 +4,16 @@ import android.os.AsyncTask;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.lifecycle.Lifecycle; import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleEventObserver;
import androidx.lifecycle.LifecycleOwner;
import org.signal.core.util.ThreadUtil; import org.signal.core.util.ThreadUtil;
import org.signal.core.util.concurrent.SignalExecutors; import org.signal.core.util.concurrent.SignalExecutors;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import io.reactivex.rxjava3.observers.DefaultObserver;
public class SimpleTask { public class SimpleTask {
/** /**
@ -37,6 +41,35 @@ public class SimpleTask {
}); });
} }
/**
* Runs a task in the background and passes the result of the computation to a task that is run
* on the main thread. Will only invoke the {@code foregroundTask} if the provided {@link Lifecycle}
* is or enters in the future a valid (i.e. visible) state. In this way, it is very similar to
* {@link AsyncTask}, but is safe in that you can guarantee your task won't be called when your
* view is in an invalid state.
*/
public static <E> void runWhenValid(@NonNull Lifecycle lifecycle, @NonNull BackgroundTask<E> backgroundTask, @NonNull ForegroundTask<E> foregroundTask) {
lifecycle.addObserver(new LifecycleEventObserver() {
@Override public void onStateChanged(@NonNull LifecycleOwner lifecycleOwner, @NonNull Lifecycle.Event event) {
if (isValid(lifecycle)) {
lifecycle.removeObserver(this);
SignalExecutors.BOUNDED.execute(() -> {
final E result = backgroundTask.run();
if (isValid(lifecycle)) {
ThreadUtil.runOnMain(() -> {
if (isValid(lifecycle)) {
foregroundTask.run(result);
}
});
}
});
}
}
});
}
/** /**
* Runs a task in the background and passes the result of the computation to a task that is run on * Runs a task in the background and passes the result of the computation to a task that is run on
* the main thread. Essentially {@link AsyncTask}, but lambda-compatible. * the main thread. Essentially {@link AsyncTask}, but lambda-compatible.

Wyświetl plik

@ -25,6 +25,10 @@ import java.util.concurrent.Executors
abstract class SmsExportService : Service() { abstract class SmsExportService : Service() {
companion object { companion object {
fun clearProgressState() {
progressState.onNext(SmsExportProgress.Init)
}
private val TAG = Log.tag(SmsExportService::class.java) private val TAG = Log.tag(SmsExportService::class.java)
/** /**
@ -95,6 +99,7 @@ abstract class SmsExportService : Service() {
Log.d(TAG, "Export complete") Log.d(TAG, "Export complete")
stopForeground(true) stopForeground(true)
stopSelf()
isStarted = false isStarted = false
} }
} }