Add some polish to backups changes.

This commit is contained in:
Alex Hart 2020-10-22 12:07:01 -03:00 committed by Cody Henthorne
parent 9c97cd8816
commit e93d7518f3
8 changed files with 83 additions and 28 deletions

View File

@ -6,6 +6,8 @@ import android.content.ClipboardManager;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Build;
import android.provider.DocumentsContract;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.widget.Button; import android.widget.Button;
@ -21,7 +23,6 @@ import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.components.SwitchPreferenceCompat;
import org.thoughtcrime.securesms.keyvalue.SignalStore; import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.logging.Log; import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.registration.fragments.RestoreBackupFragment; import org.thoughtcrime.securesms.registration.fragments.RestoreBackupFragment;
@ -31,8 +32,6 @@ import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.text.AfterTextChanged; import org.thoughtcrime.securesms.util.text.AfterTextChanged;
import java.util.Objects;
public class BackupDialog { public class BackupDialog {
private static final String TAG = Log.tag(BackupDialog.class); private static final String TAG = Log.tag(BackupDialog.class);
@ -119,6 +118,10 @@ public class BackupDialog {
.setPositiveButton(R.string.BackupDialog_choose_folder, ((dialog, which) -> { .setPositiveButton(R.string.BackupDialog_choose_folder, ((dialog, which) -> {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE); Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
if (Build.VERSION.SDK_INT >= 26) {
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, SignalStore.settings().getLatestSignalBackupDirectory());
}
intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION | intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION |
Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION |
Intent.FLAG_GRANT_READ_URI_PERMISSION); Intent.FLAG_GRANT_READ_URI_PERMISSION);

View File

@ -11,7 +11,8 @@ public final class SettingsValues extends SignalStoreValues {
public static final String LINK_PREVIEWS = "settings.link_previews"; public static final String LINK_PREVIEWS = "settings.link_previews";
public static final String KEEP_MESSAGES_DURATION = "settings.keep_messages_duration"; public static final String KEEP_MESSAGES_DURATION = "settings.keep_messages_duration";
private static final String SIGNAL_BACKUP_DIRECTORY = "settings.signal.backup.directory"; private static final String SIGNAL_BACKUP_DIRECTORY = "settings.signal.backup.directory";
private static final String SIGNAL_LATEST_BACKUP_DIRECTORY = "settings.signal.backup.directory,latest";
public static final String THREAD_TRIM_LENGTH = "pref_trim_length"; public static final String THREAD_TRIM_LENGTH = "pref_trim_length";
public static final String THREAD_TRIM_ENABLED = "pref_trim_threads"; public static final String THREAD_TRIM_ENABLED = "pref_trim_threads";
@ -61,11 +62,23 @@ public final class SettingsValues extends SignalStoreValues {
public void setSignalBackupDirectory(@NonNull Uri uri) { public void setSignalBackupDirectory(@NonNull Uri uri) {
putString(SIGNAL_BACKUP_DIRECTORY, uri.toString()); putString(SIGNAL_BACKUP_DIRECTORY, uri.toString());
putString(SIGNAL_LATEST_BACKUP_DIRECTORY, uri.toString());
} }
public @Nullable public @Nullable Uri getSignalBackupDirectory() {
Uri getSignalBackupDirectory() { return getUri(SIGNAL_BACKUP_DIRECTORY);
String uri = getString(SIGNAL_BACKUP_DIRECTORY, ""); }
public @Nullable Uri getLatestSignalBackupDirectory() {
return getUri(SIGNAL_LATEST_BACKUP_DIRECTORY);
}
public void clearSignalBackupDirectory() {
putString(SIGNAL_BACKUP_DIRECTORY, null);
}
private @Nullable Uri getUri(@NonNull String key) {
String uri = getString(key, "");
if (TextUtils.isEmpty(uri)) { if (TextUtils.isEmpty(uri)) {
return null; return null;
@ -73,8 +86,4 @@ public final class SettingsValues extends SignalStoreValues {
return Uri.parse(uri); return Uri.parse(uri);
} }
} }
public void clearSignalBackupDirectory() {
putString(SIGNAL_BACKUP_DIRECTORY, null);
}
} }

View File

@ -4,6 +4,7 @@ import android.Manifest;
import android.app.Activity; import android.app.Activity;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.text.method.LinkMovementMethod; import android.text.method.LinkMovementMethod;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -102,17 +103,15 @@ public class BackupsPreferenceFragment extends Fragment {
@Override @Override
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
if (requestCode == CHOOSE_BACKUPS_LOCATION_REQUEST_CODE && resultCode == Activity.RESULT_OK && data != null && data.getData() != null) { if (Build.VERSION.SDK_INT >= 29 &&
requestCode == CHOOSE_BACKUPS_LOCATION_REQUEST_CODE &&
DocumentFile backupDirectory = DocumentFile.fromTreeUri(requireContext(), data.getData()); resultCode == Activity.RESULT_OK &&
if (backupDirectory == null || !backupDirectory.isDirectory()) { data != null &&
Log.w(TAG, "Could not open backup directory."); data.getData() != null)
return; {
}
BackupDialog.showEnableBackupDialog(requireContext(), BackupDialog.showEnableBackupDialog(requireContext(),
data, data,
backupDirectory.getName(), StorageUtil.getDisplayPath(requireContext(), data.getData()),
this::setBackupsEnabled); this::setBackupsEnabled);
} }
} }
@ -159,13 +158,10 @@ public class BackupsPreferenceFragment extends Fragment {
if (BackupUtil.isUserSelectionRequired(requireContext()) && if (BackupUtil.isUserSelectionRequired(requireContext()) &&
BackupUtil.canUserAccessBackupDirectory(requireContext())) BackupUtil.canUserAccessBackupDirectory(requireContext()))
{ {
Uri backupUri = Objects.requireNonNull(SignalStore.settings().getSignalBackupDirectory()); Uri backupUri = Objects.requireNonNull(SignalStore.settings().getSignalBackupDirectory());
DocumentFile backupFile = Objects.requireNonNull(DocumentFile.fromTreeUri(requireContext(), backupUri));
if (backupFile.getName() != null) { folder.setVisibility(View.VISIBLE);
folder.setVisibility(View.VISIBLE); folderName.setText(StorageUtil.getDisplayPath(requireContext(), backupUri));
folderName.setText(backupFile.getName());
}
} else if (StorageUtil.canWriteInSignalStorageDir()) { } else if (StorageUtil.canWriteInSignalStorageDir()) {
try { try {
folder.setVisibility(View.VISIBLE); folder.setVisibility(View.VISIBLE);

View File

@ -2,7 +2,9 @@ package org.thoughtcrime.securesms.registration.fragments;
import android.app.Activity; import android.app.Activity;
import android.content.Intent; import android.content.Intent;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.provider.DocumentsContract;
import android.text.method.LinkMovementMethod; import android.text.method.LinkMovementMethod;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
@ -20,8 +22,6 @@ import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.logging.Log; import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.util.BackupUtil; import org.thoughtcrime.securesms.util.BackupUtil;
import java.util.Objects;
public class ChooseBackupFragment extends BaseRegistrationFragment { public class ChooseBackupFragment extends BaseRegistrationFragment {
private static final String TAG = Log.tag(ChooseBackupFragment.class); private static final String TAG = Log.tag(ChooseBackupFragment.class);
@ -71,6 +71,10 @@ public class ChooseBackupFragment extends BaseRegistrationFragment {
intent.setType("application/octet-stream"); intent.setType("application/octet-stream");
if (Build.VERSION.SDK_INT >= 26) {
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, SignalStore.settings().getLatestSignalBackupDirectory());
}
startActivityForResult(intent, OPEN_FILE_REQUEST_CODE); startActivityForResult(intent, OPEN_FILE_REQUEST_CODE);
} }
} }

View File

@ -8,7 +8,9 @@ import android.graphics.Canvas;
import android.graphics.Paint; import android.graphics.Paint;
import android.net.Uri; import android.net.Uri;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.provider.DocumentsContract;
import android.text.Editable; import android.text.Editable;
import android.text.Spanned; import android.text.Spanned;
import android.text.TextWatcher; import android.text.TextWatcher;
@ -26,6 +28,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi; import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import androidx.documentfile.provider.DocumentFile;
import androidx.navigation.Navigation; import androidx.navigation.Navigation;
import com.dd.CircularProgressButton; import com.dd.CircularProgressButton;
@ -49,6 +52,7 @@ import org.thoughtcrime.securesms.notifications.NotificationChannels;
import org.thoughtcrime.securesms.service.LocalBackupListener; import org.thoughtcrime.securesms.service.LocalBackupListener;
import org.thoughtcrime.securesms.util.BackupUtil; import org.thoughtcrime.securesms.util.BackupUtil;
import org.thoughtcrime.securesms.util.DateUtils; import org.thoughtcrime.securesms.util.DateUtils;
import org.thoughtcrime.securesms.util.StorageUtil;
import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.concurrent.SimpleTask; import org.thoughtcrime.securesms.util.concurrent.SimpleTask;

View File

@ -19,6 +19,7 @@ import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi; import androidx.annotation.RequiresApi;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import android.os.storage.StorageManager;
import android.telephony.SubscriptionManager; import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager; import android.telephony.TelephonyManager;
import android.view.WindowManager; import android.view.WindowManager;
@ -34,6 +35,10 @@ public class ServiceUtil {
return (WindowManager) context.getSystemService(Activity.WINDOW_SERVICE); return (WindowManager) context.getSystemService(Activity.WINDOW_SERVICE);
} }
public static StorageManager getStorageManager(Context context) {
return ContextCompat.getSystemService(context, StorageManager.class);
}
public static ConnectivityManager getConnectivityManager(Context context) { public static ConnectivityManager getConnectivityManager(Context context) {
return (ConnectivityManager) context.getSystemService(Activity.CONNECTIVITY_SERVICE); return (ConnectivityManager) context.getSystemService(Activity.CONNECTIVITY_SERVICE);
} }

View File

@ -5,17 +5,24 @@ import android.content.Context;
import android.net.Uri; import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.os.Environment; import android.os.Environment;
import android.os.storage.StorageManager;
import android.os.storage.StorageVolume;
import android.provider.MediaStore; import android.provider.MediaStore;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import org.thoughtcrime.securesms.BuildConfig; import org.thoughtcrime.securesms.BuildConfig;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.database.NoExternalStorageException; import org.thoughtcrime.securesms.database.NoExternalStorageException;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.permissions.Permissions; import org.thoughtcrime.securesms.permissions.Permissions;
import java.io.File; import java.io.File;
import java.util.List;
import java.util.Objects;
public class StorageUtil { public class StorageUtil {
@ -45,6 +52,30 @@ public class StorageUtil {
return backups; return backups;
} }
@RequiresApi(24)
public static @NonNull String getDisplayPath(@NonNull Context context, @NonNull Uri uri) {
String lastPathSegment = Objects.requireNonNull(uri.getLastPathSegment());
String backupVolume = lastPathSegment.replaceFirst(":.*", "");
String backupName = lastPathSegment.replaceFirst(".*:", "");
StorageManager storageManager = ServiceUtil.getStorageManager(context);
List<StorageVolume> storageVolumes = storageManager.getStorageVolumes();
StorageVolume storageVolume = null;
for (StorageVolume volume : storageVolumes) {
if (Objects.equals(volume.getUuid(), backupVolume)) {
storageVolume = volume;
break;
}
}
if (storageVolume == null) {
return backupName;
} else {
return context.getString(R.string.StorageUtil__s_s, storageVolume.getDescription(context), backupName);
}
}
public static File getBackupCacheDirectory(Context context) { public static File getBackupCacheDirectory(Context context) {
return context.getExternalCacheDir(); return context.getExternalCacheDir();
} }

View File

@ -2750,6 +2750,9 @@
<string name="VoiceNoteMediaDescriptionCompatFactory__voice_message">Voice message &#183; %1$s</string> <string name="VoiceNoteMediaDescriptionCompatFactory__voice_message">Voice message &#183; %1$s</string>
<string name="VoiceNoteMediaDescriptionCompatFactory__s_to_s">%1$s to %2$s</string> <string name="VoiceNoteMediaDescriptionCompatFactory__s_to_s">%1$s to %2$s</string>
<!-- StorageUtil -->
<string name="StorageUtil__s_s">%1$s/%2$s</string>
<!-- EOF --> <!-- EOF -->
</resources> </resources>